How to scale a matrix obtained with glm::lookat()? - c++

I am trying to create an orthographic view (separate from the final perspective view). I know the view's scale, position, it's up vector, and the point it's looking at. So it seems easiest to simply use glm::lookAt() to create the view matrix, except there's no way to specify scale.
Is there a way to introduce scaling with glm::lookAt()? I don't think it's possible to scale the matrix made by lookAt, since scaling needs to happen first to get the 'expected' result (objects appearing larger or smaller, like zooming a camera in or out). I may be wrong there though.
If it's not possible while using lookAt, is there a series of glm functions that would be equivalent?

In terms of matrix transformations, you can start with a scale and apply the glm::lookAt() matrix afterwards. I'm not familiar with glm, but I have used GLUT before. You should be able to do a matrix multiplication like this (I'm assuming that you've already transformed everything into scene space, defined all the variables etc.)
TransformedVector = glm::lookAt(cameraPosition,
cameraTarget,
upVector) *
glm::scale(scalingFactor,
scalingFactor,
scalingFactor) *
OriginalVector;
If this behaves peculiarly try swapping the glm::lookAt() and glm::scale() order.

Related

Asymmetric Projection Matrix

I have a little "2 1/2-D" Engine I'm working on that targets multiple platforms, but currently I am upgrading my DirectX 11 version.
One of the things that is really important for my engine to do is to be able to adjust the horizon point so that the perspective below the horizon moves into the distance at a different angle than the perspective above the horizon.
In a normal 3D environment this would be typically accomplished by tilting the camera up above the horizon, however, in my engine, which makes heavy use of 2D sprites, tilting the camera in the traditional sense would also tilt the sprites... something I don't want to do (It ruins the 16-bit-arcade-style of the effect)
I had this working at one point by manually doing the perspective divide in the CPU using a center-point that was off-center, but I'd like to do this with a special projection matrix if possible. Right now I'm using a stock matrix that uses FOV, Near-Plane, and Far-Plane arguments.
Any ideas? Is this even possible with a matrix? Isn't the perpective divide automatic in the DX11 pipeline? How do I control when or how the perspective divide is performed? Am I correct in assuming that the perspective divide cannot be accomplished with a matrix alone? It requires each vertex to be manually divided by Z, correct?
What you are looking for is an off center perspective projection matrix, instead of a fov and aspect ratio, you provide left/right/top/bottom has tan(angle). The result is more or less the same as with a symmetric projection matrix with the addition of two extra non zero values.
You are right also, the GPU is hard wired to perform the w divide, and it is not a good idea to do it in the vertex shader, it will mess with perspective correction for the texture coordinates and clipping ( either not a big deal with the sprite special case ).
You can find an example of such a matrix here : https://msdn.microsoft.com/en-us/library/windows/desktop/bb205353(v=vs.85).aspx

Rotating, scaling and translating 2d points in GLM

I am currently trying to create a 2d game and I am a bit shocked that I can not find any transformations like rotation, scale, translate for vec2.
For example as far as I know rotate is only available for a mat4x4 and mat4x4 can only be multiplied by a vec4.
Is there any reason for that?
I want to calculate my vertices on the CPU
std::vector<glm::mat2> m;
Gather all matrices, generate the vertices, fill the GPU buffer and then draw everything in one draw call.
How would I do this in glm? Just use a mat4 and then ignore the z and w component?
One thing that you should understand is that you can't just ignore the z component, let alone the w component. It depends on how you want to view the problem. The problem is that you want to use a mat2 and a vec2 for 2D, but alas it's not as simple as you may think. You are using OpenGL, and presumably it's with shaders too. You need to use at least a glm::mat3, or better: mat4. The reason for this is that although you want everything in 2D, it has to be done in terms of 3D. 2D is really just 3D with the z-buffer being 1 and the clip pane simply static, relative to the Window size.
So, what I suggest is this:
For your model matrix, you have it as a glm::mat4 which contains all data, even if you don't intend to use it. Consistency is important here, especially for transformations.
Don't ignore the z and w component in glm::mat4; they are important because their values dictate where they are on screen. OpenGL needs to know where in the z-plane a value is. And for matrix multiplication, homogenous coordinates are required, so the w component is also important. In other words, you are virtually stuck with glm::mat4.
To get transformations for glm::mat4 you should
#include <glm/gtc/matrix_transform.hpp>
Treat your sprites separately; as in have a Sprite class, and group them outside that class. Don't do the grouping recursively as this leads to messy code. Generating vertices should be done on a per-Sprite basis; don't worry about optimisation because OpenGL takes care of that for you, let alone the compiler on the C++ side of things. You'll soon realise that by breaking down this problem you can have something like
std::vector<Sprite*> sprites;
for (const auto& : i)
i->init();
// etc...
for (const auto& : i)
i->render();
With regards to the shaders, you shouldn't really have them inside the Sprite class. Have a resource loader, and simply have each Sprite class retrieve the shader from that loader.
And most importantly: remember the order of transformations!
With regards to transformations of sprites, what you can do is have a glm::vec3 for sprite positions, setting the z-component to 0. You can then move your sprite by simply having a function which wants x and y values. Feed these values into the model matrix using glm::translate(..). With regards to rotation, you use glm::rotate() and simply have functions which get rotation angles. ALWAYS ROTATE ON THE Z-PANE thus it should be similar to this:
modelMatrix = glm::rotate(modelMatrix, glm::radians(angle), glm::vec3(0.f, 0.f, 1.f));
As for scaling, again a suitable setScale() function that accepts two values for x and y. Set the z component to 1 to prevent the Sprite from being scaled in z. Feed the values into glm::scale like so:
modelMatrix = glm::scale(modelMatrix, glm::vec3(scale));
Remember, that storing matrices provides little benefit because they're just numbers; they don't indicate what you really want to do with them. It's better for a Sprite class to encapsulate a matrix so that it's clear what they stand for.
You're welcome!
It seems that I haven't looked hard enough:
GLM_GTX_matrix_transform_2d from glm/gtx/matrix_transform_2d.hpp.

