I'm writing an Android app using OpenGL ES and encountered this problem in the Nexus 5 emulator that comes with Android Studio. I have reduced my code to this small app, which simply draws a box going back and forth:
package net.jesbus.stuttertest;
import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
public class MainActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// Create GLSurfaceView
GLSurfaceView glsv = new GLSurfaceView(this);
glsv.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
// Create GLSurfaceView.Renderer
glsv.setRenderer(new GLSurfaceView.Renderer()
{
float step = 0;
boolean direction = false;
ShortBuffer iBuff;
FloatBuffer vBuff;
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// Generate vertices index buffer
short[] pIndex = {0, 1, 2, 3};
ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length * 2);
pbBuff.order(ByteOrder.nativeOrder());
iBuff = pbBuff.asShortBuffer();
iBuff.put(pIndex);
iBuff.position(0);
// Generate vertices buffer
float[] vs = new float[]
{
-1, +1, 0,
+1, +1, 0,
-1, -1, 0,
+1, -1, 0,
};
ByteBuffer bBuff = ByteBuffer.allocateDirect(vs.length * 4);
bBuff.order(ByteOrder.nativeOrder());
vBuff = bBuff.asFloatBuffer();
vBuff.put(vs);
vBuff.position(0);
}
#Override
public void onDrawFrame(final GL10 gl)
{
// Animation calculation
step += direction ? 0.02f : -0.02f;
if (step > 1) direction = false;
else if (step < 0) direction = true;
// Set background color
gl.glClearColor(0.7f, 0.7f, 1, 1);
// Clear screen
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// Set matrix to correct location
gl.glLoadIdentity();
gl.glTranslatef(-1 + step * 2, 0, 0);
gl.glScalef(0.25f, 0.4f, 1);
// Draw box
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glFrontFace(GL10.GL_CW);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuff);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 4, GL10.GL_UNSIGNED_SHORT, iBuff);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height)
{
}
});
setContentView(glsv);
}
}
I looked at it frame by frame, and it seems that instead of showing the next frame, it shows the previous frame, and then skips the frame it was supposed to show and continues:
The circles represent frames produced in onDrawFrame, and the arrows represent the flow of time.
Video showing the problem
I don't exactly know how threading is used OpenGL, but try this:
// Animation calculation
synchronized (this) {
step += direction ? 0.02f : -0.02f;
if (step > 1) direction = false;
else if (step < 0) direction = true;
}
or make the whole onDrawFrame() method synchronized if the compiler consents and OpenGL doesn't lock up...
Related
I've tried to search both on google and here the solution to my problem and I don't think it has been asked before (or may I be using the wrong words in my search? ^^')
Anyway, this is what I want to have: a OpenGL surface view (showing a cube for instance) that can rotate according to the orientation of the tablet. So far, nothing hard I guess and I have the code below that works perfectly well
public class RotationVectorDemo extends Activity {
private GLSurfaceView mGLSurfaceView;
private SensorManager mSensorManager;
private MyRenderer mRenderer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get an instance of the SensorManager
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
// Create our Preview view and set it as the content of our
// Activity
mRenderer = new MyRenderer();
mGLSurfaceView = new GLSurfaceView(this);
mGLSurfaceView.setRenderer(mRenderer);
setContentView(mGLSurfaceView);
}
#Override
protected void onResume() {
// Ideally a game should implement onResume() and onPause()
// to take appropriate action when the activity looses focus
super.onResume();
mRenderer.start();
mGLSurfaceView.onResume();
}
#Override
protected void onPause() {
// Ideally a game should implement onResume() and onPause()
// to take appropriate action when the activity looses focus
super.onPause();
mRenderer.stop();
mGLSurfaceView.onPause();
}
class MyRenderer implements GLSurfaceView.Renderer, SensorEventListener {
private Cube mCube;
private Sensor mRotationVectorSensor;
private final float[] mRotationMatrix = new float[16];
public MyRenderer() {
// find the rotation-vector sensor
mRotationVectorSensor = mSensorManager.getDefaultSensor(
Sensor.TYPE_ROTATION_VECTOR);
mCube = new Cube();
// initialize the rotation matrix to identity
mRotationMatrix[ 0] = 1;
mRotationMatrix[ 4] = 1;
mRotationMatrix[ 8] = 1;
mRotationMatrix[12] = 1;
}
public void start() {
// enable our sensor when the activity is resumed, ask for
// 10 ms updates.
mSensorManager.registerListener(this, mRotationVectorSensor, 10000);
}
public void stop() {
// make sure to turn our sensor off when the activity is paused
mSensorManager.unregisterListener(this);
}
public void onSensorChanged(SensorEvent event) {
// we received a sensor event. it is a good practice to check
// that we received the proper event
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
// convert the rotation-vector to a 4x4 matrix. the matrix
// is interpreted by Open GL as the inverse of the
// rotation-vector, which is what we want.
SensorManager.getRotationMatrixFromVector(
mRotationMatrix , event.values);
}
}
public void onDrawFrame(GL10 gl) {
// clear screen
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
// set-up modelview matrix
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -3.0f);
gl.glMultMatrixf(mRotationMatrix, 0);
// draw our object
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
mCube.draw(gl);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
// set view-port
gl.glViewport(0, 0, width, height);
// set projection matrix
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// dither is enabled by default, we don't need it
gl.glDisable(GL10.GL_DITHER);
// clear screen in white
gl.glClearColor(1,1,1,1);
}
class Cube {
// initialize our cube
private FloatBuffer mVertexBuffer;
private FloatBuffer mColorBuffer;
private ByteBuffer mIndexBuffer;
public Cube() {
final float vertices[] = {
-1, -1, -1, 1, -1, -1,
1, 1, -1, -1, 1, -1,
-1, -1, 1, 1, -1, 1,
1, 1, 1, -1, 1, 1,
};
final float colors[] = {
0, 0, 0, 1, 1, 0, 0, 1,
1, 1, 0, 1, 0, 1, 0, 1,
0, 0, 1, 1, 1, 0, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1,
};
final byte indices[] = {
0, 4, 5, 0, 5, 1,
1, 5, 6, 1, 6, 2,
2, 6, 7, 2, 7, 3,
3, 7, 4, 3, 4, 0,
4, 7, 6, 4, 6, 5,
3, 0, 1, 3, 1, 2
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
vbb.order(ByteOrder.nativeOrder());
mVertexBuffer = vbb.asFloatBuffer();
mVertexBuffer.put(vertices);
mVertexBuffer.position(0);
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);
cbb.order(ByteOrder.nativeOrder());
mColorBuffer = cbb.asFloatBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
mIndexBuffer.put(indices);
mIndexBuffer.position(0);
}
public void draw(GL10 gl) {
gl.glEnable(GL10.GL_CULL_FACE);
gl.glFrontFace(GL10.GL_CW);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mVertexBuffer);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
gl.glDrawElements(GL10.GL_TRIANGLES, 36, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
}
However, when I am locking the screen, moving around and unlocking it afterwards the cube has moved too. Which is logical and I understand perfectly well why. Yet, I would like to know if it's possible to avoid that, like kinda resetting the sensors or something like that, and how I can do it.
I'm not sure I'm using the good kind of sensor at all of if I should change it, or if it's something that can be solved in the code or so. Bear with me as I'm just beginning to work with android sensors.
Basically, this problem is linked to an other that I have on a bigger application but I figured out it would be simpler to use this example to try and solve that. However, if you want to know what my problem is in my bigger application it's essentially the same except that to move the cube, people can either use their fingers (finger_mode) or the sensors (phone_mode). What I want is somehow to be able to rotate the cube with the fingers without paying attention to the sensors and when I go into sensor_mode that they do not change the orientation of the cube just because they are activated. I'm not sure it's clear, if it's not, lemme know.
I'm guessing, since i use touch to modify the rotation matrix that is used by OpenGL there might be some operations that can be done on rotation matrices to solve my problem. Or maybe it's just a sensor problem. Maybe both actually I have no clue so far but these are the different solutions I have been trying to use.
Thanks in advance for helping me figuring this out.
Best,
So the rotation vector is definitely the good kind of sensor to use. Both the accelerometer and the gyroscope won't be of any help for what I want to do.
However I still have to figure out what to do with the rotation matrices that I have now.
I have started to learn OpenGL ES 2.0. I currently am trying to make an object dynamic by using the translateM method on it on the onDrawFrame() method. Unfortunately, when I do this, the object appears briefly and then disappears. I'm not sure what is going on. If I put the same code for translating it in onSurfaceChanged(), it works. Here is my code(without the x integer that should move it on the x-axis, so I know it wouldn't move. But even removing the dynamic int has it disappearing):
package com.background.gl.glcirclebackgroundanimation;
import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
import static android.opengl.GLES20.glClear;
import static android.opengl.GLES20.glClearColor;
import static android.opengl.GLES20.glViewport;
import static android.opengl.Matrix.multiplyMM;
import static android.opengl.Matrix.setIdentityM;
import static android.opengl.Matrix.translateM;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.opengl.GLSurfaceView.Renderer;
import com.background.gl.helper.ColorShaderProgram;
import com.background.gl.helper.TextureShaderProgram;
import com.background.gl.objects.GLCircle;
import com.background.gl.objects.Mallet;
import com.background.gl.objects.Table;
import com.background.gl.util.MatrixHelper;
import com.background.gl.util.TextureHelper;
public class CircleDynamicBackgroundRenderer implements Renderer {
private final Context context;
private final float[] projectionMatrix = new float[16];
private final float[] modelMatrix = new float[16];
private Table table;
private Mallet mallet;
private GLCircle circle;
float x = 0.01f;
private TextureShaderProgram textureProgram;
private ColorShaderProgram colorProgram;
private int texture;
public CircleDynamicBackgroundRenderer(Context context) {
this.context = context;
}
#Override
public void onSurfaceChanged(GL10 glUnused, int width, int height) {
glViewport(0, 0, width, height);
MatrixHelper.perspectiveM(projectionMatrix, 45, (float) width
/ (float) height, 1f, 10f);
setIdentityM(modelMatrix, 0);
}
#Override
public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
table = new Table();
mallet = new Mallet();
circle = new GLCircle();
textureProgram = new TextureShaderProgram(context);
colorProgram = new ColorShaderProgram(context);
texture = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface);
//texture2 = TextureHelper.loadTexture(context, R.drawable.air_hockey_surface_2);
}
#Override
public void onDrawFrame(GL10 glUnused) {
//Clear the rendering surface
glClear(GL_COLOR_BUFFER_BIT);
//x+=0.01f;
translateM(modelMatrix, 0, 0f, 0f, -10f);
final float[] temp = new float[16];
multiplyMM(temp, 0, projectionMatrix, 0, modelMatrix, 0);
System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
textureProgram.useProgram();
//Pass data into our shaders(u_matrix) and enable/bind the texture
//textureProgram.setUniforms2(projectionMatrix, texture, texture2);
textureProgram.setUniforms(projectionMatrix, texture);
//Bind our [vertex array] data to our shaders(attribute data)
circle.bindData(textureProgram);
//Draw it
circle.draw();
/*
// Draw the mallets.
colorProgram.useProgram();
colorProgram.setUniforms(projectionMatrix);
mallet.bindData(colorProgram);
mallet.draw();*/
}
}
I've searched for multiple solutions but I couldn't get any of them to work. I could really use some assistance. :)
Edit: Is it, because I'm multiplying the matrices, automatically moving it back -10 per frame? Because that would explain my issues.
Edit2: So I changed it from -10f to -0.01f, and it works. But, when I try the same for the x axis, it just stays the same. Why is that? Is it because of how the projection matrix divides all the values by w, so that's why the z changes, but not x or y? How would I move it left and right on the x-axis then?
Edit3: My width and height are 768, 1184. So why is there a big difference if I translate it on the x by 0.1f? Is the width and height 768 and 1184, or 1 and 1?
Edit4: Ok, now even if I remove the translateM from onDrawFrame, it still moves. I'm lost
This line is wrong
System.arraycopy(temp, 0, projectionMatrix, 0, temp.length);
I don't know what you thought when you wrote it, so I can't explain how you failed, you may only ever override the projection matrix when the window aspect ratio changes. The rest of the time this matrix has to be constant and you may not write to it. In the shader you need to pass the product of the projection and translation matrix. But when you multiply it, store the result in temp and pass temp to the shader.
Try it
translateM(modelMatrix, 0, 0.5f, 0f, -10f);
X and Y axis must be in range [-1,1]
I try to draw a quad with open GL ES 1.0.
But I have an exception which say me that i try to draw more vertices than i have.
Code of Renderer :
package com.example.MyGLTest;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class OpenGLRenderer implements GLSurfaceView.Renderer{
FloatBuffer plaineVerticesBuffer;
FloatBuffer plaineIndicesBuffer;
private float[] plaineVertices = {
-1, -1, 0, //bottom left corner
-1, 1, 0, //top left corner
1, 1, 0, //top right corner
1, -1, 0 // bottom right rocner
};
private float plaine_indices[] = {
0,1,2, // first triangle (bottom left - top left - top right)
0,2,3 // second triangle (bottom left - top right - bottom right);
};
#Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
ByteBuffer bb = ByteBuffer.allocateDirect(plaineVertices.length * 4);
bb.order(ByteOrder.nativeOrder());
plaineVerticesBuffer = bb.asFloatBuffer();
plaineVerticesBuffer.put(plaineVertices);
ByteBuffer bb1 = ByteBuffer.allocateDirect(plaine_indices.length * 4);
bb1.order(ByteOrder.nativeOrder());
plaineIndicesBuffer = bb1.asFloatBuffer();
plaineIndicesBuffer.put(plaine_indices);
}
#Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
}
#Override
public void onDrawFrame(GL10 gl) {
//GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(4,GL10.GL_FLOAT,0, plaineVerticesBuffer);
gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 6 ,GL10.GL_FLOAT, plaineIndicesBuffer);
}
}
Error of logcat :
java.lang.ArrayIndexOutOfBoundsException: remaining() < count < needed
at com.google.android.gles_jni.GLImpl.glDrawElements(Native Method)
at com.example.MyGLTest.OpenGLRenderer.onDrawFrame(OpenGLRenderer.java:60)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1531)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1248)
Can anyone explain me why i getting this error?
You are tracing a strip of 2 triangles, and you are passing 6 vertices. You should either draw GL_TRIANGLES or fix the indices.
Do there is any special emulator settings needed to run OpenGL Apps?
I already set "GPU emulation" property to "yes".
I am trying to run an Android sample live wallpaper, using the sample source found from this link, The desired output is a rotating triangle.
After a little effort I got the app running but it doesn't draw anything in emulator but when I tested in device it works, But in the emulator it still just shows a green screen, I found a discussion on it in Google groups here. I tried to set view port as said in it. But still it doesn't show any result, on surface changed I had added this line
gl.glViewport(0, 0, width, height);
Do this is the correct way to set view port?
This is my render class,
public class MyRenderer implements GLWallpaperService.Renderer {
GLTriangle mTriangle;
public void onDrawFrame(GL10 gl) {
gl.glClearColor(0.2f, 0.4f, 0.2f, 1f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
autoRotate(gl);
gl.glColor4f(.2f, 0f, .5f, 1f);
mTriangle.draw(gl);
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 60f, (float)width/(float)height, 1f, 100f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0, 0, -5);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
mTriangle = new GLTriangle();
gl.glClearDepthf(1f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
}
/**
* Called when the engine is destroyed. Do any necessary clean up because
* at this point your renderer instance is now done for.
*/
public void release() {
}
private void autoRotate(GL10 gl) {
gl.glRotatef(1, 0, 1, 0);
gl.glRotatef(0.5f, 1, 0, 0);
}
}
Herse is GLTriangle class
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
import javax.microedition.khronos.opengles.GL10;
public class GLTriangle {
private FloatBuffer _vertexBuffer;
private final int _nrOfVertices = 3;
private ShortBuffer _indexBuffer;
public GLTriangle() {
init();
}
private void init() {
// We use ByteBuffer.allocateDirect() to get memory outside of
// the normal, garbage collected heap. I think this is done
// because the buffer is subject to native I/O.
// See http://download.oracle.com/javase/1.4.2/docs/api/java/nio/ByteBuffer.html#direct
// 3 is the number of coordinates to each vertex.
_vertexBuffer = BufferFactory.createFloatBuffer(_nrOfVertices * 3);
_indexBuffer = BufferFactory.createShortBuffer(_nrOfVertices);
// Coordinates for the vertexes of the triangle.
float[] coords = {
-1f, -1f, 0f, // (x1, y1, z1)
1f, -1f, 0f, // (x2, y2, z2)
0f, 1f, 0f // (x3, y3, z3)
};
short[] _indicesArray = {0, 1, 2};
_vertexBuffer.put(coords);
_indexBuffer.put(_indicesArray);
_vertexBuffer.position(0);
_indexBuffer.position(0);
}
public void draw(GL10 gl) {
// 3 coordinates in each vertex
// 0 is the space between each vertex. They are densely packed
// in the array, so the value is 0
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, getVertexBuffer());
// Draw the primitives, in this case, triangles.
gl.glDrawElements(GL10.GL_TRIANGLES, _nrOfVertices, GL10.GL_UNSIGNED_SHORT, _indexBuffer);
}
private FloatBuffer getVertexBuffer() {
return _vertexBuffer;
}
}
What's going wrong here? Is there a better sample code for Open GL live wallpaper?
AT LAST I FOUND IT..
What I need to do is just add
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
to onSurfaceCreated method along with the code line
gl.glViewport(0, 0, width, height);
in the onSurfaceChanged method in MyRenderer Class
I found a similar question in stack itself [ But Solution worked for me is not marked as correct :( ]
I have been trying to make a point rotate around another point in Opengl es for android. It works but in a particular way. As the rotation gets bigger (i.e close to 90°) the point gets further away from the centre of rotation.Eventually the point rotates around the centre of rotation in an elliptical orbit however I want it to rotate in a circular fashion. anyone knows how I could be able to do this? thank you
package org.example.pointtest;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class LegRoot
{
public FloatBuffer hipVertexBuffer;
float[]hip={1.75f,-2.75f,0.0f};//0 hip
float[]knee={1.75f,-6.75f,0.0f};//1 knee
float[]ankle={1.75f,-10.75f,0.0f};//2 ankle
public float distance2D(float[]origin,float[]extremity)
{
float a=extremity[0]-origin[0];
float b=extremity[1]-origin[1];
float c=extremity[2]-origin[2];
float[] d={a,b,c};
return d[1];
}
public LegRoot()
{
float []hippoint=
{
1.75f,-2.75f,0.0f
};//0 hip
ByteBuffer vbb = ByteBuffer.allocateDirect(1*3*4);
vbb.order(ByteOrder.nativeOrder());
hipVertexBuffer=vbb.asFloatBuffer();
hipVertexBuffer.put(hippoint);
hipVertexBuffer.position(0);
}
public void hip(GL10 gl)
{
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0,hipVertexBuffer);// root joint transformation matrix(supposition)
gl.glPushMatrix();
gl.glColor4f(1f, 0f, 0f, 1f);
gl.glRotatef(0f, 0, 0, 1);
gl.glTranslatef(0f,0f, 0);
gl.glDrawArrays(GL10.GL_POINTS, 0, 1);
gl.glPopMatrix();
}
public void knee(GL10 gl)
{
gl.glPushMatrix();
gl.glTranslatef(-hip[0], -hip[1], 0);
gl.glRotatef(0f, 0, 0, 1);
gl.glTranslatef(hip[0], hip[1], 0);
gl.glTranslatef(0,distance2D(hip,knee), 0);
hip(gl);
gl.glPopMatrix();
}
public void ankle(GL10 gl)
{
gl.glPushMatrix();
gl.glTranslatef(-knee[0], -knee[1], 0);
gl.glRotatef(90f, 0, 0, 1);
gl.glTranslatef(knee[0], knee[1], 0);
gl.glTranslatef(0, distance2D(knee, ankle), 0);
knee(gl);
gl.glPopMatrix();
}
}
Just to have an answer here I copied my comment.
You probably have a glScale in your Matrix. You could try to load the identity matrix before drawing to ensure there is no scale involved. But this would remove all other transformations you did before.
Also note: When you have a non square display and don't take in account the aspect ratio of your display this will also look like scaled.
For your second problem: Can you post the rotate statement you mean? And maybe it is better to open a new question for a new problem.