I am new to open GL, I just want to move a circle randomly in the screen , when the user touches the circle , I need to know the hit and miss.
this is what I'm able to achieve through the online classes.
render class:
public class HelloOpenGLES10Renderer implements Renderer {
private int points = 250;
private float vertices[] = { 0.0f, 0.0f, 0.0f };
private FloatBuffer vertBuff;
public float x = 0.0f, y = 0.0f;
public boolean color = false;
boolean first = true;
#Override
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(x, y, 0);
gl.glColor4f(1.0f, 1.0f, 1.0f, 0f);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertBuff);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, points);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.i("TAG", "change" + width + ":" + height);
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);
GLU.gluLookAt(gl, 0f, 0f, -5f, 0.0f, 0.0f, 0f, 0.0f, 1.0f, 0.0f);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.i("TAG", "CREATE");
gl.glClearColor(0.1f, 0.1f, 0.0f, 1.0f);
initShapes();
}
private void initShapes() {
vertices = new float[(points + 1) * 3];
for (int i = 3; i < (points + 1) * 3; i += 3) {
double rad = (i * 360 / points * 3) * (3.14 / 180);
vertices[i] = (float) Math.cos(rad) * 0.10f;
vertices[i + 1] = (float) Math.sin(rad) * 0.10f;
vertices[i + 2] = 0;
}
ByteBuffer bBuff = ByteBuffer.allocateDirect(vertices.length * 4);
bBuff.order(ByteOrder.nativeOrder());
vertBuff = bBuff.asFloatBuffer();
vertBuff.put(vertices);
vertBuff.position(0);
}
}
Activity:
package com.example.opengltrail;
import java.util.Random;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
public class MainActivity extends Activity implements OnTouchListener {
private GLSurfaceView mGLView;
float oldx = 0, oldy = 0;
private HelloOpenGLES10Renderer m;
ProgressDialogThread p;
ProgressDialogThread123 t;
boolean stop = true;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(this);
m = new HelloOpenGLES10Renderer();
mGLView.setRenderer(m);
mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
setContentView(mGLView);
mGLView.setOnTouchListener(this);
p = new ProgressDialogThread();
}
#Override
protected void onPause() {
super.onPause();
mGLView.onPause();
p.stop();
stop = false;
}
#Override
protected void onResume() {
super.onResume();
mGLView.onResume();
t = new ProgressDialogThread123();
t.start();
p.start();
}
/**
* gets u the random number btw 0.0 to 1.0
*/
public float getmearandom() {
Random rng = new Random();
float next = rng.nextFloat();
Integer i = rng.nextInt();
if (i % 2 == 0)
next = next * (-1);
return next;
}
class ProgressDialogThread123 extends Thread {
#Override
public void run() {
// TODO Auto-generated method stub
super.run();
for (; stop;) {
p.run();
}
}
}
class ProgressDialogThread extends Thread {
#Override
public void run() {
super.run();
if (stop) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
m.x = getmearandom();
m.y = getmearandom();
Log.i("m.x=" + m.x + ":", "m.y=" + m.y);
mGLView.requestRender();
}
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
float x1 = ((x * 2) / 480);
float y1 = ((y * 2) / 724);
x1 = -1 + x1;
y1 = -1 + y1;
if (y < 362) {
if (y1 > 0)
y1 = -y1;
} else if (y > 362) {
if (y1 < 0)
y1 = -y1;
} else {
y1 = 0;
}
if (x > 240) {
if (x1 < 0)
x1 = -x1;
} else if (x < 240) {
if (x1 > 0)
x1 = -x1;
} else {
x1 = 0;
}
Log.i("x1=" + x1, "y1=" + y1);
float d = (((m.x - x1) * (m.x - x1)) + ((m.y - y1) * (m.y - y1)));
float dd = FloatMath.sqrt(d);
if (dd <= 0.10f) {
m.color = true;
// mGLView.requestRender();
Log.i("Tag", "Circle");
}
// m.x += 0.10f;
return true;
}
}
Please anyone help me !! thanks in advance
If you are only drawing in 2d I suggest you loose "frustum" and "lookAt" and replace them with "ortho" with coordinates: ortho(viewOrigin.x, viewOrigin.x + viewSize.width, viewOrigin.y + viewSize.height, viewOrigin.y, -1.0f, 1.0f). This will make your GL coordinate system same as your view coordinates. As for circle vertices rather create them with radius of 1.0f. Now to draw the circle, before the draw call you just have to "push" matrix, translate to screen coordinates (X, Y, .0f), scale to radius R in pixels (R, R, 1.0f) and "pop" the matrix after the call.. Now to check on touch if the circle was hit:
`bool didHit = ((touch.x-cicrcleCenter.x)*(touch.x-cicrcleCenter.x) +
(touch.y-cicrcleCenter.y)*(touch.y-cicrcleCenter.y))
< R*R`;
Note that "viewOrigin" in "ortho" depends on where you are catching touches: If you are catching them in the same view it will probably be at (0,0) no matter where the view is. Those coordinates should correspond to coordinates you receive in your touch event when pressing at upper left and bottom right corners of your view.
If you really need to draw in 3d and you will have to use frustum, you will need to get inverse of your projection matrix to create 3d rays from your touches and then check for hits the same way you would for bullets if you like.
Related
I've created a custom view that draws a dial gauge. If I set a static value for the angle of the needle, the gauge draws as expected (see first image below). If I attempt to set the angle of the needle through runOnUiThread, then I have weird needle artifacts (see second image).
I am calling canvas.drawColor(color.BLACK) each time onDraw() is called, so I am not sure how the artifacts are being carried over. My best guess is that I am not handling threading correctly in the method that calls runOnUiThread().
DialGaugeView class:
package net.dynu.kubie.redneksldhlr;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
public class DialGaugeView extends View {
private int height, width, min = 0;
private int numberFontSize, titleFontSize = 0;
private float dialEdgeStroke, dialEdgeRadius = 0;
private float dialFaceRadius = 0;
private float tickMajorStroke, tickSweep, tickAngleStart, tickAngleEnd, tickEdgeRadius, tickInnerMajorRadius, tickInnerMinorRadius = 0;
private int tickMajorCount = 0;
private float tickMinorStroke = 0;
private int tickMinorCount = 0;
private int tickTotalCount = 0;
private int numberMin, numberMax = 0;
private float numberRadius = 0;
private float arrowTipRadius, arrowRearRadius = 0;
private float arrowCenterRadius, arrowPinRadius = 0;
private float sensorInput = 0;
private float temp = 0;
private Paint paint;
private boolean isInit;
private float titleRadius = 0;
private Rect rect = new Rect();
private Path path = new Path();
private String titleStr = "";
//Variables common to drawing functions
private float center_x, center_y = 0;
private float x1, x2, x3, y1, y2, y3 = 0;
private float angle = 0;
private int number = 0;
private String str = "";
public DialGaugeView(Context context) {
super(context);
}
public DialGaugeView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.DialGaugeView,
0, 0);
try {
tickMajorCount = a.getInteger(R.styleable.DialGaugeView_tickCountMajor, 5);
tickMinorCount = a.getInteger(R.styleable.DialGaugeView_tickCountMinor, 0);
tickSweep = a.getFloat(R.styleable.DialGaugeView_tickSweep, 270) / 2;
numberMin = a.getInteger(R.styleable.DialGaugeView_displayMin, 0);
numberMax = a.getInteger(R.styleable.DialGaugeView_displayMax, 1);
titleStr = a.getString(R.styleable.DialGaugeView_displayTitle);
} finally {
a.recycle();
}
}
public DialGaugeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public int getTickMajorCount() {
return tickMajorCount;
}
public void setTickMajorCount(int i) {
tickMajorCount = i;
isInit = false;
invalidate();
requestLayout();
}
public int getTickMinorCount() {
return tickMinorCount;
}
public void setTickMinorCount(int i) {
tickMinorCount = i;
isInit = false;
invalidate();
requestLayout();
}
public float getTickSweep() {
return tickSweep;
}
public void setTickSweep(float i) {
tickSweep = i / 2;
isInit = false;
invalidate();
requestLayout();
}
public int getDisplayMin() {
return numberMin;
}
public void setDisplayMin(int i) {
numberMin = i;
isInit = false;
invalidate();
requestLayout();
}
public int getDisplayMax() {
return numberMax;
}
public void setDisplayMax(int i) {
numberMax = i;
isInit = false;
invalidate();
requestLayout();
}
public float getSensorInput() {
return sensorInput;
}
public void setSensorInput(float i) {
sensorInput = i;
isInit = false;
invalidate();
requestLayout();
}
public String getTitle() {
return titleStr;
}
public void setTitle(String i) {
titleStr = i;
invalidate();
requestLayout();
}
private void initGauge() {
//Common variables
height = getHeight();
width = getWidth();
min = Math.min(height, width);
center_x = width / 2;
center_y = height / 2;
paint = new Paint();
isInit = true;
//Dial face variables
dialEdgeStroke = min / 20;
dialEdgeRadius = min / 2 - dialEdgeStroke / 2;
dialFaceRadius = dialEdgeRadius - dialEdgeStroke / 2;
//Tick variables
//tickMajorCount = 7; //TODO - Class input needed
//tickMinorCount = 1; //TODO - Class input needed
//tickSweep = 270 / 2; //TODO - Class input needed //Degrees +/- from 90 degrees
tickEdgeRadius = dialFaceRadius - dialEdgeStroke / 2;
tickInnerMajorRadius = (float) (tickEdgeRadius - dialEdgeStroke * 1.5);
tickInnerMinorRadius = ((tickEdgeRadius + tickInnerMajorRadius) / 2);
tickMajorStroke = min / 75;
tickAngleStart = 90 + tickSweep;
tickAngleEnd = 90 - tickSweep;
tickMinorStroke = tickMajorStroke / 2;
tickTotalCount = tickMajorCount + (tickMajorCount - 1) * tickMinorCount;
//Numeral variables
//numberMin = 0; //TODO - Class input needed
//numberMax = 120; //TODO - Class input needed
numberRadius = (tickInnerMajorRadius); // - (tickEdgeRadius - tickInnerMajorRadius) * 1.25);
numberFontSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, min / 40,
getResources().getDisplayMetrics());
//Title variables
titleRadius = tickInnerMajorRadius;
titleFontSize = numberFontSize;
//Arrow variables
//sensorInput = (float) (numberMax * .4965); //TODO - Class input needed
arrowTipRadius = tickEdgeRadius;
arrowRearRadius = arrowTipRadius / 2;
arrowCenterRadius = (arrowTipRadius * 1 / 8);
arrowPinRadius = (arrowTipRadius * 1 / 24);
}
#Override
protected void onDraw(Canvas canvas) {
if (!isInit) {
initGauge();
}
canvas.drawColor(Color.BLACK);
drawDialFace(canvas);
drawTicks(canvas);
drawNumeral(canvas);
drawTitle(canvas);
drawArrow(canvas);
postInvalidateDelayed(500);
invalidate();
requestLayout();
}
private void drawDialFace(Canvas canvas) {
paint.reset();
paint.setColor(getResources().getColor(android.R.color.black));
paint.setStrokeWidth(dialEdgeStroke);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
canvas.drawCircle(center_x, center_y, dialEdgeRadius, paint);
paint.reset();
paint.setColor(getResources().getColor(android.R.color.white));
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
canvas.drawCircle(center_x, center_y, dialFaceRadius, paint);
}
private void drawTicks(Canvas canvas) {
paint.reset();
paint.setColor(getResources().getColor(android.R.color.black));
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
for(int i = 0; i < tickTotalCount; i++) {
angle = (float) (((tickAngleEnd - tickAngleStart) * i / (tickTotalCount - 1) + tickAngleStart) / 180 * Math.PI);
x1 = (float) (center_x + Math.cos(angle) * tickEdgeRadius);
y1 = (float) (center_y - Math.sin(angle) * tickEdgeRadius);
if((i % (tickMinorCount + 1)) == 0) {
paint.setStrokeWidth(tickMajorStroke);
x2 = (float) (center_x + Math.cos(angle) * tickInnerMajorRadius);
y2 = (float) (center_y - Math.sin(angle) * tickInnerMajorRadius);
} else {
paint.setStrokeWidth(tickMinorStroke);
x2 = (float) (center_x + Math.cos(angle) * tickInnerMinorRadius);
y2 = (float) (center_y - Math.sin(angle) * tickInnerMinorRadius);
}
canvas.drawLine(x1, y1, x2, y2, paint);
}
}
private void drawNumeral(Canvas canvas) {
paint.reset();
paint.setTextSize(numberFontSize);
paint.setColor(getResources().getColor(android.R.color.black));
for(int i = 0; i < tickMajorCount; i++) {
angle = (float) (((tickAngleEnd - tickAngleStart) * i / (tickMajorCount - 1) + tickAngleStart) / 180 * Math.PI);
number = (numberMax - numberMin) * i / (tickMajorCount - 1) + numberMin;
str = String.valueOf(number);
paint.getTextBounds(str, 0, str.length(), rect);
double c = Math.cos(angle);
double s = Math.sin(angle);
if(rect.width() * Math.abs(s) < rect.height() * Math.abs(c)) {
x2 = (float) (Math.signum(c) * rect.width() / 2);
y2 = (float) (Math.tan(angle) * x2);
} else {
y2 = (float) (Math.signum(s) * rect.height() / 2);
x2 = (float) (1 / Math.tan(angle) * y2);//Math.cotg(angle) * y;
}
x1 = (float) (center_x + Math.cos(angle) * numberRadius - rect.width() / 2 - x2 * 1.25);
y1 = (float) (center_y - Math.sin(angle) * numberRadius + rect.height() / 2 + y2 * 1.25);
canvas.drawText(str, x1, y1, paint);
}
}
private void drawTitle(Canvas canvas) {
paint.reset();
paint.setTextSize(titleFontSize);
paint.setColor(getResources().getColor(android.R.color.black));
angle = (float) ((270.0 / 180) * Math.PI);
paint.getTextBounds(titleStr, 0, str.length(), rect);
x1 = (float) (center_x + Math.cos(angle) * titleRadius - rect.width() / 2);
y1 = (float) (center_y - Math.sin(angle) * titleRadius + rect.height() / 3);
canvas.drawText(titleStr, x1, y1, paint);
}
private void drawArrow(Canvas canvas) {
paint.reset();
paint.setColor(getResources().getColor(android.R.color.holo_red_dark));
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
//Calculate (x,y) coordinates for the arrow path.
temp = (tickAngleEnd - tickAngleStart) * sensorInput / numberMax + tickAngleStart;
angle = (float) (temp / 180 * Math.PI);
x1 = (float) (center_x + Math.cos(angle) * arrowTipRadius);
y1 = (float) (center_y - Math.sin(angle) * arrowTipRadius);
angle = (float) ((temp + 170) / 180 * Math.PI);
x2 = (float) (center_x + Math.cos(angle) * arrowRearRadius);
y2 = (float) (center_y - Math.sin(angle) * arrowRearRadius);
angle = (float) ((temp - 170) / 180 * Math.PI);
x3 = (float) (center_x + Math.cos(angle) * arrowRearRadius);
y3 = (float) (center_y - Math.sin(angle) * arrowRearRadius);
//Draw arrow path using calculated coordinates.
path.moveTo(x1, y1);
path.lineTo(x2, y2);
path.lineTo(x3, y3);
path.close();
canvas.drawPath(path, paint);
//Calculate (x,y) coordinates for dial center.
x1 = center_x;
y1 = center_y;
canvas.drawCircle(x1, y1, arrowCenterRadius, paint);
paint.setColor(getResources().getColor(android.R.color.darker_gray));
canvas.drawCircle(x1, y1, arrowPinRadius, paint);
}
}
My MainActivity:
package net.dynu.kubie.redneksldhlr;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import org.w3c.dom.Text;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hideSystemUI();
startGenerating();
}
#Override
protected void onResume() {
super.onResume();
hideSystemUI();
//demoData();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
hideSystemUI();
//demoData();
}
}
private void hideSystemUI() {
// Enables regular immersive mode.
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
// Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
// Hide the nav bar and status bar
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN);
}
private void startGenerating() {
DoSomethingThread randomWork = new DoSomethingThread();
randomWork.start();
}
public class DoSomethingThread extends Thread {
private static final String TAG = "DoSomethingThread";
private static final int DELAY = 15000; // 5 seconds
private static final int RANDOM_MULTIPLIER = 120;
#Override
public void run() {
//Log.v(TAG, "doing work in Random Number Thread");
while (true) {
float randNum = (float) (Math.random() * RANDOM_MULTIPLIER);
// need to publish the random number back on the UI at this point in the code through the publishProgress(randNum) call
publishProgress(randNum);
try {
Thread.sleep(DELAY);
} catch (InterruptedException e) {
// Log.v(TAG, "Interrupting and stopping the Random Number Thread");
return;
}
}
}
}
private void publishProgress(float randNum) {
//Log.v(TAG, "reporting back from the Random Number Thread");
//final String text = String.format(getString(R.string.service_msg), randNum);
//final String text = Integer.toString(randNum);
final float text = randNum;
runOnUiThread(new Runnable() {
#Override
public void run() {
updateResults(text);
}
});
}
public void updateResults(float results) {
//TextView myTextView = (TextView) findViewById(R.id.testTextView);
DialGaugeView myDial = findViewById(R.id.my_gauge);
myDial.setSensorInput(results);
}
}
I eventually realized that my issue wasn't artifacts at all. My arrow is being drawn as a series of paths. If I do not reset the path prior to adding coordinates for the new arrow, the previous arrow(s) just get dragged along. Adding path.reset(); prior to the addition of the first arrow coordinate solved my problem.
//Draw arrow path using calculated coordinates.
path.reset();
path.moveTo(x1, y1);
path.moveTo(x2, y2);
path.moveTo(x3, y3);
path.close();
canvas.drawPath(path, paint);
Ok so I was able to get the coordinates in 3d space for the touch now I need to test whether that ray intersected a triangle. What I am asking is for help to understand the Test Class. BTW this code came from http://android-raypick.blogspot.ca/2012/04/first-i-want-to-state-this-is-my-first.html. I know to pass in the ray and an empty float array into intersectRayAndTriangle() but the Test T is the V0[], V1[], and V2[] but where do I get those at? Are they the converted coordinates of my object? If so then how would I implement a object with more than one triangle?
My code is:
Surface View:
public class MGLSurface extends GLSurfaceView {
MRenderer mRenderer = new MRenderer();
public static int select_Touch=0;
public static boolean selectButtonOn = false;
float x,y;
static float touchX;
static float touchY;
public MGLSurface(Context context) {
super(context);
// setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
setRenderer(new MRenderer());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getActionMasked();
x = event.getX();
y = event.getY();
switch(action){
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
return true;
case MotionEvent.ACTION_UP:
if (selectButtonOn== true) {
select_Touch = 1;
touchX = event.getX();
touchY = event.getY();
requestRender();
}
}
return true;
}
}
Then my Renderer:
public class MRenderer implements GLSurfaceView.Renderer {
private final String TAG ="Ray Picked";
private int H,W;
Cube cube;
float[] convertedSquare = new float[Cube.vertices.length];
float[] resultVector = new float[4];
float[] inputVector = new float[4];
MatrixGrabber matrixGrabber = new MatrixGrabber();
public MRenderer() {
cube = new Cube();
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST);
gl.glClearColor(.8f,0f,.2f,1f);
gl.glClearDepthf(1f);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0,0,width,height);
H = height;
W = width;
float ratio = (float) width/height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio,ratio,-1,1f,1,25);
}
#Override
public void onDrawFrame(GL10 gl) {
gl.glDisable(GL10.GL_DITHER);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
GLU.gluLookAt(gl, 0, 0, -5, 0, 0, 0, 0, 2, 0);
matrixGrabber.getCurrentState(gl);
// long time = SystemClock.uptimeMillis()% 400l;
// float angle = 0.90f* ((int)time);
gl.glRotatef(1,1,0,0);
gl.glRotatef(10,0,0,5);
cube.draw(gl);
//Converting object cords to 3d space
for(int i =0; i < Cube.vertices.length;i = i+3){
inputVector[0] = Cube.vertices[i];
inputVector[1] = Cube.vertices[i+1];
inputVector[2] = Cube.vertices[i+2];
inputVector[3] = 1;
Matrix.multiplyMV(resultVector, 0, matrixGrabber.mModelView, 0, inputVector, 0);
convertedSquare[i] = resultVector[0]/resultVector[3];
convertedSquare[i+1] = resultVector[1]/resultVector[3];
convertedSquare[i+2] = resultVector[2]/resultVector[3];
//Handle Touch in gl thread
if (MGLSurface.selectButtonOn==true && MGLSurface.select_Touch==1 ) {
this.Ray(gl, W, H, MGLSurface.touchX, MGLSurface.touchY);
MainActivity.mHandler.sendEmptyMessage(1);
MGLSurface.select_Touch = 0;
Log.d(TAG, "Near Coord =" + Arrays.toString(MainActivity.P0));
Log.d(TAG, "Far Coord =" + Arrays.toString(MainActivity.P1));
}
else {
}
}}
public void Ray(GL10 gl, int width, int height, float xTouch, float yTouch) {
matrixGrabber.getCurrentState(gl);
int[] viewport = {0, 0, width, height};
float[] nearCoOrds = new float[3];
float[] farCoOrds = new float[3];
float[] temp = new float[4];
float[] temp2 = new float[4];
// get the near and far ords for the click
float winx = xTouch, winy =(float)viewport[3] - yTouch;
// Log.d(TAG, "modelView is =" + Arrays.toString(matrixGrabber.mModelView));
// Log.d(TAG, "projection view is =" + Arrays.toString(matrixGrabber.mProjection));
int result = GLU.gluUnProject(winx, winy, 1.0f, matrixGrabber.mModelView, 0,
matrixGrabber.mProjection, 0, viewport, 0, temp, 0);
Matrix.multiplyMV(temp2, 0, matrixGrabber.mModelView, 0, temp, 0);
if(result == GL10.GL_TRUE){
nearCoOrds[0] = temp2[0] / temp2[3];
nearCoOrds[1] = temp2[1] / temp2[3];
nearCoOrds[2] = temp2[2] / temp2[3];
}
result = GLU.gluUnProject(winx, winy, 0, matrixGrabber.mModelView, 0,
matrixGrabber.mProjection, 0, viewport, 0, temp, 0);
Matrix.multiplyMV(temp2,0,matrixGrabber.mModelView, 0, temp, 0);
if(result == GL10.GL_TRUE){
farCoOrds[0] = temp2[0] / temp2[3];
farCoOrds[1] = temp2[1] / temp2[3];
farCoOrds[2] = temp2[2] / temp2[3];
}
MainActivity.P0 = farCoOrds;
MainActivity.P1 = nearCoOrds;
}
}
The Test Class:
public class Tests {
public float[] V0;
public float[] V1;
public float[] V2;
public Tests(float[] V0, float[] V1, float[] V2){
this.V0 =V0;
this.V1 = V1;
this.V2 = V2;
}
private static final float SMALL_NUM = 0.00000001f; // anything that avoids division overflow
// intersectRayAndTriangle(): intersect a ray with a 3D triangle
// Input: a ray R, and a triangle T
// Output: *I = intersection point (when it exists)
// Return: -1 = triangle is degenerate (a segment or point)
// 0 = disjoint (no intersect)
// 1 = intersect in unique point I1
// 2 = are in the same plane
public static int intersectRayAndTriangle(MRenderer R, Tests T, float[] I)
{
float[] u, v, n; // triangle vectors
float[] dir, w0, w; // ray vectors
float r, a, b; // params to calc ray-plane intersect
// get triangle edge vectors and plane normal
u = Vector.minus(T.V1, T.V0);
v = Vector.minus(T.V2, T.V0);
n = Vector.crossProduct(u, v); // cross product
if (Arrays.equals(n, new float[]{0.0f, 0.0f, 0.0f})){ // triangle is degenerate
return -1; // do not deal with this case
}
dir = Vector.minus(MainActivity.P1, MainActivity.P0); // ray direction vector
w0 = Vector.minus( MainActivity.P0 , T.V0);
a = - Vector.dot(n,w0);
b = Vector.dot(n,dir);
if (Math.abs(b) < SMALL_NUM) { // ray is parallel to triangle plane
if (a == 0){ // ray lies in triangle plane
return 2;
}else{
return 0; // ray disjoint from plane
}
}
// get intersect point of ray with triangle plane
r = a / b;
if (r < 0.0f){ // ray goes away from triangle
return 0; // => no intersect
}
// for a segment, also test if (r > 1.0) => no intersect
float[] tempI = Vector.addition(MainActivity.P0, Vector.scalarProduct(r,
dir)); // intersect point of ray and plane
I[0] = tempI[0];
I[1] = tempI[1];
I[2] = tempI[2];
// is I inside T?
float uu, uv, vv, wu, wv, D;
uu = Vector.dot(u,u);
uv = Vector.dot(u,v);
vv = Vector.dot(v,v);
w = Vector.minus(I, T.V0);
wu = Vector.dot(w,u);
wv = Vector.dot(w,v);
D = (uv * uv) - (uu * vv);
// get and test parametric coords
float s, t;
s = ((uv * wv) - (vv * wu)) / D;
if (s < 0.0f || s > 1.0f) // I is outside T
return 0;
t = (uv * wu - uu * wv) / D;
if (t < 0.0f || (s + t) > 1.0f) // I is outside T
return 0;
return 1; // I is in T
}
}
I've a 3d-model in OpenGL ES in Android. I've already implemented swipe-gestures for translating, rotating and zooming into the model. Everything but the zooming works fine. I'm not sure what I'm missing or what I have to change but I'm not able to zoom into my model.
The model is a building. What I'd like to do is to zoom into the different floors of the building. But no matter how I change my implementation, I'm not able to do this.
Either the building disappears when I zoom in or the zoom has a limitation so that I can't zoom into it further....
First of all I decreased the field of view by modifying the Matrix:
frustumM(matrix, 0, -ratio/zoom, ratio/zoom, -1/zoom, 1/zoom, nearPlane, farPlane).
Someone told me, that this is not the correct approach and I should modify the eyeZ value like:
eyeZ = -1.0/zoom
The first approach is working, but I'd like to know what my mistake with the second approach is, because it has the issues I mentioned in the beginning.
My renderer-class is the following:
public class MyGLRenderer implements GLSurfaceView.Renderer {
private float[] mModelMatrix = new float[16];
private final float[] mMVMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private float nearPlaneDistance = 1f;
private float farPlaneDistance = 200f;
private float modelRatio = 1.0f;
private int offset = 0;
private float eyeX = 0;
private float eyeY = 0;
private float eyeZ = -1;
private float centerX = 0f;
private float centerY = 0f;
private float centerZ = 0f;
private float upX = 0f;
private float upY = 1.0f;
private float upZ = 0.0f;
private float mZoomLevel = 1f;
private float defaultRotationX = 100.0f; //building otherwise on the wrong side
private float defaultRotationZ = 180.0f; //building otherwise on the wrong side
private float rotationX = defaultRotationX;
private float rotationY = 0.0f;
private float rotationZ = defaultRotationZ;
private float translateX = 0.0f;
private float translateY = 0.0f;
private float translateZ = 0.0f;
private float scaleFactor = 20.0f; //no matter what scale factor -> it's not possible to zoom into the building...
private float ratio;
private float width;
private float height;
private List<IDrawableObject> drawableObjects;
public Model3D model3d;
public MyGLRenderer(Model3D model3d) {
this.model3d = model3d;
getModelScale();
}
private void getModelScale() {
float highestValue = (model3d.width > model3d.height) ? model3d.width
: model3d.height;
modelRatio = 2f / highestValue;
}
#Override
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
drawableObjects = ... ; //to much detail, basically getting triangles
}
#Override
public void onDrawFrame(GL10 unused) {
float[] mMVPMatrix = new float[16];
// Draw background color
Matrix.setIdentityM(mModelMatrix, 0);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// model is in origin-solution too big
Matrix.scaleM(mModelMatrix, 0, modelRatio * scaleFactor, modelRatio
* scaleFactor, modelRatio * scaleFactor);
Matrix.translateM(mModelMatrix, 0, translateX, translateY, translateZ);
rotateModel(mModelMatrix, rotationX, rotationY, rotationZ, true);
// Set the camera position (View matrix)
Matrix.setLookAtM(mViewMatrix, offset, eyeX, eyeY, eyeZ / mZoomLevel,
centerX, centerY, centerZ, upX, upY, upZ);
// combine the model with the view matrix
Matrix.multiplyMM(mMVMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, 1, -1,
nearPlaneDistance, farPlaneDistance);
// Calculate the projection and view transformation
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVMatrix, 0);
for (IDrawableObject d : drawableObjects) {
d.draw(mMVPMatrix);
}
}
private void rotateModel(float[] mModelMatrix, Float x, Float y, Float z,
boolean rotateAroundCenter) {
// translation for rotating the model around its center
if (rotateAroundCenter) {
Matrix.translateM(mModelMatrix, 0, (model3d.width / 2f), 0,
(model3d.height / 2f));
}
if (x != null) {
Matrix.rotateM(mModelMatrix, 0, x, 1.0f, 0.0f, 0.0f);
}
if (y != null) {
Matrix.rotateM(mModelMatrix, 0, y, 0.0f, 1.0f, 0.0f);
}
if (z != null) {
Matrix.rotateM(mModelMatrix, 0, z, 0.0f, 0.0f, 1.0f);
}
// translation back to the origin
if (rotateAroundCenter) {
Matrix.translateM(mModelMatrix, 0, -(model3d.width / 2f), 0,
-(model3d.height / 2f));
}
}
#Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
// Adjust the viewport based on geometry changes,
// such as screen rotation
GLES20.glViewport(0, 0, width, height);
this.width = width;
this.height = height;
ratio = (float) width / height;
}
public static int loadShader(int type, String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public int getFPS() {
return lastMFPS;
}
public static void checkGlError(String glOperation) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.e(TAG, glOperation + ": glError " + error);
throw new RuntimeException(glOperation + ": glError " + error);
}
}
public void setZoom(float zoom) {
this.mZoomLevel = zoom;
}
public void setDistance(float distance) {
eyeZ = distance;
}
public float getDistance() {
return eyeZ;
}
public float getRotationX() {
return rotationX;
}
public void setRotationX(float rotationX) {
this.rotationX = defaultRotationX + rotationX;
}
public float getRotationY() {
return rotationY;
}
public void setRotationY(float rotationY) {
this.rotationY = rotationY;
}
public float getRotationZ() {
return rotationZ;
}
public void setRotationZ(float rotationZ) {
this.rotationZ = defaultRotationZ + rotationZ;
}
public float getFarPlane() {
return farPlaneDistance;
}
public float getNearPlane() {
return nearPlaneDistance;
}
public void addTranslation(float mPosX, float mPosY) {
this.translateX = mPosX;
this.translateY = mPosY;
}
public void downPressed() {
translateX -= 10;
}
public void upPressed() {
translateX += 10;
}
public void actionMoved(float mPosX, float mPosY) {
float translationX = (mPosX / width);
float translationY = -(mPosY / height);
addTranslation(translationX, translationY);
}
public float getmZoomLevel() {
return mZoomLevel;
}
public void setmZoomLevel(float mZoomLevel) {
this.mZoomLevel = mZoomLevel;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
public void setTranslation(Float x, Float y, Float z) {
if (x != null) {
this.translateX = -x;
}
if (y != null) {
this.translateY = y;
}
if (z != null) {
this.translateZ = -z;
}
}
public void setRotation(Float x, Float y, Float z) {
if (x != null) {
this.rotationX = defaultRotationX + x;
}
if (y != null) {
this.rotationY = y;
}
if (z != null) {
this.rotationZ = defaultRotationZ + z;
}
}
public void setScale(float scale) {
this.mZoomLevel = scale;
}
public float getDefaultRotationX() {
return defaultRotationX;
}
}
Do you see any mistake I'm currently doing? You can also have a look into the github repository: https://github.com/Dalanie/OpenGL-ES/tree/master/buildingGL
First you must define what you mean by "zoom". In the scenario of a perspective projection, there are a few possibilities:
You change the field of view. This is analogous to the zoom of cameras, where zooming results in changing the focal width.
You just scale the model before the projection.
You change the distance of the model (nearer to the camera to zoom in, farer away to zoom out)
The variant 1 is what you did by changing the frustum. In my opinion, that is the most intuitive effect. At least to someone who is used to cameras. ALso note that this has the same effect as upscaling some sub-rectangle of the 2d projected image to fill the whole screen.
Changing eyeZ is approach 3. But now you must be carefol to not move the object out of the viewing volume (which seems to be the issue you are describing). Ideally you would modify the frustum here, too. But to keep the field of view, while moving the near/far planes so that the object always stays inbetween. Note that this requires changing all 6 values of the frustum, what stays the same should be the ratios left/near, right/near, top/near and bottom/near to keep the FOV/aspect you had before.
I am creating a bar graph in android using opengl
from an activity I'm calling the renderer and from the renderer I'm calling a cube(im using cubes for showing the bars)
Here is my renderer code:
public class BarRenderer implements Renderer {
int[] vals;
private float translatex, translatez, scaly;
public BarRenderer(boolean useTranslucentBackground, int[] vals) {
mTranslucentBackground = useTranslucentBackground;
this.vals = vals;
for (int i = 0; i < this.vals.length; i++) {
mcube[i] = new Cube();
}
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
translatex = 0.5f;
scaly = 0.8f;
for (int i = 0; i < vals.length; i++) {
gl.glTranslatef((-1.0f + (translatex * i)), 0.0f, translatez);
gl.glRotatef(mAngle, 0.0f, 1.0f, 0.0f);
gl.glScalef(0.4f, scaly * vals[i], 0.6f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
mcube[i].draw(gl);
}
mTransY = .075f;
mAngle = -60.0f;
translatez = -7.0f;
Log.i("Draw", "called");
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float aspectRatio;
float zNear = .1f;
float zFar = 1000;
float fieldOfView = 80.0f / 57.3f;
float size;
gl.glEnable(GL10.GL_NORMALIZE);
aspectRatio = (float) width / (float) height;
gl.glMatrixMode(GL10.GL_PROJECTION);
size = zNear * (float) (Math.tan((double) (fieldOfView / 2.0f)));
gl.glFrustumf(-size, size, -size / aspectRatio, size / aspectRatio,
zNear, zFar);
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
if (mTranslucentBackground) {
gl.glClearColor(0, 0, 0, 0);
} else {
gl.glClearColor(1, 1, 1, 1);
}
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_POINT_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
}
private boolean mTranslucentBackground;
private Cube[] mcube = new Cube[4];
private float mTransY;
private float mAngle;
}
but unfortunately it is giving the bar graph like this:
anyone will understand this is not exactly like a bar graph
but please point out my faults here, where am i doing wrong:
1>the bar heights are 4 1 2 1 but they r not accurately of their sizes
2>the space between the bars are supposed to be .5f apart but they start with a big gap but reduce repeatedly after every bar
3>how to start them from one base plane
EDIT:
4> can I animate the growth of this bars?how to do that
My cube code:
public class Cube {
private ByteBuffer mTfan1;
private ByteBuffer mTfan2;
private int bar;
public Cube(int i) {
this.bar = i;
float vertices[] = {
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, -1.0f,1.0f,
-1.0f, -1.0f, 1.0f,
-1.0f, 1.0f, -1.0f,
1.0f, 1.0f, -1.0f,
1.0f, -1.0f, -1.0f,
-1.0f, -1.0f, -1.0f
};
byte maxColor = (byte) 255;
byte colors[][] =
{
{maxColor,maxColor, 0,maxColor},
{0, maxColor,maxColor,maxColor},
{0, 0, 0,maxColor},
{maxColor, 0,maxColor,maxColor},
{maxColor, 0, 0,maxColor},
{0, maxColor, 0,maxColor},
{0, 0,maxColor,maxColor},
{0, 0, 0,maxColor}
};
byte tfan1[] =
{
1,0,3,
1,3,2,
1,2,6,
1,6,5,
1,5,4,
1,4,0
};
byte tfan2[] =
{
7,4,5,
7,5,6,
7,6,2,
7,2,3,
7,3,0,
7,0,4
};
byte indices[] =
{ 0, 3, 1, 0, 2, 3 };
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
mFVertexBuffer.put(vertices);
mFVertexBuffer.position(0);
mColorBuffer = ByteBuffer.allocateDirect(colors.length);
mColorBuffer.put(colors[bar]);
mColorBuffer.position(0);
mTfan1 = ByteBuffer.allocateDirect(tfan1.length);
mTfan1.put(tfan1);
mTfan1.position(0);
mTfan2 = ByteBuffer.allocateDirect(tfan2.length);
mTfan2.put(tfan2);
mTfan2.position(0);
}
public void draw(GL10 gl)
{
gl.glVertexPointer(3, GL11.GL_FLOAT, 0, mFVertexBuffer);
gl.glColorPointer(4, GL11.GL_UNSIGNED_BYTE, 0, mColorBuffer);
gl.glDrawElements( gl.GL_TRIANGLE_FAN, 6 * 3, gl.GL_UNSIGNED_BYTE, mTfan1);
gl.glDrawElements( gl.GL_TRIANGLE_FAN, 6 * 3, gl.GL_UNSIGNED_BYTE, mTfan2);
}
private FloatBuffer mFVertexBuffer;
private ByteBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
}
i think something has to be done in the draw method but what??how to animate here?
please help
thanks
2 Before glTranslate and rotate calls you should use glPushMatrix and after that glPopMatrix functions, or call glTranslate without increment. Because glTranslate multiply existing projection matrix on new matrix from glTranslate parameters
3
gl.glPushMatrix() ;
gl.glTranslate(0,y,0);
mcube[i].draw(gl);
gl.glPopMatrix();
with y= - Barheight/2 in your case or change vertex coordinates of your bars
I have done creating the 3d bar graph though I have some other issues right now
but I believe some one might be helpful with this code.
Myrenderer class:
public class BarRenderer implements GLSurfaceView.Renderer {
int[] vals;
private float translatex, scaly;
// For controlling cube's z-position, x and y angles and speeds (NEW)
float angleX = 0; // (NEW)
float angleY = 0; // (NEW)
float speedX = 0; // (NEW)
float speedY = 0; // (NEW)
float translatez;
public BarRenderer(Context context, boolean useTranslucentBackground,
int[] vals) {
mTranslucentBackground = useTranslucentBackground;
mfloor = new Cube(0);
mwall = new Cube(0);
this.vals = vals;
for (int i = 0; i < this.vals.length; i++) {
mcube[i] = new Cube(i);
}
}
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glClearColor(0.0f, 0.5f, 0.5f, 1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
translatex = 2.0f;
scaly = 0.8f;
for (int i = 0; i < vals.length; i++) {
gl.glPushMatrix();
mTransY = -5 + (scaly * vals[i]);
gl.glTranslatef((-3.0f + (translatex * i)), mTransY, translatez);
gl.glRotatef(mAngleX, 1.0f, 0.0f, 0.0f);
gl.glRotatef(mAngleY, 0.0f, 1.0f, 0.0f);
gl.glScalef(0.4f, scaly * vals[i], 0.4f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
mcube[i].draw(gl);
gl.glPopMatrix();
}
mTransY = .075f;
// mAngleX = -90.0f;
// mAngleY = -0.01f;
mAngleX += speedX;
mAngleY += speedY;
translatez = -6.0f;
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float aspectRatio;
float zNear = .1f;
float zFar = 1000;
float fieldOfView = 80.0f / 57.3f;
float size;
gl.glEnable(GL10.GL_NORMALIZE);
aspectRatio = (float) width / (float) height;
gl.glMatrixMode(GL10.GL_PROJECTION);
size = zNear * (float) (Math.tan((double) (fieldOfView / 2.0f)));
gl.glFrustumf(-size, size, -size / aspectRatio, size / aspectRatio,
zNear, zFar);
gl.glMatrixMode(GL10.GL_MODELVIEW);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glDisable(GL10.GL_DITHER);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
if (mTranslucentBackground) {
gl.glClearColor(0, 0, 0, 0);
} else {
gl.glClearColor(1, 1, 1, 1);
}
gl.glEnable(GL10.GL_CULL_FACE);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_POINT_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
}
private boolean mTranslucentBackground;
private Cube[] mcube = new Cube[4];
private Cube mfloor, mwall;
private float mTransY;
private float mAngleX,mAngleY;
}
and myGLsurfaceview class:
public class MyBarGLSurfaceView extends GLSurfaceView {
BarRenderer renderer; // Custom GL Renderer
// For touch event
private final float TOUCH_SCALE_FACTOR = 180.0f / 320.0f;
private float previousX;
private float previousY;
public MyBarGLSurfaceView(Context context,
boolean useTranslucentBackground, int[] vals) {
super(context);
renderer = new BarRenderer(context, useTranslucentBackground, vals);
this.setRenderer(renderer);
// Request focus, otherwise key/button won't react
this.requestFocus();
this.setFocusableInTouchMode(true);
}
// Handler for key event
#Override
public boolean onKeyUp(int keyCode, KeyEvent evt) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_LEFT: // Decrease Y-rotational speed
renderer.speedY -= 01.1f;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT: // Increase Y-rotational speed
renderer.speedY += 01.1f;
break;
case KeyEvent.KEYCODE_DPAD_UP: // Decrease X-rotational speed
renderer.speedX -= 01.1f;
break;
case KeyEvent.KEYCODE_DPAD_DOWN: // Increase X-rotational speed
renderer.speedX += 01.1f;
break;
case KeyEvent.KEYCODE_A: // Zoom out (decrease z)
renderer.translatez -= 0.2f;
break;
case KeyEvent.KEYCODE_Z: // Zoom in (increase z)
renderer.translatez += 0.2f;
break;
}
return true; // Event handled
}
// Handler for touch event
#Override
public boolean onTouchEvent(final MotionEvent evt) {
float currentX = evt.getX();
float currentY = evt.getY();
float deltaX, deltaY;
switch (evt.getAction()) {
case MotionEvent.ACTION_MOVE:
// Modify rotational angles according to movement
deltaX = currentX - previousX;
deltaY = currentY - previousY;
renderer.angleX += deltaY * TOUCH_SCALE_FACTOR;
renderer.angleY += deltaX * TOUCH_SCALE_FACTOR;
}
// Save current x, y
previousX = currentX;
previousY = currentY;
return true; // Event handled
}
}
though it is done still I would like if anyone can please answer me
1> how to make this bar graphs to grow animatedly, right now when this bar graph activity starts the bar graph appears but i want the bar graph to grow animatedly not just show it
2> how to create a base and a background wall to the bar graph like this link http://www.fusioncharts.com/demos/gallery/#column-and-bar
3> and I was trying to rotate or move the bar graph as per user touch movements i tried the code like another example, you will see that code too and that is why i created this glsurfaceview class of my own, but for some reason it is not working, don't know where and what i have missed, if anyone have any idea please point it out to me
thanks
I have a problem with my projection i think. This is how i setup my gl view:
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
_displayWidth = width;
_displayHeight = height;
_halfWidth = width / 2;
_halfHeight = height / 2;
_scaleX = 0.5F;
_scaleY = 0.5F;
gl.glViewport(0, 0, _displayWidth, _displayHeight);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, _displayWidth, _displayHeight, 0);
DebugLog.i(TAG, "Size changed: " + _displayWidth + " * "
+ _displayHeight);
}
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GlSystem.setGl(gl);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
gl.glClearColor(0.0f, 0.0f, 0.0f, 1);
gl.glShadeModel(GL10.GL_FLAT);
gl.glDisable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glDisable(GL10.GL_DITHER);
gl.glDisable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glTexEnvx(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
GL10.GL_MODULATE);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
String version = gl.glGetString(GL10.GL_VERSION);
String renderer = gl.glGetString(GL10.GL_RENDERER);
boolean isSoftwareRenderer = renderer.contains("PixelFlinger");
boolean isOpenGL10 = version.contains("1.0");
boolean supportsDrawTexture = extensions.contains("draw_texture");
boolean supportsVBOs = !isSoftwareRenderer
&& (!isOpenGL10 || extensions.contains("vertex_buffer_object"));
DebugLog.i(TAG, version + " (" + renderer + "): "
+ (supportsDrawTexture ? "draw texture," : "")
+ (supportsVBOs ? "vbos" : ""));
_game.load();
}
Drawing:
public void draw(float x, float y, float scaleX, float scaleY) {
GL10 gl = GlSystem.getGl();
if (gl != null && _sprite != null) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, _sprite.getTexture());
float localX = x - (getWidth() * scaleX) / 2;
float localY = y - (getHeight() * scaleY) / 2;
float width = getWidth() * scaleX;
float height = getHeight() * scaleY;
((GL11Ext) gl).glDrawTexfOES(localX, localY, 0, width, height);
}
}
Problem is my however I initialize my projection i have origin in lower left corner of screen with Y-axis increasing upwards (screen relative). Origin should be top left corner Y-axis increasing downwards (screen relative).
This would have not been a problem, but as the cordinates i receive from MotionEvent is based on a topleft corner origin.
public class GameView extends GLSurfaceView {
private TouchHandler _motionHandler;
public GameView(Context context) {
super(context);
}
#Override
public boolean onTouchEvent(MotionEvent e) {
_motionHandler.setMotionEvent(e);
queueEvent(_motionHandler);
return true;
}
public TouchHandler getMotionHandler() {
return _motionHandler;
}
public void setMotionHandler(TouchHandler motionHandler) {
_motionHandler = motionHandler;
}
}
This just confuses me right now, and im afraif it will lead to more serious problems if i dont solve/understand whats causing these problems.
In opengl, the bottom left corner is the default origin, by default.