Finding Your Way in OpenGL: A Beginner’s Guide to Coordinates
Hello there! Ever wondered about Coordinate Systems? Today, let’s unravel the mysteries of OpenGL and OpenGL ES as we explore the fascinating world of Coordinate Systems, including how OpenGL uses the Right-Handed Coordinate System (RHS). Our goal? To map the Android Coordinates system onto OpenGL RHS! 🚀✨
Let’s kick things off with what developer.android.com says:
One of the basic problems in displaying graphics on Android devices is that their screens can vary in size and shape. OpenGL assumes a square, uniform coordinate system and, by default, happily draws those coordinates onto your typically non-square screen as if it is perfectly square.
Think of it as giving directions in the world of graphics. How do you say, “Hey, be here!”? That’s what coordinates are all about, and we’re diving in.
In the realm of OpenGL coordinates, (0, 0) stands at the center, (-1, 1) defines the top-left, (1, 1) marks the top-right, (-1, -1) designates the bottom-left, and (1, -1) signifies the bottom-right — key points crucial for accurate positioning and rendering in the OpenGL universe.
Meanwhile, in the default Android coordinate system, the top-left is denoted by (0, 0), the top-right by (width, 0), the center by (width/2, height/2), and the bottom-left by (0, height), while the bottom-right is represented by (width, height).
Embarking on our first quest, we aim to forge a seamless connection between the Android coordinate system and the OpenGL Right-Hand Coordinate System. To achieve this, we are on a mission to discover a precise linear transformation.
Envision the linear equation sa + t = b
, where a
represents the position on the Android Coordinate System, b
denotes the position on the OpenGL Right-Hand Coordinate System, and s
signifies the scale of a, while t
embodies the translation of a.
Let’s focus on the x-axis:
In the left point transformation, where OpenGL’s -1 aligns with Android’s 0, the equation sa + t = b
simplifies to s * 0 + t = -1
, yielding t = -1.
In the transformation for the position of the center point, where OpenGL’s 0 aligns with Android’s width/2, the equation sa + t = b
simplifies to s * (width/2) - 1 = 0
, resulting in the determination that s equals 2/width
.
Let’s shift our focus to the y-axis:
In the top point transformation, where OpenGL’s 1 aligns with Android’s 0, the equation sa + t = b
simplifies to s * 0 + t = 1
, yielding t = 1.
In the transformation for the position of the center point, where OpenGL’s 0 aligns with Android’s height/2, the equation sa + t = b
simplifies to s * (height/2) + 1 = 0
, resulting in the determination that s equals -2/height
.
Awesome! Now that we’ve determined the scale (s) and translation (t) values for both the x and y axes, we can map our position in the Android Coordinate System onto OpenGL RHS using matrix multiplication.
Let’s dive into greater precision, shifting our focus from the generic ‘width and height’ to the specifics of ‘left, top, right, and bottom’:
X-Axis:
The left point in OpenGL is denoted as -1, the equation s*left + t = -1
simplifies t = -1 — s*left
.
The right point in OpenGL is denoted as 1, the equation s*right + t = 1
simplifies t = 1 — s*right
.
By equating these two expressions 1 — s*right = -1 — s*left
we derive s = 2/(right-left)
.
Consequently, the translation factor t
is determined as t = -(right+left)/(right-left)
.
Y-Axis:
The top point in OpenGL is denoted as 1, the equation s*top + t = 1
simplifies t = 1 — s*top
.
The bottom point in OpenGL is denoted as -1, the equation s*bottom + t = -1
simplifies t = -1 — s*bottom
.
By equating these two expressions 1 — s*top = -1 — s*bottom
we derive s = 2/(top-bottom)
.
Consequently, the translation factor t
is determined as t = -(top+bottom)/(top-bottom)
.
Let’s put our calculations to the test:
Imagine we have a device with screen resolutions of 1080 x 2220, and our goal is to determine the location of the screen center on the OpenGL RHS.
We have one more crucial detail to address! OpenGL operates within a 3D Coordinate System. To accommodate this, we’ll extend our matrix to a 4x4 format, incorporating depth for a comprehensive representation.
At the end of this section, we’ve successfully explored the process of mapping the Android coordinate system onto the OpenGL RHS using matrix multiplication. Achieving the representation of three-dimensional objects in two dimensions involves Orthographic projection. We can easily generate this matrix using the following code:
val projectionMatrix = FloatArray(16)
Matrix.orthoM(projectionMatrix, 0, left, right, bottom, top, near, far)
//Matrix.orthoM(projectionMatrix, 0, 0f, width, height, 0f, -1f, 1f)