scaling is moving the object - c++

Video Link for the issue.
https://www.youtube.com/watch?v=iqX1RPo4NDE&feature=youtu.be
This is what i want to attain.
https://www.youtube.com/watch?v=bWwYV0VhXqs
Here after scaling the object i can move pivot independently , position of the pivot does not affect the position of the object.
These are my matrices.
when i move the pivot point to one unit in x and if the scaling is set to 1 than everthing works fine.
the pivot point has moved to one unit and the cube has stayed in its position.
But when i first scale the object to 0.5 and than move the pivot point than the cube follows the pivot point , which should not be he case as i am only moving pivot point.
Please help me with this , how can i keep the cube in position.
Though i am moving the axis not the cube so the cube should stay in original position.
glm::mat4x4 Container::GetPositionMatrix()
{
// posx is the x position of the object.
// posy is the y position of the object.
// posz is the y position of the object.
glm::mat4 TransformationPosition = glm::translate(glm::mat4x4(1.0),
glm::vec3(posx, posy, posz ));
return TransformationPosition;
}
glm::mat4x4 Container::GetRotationMatrix()
{
// posx is the x positon of the object
// pivotx is the x position on the pivot point
// rotx is the x rotation of the object
glm::vec3 pivotVector(posx - pivotx, posy - pivoty, posz - pivotz);
glm::mat4 TransPivot = glm::translate(glm::mat4x4(1.0f), pivotVector);
glm::mat4 TransPivotInverse = glm::translate(glm::mat4x4(1.0f),
glm::vec3( -pivotVector.x , -pivotVector.y , -pivotVector.z));
glm::mat4 TransformationRotation(1.0);
TransformationRotation = glm::rotate(TransformationRotation,
glm::radians(rotx), glm::vec3(1.0, 0.0, 0.0));
TransformationRotation = glm::rotate(TransformationRotation,
glm::radians(roty), glm::vec3(0.0, 1.0, 0.0));
TransformationRotation = glm::rotate(TransformationRotation,
glm::radians(rotz ), glm::vec3(0.0, 0.0, 1.0));
return TransPivotInverse * TransformationRotation * TransPivot;
}
glm::mat4x4 Container::GetScalingMatrix()
{
// posx is the x positon of the object
// pivotx is the x position on the pivot point
// scax is the x scaling of the object
glm::vec3 pivotVector(posx - pivotx, posy - pivoty, posz - pivotz);
glm::mat4 TransPivot = glm::translate(glm::mat4x4(1.0f), pivotVector);
glm::mat4 TransPivotInverse = glm::translate(glm::mat4x4(1.0f),
glm::vec3(-pivotVector.x, -pivotVector.y, -pivotVector.z));
glm::mat4 TransformationScale = glm::scale(glm::mat4x4(1.0 ),
glm::vec3(scax, scay, scaz));
return TransPivotInverse * TransformationScale * TransPivot;
}
final matrix for the Object position.
TransformationPosition * TransformationRotation * TransformationScaling
This is my final matrix for the pivot point
PivotPointPosition = MatrixContainerPosition * MatrixPivotPointPosition *
MatrixRotationContainer * MatrixScaleContainer

