GLM SIMD implementation of LookAt - c++

I've a problem using glm math lib with simd.
I've encounter a problem during the calculation of the lookat matrix.
Follow my lookAt functions:
FORCE_INLINE_ALWAYSINLINE const glm::detail::fmat4x4SIMD LookAt( const glm::detail::fvec4SIMD &eyePos, const glm::detail::fvec4SIMD &lookAtPos, const glm::detail::fvec4SIMD &upVec )
{
glm::detail::fvec4SIMD v3X, v3Y, v3Z;
v3Y = glm::normalize(upVec);
v3Z = glm::normalize(eyePos - lookAtPos);
v3X = glm::normalize(glm::cross(v3Y, v3Z));
v3Y = glm::cross(v3Z, v3X);
glm::detail::fmat4x4SIMD m4EyeFrame = glm::detail::fmat4x4SIMD(v3X, v3Y, v3Z, eyePos);
return m4EyeFrame;
}
Unfortunately doesn't work well, for example:
If the eyePos (the camera position) is in 0,0,-10 and lookAtPos (target position) is in 0,0,0 and the object is at that position, the view work well. But if I move eyePos on X or Y axis, the model seems deformed (like stretched) or disappears as if it had gone outside of the frustum, but in real it is still within.
NOTE: every fourth element of fvec4SIMD is set to 1.0f
I've also read this post:
My SSE implementation of lookAt doesn't work
but I cannot use within fmat4x4SIMD because of rows to columns translation, maybe I need to shuffle all elements to convert from row to column, but I don't know how to do it in a fast way. This is just my impression, but maybe the problem lies elsewhere.
Any suggestion?

Related

Moving and Imported model along the forward Vector - DirectX11 C++

I have spent ages trying to work out the way to create the forward vector of any imported object, This is so that I can complete the players controls and also add billboarding. This is for a University project where I have been given a set GameObject class to load in the objects using a MeshLoader and OBJLoader class.
I currently am using A .GetWorld(); which returns me an XMFLOAT4X4 which should give me the data of the object in the world. I then convert it to a XMMATRIX using the XMLoadFloat4X4 and then grab each row of data from that matrix into its own XMVECTOR. I have tested these and Believe that they are in the correct order but am still having the problem of my character never moving when I hit the forward key. I wondered If I am doing anything completely wrong or if I have just missed something out.
else if (GetAsyncKeyState(VK_UP))
{
XMFLOAT4X4 currrentWorld = _zaz.GetWorld();
XMMATRIX currentWorldM = XMLoadFloat4x4(&currrentWorld);
XMVECTOR scale = currentWorldM.r[1];
XMVECTOR rotation = currentWorldM.r[2];
XMVECTOR translation = currentWorldM.r[3];
XMVECTOR forward = currentWorldM.r[4];
forward = XMVector3Normalize(forward);
translation = XMVectorAdd(translation, forward);
newWorld = XMMATRIX(scale, rotation, translation, forward);
_zaz.SetWorld(&newWorld);
_zaz.UpdateWorld();
}
The other problem is that “_zaz.UpdateWorld(); only seems to work inside my update method even though all Keyboard controls are checked on update.
void GameObject::UpdateWorld()
{
XMMATRIX scale = XMLoadFloat4x4(&_scale);
XMMATRIX rotate = XMLoadFloat4x4(&_rotate);
XMMATRIX translate = XMLoadFloat4x4(&_translate);
XMStoreFloat4x4(&_world, scale * rotate * translate);
}
void GameObject::SetWorld(XMMATRIX* world)
{
XMStoreFloat4x4(&_world, *world);
}
It is definitely reading in the values, I get the game to break on the key “up” being pressed which should run the above code. All of the values are set. The car does currently rotate and If I rotate the car slightly and then break the game only the rotation and forward vectors change, Which should be ok?
The watch of all of the vectors after the second iteration of the elseif keypressed up code is called
If you have any Ideas it would help massively.
I assumed that It would be similar to:
else if (GetAsyncKeyState(VK_CONTROL))
{
XMFLOAT4 position = _cameraFree.GetEye();
XMFLOAT4 direction = _cameraFree.GetForward();
position.x -= (direction.x * 0.05f);
position.y -= (direction.y * 0.05f);
position.z -= (direction.z * 0.05f);
_cameraFree.SetEye(position);
_cameraFree.CalculateViewProjection();
}
Which uses XMFLOAT4's for the cameras data, which was easy to do, With the XMFLOAT4X4's and XMMATRIX's that my GameObject rely on it has so far been impossible to get to work. If there is anymore info that I can supply to help then please say!
Hope this helps you help me.
The way you imagine currentWorldM is completely wrong.
First, you do an out of bound access, XMMATRIX::r is only 4 elements, the valid range is [0..3].
Second, a 4x4 matrix is not built like that, it contains everything merged, you have to see it more like a frame, with 3 vectors i j k and a position O. One of them is your forward vector, one up and one right ( or left ).
A scale matrix is for example in r[0].x r[1].y and r[2].z, and this is only true as long as you do not concatenate it with a rotation, after that, it will be spread over the full matrix.

