Languages

Menu
Sites
Language
Homogeneous Coordinates

Homogeneous Coordinates is a mathematic fundation that OpenGL to create the perspective 3D world on the device screen.

"In Euclidean space (geometry), two parallel lines on the same plane cannot intersect, or cannot meet each other forever. It is a common sense that everyone is familiar with.

However, it is not true any more in projective space, for example, the train railroad on the side picture becomes narrower while it moves far away from eyes. Finally, the two parallel rails meet at the horizon, which is a point at infinity."

                   Railroad gets narrower and meets at horizon.

Above content come from following link, you can find the clear clarification on Homogeneous Coordinates theory.

http://www.songho.ca/math/homogeneous/homogeneous.html

In Tizen, we realize homogenous coordinates by set perspective projection on the view matrix.

Please find the definition of funtion view_set_perspective() and view_set_frustum() in another topic:

https://developer.tizen.org/forums/native-application-development/produce-perspective-projection-on-tizen.?tab=active

You can see below pictures which shows the perspective projection implementation on Tizen.

     

You can see the pink line which is parallel with the red axis seems meet at the right side of the third picture, which is a point at infinity.

Let's have a look at the code to draw these objects.

Firstly, the definition of the vertices of the axises and line, I do not list the definition for the cube here.

const float full_coords_vertices[] =
{
        0.0f, 0.0f, 0.0f,                // [0] Coordinate system origin
        50000.0f, 0.0f, 0.0f,      // [1] +x
        0.0f, 0.0f, 0.0f,               // [2] origin
        -50000.0f, 0.0f, 0.0f,    // [3] -x
        0.0f, 0.0f, 0.0f,               // [4] origin
        0.0f, 50000.0f, 0.0f,     // [5] +y
        0.0f, 0.0f, 0.0f,              // [6] origin
        0.0f, -50000.0f, 0.0f,   // [7] -y
        0.0f, 0.0f, 0.0f,              // [8] origin
        0.0f, 0.0f, 50000.0f,    // [9] +z
        0.0f, 0.0f, 0.0f,              // [10] origin
        0.0f, 0.0f, -50000.0f,  // [11] -z
        100.0f, 100.0f, 50000.0f,  // [12] +      Parallel to z axis
        100.0f, 100.0f, 0.0f,            // [13] origin Parallel to z axis
        100.0f, 100.0f, -50000.0f, // [14] -      Parallel to z axis
};

The colors for these vertices defined as:

const float full_coords_colors[] =
{
        0.0, 1.0, 0.0, 1.0,    // [0] green
        0.0, 1.0, 0.0, 1.0,    // [1] green
        0.8, 1.0, 0.8, 1.0,    // [2] pale green
        0.8, 1.0, 0.8, 1.0,    // [3] pale green
        0.0, 0.0, 1.0, 1.0,    // [4] blue
        0.0, 0.0, 1.0, 1.0,    // [5] blue
        0.8, 0.8, 1.0, 1.0,    // [6] light basket
        0.8, 0.8, 1.0, 1.0,    // [7] light basket
        1.0, 0.0, 0.0, 1.0,    // [8] red
        1.0, 0.0, 0.0, 1.0,    // [9] red
        1.0, 0.8, 0.8, 1.0,    // [10] light red
        1.0, 0.8, 0.8, 1.0,    // [11] light red
        0.88, 0.06, 0.9, 1.0,  // [12] is pink
        0.88, 0.06, 0.9, 1.0,  // [13] is pink
        0.88, 0.06, 0.9, 1.0,  // [14] is pink
};

The vertices indices and count to be drawn:

const int full_coords_indices_count = 16;
const unsigned short full_coords_indices[] =
{
        0, 1,
        2, 3,
        4, 5,
        6, 7,
        8, 9,
        10, 11,

       12, 13,
        13, 14,

};

Below are codes to draw the objects defined as above. To get the perspective effect, we called view_set_perspective() function. You can find the implementation of this function in the topic we mentioned earlier.

static void draw_gl(Evas_Object *obj) {
        appdata_s *ad = evas_object_data_get(obj, "ad");
        float model[16], view[16];
        float aspect;
        int w, h;

        if (!ad)
            return;

        init_matrix(model);
        init_matrix(view);

        elm_glview_size_get(obj, &w, &h);
        if (!h)
            return;

        aspect = (float) w / (float) h;
        view_set_perspective(view, 60.0f, aspect, 1.0f, 50000.0f);

        translate_xyz(model, 0.0f, 0.0f, -800.0f);
        rotate_xyz(model, ad->xangle, ad->yangle, 0.0f);

        multiply_matrix(ad->mvp, view, model);

        glViewport(0, 0, w, h);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // draw cube
        glVertexAttribPointer(ad->idx_position, 3, GL_FLOAT, GL_FALSE,
            3 * sizeof(float), cube_vertices);
        glVertexAttribPointer(ad->idx_color, 4, GL_FLOAT, GL_FALSE,
            4 * sizeof(float), cube_colors);
        glEnableVertexAttribArray(ad->idx_position);
        glEnableVertexAttribArray(ad->idx_color);
        glUniformMatrix4fv(ad->idx_mvp, 1, GL_FALSE, ad->mvp);

        glDrawElements(GL_TRIANGLES, cube_indices_count, GL_UNSIGNED_SHORT,
            cube_indices);

        //draw axies by full_coords_vertices
        glVertexAttribPointer(ad->idx_position, 3, GL_FLOAT, GL_FALSE,
            3 * sizeof(float), full_coords_vertices);
        glVertexAttribPointer(ad->idx_color, 4, GL_FLOAT, GL_FALSE,
            4 * sizeof(float), full_coords_colors);
        glEnableVertexAttribArray(ad->idx_position);
        glEnableVertexAttribArray(ad->idx_color);
        glUniformMatrix4fv(ad->idx_mvp, 1, GL_FALSE, ad->mvp);
  
        glDrawElements(GL_LINES, full_coords_indices_count, GL_UNSIGNED_SHORT,
            full_coords_indices);

        glFlush();
        display_fps();
}