So I have looked absolutely everywhere and can't find the anser. When I draw a 3d cube in opengl es for android it seems to look fine as long as I'm in portrait mode but when I switch to landscape it looks more like a diamond. I assume the issue is with the ratio but I really cant say so here's the code i'm using for the ratios.
public void onSurfaceChanged(GL10 gl, int width, int height){
gl.glViewport(0, 0, width, height);
float ratio = (float) width/height;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 11);
}
The other option that may be the issue I believe is the cube its self but again not sure so here's the vertices and indices.
private int vertices[] = {
-one, -one, -one,
one, -one, -one,
one, one, -one,
-one, one, -one,
-one, -one, one,
one, -one, one,
one, one, one,
-one, one, one
};
private 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
};
Alright so I guess I'm gonna answer my own question here and for all who need it. I used this ratio code instead under the onSurfaceChanged method.
double w = width/4.5;
gl.glViewport(0, (int)-w, width, width);
float ratio = (float) width/width;
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1, 14);
Related
To add some lightning to my OpenGL ES20 cube, I need to calculate the normals for each plane. I've found a "tutorial" on lightning, but they simply hard-coded the normals into the cube, which appears to me as not the best option, since it seems limited?
So my approach to the cube is as follows:
private float[] mVertices = {
-1, -1, -1, // bottom left
1, -1, -1, // bottom right back
1, 1, -1, // top right
-1, 1, -1, // top left
-1, -1, 1, // bottom left
1, -1, 1, // bottom right front
1, 1, 1, // top right
-1, 1, 1 // top left
};
private float[] mColors = {
0.6f, 0f, 0.6f,
0.6f, 0f, 0.6f,
0.6f, 0f, 0.6f,
0.6f, 0f, 0.6f,
0.8f, 0f, 0.6f,
0.8f, 0f, 0.6f,
0.8f, 0f, 0.6f,
0.8f, 0f, 0.6f
};
private float[] mNormal = new float[?]; ?
private short[] mIndices = {
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
};
i.e. i have all 8 vertices defined as well as indices, on how to combine them to triangles.
To get the normal matrix, I've read that I am supposed to invert the matrix, then transpose it. So I've tried this:
float[] mTempMatrix = new float[mVertices.length];
Matrix.invertM(mTempMatrix, 0, mVertices, 0);
Matrix.transposeM(mNormal, 0, mTempMatrix, 0);
But this is always filled with zeros, and my cube stays black. How example am I supposed to calculate the normal matrix? Should it be something with the model matrix? If yes, where am I supposed to do this, since the only place they are really combined is in the shader? Is there another way to do this which would be more appropriate?
The issue you are facing is that you share vertices between cube faces. The normal is a vector that points othogonal to the plane of the surface.
Consider the top/right/front vertex as an example (that you share with the front, right and top faces).
When used on the front face, the normal needs to point towards you as 0, 0, 1
When used on the right face, the normal needs to point to the right as 1, 0, 0
When used on the top face, the normal needs to point up as 0, 1, 0
So how to reconcile that?
You could set the normal for the vertex to point out from the corner, e.g. as 0.707, 0.707, 0.707. That'll most likely give you an interesting lighting effect on the corner but is probably not what you're after.
The other solution is not to re-use the vertices between faces. So you'll need 24 (4 per side) instead of 8. You'll then have 3 versions of each vertex but each one of those now belongs to just one face, hence you can set the normal vector as perpendicular to that face. You'll also be able to set the color for just that face as well since you'll no longer be sharing the vertex with other faces.
I've been trying to illuminate plane meshes generated by the following:
private Model createPlane(float w, float h, Texture texture) {
Mesh mesh = new Mesh(true, 4, 6, new VertexAttribute(Usage.Position, 3, "a_position"),
new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoord0"),
new VertexAttribute(Usage.Normal, 3, "a_normal"));
float w2 = w * this.CELL_SIZE;
float h2 = h * this.CELL_SIZE;
mesh.setVertices(new float[]
{ w2, 0f, h2, 0, 0, 0, 1, 0,
w2, 0f, -h2, 0, h, 0, 1, 0,
-w2, 0f, h2, w, 0, 0, 1, 0,
-w2, 0f, -h2 , w,h, 0, 1, 0
});
mesh.setIndices(new short[] { 0, 1, 2, 1, 3, 2});
Model model = ModelBuilder.createFromMesh(mesh, GL10.GL_TRIANGLES, new Material(TextureAttribute.createDiffuse(texture)));
return model;
}
and are rendered using:
//the environment setup
env = new Environment();
env.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
env.add(new PointLight().set(Color.ORANGE, 5f, 1f, 5f, 10f));
env.add(new DirectionalLight().set(Color.WHITE, -1f, -0.8f, -0.2f));
...
//the render method
batch.begin();
batch.render(inst, env);//inst is a ModelInstance created using the Model generated from createPlane(...)
batch.end();
The meshes display correctly (UVs, textured) and seem to be properly affected by directional and ambient lighting.
When I try to add a point light (see above environment) none of the planes generated from createPlane(...) are affected. I've tried creating another bit of geometry using the ModelBuilder class's createBox(...) and it seems to properly respond to the point light. Because of that I'm assuming that I'm not generating the plane correctly, but the fact that it's apparently being affected by directional/ambient light is throwing me off a bit.
It's worth noting that the size of the planes generated vary, I'm not particularly sure if a point light would affect 4 vertices very much but I expected more than nothing. Moving the point light around (closer to certain vertices) doesn't do anything either.
Any help would be greatly appreciated.
Thanks!
It would be great to know which shader you are using. The default one? I am not sure if they fixed that already, they had a bug a while ago, where pointlightning was only working on some devices (this had something todo with the implementation of opengles by the manufacturer. I personally fixed this by using my own shader.
Edit: This seems to be fixed
I checked the code I am using. The problem was to determine the correct light array in the shader.
Did it like this in the end:
// on some devices this was working
int u_lightPosition = program.getUniformLocation("u_lightPosition[0]");
int u_lightColors = program.getUniformLocation("u_lightColor[0]");
if(u_lightPosition < 0 && u_lightColors < 0) {
// on others this was working
u_lightPosition = program.getUniformLocation("u_lightPosition");
u_lightColors = program.getUniformLocation("u_lightColor");
}
I hope this helps!
consider a Car Object that should move forward in a road . I dont a have car object yet but I'll add that shape later . Instead of a car I have a square now how can I move it forward with specific speed?
any ideas?
here is my code
public class GLqueue {
private float vertices[] = { 1, 1, -1, // topfront
1, -1, -1, // bofrontright
-1, -1, -1, // botfrontleft
-1, 1, -1,
1, 1, 1,
1, -1, 1,
-1, -1, 1,
-1, 1, 1,
};
private FloatBuffer vertBuff;
private short[] pIndex = { 3, 4, 0, 0, 4, 1, 3, 0, 1,
3, 7, 4, 7, 6, 4, 7, 3, 6,
3, 1, 2, 1, 6, 2, 6, 3, 2,
1, 4, 5, 5, 6, 1, 6, 5, 4,
};
private ShortBuffer pBuff;
public GLqueue() {
ByteBuffer bBuff = ByteBuffer.allocateDirect(vertices.length * 4);
bBuff.order(ByteOrder.nativeOrder());
vertBuff = bBuff.asFloatBuffer();
vertBuff.put(vertices);
vertBuff.position(0);
ByteBuffer pbBuff = ByteBuffer.allocateDirect(pIndex.length * 4);
pbBuff.order(ByteOrder.nativeOrder());
pBuff = pbBuff.asShortBuffer();
pBuff.put(pIndex);
pBuff.position(0);
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CW);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertBuff);
gl.glDrawElements(GL10.GL_TRIANGLES, pIndex.length,
GL10.GL_UNSIGNED_SHORT, pBuff);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisable(GL10.GL_CULL_FACE);
}
}
Velocity depends on two factors - time and distance: v = d/t.
'Moving' an object is usually done my changing the position relative to the starting position. This distance is calculated according to the above formula: d = vt.
This means that in order to know where to position our object when drawing we must know the velocity and the time.
The velocity is probably decided by the user or the program somehow (I.E the user pushes the button for driving faster and the velocity goes up).
The current time can be retrieved by calling System.currentTimeMillis().
Here is a very simple example of an implementation:
//Variables:
long time1, time2, dt;
float velocity;
float direction;
//In game loop:
time1 = System.currentTimeMillis(); dt = time1-time2;
float ds = velocity*dt; //ds is the difference in position since last frame. car.updatePosition(ds, direction); //Some method that translates the car by ds in direction.
time2 = time1;
I am new to OpenGL programming.I have made a rotating cube with different images on different faces of the cube..i want to set background for the Screen..Any help will be appreciated..
Draw a textured quad covering the whole viewport. To do this, switch the projection and modelview to identity and disable depth testing. With projection and modelview being identity vertex coordinates [-1 … 1] will cover the whole viewport. In code:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
GLfloat tex_quad[16] = {
/* x, y, s, t */
-1, -1, 0, 0,
1, -1, 1, 0,
1, 1, 1, 1,
-1, 1, 0, 1
};
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*4, &tex_quad[0]);
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat)*4, &tex_quad[2]);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, background_image_texture_ID);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDisable(GL_TEXTURE_2D);
In my project all code of creation GLSurfaceView looks like:
glSurfaceView = ...
glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
glSurfaceView.setBackgroundResource(R.drawable.my_background);
glSurfaceView.setZOrderOnTop(true);
glSurfaceView.setRenderer(...);
glSurfaceView.setRenderMode(...);
NOTE: Do not use
_glSurfaceView.setBackgroundDrawable(this.getResources().getDrawable(R.drawable.my_background));
I wasted a few days on it.
And do not call
gl.glClearColor(...)
in
Renderer.onDrawFrame
I think the OP wants to turn his code into an android live wallpaper.
#Sumit : if I'm right you should do your due dilligence: http://developer.android.com/resources/articles/live-wallpapers.html
If I'm wrong, then please be more precise in your question.
As I m beginneers in Android OpenGl Es.
I am working on 3D project,when I run project on G1 android phone, texture is rendering on Screen. But With Same code is run on Samsang Galaxy, Texture has not been displayed. Screen is displayed Black. I don't understand what should do. plz tell me solution if anybody know.
I have This Egl configuration used.
public int[] getConfigSpec()
{
int[] configSpec =
{
EGL10.EGL_DEPTH_SIZE,16,
//EGL10.EGL_STENCIL_SIZE,0,
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_NONE
};
Then no ms3d Texture was dispalyed.Only blackscreen was diaplayed.
After I modified code then to then texture was getting displayed in White.
public int[] getConfigSpec()
{
int[] configSpec =
{
EGL10.EGL_DEPTH_SIZE,16,
//EGL10.EGL_STENCIL_SIZE,0,
//EGL10.EGL_RED_SIZE, 5,
//EGL10.EGL_GREEN_SIZE, 6,
//EGL10.EGL_BLUE_SIZE, 5,
,
EGL10.EGL_NONE
};
public void sizeChanged(GL10 gl, int width, int height)
{
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf( -0.1f,0.1f,-0.15f,0.15f,0.55f,1000.0f);
gl.glTranslatef(0.0f, 0.0f, -296);
gl.glMatrixMode(GL10.GL_MODELVIEW); // Select The Modelview Matrix
gl.glLoadIdentity();
}
Can Anybody tell what need to be Changed. How to set getConfig for samsang Galaxy (480*800)
Thanking you.
pratibha