Orbiting object around orbiting object - c++

How do I get to orbit green circle around orange and blue around green ?
I found many solutions which works fine with rotating around static point(int this case orange circle) but didn't find any good maths equation which would work for both static and moving points.
angle += sunRot;
if(angle > 360.0f)
{
angle = 0.0f;
}
float radian = glm::radians(angle);
float radius = glm::distance(position, rotCenter);
float x = rotCenter.x + (radius * cosf(radian));
float z = rotCenter.z + (radius * sinf(radian));
glm::vec3 newPos = glm::vec3(x, 0, z);
setPosition(newPos);
Here is what I'm trying to achieve (Thanks to #George Profenza for sharing link)

Base all your calculations on the radius and angle of the current object where possible and store the radius and angle with the object.
In particular, do not calculate the radius based on the x/y coordinates in every iteration: If the base object has moved between steps, your calculated radius will be slightly off and the error will accumulate.

You should be able to nest coordinate spaces using opengl using glPushMatrix(), glPopMatrix() calls. Here's a basic example(press mouse to see coordinate spaces).
The syntax isn't c++, but it's easy to see what I mean.
You can do this multiple ways:
polar coordinate formula
manually multiplying transformation matrices
simply using push/pop matrix calls (along with translate/rotate where needed), which does the matrix multiplication for you behind the scenes.
Just in case you want to try the polar coordinate formula:
x = cos(angle) * radius
y = sin(angle) * radius
Where angle is the current rotation of a circle and the radius is it's distance from the centre of rotation.

Related

How to get angle between two vectors in 3D

I have two objects one sphere and a cone. I want cone to always face the sphere as shown in the images.
we have constructed the cone in local coordinate system in such a way, that the tip of the cone points upward the y-axis and the center is at the origin (0,0,0).
The angle between two 3D vectors would be
float fAngle = std::acos(dot(sphereVector, coneVector) / magnitude(sphereVector * magnitude(coneVector)));
For cone to be always facing the sphere it need to be rotated in all three axis based on the position of the sphere but i am getting only one angle from the maths formula.
How do i calculate all the three angles for the cone that it is always perpendicular to the sphere.
First, you need the vector where the cone should point to:
direction = center_cone - center_sphere;
Then, we assume, that you've constructed your cone in the local coordinate system in such a way, that the tip of the cone points upward the y-axis and the center is at the origin (0,0,0).
The axises to rotate are:
x_axis(1, 0, 0);
y_axis(0, 1, 0);
z_axis(0, 0, 1);
Now, you simply have to project the axises to the direction vector to get the 3 angles.
Example:
float angle(vec a, vec b)
{
return acos(dot(a, b) / (magnitude(a) * magnitude(b)));
}
vec direction = normalize(center_cone - center_sphere);
float x_rot = angle(x_axis, direction);
float y_rot = angle(y_axis, direction);
float z_rot = angle(z_axis, direction);

Why is there a difference of 90 degrees between rotation and direction?

Firstly, this problem is not unique to the current project I am currently working on and has happened several times before. Here is the problem.
I have a Triangle struct. olc::vf2d is a vector class with x and y components.
struct Triangle
{
olc::vf2d p1 = { 0.0f, -10.0f };
olc::vf2d p2 = { -5.0f, 5.0f };
olc::vf2d p3 = { 5.0f, 5.0f };
};
I create a triangle along with position and angle for it.
Triangle triangle
olc::vf2d position = { 0.0f, 0.0f };
float angle = 0.0f;
Now, I rotate (and offset) the triangle as so:
float x1 = triangle.p1.x * cosf(angle) - triangle.p1.y * sinf(-angle) + position.x;
float y1 = triangle.p1.x * sinf(-angle) + triangle.p1.y * cosf(angle) + position.y;
float x2 = triangle.p2.x * cosf(angle) - triangle.p2.y * sinf(-angle) + position.x;
float y2 = triangle.p2.x * sinf(-angle) + triangle.p2.y * cosf(angle) + position.y;
float x3 = triangle.p3.x * cosf(angle) - triangle.p3.y * sinf(-angle) + position.x;
float y3 = triangle.p3.x * sinf(-angle) + triangle.p3.y * cosf(angle) + position.y;
When I increase the angle every frame and draw it, it rotates and works as expected. But now here is the problem. When I try to calculate the direction for it to move towards, like this:
position.x -= cosf(angle) * elapsedTime;
position.y -= sinf(-angle) * elapsedTime;
It moves, but is look 90 degrees off from the rotation. Example, it is facing directly up and is moving to the right.
Up until this point, I have always solved this problem by using different angles values, i.e taking away 3.14159f / 2.0f radians from angle used in direction calculation
position.x -= cosf(angle - (3.14159f / 2.0f));
position.y -= sinf(-angle - (3.14159f / 2.0f));
or vice-versa and this fixes the problem (now it moves in the direction it is facing).
But now I want to know exactly why this happens and a proper way to solve this problem, many thanks.
There are some missing items to be able to diagnose. You have to have some kind of coordinate system. Is it a right-handed coordinate system or a left-handed coordinate system. You determine this by taking your X/Y origin, and visualizing your hand over it with your thumb pointing towards you. When the X-axis rotates counter-clockwise, i.e. the way the fingers of your right hand curl when held as visualized, does the positive X-axis move towards the positive Y-axis (right-handed system) or does it move towards the negative Y-axis (left-handed system).
As an example, most algebra graphing is done with a right-handed system, but on the raw pixels of a monitor positive Y is down instead of up as typically seen in algebra.
Direction of motion should be independent of rotation angle -- unless you really want them coupled, which is not typically the case.
Using two different variables for direction-of-motion and angle-of-rotation will allow you to visually and mentally decouple the two and see better what is happening.
Now, typically -- think algebra -- angles for rotation are measured starting from "east" -- pointing to the right -- is zero degrees, "north" is 90 degrees -- pointing up -- and so on.
If you want to move "straight up" you are not moving in the zero-degree direction, but rather in the 90-degree direction. So if your rotation is zero degrees but movement is desired to be "straight up" like the triangle points, then you should be using a 90-degree offset for your movement versus your rotation.
If you decouple rotation and motion, this behavior is much easier to understand and observe.