The object should be orientated and located as follows:
The reference point (pivotx, pivoty, pivotz) is a point in object space.
The object has to be scaled (scax, scay, scaz) and rotated (rotx, roty, rotz) relative to the reference point (pivotx, pivoty, pivotz).
The point (posx, posy, posz) defines the position of the object in the scene, where the reference point has finally to be placed.
Do the following steps:
Scale the object to the desired size, with respect to the reference point:
glm::mat4 GetScalingMatrix()
{
glm::vec3 refVector(pivotx, pivoty, pivotz);
glm::mat4 TransRefToOrigin = glm::translate(glm::mat4(1.0f), -refVector);
glm::mat4 TransRefFromOrigin = glm::translate(glm::mat4(1.0f), refVector);
glm::vec3 scale = glm::vec3(scax, scay, scaz);
glm::mat4 TransformationScale = glm::scale(glm::mat4(1.0), scale);
return TransRefFromOrigin * TransformationScale * TransRefToOrigin;
}
Rotate the scaled object around the pivot, like in the answer to one of your previous questions (How to use Pivot Point in Transformations):
glm::mat4 GetRotationMatrix()
{
glm::vec3 pivotVector(pivotx, pivoty, pivotz);
glm::mat4 TransPivotToOrigin = glm::translate(glm::mat4(1.0f), -pivotVector);
glm::mat4 TransPivotFromOrigin = glm::translate(glm::mat4(1.0f), pivotVector);
glm::mat4 TransformationRotation(1.0);
TransformationRotation = glm::rotate(TransformationRotation,
glm::radians(rotx), glm::vec3(1.0, 0.0, 0.0));
TransformationRotation = glm::rotate(TransformationRotation,
glm::radians(roty), glm::vec3(0.0, 1.0, 0.0));
TransformationRotation = glm::rotate(TransformationRotation,
glm::radians(rotz), glm::vec3(0.0, 0.0, 1.0));
return TransPivotFromOrigin * TransformationRotation * TransPivotToOrigin;
}
Move the scaled and rotated object to its final position (posx, posy, posz).
glm::mat4 GetPositionMatrix()
{
glm::vec3 trans = glm::vec3(posx-pivotx, posy-pivoty, posz-pivotz);
glm::mat4 TransformationPosition = glm::translate(glm::mat4(1.0), trans);
return TransformationPosition;
}
The order matters:
glm::mat4 model = GetPositionMatrix() * GetRotationMatrix() * GetScalingMatrix();
All this can be simplified:
// translate "pivot" to origin
glm::mat4 ref2originM = glm::translate(glm::mat4(1.0f), -glm::vec3(pivotx, pivoty, pivotz));
// scale
glm::mat4 scaleM = glm::scale(glm::mat4(1.0), glm::vec3(scax, scay, scaz));
// rotate
glm::mat4 rotationM(1.0);
rotationM = glm::rotate(rotationM, glm::radians(rotx), glm::vec3(1.0, 0.0, 0.0));
rotationM = glm::rotate(rotationM, glm::radians(roty), glm::vec3(0.0, 1.0, 0.0));
rotationM = glm::rotate(rotationM, glm::radians(rotz), glm::vec3(0.0, 0.0, 1.0));
// translate to "pos"
glm::mat4 origin2posM = glm::translate(glm::mat4(1.0), glm::vec3(posx, posy, posz));
// concatenate matrices
glm::mat4 model = origin2posM * rotationM * scaleM * ref2originM;

Related

Rotating a 3D cube using opengl glm

I create a cube like normal using 8 vertex points that outline a cube and use indices to draw each individual triangle. However, when I create my camera matrix and rotate it using the lookat function with glm it rotates the entire screen positions not world positions.
glm::mat4 Projection = glm::mat4(1);
Projection = glm::perspective(glm::radians(60.0f), (float)window_width / (float)window_hight, 0.1f, 100.0f);
const float radius = 10.0f;
float camX = sin(glfwGetTime()) * radius;
float camZ = cos(glfwGetTime()) * radius;
glm::mat4 View = glm::mat4(1);
View = glm::lookAt(
glm::vec3(camX, 0, camZ),
glm::vec3(0, 0, 0),
glm::vec3(0, 1, 0)
);
glm::mat4 Model = glm::mat4(1);
glm::mat4 mvp = Projection * View * Model;
Then in glsl:
uniform mat4 camera_mat4
void main()
{
vec4 pos = vec4(vertexPosition_modelspace, 1.0) * camera_mat4;
gl_Position.xyzw = pos;
}
Example: GLM rotating screen coordinates not cube

compute a quaternion then convert it to matrix, but when i multiply this matrix it becomes very weird

i want to rotate a cube so first i compute a quaternion, convert it into a rotatematrix, then multiplies it with the vertex, is that right?
i did that with glm.hpp, but the rotation of the cube is very weird when the rotationaxis was not (0,1,0) or (1,0,1) or (0,0,1).
the code goes like this:
glm::vec3 rotationAxis = glm::normalize((glm::cross(glm::vec3(0,1,1), glm::vec3(1,1,0))));
GLfloat cosAngle = glm::dot(glm::normalize(glm::vec3(0, 1, 1)), glm::normalize(glm::vec3(1, 1, 0)));
GLfloat s = glm::sqrt((1 + cosAngle) * 2);
GLfloat invs = 1 / s;
glm::quat rotationQuat = glm::quat(
s * 0.5f,
rotationAxis.x * invs,
rotationAxis.y * invs,
rotationAxis.z * invs);
glm::mat4 matTemp = glm::mat4_cast(rotationQuat);
ArcballMatrix = matTemp*ArcballMatrix;
and the vertexshader goes like this:
gl_Position = projection * view * ArcballMatrix * vec4(vertexPosition, 1.0f);
did i miss something?

