How to tell where the texture is drawn in OpenGL / libgdx? - java

How do we know which texture is related to which mesh in OpenGL? In this example, we tell the mesh we use texture coordinates, but we don't say which texture (if we have more than one), and we don't tell the texture where to be drawn. How does it work? (I know the concept of UVs, but I don't know the concept of "where" the texture is drawn) :
mesh = new Mesh(true, 4, 6,
new VertexAttribute(VertexAttributes.Usage.Position, 3,"attr_Position"),
new VertexAttribute(Usage.TextureCoordinates, 2, "attr_texCoords"));
texture = new Texture(Gdx.files.internal("data/img.png"));
mesh.setVertices(new float[] {
-1024f, -1024f, 0, 0, 1,
1024f, -1024f, 0, 1, 1,
1024f, 1024f, 0, 1, 0,
-1024f, 1024f, 0, 0, 0
});
#Override
public void render() {
// Texturing --------------------- /
gl.glActiveTexture(GL10.GL_TEXTURE0);
gl.glEnable(GL10.GL_TEXTURE_2D);
texture.bind();
mesh.render(GL10.GL_TRIANGLES);
}

OK I actually found the solution : https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/DecalTest.java

Related

Update view after applying rotation on one 3D object OpenGL ES 2.0

I have been working on an app based on the ARCore sample for Android Studio. I have managed to bring different objects of my choice in the view and now I am trying to rotate only one object, that being the last object placed. That means that when selecting an object, I should be able to rotate it and change its position, until I select another object. Than I shouldn't be able to manipulate that object anymore.
Now this is my draw() method that is called for every placed object
public void draw(float[] cameraView, float[] cameraPerspective, float lightIntensity) {
ShaderUtil.checkGLError(TAG, "Before draw");
// Build the ModelView and ModelViewProjection matrices
// for calculating object position and light.
Matrix.multiplyMM(modelViewMatrix, 0, cameraView, 0, modelMatrix, 0);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, cameraPerspective, 0, modelViewMatrix, 0);
if(this.movable==true) {
//rotation
Matrix.setRotateM(mRotationMatrix, 0, FactorsClass.rotateF, 0.0f, 1.0f, 0.0f);
Matrix.multiplyMM(mFinalModelViewProjectionMatrix, 0, modelViewProjectionMatrix, 0, mRotationMatrix, 0);
}
GLES20.glUseProgram(program);
// Set the lighting environment properties.
Matrix.multiplyMV(viewLightDirection, 0, modelViewMatrix, 0, LIGHT_DIRECTION, 0);
normalizeVec3(viewLightDirection);
GLES20.glUniform4f(
lightingParametersUniform,
viewLightDirection[0],
viewLightDirection[1],
viewLightDirection[2],
lightIntensity);
// Set the object material properties.
GLES20.glUniform4f(materialParametersUniform, ambient, diffuse, specular, specularPower);
// Attach the object texture.
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
GLES20.glUniform1i(textureUniform, 0);
// Set the vertex attributes.
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
GLES20.glVertexAttribPointer(
positionAttribute, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, verticesBaseAddress);
GLES20.glVertexAttribPointer(normalAttribute, 3, GLES20.GL_FLOAT, false, 0, normalsBaseAddress);
GLES20.glVertexAttribPointer(
texCoordAttribute, 2, GLES20.GL_FLOAT, false, 0, texCoordsBaseAddress);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
// Set the ModelViewProjection matrix in the shader.
GLES20.glUniformMatrix4fv(modelViewUniform, 1, false, modelViewMatrix, 0);
GLES20.glUniformMatrix4fv(modelViewProjectionUniform, 1, false, modelViewProjectionMatrix, 0);
if(this.movable==true) {
GLES20.glUniformMatrix4fv(modelViewProjectionUniform, 1, false, mFinalModelViewProjectionMatrix, 0);
}
// Enable vertex arrays
GLES20.glEnableVertexAttribArray(positionAttribute);
GLES20.glEnableVertexAttribArray(normalAttribute);
GLES20.glEnableVertexAttribArray(texCoordAttribute);
if (blendMode != null) {
GLES20.glDepthMask(false);
GLES20.glEnable(GLES20.GL_BLEND);
switch (blendMode) {
case Shadow:
// Multiplicative blending function for Shadow.
GLES20.glBlendFunc(GLES20.GL_ZERO, GLES20.GL_ONE_MINUS_SRC_ALPHA);
break;
case Grid:
// Grid, additive blending function.
GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
break;
}
}
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBufferId);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indexCount, GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
if (blendMode != null) {
GLES20.glDisable(GLES20.GL_BLEND);
GLES20.glDepthMask(true);
}
// Disable vertex arrays
GLES20.glDisableVertexAttribArray(positionAttribute);
GLES20.glDisableVertexAttribArray(normalAttribute);
GLES20.glDisableVertexAttribArray(texCoordAttribute);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
ShaderUtil.checkGLError(TAG, "After draw");
}
At the moment, I can rotate an object as I wish (when the movable variable is true, meaning that it is the last object placed in the scene), but once I select another one, the old object returns to its initial position, as if it was never rotated. How can I update the matrix so that the rotations remain applied?
Thank you!
but once I select another one, the old object returns to its initial position, as if it was never rotated. How can I update the matrix so that the rotations remain applied?
I assume that mRotationMatrix is a member of the class. Ensure that mRotationMatrix is intilaized by the identity matrix.
Update mRotationMatrix, if this.movable==true, but use mRotationMatrix in any case to calculate mFinalModelViewProjectionMatrix. Use mFinalModelViewProjectionMatrix in any case to set modelViewProjectionUniform.
public void draw(float[] cameraView, float[] cameraPerspective, float lightIntensity) {
.....
Matrix.multiplyMM(modelViewMatrix, 0, cameraView, 0, modelMatrix, 0);
Matrix.multiplyMM(modelViewProjectionMatrix, 0, cameraPerspective, 0, modelViewMatrix, 0);
if(this.movable==true) {
Matrix.setRotateM(mRotationMatrix, 0, FactorsClass.rotateF, 0.0f, 1.0f, 0.0f);
}
Matrix.multiplyMM(mFinalModelViewProjectionMatrix, 0, modelViewProjectionMatrix, 0, mRotationMatrix, 0);
.....
GLES20.glUniformMatrix4fv(modelViewProjectionUniform, 1, false, mFinalModelViewProjectionMatrix, 0);
.....
}

