using spherical coordinates in opengl - c++11

I am trying to plot points around a center point using spherical coordinates. I know this is by far not the most efficient way to plot a sphere in OpenGL but i want to do it as an excersive to understand spherical coordinates better.
I want to step through each point by a certain angle so for this i have a nested for loop itterating through theta 0 - 360 and phi 0-360 and i am attempting to get the Cartesian coordinates of each of these steps and display it as a single point.
so far i have this:
float r = 1.0;
for( float theta = 0.0; theta < 360.0; theta += 10.0){
for(float phi = 0.0; phi < 360.0; phi += 10.0){
float x = r * sin(theta) * cos(phi);
float y = r * sin(theta) * sin(phi);
float z = r * cos(theta);
}
}
i store these points a display them. the display function works fine as i have used it to display other point structure before but for some reason i can't get this to work.
I have also tried converting the angles from degrees to radians:
float rTheta = theta * M_PI * 180.0;
float rPhi = phi * M_PI * 18.0;
as sin() and cos() both use radians but it yields the same results.
Am i doing something wrong and badly misunderstanding something?

In the conversion from degrees to radians of angle x, the correct formula is x * M_PI / 180..

Related

Why is xspeed != 0?

I'm making a game in which the player should move in its facing direction.
So I've come up with this.
int speed = 50;
float rotation = 90;
int speedx = speed * cos(rotation);
int speedy = speed * sin(rotation);
player->move(speedx, speedy);
But the problem is this:cos(90) returns -0.448074 and sin(90) returns 0.893997. They should return 0 and 1.
Does any one of you have an idea why?
Your cos and sin functions are expecting angles in radians, not degrees.
Cosine of 90 radians is -0.448074 as you've found.

How do you add a swirl to an image (image distortion)?

I was trying to figure out how to make a swirl in the photo, tried looking everywhere for what exactly you do to the pixels. I was talking with a friend and we kinda talked about using sine functions for the redirection of pixels?
Let's say you define your swirl using 4 parameters:
X and Y co-ordinates of the center of the swirl
Swirl radius in pixels
Number of twists
Start with a source image and create a destination image with the swirl applied. For each pixel (in the destination image), you need to adjust the pixel co-ordinates based on the swirl and then read a pixel from the source image. To apply the swirl, figure out the distance of the pixel from the center of the swirl and it's angle. Then adjust the angle by an amount based on the number of twists that fades out the further you get from the center until it gets to zero when you get to the swirl radius. Use the new angle to compute the adjusted pixel co-ordinates to read from. In pseudo code it's something like this:
Image src, dest
float swirlX, swirlY, swirlRadius, swirlTwists
for(int y = 0; y < dest.height; y++)
{
for(int x = 0; x < dest.width; x++)
{
// compute the distance and angle from the swirl center:
float pixelX = (float)x - swirlX;
float pixelY = (float)y - swirlY;
float pixelDistance = sqrt((pixelX * pixelX) + (pixelY * pixelY));
float pixelAngle = arc2(pixelY, pixelX);
// work out how much of a swirl to apply (1.0 in the center fading out to 0.0 at the radius):
float swirlAmount = 1.0f - (pixelDistance / swirlRadius);
if(swirlAmount > 0.0f)
{
float twistAngle = swirlTwists * swirlAmount * PI * 2.0;
// adjust the pixel angle and compute the adjusted pixel co-ordinates:
pixelAngle += twistAngle;
pixelX = cos(pixelAngle) * pixelDistance;
pixelY = sin(pixelAngle) * pixelDistance;
}
// read and write the pixel
dest.setPixel(x, y, src.getPixel(swirlX + pixelX, swirlY + pixelY));
}
}

Not getting the correct orientation of the user with respect to Kinect

