Moving cube in opengl on android help - java
After a lot of trial and error I was able to draw a cube and a tile map for the cube to be infront of. I added input so that when you move your finger, the camera moves. But now I want to add the next step in my games progression. I want it to have my cube move to where i pressed my finger in 3d space. It sounds a bit difficult. What I wanted to do is have you use one finger to slide the camera around the map and the other to double tap and move. So far my cube jitters and wobbles in place but doesn't move to where I want it to go. Of course none of my code is perfect and my following of gluunproject might be far from correct. Here is my code so far
The cube creator and update code//its short
public shapemaker(int x, int y, int z,int width)
{
centerx =x;
centery =y;
centerz =z;
mysquare1= new square(centerx,centery,centerz-5,1,.0f,.0f,1f,"vert");
mysquare2= new square(centerx-1,centery,centerz-6f,1,.0f,1.0f,.0f,"side");
mysquare3= new square(centerx,centery,centerz-7,1,1.0f,.0f,.0f,"vert");
mysquare4= new square(centerx+1,centery,centerz-6f,1,.0f,.5f,.5f,"side");
mysquare5= new square(centerx,centery-1,centerz-6f,1,.5f,.5f,.0f,"horiz");
mysquare6= new square(centerx,centery+1,centerz-6f,1,.5f,.0f,.5f,"horiz");
}
public void updatecube(float x, float y, float z)
{
centerx =x;
centery =y;
centerz =z;
mysquare1= new square(centerx,centery,centerz-5,1,.0f,.0f,1f,"vert");
mysquare2= new square(centerx-1,centery,centerz-6f,1,.0f,1.0f,.0f,"side");
mysquare3= new square(centerx,centery,centerz-7,1,1.0f,.0f,.0f,"vert");
mysquare4= new square(centerx+1,centery,centerz-6f,1,.0f,.5f,.5f,"side");
mysquare5= new square(centerx,centery-1,centerz-6f,1,.5f,.5f,.0f,"horiz");
mysquare6= new square(centerx,centery+1,centerz-6f,1,.5f,.0f,.5f,"horiz");
}
public void drawcube(GL10 gl)
{
mysquare1.draw(gl);
mysquare2.draw(gl);
mysquare3.draw(gl);
mysquare4.draw(gl);
mysquare5.draw(gl);
mysquare6.draw(gl);
}
public float getcenterx()
{
return centerx;
}
public float getcentery()
{
return centery;
}
public float getcenterz()
{
return centerz;
}
Here is the actual implementation code , it is based off of googles intro to opengl
class ClearGLSurfaceView extends GLSurfaceView {
private static final String BufferUtils = null;
float x =0;
float y =0;
float z =0f;
float prevx=0;
float prevy=0;
GL10 mygl;
// GL gl;
float mywidth;
float myheight;
public ClearGLSurfaceView(Context context,float width, float height) {
super(context);
mRenderer = new ClearRenderer();
setRenderer(mRenderer);
mywidth = width;
myheight = height;
}
#Override
public boolean onTouchEvent(final MotionEvent event)
{
queueEvent(new Runnable() {
// Find the index of the active pointer and fetch its position
public void run()
{
float curx = event.getX();
float cury = event.getY();
final int action = event.getAction();
if(action == MotionEvent.ACTION_MOVE)
{
if(curx>prevx)
{
x-=.1f;
}
if(curx<prevx)
{
x+=.1f;
}
if(cury>prevy)
{
y+=.1f;
}
if(cury<prevy)
{
y-=.1f;
}
}
if(action == MotionEvent.ACTION_DOWN)
{
// GLU.gluUnProject(winX, winY, winZ, model,
// modelOffset, project, projectOffset, view, viewOffset, obj, objOffset)
vector2d moveto = new vector2d(0,0);
moveto = mRenderer.getworkcoords(curx,cury);
Log.i("move to ", "x "+moveto.x+" y "+ moveto.y+" z " + moveto.z);
mRenderer.updatemoveto(moveto.x, moveto.y);
}
prevx= curx;
prevy = cury;
mRenderer.updatecamera(x, y, z);
}
});
return true;
}
ClearRenderer mRenderer;
}
class ClearRenderer implements GLSurfaceView.Renderer {
GL10 mygl;
GL11 mygl11;
int viewport[] = new int[4];
float modelview[] = new float[16];
float projection[] = new float[16];
float wcoord[] = new float[4];
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // OpenGL docs.
gl.glShadeModel(GL10.GL_SMOOTH);// OpenGL docs.
gl.glClearDepthf(1.0f);// OpenGL docs.
gl.glEnable(GL10.GL_DEPTH_TEST);// OpenGL docs.
gl.glDepthFunc(GL10.GL_LEQUAL);// OpenGL docs.
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, // OpenGL docs.
GL10.GL_NICEST);
mygl = gl;
mygl11 = (GL11) gl;
int index;
int counter = 0;
float zcoord = -7.0f;
mygl11.glGetFloatv(GL11.GL_MODELVIEW_MATRIX, modelview, 0);
mygl11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, projection, 0);
mygl11.glGetIntegerv(GL11.GL_VIEWPORT, viewport, 0);
for(int x=0;x<11;x++)
{
for(int y =0;y<10;y++)
{
index = tilemap1[y][x];
if(index==0)
{
tiles[counter]=new square(x,y,zcoord,0.5f,1.0f,0.0f,0f,"vert");
}
if(index==1)
{
tiles[counter]=new square(x,y,zcoord,0.5f,0f,1.0f,0f,"vert");
}
if(index==2)
{
tiles[counter]=new square(x,y,zcoord,0.5f,0.0f,0.0f,1f,"vert");
}
counter++;
}
}
}
public vector2d getworkcoords(float width,float height)
{
float[] depth = new float[1];
float winx = width;
float winy =viewport[3]-height;
//vector2d position = new vector2d(0,0);
int test = GLU.gluUnProject(winx, winy,0.0f, modelview, 0, projection,
0, viewport, 0, wcoord, 0);
vector2d v = new vector2d(0,0);
v.x = wcoord[0];
v.y = wcoord[1];
v.z = wcoord[2];
return v ;
}
public void onSurfaceChanged(GL10 gl, int w, int h) {
gl.glViewport(0, 0, w, h);
gl.glMatrixMode(GL10.GL_PROJECTION);// OpenGL docs.
gl.glLoadIdentity();// OpenGL docs.
GLU.gluPerspective(gl, 45.0f,
(float) w / (float) h,
0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);// OpenGL docs.
gl.glLoadIdentity();// OpenGL docs.
}
public float movetox;
public float movetoy;
float currentposx;
float currentposy;
public void updatemoveto(float x , float y)
{
movetox = x;
movetoy = y;
}
public void onDrawFrame(GL10 gl) {
gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
currentposx = mycube.getcenterx();
currentposy = mycube.getcentery();
float x = movetox -currentposx;
float y = movetoy - currentposy;
double angle = Math.atan2(y, x);
double mx =.5f* Math.cos(angle);
double my = .5f* Math.sin(angle);
double mmx = mx+ currentposx;
double mmy = my+ currentposy;
mycube.updatecube((float)(mmx), (float)(mmy),0);
mycube.drawcube(gl);
for(int i = 0;i<110;i++)
{
tiles[i].draw(gl);
}
}
public void setColor(float r, float g, float b) {
mRed = r;
mGreen = g;
mBlue = b;
}
public void updatecamera(float myx, float myy, float myz)
{
mygl.glLoadIdentity();// OpenGL docs.
GLU.gluLookAt(mygl, myx, myy, myz, myx, myy, myz-10, 0, 1, 0);
}
private float mRed;
private float mGreen;
private float mBlue;
int tilemap1[][] = {
{0,0,0,0,0,0,0,0,0,0,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,1,1,1,1,1,1,1,0},
{0,1,2,2,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,1,1,1,1,1,0},
{0,1,1,1,2,2,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0},
};
square[] tiles = new square[110];
shapemaker mycube = new shapemaker(0,0,0,1);
}
I did not include the on create method and the on pause ones. I would also like advice on designing the code structure because my implementation is far from perfect.
So in short. I would like help figuring out how to modify the code I made to have a cube move to where i press. And how you would improve the code
Thanks
First of all,
you don't need to recreate vertices on every moving. It is very complex task and it will low the framerate (FPS). In you code you have model matrix. Usually it is responsible for translating, scaling rotating of your model(mesh, cube in your example). In common case you have to translate the model matrix and then multiple model, projection and view matrixes, you will get the matrix for your device screen. Then by multiplication of vertex postion and this matrix you'll get the right position of vertex.
you can look at this question/answer
Related
Java Custom 3D Rotation doesn't look right
Java 3D Renderering Context Currently, I am working on a small 3D renderer. I am using Java. The Problem When I am rotating shapes, I noticed that the rotation is completely incorrect (video on bottom) What have I done? I have: Searched Stack Overflow Printed out debug info Redid rotation None of these has worked. Code TVector public class TVector { public float x, y, z; public TVector ogPos; public TVector(float _x, float _y, float _z) { this.x = _x; this.y = _y; this.z = _z; this.ogPos = new TVector(this.x, this.y, this.z, true); } private TVector(float _x, float _y, float _z, boolean _throw) { this.x = _x; this.y = _y; this.z = _z; } public TVector convertToOrthographic() { return new TVector(this.x, this.y, 0); } } Mesh public class Mesh { public Triangle[] tris; public TVector rot = new TVector(0, 0, 0); public void RotateX(float theta) { this.rot.x += theta; this.rot.x %= 360; double cos = Math.cos(this.rot.x); double sin = Math.sin(this.rot.x); for (Triangle t : this.tris) { for (TVector p : t.points) { double[][] rotMatrix = new double[][] { new double[] { 1, 0, 0 }, new double[] { 0, cos, -sin }, new double[] { 0, sin, cos } }; double[][] posMatrix = new double[][] { new double[] { p.ogPos.x }, new double[] { p.ogPos.y }, new double[] { p.ogPos.z } }; double[][] finalRes = Utils.multiplyMatrices(rotMatrix, posMatrix); p.x = (float) finalRes[0][0]; p.y = (float) finalRes[1][0]; p.z = (float) finalRes[2][0]; System.out.println(p.x); System.out.println(p.y); } } } } Plane public class Plane extends Mesh { public Plane(int x, int y, int z, int length) { this.tris = new Triangle[] { new Triangle( new TVector(x, y, z), new TVector(x + length, y, z), new TVector(x, y + length, z) ), new Triangle( new TVector(x + length, y - length, z), new TVector(x + length, y, z), new TVector(x, y + length, z) ) }; } } Note: There is a window rendering this stuff, and rotating the plane. Gif: I use REPLIT Thanks in advance! Rotation is in degrees. EDIT: Rotation is less buggier now
Libgdx - Parallax background set horizontally, can't implement scrolling up and down
I found a tutorial online to create a horizontally scrolling parallax background with this custom class: public class ParallaxBackground extends Actor { private float scroll; private Array<Texture> layers; private final int LAYER_SPEED_DIFFERENCE = 2; float x, y, width, height, scaleX, scaleY; float originX, originY, rotation; float srcX, srcY; boolean flipX, flipY; private float speed; public ParallaxBackground(Array<Texture> textures, HeroKnight player) { layers = textures; for(int i = 0; i <textures.size;i++){ layers.get(i).setWrap(Texture.TextureWrap.MirroredRepeat, Texture.TextureWrap.MirroredRepeat); } scroll = 0; speed = 0; x = y = originX = originY = rotation = 0; srcY = 0; width = Gdx.graphics.getWidth(); height = Gdx.graphics.getHeight(); scaleX = scaleY = 1; flipX = flipY = false; } public void setSpeed(float newSpeed){ this.speed = newSpeed; } public void update(float deltaTime) { } #Override public void draw(Batch batch, float parentAlpha) { batch.setColor(getColor().r, getColor().g, getColor().b, getColor().a * parentAlpha); scroll+=speed; srcX = scroll; batch.draw(layers.get(0), x, y, originX, originY, width, height, scaleX, scaleY, rotation, (int)srcX, (int) srcY, layers.get(0).getWidth(), layers.get(0).getHeight(), flipX, flipY); for(int i = 1;i<layers.size;i++) { srcX = scroll + i*this.LAYER_SPEED_DIFFERENCE *scroll; batch.draw(layers.get(i), x, y, originX, originY, width, height,scaleX,scaleY,rotation,(int)srcX,(int)srcY,layers.get(i).getWidth(),layers.get(i).getHeight(),flipX,flipY); } } . backgroundViewport = new ScreenViewport(); stage = new Stage(backgroundViewport); Array<Texture> textures = new Array<Texture>(); for(int i = 1; i <= 5;i++){ textures.add(new Texture(Gdx.files.internal("images/"+ i+".png"))); textures.get(textures.size-1).setWrap(Texture.TextureWrap.MirroredRepeat, Texture.TextureWrap.MirroredRepeat); } parallaxBackground = new ParallaxBackground(textures, player); parallaxBackground.setSize(Gdx.graphics.getWidth(),Gdx.graphics.getHeight()); parallaxBackground.setSpeed(0); stage.addActor(parallaxBackground); In the render method: stage.act(); stage.draw(); Eveything works well when you are moving left to right. However, on my background image there is water down, so logically I want the screen to show it when the player is on the lower platforms, and make it scroll higher so that the water disappears when you go up. So the question is: how do I make the blue part visible when the player is lower, and scroll it to the red part when you go higher?
Failing to use VBOs in OpenGl/Android
Greetings my fellow programmers, I've searched the WEB, checked examples online but still can't figure it out. I'm sorry if this was asked previously, I'm tired after a week-long debug of this. I hope you can help me. Basically the problem is that I try to draw some quads (with triangles) but nothing is drawn. Previously I was drawing without VBOs the way described in 'Triangle example' on official Android website. Everything worked fine, but I decided that updating vertices/indices buffers in Renderer.OnDrawFrame() is not efficient :) So here is my code: public class FloorPlanRenderer implements GLSurfaceView.Renderer { public volatile float mAngle; // mMVPMatrix is an abbreviation for "Model View Projection Matrix" private final float[] mMVPMatrix = new float[16]; private final float[] mProjectionMatrix = new float[16]; private final float[] mViewMatrix = new float[16]; private final float[] mRotationMatrix = new float[16]; private GLSurfaceView mGlView; private GlEngine mGlEngine; private boolean dataSet = false; #Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // Set the background frame color GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Initialize the accumulated rotation matrix Matrix.setIdentityM(mRotationMatrix, 0); // Position the eye in front of the origin. final float eyeX = 0.0f; final float eyeY = 0.0f; final float eyeZ = -3.0f; // We are looking toward the distance final float lookX = 0.0f; final float lookY = 0.0f; final float lookZ = 0.0f; //-5.0f; // Set our up vector. This is where our head would be pointing were we holding the camera. final float upX = 0.0f; final float upY = 1.0f; final float upZ = 0.0f; // Set the view matrix. This matrix can be said to represent the camera position. Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); mGlEngine = new GlEngine(10); mGlEngine.registerQuad(new Wall(-0.5f, 0.4f, -0.2f, 0.4f)); mGlEngine.registerQuad(new Wall(0.5f, 0.4f, 0.2f, 0.4f)); mGlEngine.registerQuad(new Wall(0.0f, 0.0f, 0.0f, 0.3f, 0.02f)); } #Override public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); // Create a new perspective projection matrix. The height will stay the same // while the width will vary as per aspect ratio. final float ratio = (float) width / height; final float left = -ratio; final float right = ratio; final float bottom = -1.0f; final float top = 1.0f; final float near = 3.0f; final float far = 7.0f; // this projection matrix is applied to object coordinates // in the onDrawFrame() method Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); } #Override public void onDrawFrame(GL10 gl) { float[] scratch = new float[16]; // Calculate the projection and view transformation Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, 1.0f); // Combine the rotation matrix with the projection and camera view // Note that the mMVPMatrix factor *must be first* in order // for the matrix multiplication product to be correct. Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0); mGlEngine.render(scratch); } } GlEngine class: public class GlEngine { public static final int COORDS_PER_VERTEX = 3; public static final int ORDER_INDICES_PER_QUAD = 6; public static final int VERTICES_PER_QUAD = 4; public static final int SIZE_OF_FLOAT = Float.SIZE/Byte.SIZE; public static final int SIZE_OF_SHORT = Short.SIZE/Byte.SIZE; private int mQuadsNum = 0; private int mLastCoordsIndex = 0; private int mLastOrderIndex = 0; private final FloatBuffer vertexBuffer; private final ShortBuffer indexBuffer; private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of the objects that use this vertex shader "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + // the matrix must be included as a modifier of gl_Position // Note that the uMVPMatrix factor *must be first* in order // for the matrix multiplication product to be correct. " gl_Position = uMVPMatrix * vPosition;" + "}"; // Use to access and set the view transformation private int mMVPMatrixHandle; private final String fragmentShaderCode = "precision mediump float;" + "uniform vec4 vColor;" + "void main() {" + " gl_FragColor = vColor;" + "}"; private final int mProgram; private int mPositionHandle; private int mColorHandle; private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 0.0f }; private boolean mDataInitNeeded = true; public GlEngine(int quadsNum) { ByteBuffer bb = ByteBuffer.allocateDirect(quadsNum * VERTICES_PER_QUAD * COORDS_PER_VERTEX * SIZE_OF_FLOAT); bb.order(ByteOrder.nativeOrder()); // device hardware's native byte order vertexBuffer = bb.asFloatBuffer(); ByteBuffer bb2 = ByteBuffer.allocateDirect(quadsNum * ORDER_INDICES_PER_QUAD * SIZE_OF_SHORT); bb2.order(ByteOrder.nativeOrder()); indexBuffer = bb2.asShortBuffer(); int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode); int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode); mProgram = GLES20.glCreateProgram(); GLES20.glAttachShader(mProgram, vertexShader); GLES20.glAttachShader(mProgram, fragmentShader); GLES20.glLinkProgram(mProgram); } 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 void registerQuad(Wall quad) { quad.putCoords(vertexBuffer); quad.putIndices(indexBuffer); mQuadsNum++; } // This code is dealing with VBO side of things private final int[] mVerticesBufferId = new int[BUFFERS_COUNT]; private final int[] mIndicesBufferId = new int[BUFFERS_COUNT]; private static final int BUFFERS_COUNT = 1; public void copyToGpu(FloatBuffer vertices) { GLES20.glGenBuffers(BUFFERS_COUNT, mVerticesBufferId, 0); // Copy vertices data into GPU memory GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertices.capacity() * SIZE_OF_FLOAT, vertices, GLES20.GL_STATIC_DRAW); // Cleanup buffer vertices.limit(0); vertices = null; } public void copyToGpu(ShortBuffer indices) { GLES20.glGenBuffers(BUFFERS_COUNT, mIndicesBufferId, 0); // Copy vertices data into GPU memory GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, indices.capacity() * SIZE_OF_SHORT, indices, GLES20.GL_STATIC_DRAW); // Cleanup buffer indices.limit(0); indices = null; } public void render(float[] mvpMatrix) { setData(); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVerticesBufferId[0]); GLES20.glUseProgram(mProgram); mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); GLES20.glEnableVertexAttribArray(mPositionHandle); GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride, 0); mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); GLES20.glUniform4fv(mColorHandle, 1, color, 0); // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); // Pass the projection and view transformation to the shader GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]); // Draw quads GLES20.glDrawElements( GLES20.GL_TRIANGLES, mQuadsNum * ORDER_INDICES_PER_QUAD, GLES20.GL_UNSIGNED_SHORT, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); } // This method is called on gl thread GlSurfaceView.queueEvent(...) public void setData() { if (mDataInitNeeded) { // Reset positions of buffers for consuming in GL vertexBuffer.position(0); indexBuffer.position(0); copyToGpu(vertexBuffer); copyToGpu(indexBuffer); mDataInitNeeded = false; } } public void deallocateGlBuffers() { if (mVerticesBufferId[0] > 0) { GLES20.glDeleteBuffers(mVerticesBufferId.length, mVerticesBufferId, 0); mVerticesBufferId[0] = 0; } if (mIndicesBufferId[0] > 0) { GLES20.glDeleteBuffers(mIndicesBufferId.length, mIndicesBufferId, 0); mIndicesBufferId[0] = 0; } } } The Wall class which represents rectangle: public class Wall { // number of coordinates per vertex in this array private static final int COORDS_PER_VERTEX = 3; private static final int VERTICES_NUM = 4; // it's a rect after all private static final float DEFAULT_WIDTH = 0.05f; private static final float DEFAULT_COORDS_SOURCE = 0.5f; private final float mCoords[] = new float[COORDS_PER_VERTEX * VERTICES_NUM]; private final short mDrawOrder[] = { 0, 1, 2, // first triangle 1, 2, 3 }; // second triangle private int mVertexBufferPosition; private int mIndexBufferPosition; private final PointF mA = new PointF(0, 0); private final PointF mB = new PointF(0, 0); private float mWidth; public Wall() { init(-DEFAULT_COORDS_SOURCE, DEFAULT_COORDS_SOURCE, DEFAULT_COORDS_SOURCE, -DEFAULT_COORDS_SOURCE, DEFAULT_WIDTH); } public Wall(float x1, float y1, float x2, float y2) { init(x1, y1, x2, y2, DEFAULT_WIDTH); } public Wall(float x1, float y1, float x2, float y2, float width) { init(x1, y1, x2, y2, width); } private void init(float x1, float y1, float x2, float y2, float width) { mA.x = x1; mA.y = y1; mB.x = x2; mB.y = y2; mWidth = width; calcCoords(); } private void calcCoords() { float[] vector = {mA.x - mB.x, mA.y - mB.y}; float magnitude = (float) Math.sqrt(vector[0]*vector[0] + vector[1]*vector[1]); float[] identityVector = {vector[0]/magnitude, vector[1]/magnitude}; float[] orthogonalIdentityVector = {identityVector[1], -identityVector[0]}; mCoords[0] = mA.x + mWidth * orthogonalIdentityVector[0]; mCoords[1] = mA.y + mWidth * orthogonalIdentityVector[1]; mCoords[3] = mA.x - mWidth * orthogonalIdentityVector[0]; mCoords[4] = mA.y - mWidth * orthogonalIdentityVector[1]; mCoords[6] = mB.x + mWidth * orthogonalIdentityVector[0]; mCoords[7] = mB.y + mWidth * orthogonalIdentityVector[1]; mCoords[9] = mB.x - mWidth * orthogonalIdentityVector[0]; mCoords[10] = mB.y - mWidth * orthogonalIdentityVector[1]; } public void putCoords(FloatBuffer vertexBuffer) { mVertexBufferPosition = vertexBuffer.position(); for (int i = 0; i < mDrawOrder.length; i++) { mDrawOrder[i] += mVertexBufferPosition/GlEngine.COORDS_PER_VERTEX; } vertexBuffer.put(mCoords); } public void putIndices(ShortBuffer indexBuffer) { mIndexBufferPosition = indexBuffer.position(); indexBuffer.put(mDrawOrder); } public float getWidth() { return mWidth; } public void setWidth(float mWidth) { this.mWidth = mWidth; } public PointF getA() { return mA; } public void setA(float x, float y) { this.mA.x = x; this.mA.y = y; } public PointF getB() { return mB; } public void setB(float x, float y) { this.mB.x = x; this.mB.y = y; } } In Wall class I save offset where it places its vertices and indices because this class will be changing in the future and it intended to update its vertices in the main buffer (the buffer will not be recompiled for each OnDrawFrame). Thank you. I hope with your help I will somehow overcome this (another) obstacle on my way to OpenGl ES.
Shame on me! I incidentally put indices into wrong array. Instead of this: // Copy vertices data into GPU memory GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]); GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, indices.capacity() * SIZE_OF_SHORT, indices, GLES20.GL_STATIC_DRAW); There should be: // Copy vertices data into GPU memory GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferId[0]); GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indices.capacity() * SIZE_OF_SHORT, indices, GLES20.GL_STATIC_DRAW); Why shame? because in the log I saw: 07-23 16:20:05.442 5170-5264/com.example.neutrino.maze W/Adreno-ES20: : GL_INVALID_OPERATION Just after the second call to glBufferData where I put GL_ARRAY_BUFFER instead of GL_ELEMENT_ARRAY_BUFFER. This was for sure caused by copy-paste as in many cases.
Libgdx Actor undetected touch input
I am looking for touch detection. The code showed below is what I did to set a circle in my app. I want detect touch on this circle and not around or on the entire texture. The strange thing is that touch isn't detected, in nowhere I can detect it Circle class: public class Circle_Obj extends Actor{ private Vector2 position; private float radius; private com.badlogic.gdx.math.Circle circle; private Texture texture; public Circle_Obj(float x, float y, float radius) { position = new Vector2(x,y); this.radius = radius; circle = new com.badlogic.gdx.math.Circle(x,y,radius); texture = new Texture(Gdx.files.internal("texture.png")); addListener(new InputListener(){ #Override public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) { Gdx.app.log("TOUCHED", " TOUCHED "); return true; } }); } #Override public void draw(Batch batch, float parentAlpha) { batch.draw(texture,0, 0); } } Screen class : public class GameScreen implements Screen { private Stage stage; private Circle_Obj circle_obj; public GameScreen() { circle_obj = new Circle_Obj(Static_values.Width/2, Static_values.Height/2, Static_values.Width / 100 * 10); stage = new Stage(new FitViewport(Static_values.Width/3, Static_values.Height/3)); stage.addActor(circle_obj); Gdx.input.setInputProcessor(stage); } #Override public void render(float delta) { Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); stage.draw(); } #Override public void dispose() { stage.dispose(); } /** other methods **/ }
You can use libgdx's touch detection in a circle class.Only touched circle will affected. public boolean is_touched() { if (Gdx.input.justTouched()) { float xx = Gdx.input.getX(); float yy = Gdx.input.getY(); float x = position.x; float y = position.y; return (xx - x) * (xx - x) + (yy - y) * (yy - y) < radius * radius; } } If you are using a lot of circles so it is better for performance to take touch position as a parameter. in the circle class public boolean is_touched(float xx,float yy) { float x = position.x; float y = position.y; return (xx - x) * (xx - x) + (yy - y) * (yy - y) < radius * radius; } } and in another class if (Gdx.input.justTouched()) { float xx = Gdx.input.getX(); float yy = Gdx.input.getY(); if (circle0.is_touched(xx, yy)) { // do something about circle0 } if (circle1.is_touched(xx, yy)) { // do something about circle1 } if (circle2.is_touched(xx, yy)) { // do something about circle2 } } You can also ignore one of the touched circles when two circles overlaps and user touchs the overlapping area. if (Gdx.input.justTouched()) { float xx = Gdx.input.getX(); float yy = Gdx.input.getY(); if (circle0.is_touched(xx, yy)) { // do something about circle0 } else if (circle1.is_touched(xx, yy)) { // do something about circle1 } else if (circle2.is_touched(xx, yy)) { // do something about circle2 } }
To detect the touch on an actor added in a Stage, the method hit of the actor is called (hit detection in the documentation) public Actor hit (float x, float y, boolean touchable) { if (touchable && getTouchable() != Touchable.enabled) return null; return x >= 0 && x < width && y >= 0 && y < height ? this : null; } You have not set a size to your Circle_Obj actor, so hit will always return null. Now, your actor is a circle, so you probably want to override hit so that it checks if the given coordinates ares in the circle instead of the default implementation that checks if the coordinates are in a box of the size of the actor. Something like: #Override public Actor hit (float x, float y, boolean touchable) { if (touchable && getTouchable() != Touchable.enabled) return null; return (x - position.x)*(x- position.x) + (y - position.y)*(y - position.y) < radius*radius ? this : null; }
If you inherit from Actor, you need to set the bounds or it will not be click/touch-able!. Simply set the bounds to match the texture your Actor contains. //add this Set bounds the x, y, width, and height circle_obj.setBounds(0, 0,texture.getWidth(), texture.getHeight());
Getting a line to move along the tangent line of a circle in Processing
I have a point following the path of a circle, and at a determined time, I want that point to "break" off and travel along the tangent line. How do I find this? I've been told that the derivative is x = -sin(time) and y = -sin(time) (not sure if I understand the "time" part of what I was told), but I don't see how that is enough to get my point to travel along this line. Any tips? Here is what I have currently. /* Rotor draws circle for random period of time, then moves in a straight direction for a random period of time, beginning a new circle */ Rotor r; float timer = 0; boolean freeze = false; void setup() { size(1000, 600); smooth(); noFill(); frameRate(60); background(255); timeLimit(); r = new Rotor(100, 100, random(40, 100)); } void draw() { timer = timer + frameRate/1000; if(timer > timeLimit()) { timer = 0; timeLimit(); if(freeze == true) { freeze = false; } else { freeze = true; } } if(!freeze) { r.drawRotor(); } else { r.holdSteady(); } } float timeLimit() { float timeLimit = random(100); return timeLimit; } Rotor Class: class Rotor { color c; int thickness; float xPoint; float yPoint; float nXPoint; float nYPoint; float radius; float angle = 0; float centerX; float centerY; float pointSpeed = frameRate/100; Rotor(float cX, float cY, float rad) { c = color(0); thickness = 1; stroke(c); strokeWeight(thickness); centerX = cX; centerY = cY; radius = rad; } void drawRotor() { angle = angle + pointSpeed; xPoint = centerX + cos(angle) * radius; yPoint = centerY + sin(angle) * radius; ellipse(xPoint, yPoint, thickness, thickness); strokeWeight(2); ellipse(centerX, centerY, 5, 5); } void holdSteady() { xPoint = -sin(angle);//need tangent of circle yPoint = -cos(angle); ellipse(xPoint, yPoint, 4, 4); //then set new center x and y } void drawNewRotor(float cX, float cy, float rad) { } }
You can use tan() int f =100; size(300,300); stroke(0); translate(width/2, height/2); for(int i = 0; i< 360; i++){ point(cos(radians(i))*f,sin(radians(i))*f); point(f,tan(radians(i))*f); point(tan(radians(i))*f,f); }