Transform camera OpenGL

How can I transform the camera left around the interface? Need to rotate the "eye" vector around the "up" vector!?.
void Transform::left(float degrees, vec3& eye, vec3& up) {
float c = cosf(degrees * (pi / 180));
float s = sinf(degrees * (pi / 180));
}
mat4 Transform::lookAt(vec3 eye, vec3 up) {
glm::mat4 view = glm::lookAt(
glm::vec3(eye.x, eye.y, eye.z),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(up.x, up.y, up.z)
);
return view;
}
Calculate a rotated eye vector by multiplying the rotation vector by the original, unrotated, eye vector and pass that into the lookAt function.
float rotX = cosf(angle * (pi / 180));
float rotY = sinf(angle * (pi / 180));
glm::vec3 rotatedEye = glm::vec3(eye.x * rotX , eye.y * rotY, eye.z)
glam::mat4 view = lookAt(rotatedEye, up);
Note that each time your camera vectors change you will need to calculate a new view matrix.

Rotating an object with quaternion

I have a question in regards to using quaternions for the rotation of my graphics object.
I have a Transform class which has the following constructor with default parameters:
Transform(const glm::vec3& pos = glm::vec3(0.0), const glm::quat& rot = glm::quat(1.0, 0.0, 0.0, 0.0),
const glm::vec3& scale = glm::vec3(1.0))
{
m_pos = pos;
m_rot = rot;
m_scale = scale;
}
In my Transform class calculate the MVP as follows:
glm::mat4 Transform::GetModelMatrix() const
{
glm::mat4 translate = glm::translate(glm::mat4(1.0), m_pos);
glm::mat4 rotate = glm::mat4_cast(m_rot);
glm::mat4 scale = glm::scale(glm::mat4(1.0), m_scale);
return translate * rotate * scale;
}
The issue I'm facing is that when I use const glm::quat& rot = glm::quat(1.0, 0.0, 0.0, 0.0) my object appears normal on screen. The following image shows it:
However if I try to use for example const glm::quat& rot = glm::quat(glm::radians(90.0f), 0.0, 1.0, 0.0) (rotating on y axis by 90 degrees) my object appears as if it has been scaled. The following image shows it:
I can't figure out what is causing it to become like this when I try to rotate it. Am I missing something important?
If it's of any relevance, the following is how I calculate my view matrix:
glm::mat4 Camera::GetView() const
{
glm::mat4 view = glm::lookAt(m_pos, m_pos + m_forward, m_up);
return view;
}
AFAIK you can init a glm::quat using:
glm::vec3 angles(degToRad(rotx), degToRad(roty), degToRad(rotz));
glm::quat rotation(angles);
Where rotx, roty, rotz are the rotation angles around x, y and z axis and degToRad converts angles to radians. Therefore for your case:
glm::vec3 angles(degToRad(0), degToRad(90), degToRad(0));
glm::quat rotation(angles);
Regards

Third person camera flips on loop

float FoV = initialFoV - 5;
//(*it)->getParent()->getPosition() + (*it)->getOrientationQuat() * (*it)->getPosition();
glm::vec3 lookAt = carPosition;
glm::vec3 temp;
temp.x = spaceShip->orientation.y;
temp.y = spaceShip->orientation.x;
temp.z = spaceShip->orientation.z;
glm::vec3 cameraposition = carPosition + glm::quat(temp) * position;
ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);
ViewMatrix = glm::lookAt(
cameraposition, // Camera is here
lookAt, // and looks here : at the same position, plus "direction"
vec3(0, 1, 0) // Head is up (set to 0,-1,0 to look upside-down)
);
As you can see we build a third person camera, this camera is chasing our airplane. But when our airplane makes a looping, the camera will flip halfway through. So everything is upside down. How can we make sure the camera won't flip?
We fixed it by calculating the up instead of setting it.
glm::vec3 cameraposition = carPosition + glm::quat(temp) * position;
ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 RotationMatrix = eulerAngleYXZ(carDirection.x, carDirection.y, carDirection.z);
glm::vec4 up = RotationMatrix * glm::vec4(0,1,0,0);
glm::vec3 up3(up);
ViewMatrix = glm::lookAt(
cameraposition, // Camera is here
lookAt, // and looks here : at the same position, plus "direction"
up3 // Head is up (set to 0,-1,0 to look upside-down)
);