Arcball Camera: how to obtain right, direction and up

I'm trying to implement a camera that follows a moving object. I've implemented these functions:
void Camera::espheric_yaw(float degrees, glm::vec3 center_point)
{
float lim_yaw = glm::radians(89.0f);
float radians = glm::radians(degrees);
absoluteYaw += radians;
... clamp absoluteYaw
float radius = 10.0f;
float camX = cos(absoluteYaw) * cos(absoluteRoll) * radius;
float camY = sin(absoluteRoll)* radius;
float camZ = sin(absoluteYaw) * cos(absoluteRoll) * radius;
eyes.x = camX;
eyes.y = camY;
eyes.z = camZ;
lookAt = center_point;
view = glm::normalize(lookAt - eyes);
up = glm::vec3(0, 1, 0);
right = glm::normalize(glm::cross(view, up));
}
I want to use this function (and the pitch version) for a camera that follows a moving 3d model. Right now, it works when the center_point is the (0,1,0). I think i'm getting the position right but the up vector is clearly not always (0,1,0).
How can I get my up, view and right vector for the camera? And then, if I update the eyes position of the camera this way, how will my camera move when the other object (centered at center_position parameter) moves?
The idea is to update this each time I have mouse input with centered_value = center of the moving object. Then use gluLookAt with view, eyes and up values of my camera (and lookAt which will be eyes+view).
Following a moving object is matter of pointing the camera to that object. This is what typical lookAt function does. See the maths here and then use glm::lookAt().
The 'Arcball' technic is for rotating with the mouse. See some maths here.
The idea is to get two vectors (first, second) from positions on screen. For each vector, X,Y are taking depending on pixels "travelled" by mouse and the size of the window. Z is calculated by 'trackball' maths. With these two vectors (after normalizing them), its cross product gives the axis of rotation in camera coordinates, and its dot product gives the angle. Now, you can rotate the camera by glm::rotate()
If you go another route (e.g. calculating camera matrix on your own), then the "up" direction of the camera must be updated by yourself. Remember it's perpendicular to the other two axis of the camera.

Rotation About Incorrect Axes (First-Person Camera Implementation)

I am implementing a first-person camera to move about a scene using the arrow keys on my keyboard. It seems to work OK when I am only rotating about a single axis (X or Y), however if I am rotating about both axes it also gives me rotation about the third, Z, axis. I am fairly sure that the problem is that my camera does not rotate about global axis but instead its local ones, resulting in 'roll' when I just want yaw and pitch. In my code I deduce a forward vector from the X and Y rotation, stored in two variables. The most relevant code snippet is as follows:
glm::mat4 CameraManager::rotateWorld(float angle, glm::vec3 rot){
static float yRot = 0.0f;
static float xRot = 0.0f;
glm::vec3 degrees = rot * angle;
glm::vec3 radians = glm::vec3(degrees.x * (M_PI/180.0f),
degrees.y * (M_PI/180.0f),
degrees.z * (M_PI/180.0f));
yRot += radians.y;
xRot += radians.x;
forwardVector = glm::vec3(sinf(yRot) * cosf(xRot),
-sinf(xRot),
-cosf(yRot) * cosf(xRot));
return glm::rotate(glm::mat4(1.0f), angle, rot);
}
the rotateWorld function is complemented by the moveForwardfunction:
glm::mat4 CameraManager::moveForward(float dist){
glm::vec3 translation = forwardVector/glm::vec3(sqrt(forwardVector.x * forwardVector.x +
forwardVector.y * forwardVector.y +
forwardVector.z * forwardVector.z)) * dist;
return glm::translate(glm::mat4(1.0f), -translation);
}
where yRot is equivalent to yaw and xRot is equivalent to pitch.
The rotation and translation matrices are simply multiplied together in the main section of the program.
I then go on to multiply a distance d by this vector to update the position.
xRot and yRot are static doubles that get incremented/decremented when the user presses an arrow key.
When the program starts, this is the view. The plane and the monkey head are facing the 'right way' up. incrementing/decrementing the pitch and yaw individually work as expected. But when I, say, increase the pitch and then yaw, the scene flips sideways! (Picture below.) Any ideas how to fix this?
If I understand you correctly, the problem you're experiencing is that your "up" vector is not always pointing vertically upwards with respect to the intended Y axis of your viewing plane.
Determining a correct "up" vector usually requires a combination of cross product operations against the vector you have against the viewport's X and Y axes.
You may find some useful hints in the documentation for the gluLookAt function whose purpose is to calculate a view matrix with desired orientation (i.e. without roll) given an eye position and the coordinates of the intended centre of the field.

Calculate points in coordinate systems in C++

I have two points on circle. I know degree from center and coordinates of one point. I want find coordinate of the other point. I think need multiply by rotation matrix to find point. How can i do in c++? Is there any function for it?
you can calculate it directly using
x cos(angle) - y sin (angle )
x sin(angle) + y cos (angle )
the cos and sin functions are available in math.h
note that the rotation will be in anti clockwise direction
and the rotation will be about the origin. 'angle' should be in radians.
if the center of the circle is not located at origin then you'll have to first shift the origin to the center of the circle , apply rotation and shift the origin back again to get the other point