libgdx Infinitely repeating background texture

I've seen similar questions before but none helped me.
The player in my game can go to the right forever until he dies, but he can also go back.
I have a wall texture that I need to repeat forever on the top and bottom of the screen. I've seen answers where they say you need to put different values when drawing the texture at srcX, srcY, srcWidth and srcHeight, but when I do that the texture doesn't look anyting like the original. I set the texture to repeat with wallTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat)
The code I have to draw the wall on the top and bottom of the screen:
spriteBatch.draw(wallTexture, -Constants.WORLD_WIDTH, Constants.WORLD_HEIGHT - Constants.WALL_HEIGHT / 2, Constants.WALL_WIDTH / 2, Constants.WALL_HEIGHT / 2, Constants.WALL_WIDTH, Constants.WALL_HEIGHT, 1, 1, 0, 0, 0, 720, 64, false, false);
spriteBatch.draw(wallTexture, -Constants.WORLD_WIDTH, -Constants.WORLD_HEIGHT - Constants.WALL_HEIGHT / 2, Constants.WALL_WIDTH / 2, Constants.WALL_HEIGHT / 2, Constants.WALL_WIDTH, Constants.WALL_HEIGHT, 1, 1, 0, 0, 0, 720, 64, false, false);
Thanks

Opengl ES Android - Rotate camera around itself

I am developing a terrain generation app on android with Opengl ES, and I am having problems rotating the camera around itself ( the FPS effect to make it clear).
what I am doing is to move the view with Matrix.setLookAtMand then rotating the view after translating it to the origin.This is a snippet of the code:
Matrix.setLookAtM(mViewMatrix, 0, xrot, eyeY, yrot, xrot, lookY, yrot,0.0f, 1.0f, 0.0f);
Matrix.translateM(mViewMatrix,0,-xrot,0f,-yrot);
Matrix.rotateM(mViewMatrix, 0, mAngleX+mAngleY, 0.0f, 1.0f,0.0f);
Matrix.translateM(mViewMatrix,0,xrot,0f,yrot);
where xrot,yrot,mAngleX+mAngleY are input from the touchscreen.
This code works only in the origin, but when you move it rotates around the y axis of the world and not the camera one. I guess I am not doing it right but I didn't find a way to do it that works anywhere.
I found a way to do it:
Matrix.setIdentityM(mCurrentRotation, 0);
Matrix.rotateM(mCurrentRotation, 0, mAngleY+mAngleX, 0.0f,1.0f, 0.0f);
Matrix.rotateM(mCurrentRotation, 0, mAngleX, 0.0f,0.0f, 1.0f);
mAngleX = 0.0f;
mAngleY = 0.0f;
Matrix.multiplyMM(mTemporaryMatrix, 0, mCurrentRotation, 0, mAccumulatedRotation, 0);
System.arraycopy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
// multiply the rotation just for model*view
Matrix.multiplyMM(mMVPMatrix, 0, mTemporaryMatrix, 0, mMVPMatrix, 0);
//than add projection as usual
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
Where mTemporaryMatrix, mCurrentRotation,mAccumulatedRotation, are matrices to calculate total rotation, keep frame rotation and store the whole rotation of the camera, respectively. This solution works for rotation but it doesn't make the camera move in the direction it is pointing.