Why are model and view matrices specifically often combined together?

I'm having trouble understanding why the model and view matrices are traditionally combined together. I know that the less matrix multiplying you do in the vertex shader the better, but it makes much more sense to me to combine the projection and view matrices.
This is because they are both intrinsically camera properties. It makes sense to me to first transform vertices into world space with the model matrix, perform lighting etc., then use your combined camera matrix to translate to normalised clip space.
I know that I can do it that way if I want in a programmable pipeline, but I want to know why historically people combined the model and view matrices.
In graphics programming, camera doesn't exist. It's always fixed at (0,0,0) and looking towards (0,0,-1). Camera as everyone knows it is totally artificial and mimics the way we are used to observing objects, as humans, and by that I mean: moving around, pivoting our head and such. To mimic that, cg introduces the concept of camera. It is interesting and well known that it is the same thing whether will you move to camera to the right or to move all other objects in the scene to the left. That invariance is then transffered onto modelMatrix by combining all transformations on object in one matrix - MVMatrix.
View and Projection matrices are seperated because those matrices do very different transformations. One is very similar to modelMatrix and represents 3d, in-space transformations, and the other is used for calculating angles from which the objects are viewed.

What do we use matrices for in openGL?

I'm new to OpenGL and was wondering what do we use matrices for, if someone could explain me in abstract intuitive way, because when reading references or any tutorial, all of these take matrices as known mechanism. I've learned matrices in maths, but as English is not my native language, it's hard to figure out what does some stuff mean.
I found good example at www.learnopengl.com which says:
The model matrix. This matrix is used to place a model somewhere in the “world”. For example, if you have a model of a car and you want it located 1000 meters to the east, you will use the model matrix to do this.
The view matrix. This matrix represents the camera. If we want to view our car which is 1000 meters to the east, we’ll have to move ourselves 1000 meters to the east as well (another way of thinking about it is that we remain stationary, and the rest of the world moves 1000 meters to the west). We use the view matrix to do this.
The projection matrix. Since our screens are flat, we need to do a final transformation to “project” our view onto our screen and get that nice 3D perspective. This is what the projection matrix is used for.
This explains it pretty good. But, how do we build them? How large are they?
Also, I've read in this question:
What does glLoadIdentity() do in OpenGL?
that:
glMatrixMode(GL_PROJECTION) deals with the matrices used by
perspective transformation or orthogonal transformation.
glMatrixMode(GL_MODELVIEW) deals with matrices used by model-view
transformation. That is, to transform your object (aka model) to the
view coordinate space (or camera space).
What those transformation mean and how do they get calculated?
I know that here are many question, but I'm trying to make better conception of all of these to get better view on OpenGL. That's why I need some abstract explanation to dive into all details with understanding of conception beyond.
Translation, rotation, and scaling are all affine transforms, which can be implemented using matrix multiplication and addition. Actually, by augmenting the vector with a w element that's always one, the affine transform in 3 dimensions becomes a linear transformation in 4 dimensions and all you need is a matrix multiply.
Doing it with a matrix multiply is very nice because (1) it's fast and (2) you don't need special logic for any of the operations -- you can even compose as many of these affine operations as you want and still represent it with a single matrix.
Having multiple matrix modes is useful when composing. If you had only one matrix, you could add new operations at either end but not in the middle. By having 3 matrices multiplied together later, you can insert new operations at four different points in the order.
The matrix stack is also very useful because it allows you to do an operation for a few primitives and then remove it. If you tried to undo the operation by doing the inverse operation, eventually rounding errors would get out of control. But by remembering the previous matrix, you can just get it back as if the rotation or whatever never happened.
OpenGL is nice in that rather than working with matrices directly, you can call functions that will manipulate them.
So under the hood (what really happens), is that there are several matrices that transform your objects (a model-view matrix that transforms object to camera space, and projection matrix for perspective / orthogonal transformations).
glMatrixMode is like a switch that allows you to choose which type of matrix to use and manipulate, and you specify using the arguments. So glMatrixMode(GL_PROJECTION) means that you will be manipulating the projection matrix.

