I'm pretty new to opengl es. Right now I'm trying to make a simple scene, where rectangles of different sizes are just falling down and rotating around theirs own axis.
(illustration of what I want)

I created rectangle class, shader helper for it and also created a simple vertex and fragment shaders(just coloring through the vec4, nothing special I won't post the code).
Well, all this stuff looks like this:
rectangle object
public class RectObject{
private static final int POSITION_COMPONENT_COUNT = 2;
private static final int TEXTURE_COORDINATES_COMPONENT_COUNT = 2;
private static final int STRIDE = (POSITION_COMPONENT_COUNT
+ TEXTURE_COORDINATES_COMPONENT_COUNT) * BYTES_PER_FLOAT;
private final VertexArray vertexArray;
public RectObject(float x, float y, float size){
float[] newCoordinates = {
x, y, 0.5f, 0.5f,
(x-size), (y-size),0f, 1.0f,
(x+size), (y-size),1f, 1.0f,
(size + x), (size + y),1f, 0.1f,
(x-size), (size + y),0f, 0.1f,
(x-size), (y-size), - 0f, 1.0f
};
vertexArray = new VertexArray(newCoordinates);
}
public void bindData(RectShaderProgram textureProgram) {
vertexArray.setVertexAttribPointer(
0,
textureProgram.getPositionAttributeLocation(),
POSITION_COMPONENT_COUNT,
STRIDE);
}
public void draw(RectShaderProgram shader, float velocity) {
glUniform4f(shader.getMoveLocation(), 0.0f, velocity, 0.0f, 0.0f);
glUniform1f(shader.getTimerLocation(), (float)(System.nanoTime()/10000000000.0f));
glDrawArrays(GL_TRIANGLE_FAN, 0, 6);
}
}
vertex shader:
attribute vec4 a_Position;
uniform vec4 u_Move;
uniform mat4 u_Matrix;
uniform float timer;
void main()
{
mat4 rotation = mat4(
cos(timer), -sin(timer), 0.0, 0.0,
sin( timer), cos(timer), 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
gl_Position = u_Matrix * rotation* ((a_Position /*+ u_Move*/)) ;
}
shader helper
public class RectShaderProgram extends ShaderProgram{
private final int uMatrixLocation;
private final int uMoveLocation;
private final int TimerLocation;
// Attribute locations
private final int aPositionLocation;
public RectShaderProgram(Context context ) {
super(context, R.raw.rect_vertex_shader,
R.raw.rect_fragment_shader);
// TODO Auto-generated constructor stub
// Retrieve uniform locations for the shader program.
// Retrieve attribute locations for the shader program.
aPositionLocation = glGetAttribLocation(program, A_POSITION);
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
uMoveLocation= glGetUniformLocation(program, U_MOVE);
TimerLocation = glGetUniformLocation(program, TIMER);
}
public void setUniforms(float[] matrix) {
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix, 0);
}
public int getPositionAttributeLocation() {
return aPositionLocation;
}
public int getMoveLocation() {
return uMoveLocation;
}
public int getTimerLocation() {
return TimerLocation;
}
}
but the problem is that whole scene rotates around!
what I've got

So, how to make it in right way? Here's renderer class
public class ProjectRenderer implements Renderer{
private final float[] projectionMatrix = new float[16];
private final float[] modelMatrix = new float[16];
private int uMatrixLocation;
private Background wall;
//private RectObject myobject, myobject2;
private TextureShaderProgram textureProgram;
private ColorShaderProgram colorProgram;
private RectShaderProgram rectProgram;
private int texture;
private float velocity, time;
private ArrayList<RectObject> rlist = new ArrayList<RectObject>();
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
glClearColor(0.0f,0.0f,0.0f,0.0f);
velocity = 0.1f;
wall = new Background();
//myobject = new RectObject(0.1f,0.1f, 0.1f);
//myobject2 = new RectObject(0.2f,0.4f, 0.1f);
Random rand = new Random();
for (int i = 0; i < 15; i++){
rlist.add(new RectObject( (float)0.2*rand.nextInt(15)-1, (float)0.2*rand.nextInt(15)-1, (float)0.1*rand.nextInt(3)));
}
textureProgram = new TextureShaderProgram(context);
colorProgram = new ColorShaderProgram(context);
rectProgram = new RectShaderProgram(context);
texture = TextureHelper.loadTexture(context, R.drawable.sas);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
glViewport(0, 0, width, height);
// Construct the projection matrix
MatrixHelper.perspectiveM(projectionMatrix,45,(float)width
/(float)height,1f,10f);
// Make the modelMatrix identity matrix
setIdentityM(modelMatrix,0);
// Add offset of 2.5 in direction of z axle
translateM(modelMatrix,0,0f,0f,-2.0f);
// Rotation by 60 degrees in direction of x axle
//rotateM(modelMatrix,0,-60f,1f,0f,0f);
// Projection matrix * model matrix
final float[] temp=new float[16];
multiplyMM(temp,0,projectionMatrix,0,modelMatrix,0);
System.arraycopy(temp,0,projectionMatrix,0,temp.length);
}
@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw the table.
textureProgram.useProgram();
textureProgram.setUniforms(projectionMatrix, texture);
wall.bindData(textureProgram);
wall.draw();
velocity = velocity - 0.005f;
rectProgram.useProgram();
rectProgram.setUniforms(projectionMatrix);
for(Iterator<RectObject> i = rlist.iterator(); i.hasNext(); ) {
RectObject item = i.next();
item.bindData(rectProgram);
item.draw(rectProgram, velocity);
}
}
public ProjectRenderer(Context context){
this.context = context;
}
The case is in that you store coordinates of the rectangles in world coordinates. In other words you apply translation transformation to the vertices and store them transformed. So all rectangles are represented if a single frame with one global origin.
The rotation matrix transforms the coordinates of a give point in way that rotates this point around the origin. To rotate a point around an arbitrary axle in space some more complicated math is required. Thus, usually each object is represented with appropriate local frame, that allows to perform some transformation (i.e. rotation, scale) with respect to the local origin of the object. This local origin, that sometimes is referred to as pivot point usually is placed in the center of the object.
Any motion can be represented as combination of two distinct types of motion: translational motion and rotational motion. There are infinite ways of decomposition of an arbitrary motion, thus it is reasonable to select the most convenient one. The local (fixed to the object) frame should be select considering the fact, that it's origin(pivot point) position in global frame would not be effected by rotational transform.
So, summarizing all above, you should rewrite your RectObject's constructor as follows:
public RectObject(float x, float y, float size){
float[] newCoordinates = {
0, 0, 0.5f, 0.5f,
-size, -size, 0f, 1.0f,
size, -size, 1f, 1.0f,
size, size, 1f, 0.1f,
-size, size, 0f, 0.1f,
-size, -size, - 0f, 1.0f
};
vertexArray = new VertexArray(newCoordinates);
}
The origin would be in the center of the rectangle(square to be precise).
Moreover, I'd recommend you not to apply the size to the vertices of rectangle directly, but pass it as a uniform parameter into the vertex shader and apply as scale transformation. Thus you would be able to use the same array of vertices for all your rectangles. The coordinates of the vertices should be constructed as for the unit size rectangle for this case.
How to pass the transformation to the vertex shader? Usually it is done by the transformation matrix that is passed as a uniform parameter. This transformation matrix usually are the result of multiplications of all intermediate transformations such as translations, rotations and scales. So, your vertex shader should be changed as follows:
attribute vec2 a_Position;
uniform mat4 u_Matrix;
void main()
{
gl_Position = u_Matrix * vec4(a_Position, vec2(0.0, 1.0));
}
Note that you have defined the a_Position attribute as two component vector, so you must use it as a two component vector. In a shader above, a four component vector is constructed using the a_Position attribute.
Also note that if you are going to use uv coordinates you need to add them into your vertex shader.
You need to calculate the u_Matrix matrix as a result of multiplication of your projection, translation and rotation matrices. Constructing of these matrices depends on the math library you are using. Read this, this and this for a general idea how to do this.
In general terms, for your case the transformation matrix can be calculated as follows:
Translation Rotation
| | | | | 1 0 0 0 | | cos(alpha) -sin(alpha) 0 0 |
| Transformation | = | Projection | X | 0 1 0 0 | X | sin(alpha) cos(alpha) 0 0 |
| matrix | | matrix | | 0 0 1 0 | | 0 0 1 0 |
| | | | | x y 0 1 | | 0 0 0 1 |
Where:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With