If not GL_QUADS, then how?

I'm developing a simple 2D game in Java using the LWJGL wrapper for OpenGL.
For the rendering method, I use VBOs. It seems very good and faster the the other rendering methods.I was reading some articles and was seeking for some questions here on StackOverflow and I discovered that using 2 triangles is better than using one quad, since modern GPUs show only triangles (And it'll be a waste to let the GPU translate that quad into triangles).
The only way I know is creating 2 buffers for storing the vertex data and the texture coordinates data. and that's for a quad, this is how I do it:
int vertexID; //Holding the GL buffer ID for the Vertex
int texCoordsID; //Holding the GL buffer ID for the texture coords
void init(){
//BufferUtils is a Utility class provided by the SlickUtil library, I use it for creating buffers.
//Create float buffer for storing vertex data
FloatBuffer vertexBuffer = BufferUtils.createFloatBuffer(4 * 2);
//Put vertex data inside the buffer
vertexBuffer.put(new float[]{
0, 0,
100, 0,
100, 100,
0, 100
});
//Rewind the buffer
vertexBuffer.rewind();
FloatBuffer texCoordsBuffer = BufferUtils.createFloatBuffer(4 * 2);
texCoordsBuffer.put(new float[]{
0, 0,
1, 0,
1, 1,
0, 1
});
texCoordsBuffer.rewind();
vertexID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vertexID);
glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
texCoordsID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, texCoordsID);
glBufferData(GL_ARRAY_BUFFER, texCoordsBuffer, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void render(){
glBindTexture(GL_TEXTURE_2D, texture.id); //Not so important.
glBindBuffer(GL_ARRAY_BUFFER, vertexID);
glVertexPointer(2, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, texCoordsID);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Now my main question is, how can you split it into 2 triangles instead of 1 quad?
And a side question: does it really matter for a 2D game? does it make a slight change?
Just change
glDrawArrays(GL_QUADS, 0, 4);
to
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
and add a slightly different vertex buffer
vertexBuffer.put(new float[]{
1.0, 1.0
-1.0, 1.0
1.0,-1.0
-1.0,-1.0
});
This represents two triangles, two 'points' are the same, so we have only four 'points'.
Just like:
x3__x4
| \ |
| \ |
x1__x2

Translation of OpenGL ES 2.0 Shapes in Android

I recently looked at the OpenGL ES 2.0 Tutorial provided by developers.android.com. I succesfully finished it (even if it wasn't very clear) but then I bumped into a problem. Once I finished it, I was never told how to translate or scale objects. I tried different options that seemed logical at the moment but they didn't work. I am not very expirienced in OpenGL ES 2.0 in android.
Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
long time = SystemClock.uptimeMillis() % 4000L;
mAngle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
Matrix.multiplyMM(mMVPMatrix, 0, mRotationMatrix, 0, mMVPMatrix, 0);
t.draw(mMVPMatrix);
All of these matrices are size 16 float arrays. My question is, how could I do a translation with an x and y position and sam for scale (a float with the scale)? There seems to be mo setTranslateM method and, when I tried the alternative methods I was not able to make them work. What do I do?
To translate/scale/rotate your objects, you should apply these operations to your Model Matrix.
Example:
Matrix.setIdentityM(mMMatrix, 0); // reset transformations
Matrix.setRotateM(mMMatrix, 0, 0, 1.0f, 0, 0); // set rotation
Matrix.translateM(mMMatrix, 0, 10.0f, 20.0f, 0); // apply translation
Matrix.scaleM(mMMatrix, 0, 0.25f, 0.25f, 0.25f); // apply scale
Please note that certain static methods of Matrix class do memory allocations so if you do objects transformation on each frame you may want not to use them. Read more about this here http://groups.google.com/group/android-developers/browse_thread/thread/b30dd2a437cfb076?pli=1 and in my blog post here http://androidworks-kea.blogspot.com/2012/05/developers-notes-about-opengl-es.html

Categories

Resources