OpenGL glMatrixMode help

I'm starting to work a little on OpenGL stuff, and I'm seeing a lot of examples that make calls to the glMatrixMode function.
From what I've gathered, setting this to either GL_MODELVIEW or GL_PROJECTION (etc) will activate that specific transformation matrix and all subsequent calls to matrix transformation functions (glTranslatef, glPushMatrix, glLoadIdentity, glLoadMatrix etc) will affect the active matrix only.
What I don't get is why are there 3 (4 in some cases) different matrices? Which one should I use? (I'm probably going to get a lot of "Use Shaders", but I can't. Limited by school...) When should I switch and activate a different matrix? What is the benefit of utilizing all of them as opposed to only using one?
Thanks for any help :)
glMatrixMode doesn't "activate" matrices. The OpenGL fixed pipeline uses 3 matrices (sometimes 4): Two are responsible for transforming the geometry, one for transforming texture space (and some implementations one for color adjustments). Those matrices are used all the time.
The modelview matrix is used to move geoemtry around. Since OpenGL doesn't have a "camera" the viewer is positioned by moving all the geometry in the opposite (=inverse) of the movements of the "camera".
The projection matrix is used to transform the geometry from modelview space into clip space, i.e. it projects the transformed geometry into the viewport.
The texture matrix transforms the texture coordinates. In case (s,t,r,q) are directly given the benefit of this matrix isn't clear at first. But OpenGL also allows to generate texture coordinates from the vertex positions. This together with the texture matrix allows to implement projection textures.
The color matrix is seldomly used and not even available in all implementations (it's part of an extension). If available it transforms the incoming vertex colours. Since there are not implicit color generators what use is then? Well, it can be used to transform between linear colourspaces, e.g. RGB->XYZ or any other colour space conversion that can be expressed as a matrix of scalars. Nobody used the color matrix these days, shaders do the job much better.
glMatrixMode is there so that there's no bloat of functions. Otherwise you'd need:
glModelviewLoadIdentity
glModelviewLoadMatrix
glModelviewMultMatrix
glModelviewRotate
glModelviewTranslate
glModelviewScale
glModelviewPushMatrix
glModelviewPopMatrix
glProjectionLoadIdentity
glProjectionLoadMatrix
glProjectonMultMatrix
glProjectionRotate
glProjectionTranslate
glProjectionScale
glProjectionPushMatrix
glProjectionPopMatrix
and so on. Also you couldn't use functions like glFrutum in both projection and texture matrices. You'd need two of those, too.
And last but not least one important hint. Setting the viewport and the projection matrix belongs in the rendering function. Most tutorials you'll see out there place them in the window resizing handler, which is the totally wrong place for that. Don't immitate this bad habit.
You will be using all of these if you use the fixed function pipeline (i.e. "no shaders"). In fact, you'll use them with shaders too, but you'll implement them yourself in that case.
This part of OpenGL can be hard to grasp at first, although it is actually quite simple. When you select a particular matrix, then this does not turn on or off anything. All it does is that it makes functions like glTranslatef work with the one specific matrix that you've selected.
OpenGL works like this everywhere (except for direct state access), for example with textures and buffers, in the same way.
EDIT: As for why there are several matrices, they all do different things. Your models are usually in their "own space", which means they need to be somehow transferred to the "world", by scaling them appropriately and translating them to the right location. Then everything (the whole "world") needs to be transformed in a way according to your "eye position", and it must be transformed into a "normalized" clip space, because that is how the hardware can be implemented in the most efficient manner, etc, etc, etc.
All those matrices are usually multiplied together (without you knowing that this happens).If you google for opengl transform pipeline, you will get a lot of good resources that explain what happens when in detail, for example this.
Or, read the specification (freely available at opengl.org), it contains very explicit (and in my opinion easy) information on how all the seemingly complicated matrix stuff is intended.
You will probably just use glMatrixMode(GL_PROJECTION) once, followed by gluPerspective() (or maybe glOrtho()), so that you will set how the projection will be done. It is not that very common to change the perspective once set.
Then you change to GL_MODELVIEW and just use it to rotate/translate/scale stuff around. Both matrix are used on redering, being final position on screen = GL_PROJECTION * GL_MODELVIEW * your vertex. But since GL_MODELVIEW should change much more often than GL_PROJECTION, they are separated by the specification.
It's because matrix multiplies are not commutative. If you only had one matrix mode, the new transformation would always occur after all existing ones, and that's not always desirable.
By keeping several matrices which effectively get multiplied together for each piece of geometry, it's possible to e.g. have both translation to render the different bits of an object and also a point-of-view transformation, and be able to adjust these independently of each other.