I am using Microsoft Kinect in a project. One of the task that I have to accomplish is to find the orientation of the user w.r.t the Kinect sensor (when the user turns, the orientation changes)
For this, I am trying to find the angle which the line joining the shoulders makes with the x axis of Kinect.
I have come up with the following code, but it gives me very small angle values, even when I turn almost about 40 degrees.
double vector_x=skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_LEFT].x-skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_RIGHT].x;
double vector_y=skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_LEFT].y-skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_RIGHT].y;
double vector_z=skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_LEFT].z-skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_RIGHT].z;
double len1=sqrtf(vector_x * vector_x + vector_y * vector_y + vector_z * vector_z);
double vector_x1=1.0;
double vector_y1=0.0;
double vector_z1=0.0;
double len2=sqrtf(vector_x1 * vector_x1 + vector_y1 * vector_y1 + vector_z1 * vector_z1);
double dot_product = vector_x * vector_x1 + vector_y * vector_y1 + vector_z * vector_z1;
double angle = dot_product / (len1 * len2);
coor_left=Convert(vector_x)+"\t"+Convert(vector_y)+"\t"+Convert(vector_z)+"\n";
OutputDebugStringA(Convert(acos(angle)).c_str());
When I added the conversion of radians to degrees,
double angle1=angle*180.0/3.14;
I get values form -33 to -57(when I am facing the Kinect) and then to -33 again.
But in reality, it should be negative, then 0 and then positive on the other side. Where am I going wrong?
I solved it myself. I realised that I was finding the angle between incorrect vectors.
All I needed to do was to take the projection of the left and the right shoulders on the x-z plane and then reduce the problem to finding the angle between two vectors in a plane.
Here is what I did:
double CalcAngle(double p1x,double p1y, double p2x,double p2y, double p3x,double p3y, double p4x,double p4y)
{
//
// calculate the angle between the line from p1 to p2
// and the line from p3 to p4
//
double x1 = p1x - p2x;
double y1 = p1y - p2y;
double x2 = p3x - p4x;
double y2 = p3y - p4y;
//
double angle1 , angle2 , angle;
//
if (x1 != 0.0f)
angle1 = atan(y1/x1);
else
angle1 = 3.14159 / 2.0; // 90 degrees
//
if (x2 != 0.0f)
angle2 = atan(y2/x2);
else
angle2 = 3.14159 / 2.0; // 90 degrees
//
angle = fabs(angle2-angle1);
angle = angle * 180.0 / 3.14159; // convert to degrees ???
//
return angle;
}
double myangle=CalcAngle(skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_LEFT].x,skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_LEFT].z,
skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_RIGHT].x,skel.SkeletonPositions[NUI_SKELETON_POSITION_SHOULDER_RIGHT].z,
0,0,1,0);
OutputDebugStringA(Convert(myangle).c_str());
OutputDebugStringA("\n");

interpolate between rotation matrices

i have two rotation matrices that describe arbitrary rotations. (4x4 opengl compatible)
now i want to interpolate between them, so that it follows a radial path from one rotation to the other. think of a camera on a tripod looking one way and then rotating.
if i interpolate every component i get a squeezing result, so i think i need to interpolate only certain components of the matrix. but which ones?
You have to use SLERP for the rotational parts of the matrices, and linear for the other parts. The best way is to turn your matrices into quaternions and use the (simpler) quaternion SLERP: http://en.wikipedia.org/wiki/Slerp.
I suggest reading Graphic Gems II or III,specifically the sections about decomposing matrices into simpler transformations. Here's Spencer W. Thomas' source for this chapter:
http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c
Of course, I suggest you learn how to do this yourself. It's really not that hard, just a lot of annoying algebra. And finally, here's a great paper on how to turn a matrix into a quaternion, and back, by Id software: http://www.mrelusive.com/publications/papers/SIMD-From-Quaternion-to-Matrix-and-Back.pdf
Edit: This is the formula pretty much everyone cites, it's from a 1985 SIGGRAPH paper.
Where:
- qm = interpolated quaternion
- qa = quaternion a (first quaternion to be interpolated between)
- qb = quaternion b (second quaternion to be interpolated between)
- t = a scalar between 0.0 (at qa) and 1.0 (at qb)
- θ is half the angle between qa and qb
Code:
quat slerp(quat qa, quat qb, double t) {
// quaternion to return
quat qm = new quat();
// Calculate angle between them.
double cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
// if qa=qb or qa=-qb then theta = 0 and we can return qa
if (abs(cosHalfTheta) >= 1.0){
qm.w = qa.w;qm.x = qa.x;qm.y = qa.y;qm.z = qa.z;
return qm;
}
// Calculate temporary values.
double halfTheta = acos(cosHalfTheta);
double sinHalfTheta = sqrt(1.0 - cosHalfTheta*cosHalfTheta);
// if theta = 180 degrees then result is not fully defined
// we could rotate around any axis normal to qa or qb
if (fabs(sinHalfTheta) < 0.001){ // fabs is floating point absolute
qm.w = (qa.w * 0.5 + qb.w * 0.5);
qm.x = (qa.x * 0.5 + qb.x * 0.5);
qm.y = (qa.y * 0.5 + qb.y * 0.5);
qm.z = (qa.z * 0.5 + qb.z * 0.5);
return qm;
}
double ratioA = sin((1 - t) * halfTheta) / sinHalfTheta;
double ratioB = sin(t * halfTheta) / sinHalfTheta;
//calculate Quaternion.
qm.w = (qa.w * ratioA + qb.w * ratioB);
qm.x = (qa.x * ratioA + qb.x * ratioB);
qm.y = (qa.y * ratioA + qb.y * ratioB);
qm.z = (qa.z * ratioA + qb.z * ratioB);
return qm;
}
From: http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
You need to convert the matrix into a different representation - quaternions work well for this, and interpolating quaternions is a well-defined operation.