OpenGL Camera Strafing doesnt work

I'm currently working on a OpenGL FrameWork/Engine and as far as the OpenGL part goes, I'm quite satisfied with my results.
On the other hand I have a serious problem getting a Camera to work.
Moving along the Z-Axis works well, but as soon as I start to strafe (moving along the X-Axis), the whole Scene get screwed.
You can see the result of strafing in the image below.
The left part shows the actual scene, the right part shows the scene resulting from a strafe movement.
My code is the following.
In Constructor:
//Info is a Struct with Default values
m_projectionMatrix = glm::perspective(
info.fieldOfView, width / height, //info.fov = 90
info.nearPlane, info.farPlane // info.near = 0.1f, info.far = 1000
);
//m_pos = glm::vec3(0.0f,0.0f,0.0f), info.target = glm::vec3(0.0f, 0.0f, -1.0f)
m_viewMatrix = glm::lookAt(m_pos, m_pos + info.target, Camera::UP);
//combine projection and view
m_vpMatrix = m_projectionMatrix * m_viewMatrix;
In the "Update"-Method I'm currently doing the following:
glm::mat4x4 Camera::GetVPMatrix()
{
m_vpMatrix = glm::translate(m_vpMatrix, m_deltaPos);
return m_vpMatrix;
}
As far as i know:
The projection matrix achieves the actual perspective view. The view matrix, initially, translates and rotates the whole scene, that it is centered?
So why translating the VP-Matrix by any Z-Value works just fine, but by an X-Value doesn't?
I would like to achive a camera behaviour like this:
Initial Cam Pos is (0,0,0) and "Center" is e.g. (0,0,-1).
Then after Translation by X = 5: Cam Pos is (5,0,0) and Center is (5,0,-1).
Edit: Additional Question.
Why is the Z-Coordinate affekted by VP-Transformation?
Thanks for any help!
Best regards, Christoph.
Okay, I finally got the solution... As you can see, I am using GLM for my matrix math. GLM stores its matrices values in column major order. Open GL wants column major ordered matrices, too. C/C++ native 2d Array layout is row major, so most of the available OpenGL/C++ tutorials state, that one should use
glUniformMatrix4fv(location, 1, GL_TRUE, &mat[0][0]);
With GL_TRUE meaning, that the matrix should be converted (transposed?) from row major to column major order. Because of my matrices already beeing in column major format, that makes absolutely no sense...
Changing the above to
glUniformMatrix4fv(location, 1, GL_FALSE, &mat[0][0]);
fixed my problem...
Matrix math is not my strong point so I can't explain why your current approach doesn't work, though I have my suspicions (translating the projection matrix doesn't seem right). The following should allow you to move the camera though:
// update your camera position
m_pos = new_pos;
// update the view matrix
m_viewMatrix = glm::lookAt(m_pos, m_pos + info.target, Camera::UP);
// update the view-projection matrix, projection matrix never changes
m_vpMatrix = m_projectionMatrix * m_viewMatrix;

Rotate around a point with a 3x3 matrix and a translation vector

I have a 3x3 matrix in openGL format and a translation vector. I get confused when rotating around a point because my rotate function does not consider translation.
For rotating I assumed I could simply change the 3x3 matrix into a quaternion, rotate it and then change it back. This does not work when rotating about anything other than the objects current position.
The normal procedure for 4x4 matrcies is:
translate point by -(point - position)
rotate
translate point by (point - position)
Optional advice:
Bullet physics uses this format and that is why I was considering using their data format to store transformations. I do eventually have to convert to a 4x4 matrix to do projection, but that does not matter all that much. Bullet's format is attractive because it removes the useless shear data. Is it worth the bother to keep transformations in bullet format or no?
Came up with one. Just do matrix math. Create the rotation matrix manually or from a quaternion and then just multiply them. Bullet does this for you but i'll show what bullet does internally too.
*psuedo code
void Transform::rotateAroundPoint(axis, angle, point)
{
Matrix3x3 mat = createMatrixFromQuaternion(axis, angle);
Transform rotateTransform;
trans.basis = mat; // <- 3x3 matrix
trans.origin = Vector3(0,0,0); // <- Translation vector
// "this" is a pointer to the transform being edited since I decided to write
// this as a member function.
Vector3 pos = this->origin;
this->origin = this->origin - point;
(*this) = rotateTransform * (*this);
this->origin = this->origin + point;
}
// Internally bullet does basically this
resultTransform.basis = t1.basis * t2.basis;
resultTransform.origin = t1.basis * t2.origin + t1.origin;
I have not tested the code yet. I am a little bit terrified that it may suffer from gimbal lock so in my actual code I am probably going to just do quaternion math when i have to multiply 2 basis matricies.

Rotating the LookAt vector of gluLookAt

I'm a student new to opengl. Currently, I'm doing a project that creates a scene.
Right now, my team is using gluLookAt() for my camera. What I want to accomplish is to try and rotate the LookAt vector around a certain point, namely where the camera is looking at.
This accomplishes a sort of "swaying in a circle". I need this because I am making a dart game for the scene, and my camera stay still, but I need it to move in a circle, but still allow the user's mouse to influence it. I also need it to create a drunken movement. That is why I am not considering rotating the Up or Eye vectors.
Currently, my look at code is like this.
int deltax = x - mouse.mX;
int deltay = y - mouse.mY;
cameradart.mYaw -= ((deltax/360.0) * 3.142) * 0.5;
cameradart.mPitch -= deltay * 0.02;
mouse.mX = x;
mouse.mY = y;
cameradart.lookAt.x = sin (cameradart.mYaw);
cameradart.lookAt.y = cameradart.mPitch ;
cameradart.lookAt.z = cos (cameradart.mYaw);
gluLookAt (cameradart.eye.x, cameradart.eye.y, cameradart.eye.z,
cameradart.eye.x + cameradart.lookAt.x, cameradart.eye.y + cameradart.lookAt.y,
cameradart.eye.z + cameradart.lookAt.z,
cameradart.up.x, cameradart.up.y, cameradart.up.z);
I know that it could be done easier using a different camera, but I really don't want to mess with my team's code by not using gluLookAt().
There's a couple of solutions in my mind, I'll tell you the easiest to understand/implement as a new graphics student
Assuming at first you're looking at (0,0,1) -store that vector-:
Think of a point that's drawing a circle and you're looking at it,
-Do it first to turn right and left (2D on X & Z)
-Let HDiff be the horizontal difference between old mouse position and the new one
-Update the x = cos(HDiff)
-Update the z = sin(HDiff)
*I didn't try it but it should work :)
If you want to be able to manipulate the camera, using a camera matrix is a much more effective mechanism than working with gluLookat. GLM is a good library for matrix and vector math and includes a lookat mechanism you can use to initialize the matrix, or you can just initialize it with a series of operations. However, remember that lookat produces a view matrix, and the view matrix is the inverse of the camera matrix.
This piece of code has a demonstration of what I'm talking about. Specifically look at the player member variable and how it's manipulated
glm::mat4 player;
...
glm::vec3 playerPosition(0, eyeHeight, ipd * 4.0f);
player = glm::inverse(glm::lookAt(playerPosition, glm::vec3(0, eyeHeight, 0), GlUtils::Y_AXIS));
This approach lets you apply changes like rotation and translation directly to the player matrix
// Rotate on the Y axis
player = glm::rotate(player, angle, glm::vec3(0, 1, 0));
This is much more intuitive than manipulating the view matrix, since changes to the view matrix always have to be the inverse of what you'd do to the player matrix.
When you're ready to render you need to convert the player matrix to a view matrix by taking it's inverse. In my example it's done like this:
gl::Stacks::modelview().top() = riftOrientation * glm::inverse(player);
This is because I'm using an application based modelview matrix stack that gets applied to the Shader programs I'm running.
For an OpenGL 1.x program, you'd instead use LoadMatrix
glMatrixMode(GL_MODELVIEW);
glm::mat4 modelview = glm::inverse(player);
glLoadMatrixf(&modelview);

Transformations in computer graphics

I am trying to follow this course about computer graphics, but I'm stuck in the homework 1. I don't understand what's the role of the vector eye and up. The descripcion of the homework can be found in this link, there's also the skeleton of the first assignment.
So far I have the following code:
// Transform.cpp: implementation of the Transform class.
#include "Transform.h"
//Please implement the following functions:
// Helper rotation function.
mat3 Transform::rotate(const float degrees, const vec3& axis) {
// Please implement this.
float radians = degrees * M_PI / 180.0f;
mat3 r1(cos(radians));
mat3 r2(0, -axis.z, axis.y, axis.z, 0, -axis.x, -axis.y, axis.x, 0);
mat3 r3(axis.x*axis.x, axis.x*axis.y, axis.x*axis.z,
axis.x*axis.y, axis.y*axis.y, axis.y*axis.z,
axis.x*axis.z, axis.z*axis.y, axis.z*axis.z);
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
r2[i][j] = r2[i][j]*sin(radians);
r3[i][j] = r3[i][j]*(1-cos(radians));
}
}
return r1 + r2 + r3;
}
// Transforms the camera left around the "crystal ball" interface
void Transform::left(float degrees, vec3& eye, vec3& up) {
eye = eye * rotate(degrees, up);
}
// Transforms the camera up around the "crystal ball" interface
void Transform::up(float degrees, vec3& eye, vec3& up) {
vec3 newAxis = glm::cross(eye, up);
}
// Your implementation of the glm::lookAt matrix
mat4 Transform::lookAt(vec3 eye, vec3 up) {
return lookAtMatrix;
}
Transform::Transform()
{
}
Transform::~Transform()
{
}
for the left method it appears to be doing the right thing, which is, rotating the object around the y-axis (actually I'm not sure if the object is moving or what I'm moving is the camera, can someone clarify?).
for the up method I cannot make it work which will be rotating the object (or camera?) around the x-axis (at least that's what I think).
finally, I don't understand what should the lookAt method should do.
Can someone help me understand the actions to be performed?
Can someone explain what are the roles of vectors eye and up?
View transforms are often implemented using a "look-at" function. The idea being that you specify where the camera is, what direction it is looking in, and what direction represents "up" in your particular space, and you get a matrix back which represents that transform.
It looks like you're trying to implement some kind "rotating ball" navigation control. That's fairly simple - horizontal movement should rotate around some "Y" axis, and vertical movement should rotate around the "right" (or X) axis. Generally those rotations work around the current view axes, rather than globally, so that the movement is intuitive. I'm not sure exactly what you're looking for there.
A look-at function works as follows.
A 3x3 matrix representing a rotation can be viewed as being composed the 3 perpendicular unit axes of the space you are transforming into. So if you can supply those vectors, you can build the matrix.
The first axis is easy. A camera is typically oriented to look along "Z", so if you take the vector representing the direction of the thing being looked at from the camera's position, then normalise it, this is the Z axis.
Then you need to define a distinct 'up' vector - (0,1,0) is typical, but you will need to choose a different one in cases where the Z-axis is pointing in the same direction.
The cross product of this 'up' vector and the 'Z' axis gives the 'X' axis - this is because the cross product gives a perpendicular vector, and what constitutes horizontal will be perpendicular to both the 'forward' direction, and 'up'.
Then the cross product of the 'X' and 'Z' axes gives the 'Y' axis (which is not necessarily the same as the 'Y' axis - consider looking towards the ceiling or towards the floor).
These three axes, normalised, (x,y,z) directly form a rotation matrix.
The translation portion of the matrix is generally the position of the camera, transformed by the rotation's inverse (such that when transforming the camera position by the lookat matrix itself, it should end up back at the origin).
1) Your course is using the OpenGL library, and your homework assignment is to fill in the skeleton module "Transform.cpp".
2) The method you're asking about is "mat4 Transform::lookAt(vec3 eye, vec3 up)":
lookAt: Finally, you need to code in the transformation matrix, given
the eye and up vectors. You will likely need to refer to the class
notes to do this. It is likely to help to dene a uvw coordinate frame
(as 3 vectors), and to build up an auxiliary 4 4 matrix M which is
returned as the result of this function. Consult class notes and
lectures for this part.
3) A hint for what these two arguments "eye" and "up" mean should be in your class notes and lectures.
4) Another hint is to "define a uvw coordinate frame (as three vectors), and build up an auxiliary 4x4 matrix ... which is returned as a result...".
5) A final hint:
Q: What's the difference between an OpenGL mat3 and mat4?
A:
What extractly mat3(a mat4 matrix) statement in glsl do?
mat3(MVI) * normal
Returns the upper 3x3 matrix from the 4x4 matrix and multiplies the
normal by that. This matrix is called the 'normal matrix'. You use
this to bring your normals from world space to eye space.
The reason why the original matrix is 4x4 and not 3x3 is because 4x4
matrices let you do affine transformations and contain useful
information for perspective rendering. But to take a normal from world
space to eye space, you just need the 3x3 model view matrix.