Calculate direction angle from two vectors?

Say I have two 2D vectors, one for an objects current position and one for that objects previous position. How can I work out the angular direction of travel?
This image might help understand what I'm after:
(image) http://files.me.com/james.ingham/crcvmy
The direction vector of travel will be the difference of the two position vectors,
d = (x1, y1) - (x, y) = (x1 - x, y1 - y)
Now when you ask for the direction angle, that depends what direction you want to measure the angle against. Is it against the x axis? Go with Radu's answer. Against an arbitrary vector? See justjeff's answer.
Edit: To get the angle against the y-axis:
tan (theta) = (x1 -x)/(y1 - y)
the tangent of the angle is the ratio of the x-coordinate of the difference vector to the y-coordinate of the difference vector.
So
theta = arctan[(x1 - x)/(y1 - y)]
Where arctan means inverse tangent. Not to be confused with the reciprocal of the tangent, which many people do, since they're both frequently denoted tan^-1. And make sure you know whether you're working in degrees or radians.
If you're in C (or other language that uses the same function set) then you're probably looking for the atan2() function. From your diagram:
double theta = atan2(x1-x, y1-y);
That angle will be from the vertical axis, as you marked, and will be measured in radians (God's own angle unit).
Be careful to use atan2 to avoid quadrant issues and division by zero. That's what it's there for.
float getAngle(CGPoint ptA, CGPoint ptOrigin, CGPoint ptB)
{
CGPoint A = makeVec(ptOrigin, ptA);
CGPoint B = makeVec(ptOrigin, ptB);
// angle with +ve x-axis, in the range (−π, π]
float thetaA = atan2(A.x, A.y);
float thetaB = atan2(B.x, B.y);
float thetaAB = thetaB - thetaA;
// get in range (−π, π]
while (thetaAB <= - M_PI)
thetaAB += 2 * M_PI;
while (thetaAB > M_PI)
thetaAB -= 2 * M_PI;
return thetaAB;
}
However, if you don't care about whether it's a +ve or -ve angle, just use the dot product rule (less CPU load):
float dotProduct(CGPoint p1, CGPoint p2) { return p1.x * p2.x + p1.y * p2.y; }
float getAngle(CGPoint A, CGPoint O, CGPoint B)
{
CGPoint U = makeVec(O, A);
CGPoint V = makeVec(O, B);
float magU = vecGetMag(U);
float magV = vecGetMag(V);
float magUmagV = magU * magV; assert (ABS(magUmagV) > 0.00001);
// U.V = |U| |V| cos t
float cosT = dotProduct(U, V) / magUmagV;
float theta = acos(cosT);
return theta;
}
Note that in either code section above, if one ( or both ) vectors are close to 0 length this is going to fail. So you might want to trap that somehow.
Still not sure what you mean by rotation matrices, but this is a simple case of getting an azimuth from a direction vector.
The complicated answer:
Normally you should pack a few conversion/utility functions with your 2D vectors: one to convert from X,Y (carthesian) to Theta,R (polar coordinates). You should also support basic vector operations like addition, substraction and dot product.
Your answer in this case would be:
double azimuth = (P2 - P1).ToPolarCoordinate().Azimuth;
Where ToPolarCoordinate() and ToCarhtesianCoordinate() are two reciprocal functions switching from one type of vector to another.
The simple one:
double azimuth = acos ((x2-x1)/sqrt((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1));
//then do a quadrant resolution based on the +/- sign of (y2-y1) and (x2-x1)
if (x2-x1)>0 {
if (y2-y1)<0 { azimuth = Pi-azimuth; } //quadrant 2
} else
{ if (y2-y1)> 0 { azimuth = 2*Pi-azimuth;} //quadrant 4
else { azimuth = Pi + azimuth;} //quadrant 3
}

Resources