# Computing Points in 3D Space

I am working on a project for my 3D Graphics class. The project is built with C++ and OpenGL / Glut. Basically, I create a horizontal rectangle window, subdivided into two squares. On the left, I have a two dimensional coordinate plane, which allows the users to point and click and define a profile 'curve'. I then need to wrap this curve around the Y-axis $n$ number of times.

So, would anyone be able to guide me as to how I would use Trigonometry to calculate the $X$ and $Z$ values of the successive points? If for example, a user clicks and creates the point:

$(1, 1, 0)$

And their sweep resolution ($n$) is set to, say, $10$, then I need to redraw that point every $36$ ($360/10$) degrees around the Y-axis.

Am I correct in assuming that Trigonometry will help me here? If so, can someone please enlighten me a bit as to how to calculate the location of a translated point in 3D space? It's been a while since I took Trig, and I don't believe we ever left 2D space.

EDIT: I attempted to use:

$x'=x\cos\theta-z\sin\theta$

$y'=y$

$z'=x\sin\theta+z\cos\theta$

, as per my understanding of AMPerrine's answer, and I don't think it worked as I'd hoped:

// this is in a loop

// setup the new angle
double angle = i>0 ? (360/sweepResolutionMod)*i : 0;

angle = angle * (M_PI/180);

// for each point...
for( int i=0; i<clickedPoints.size(); i++ )
{
// initial point, normalized
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;

// log the initial point
cout << "(" << tempX << ", " << tempY << ", 0.0) by " << angle << " radians = ";

// generate the new point
GLfloat newX = (tempX * cos(angle)) - (tempZ * sin(angle));
GLfloat newY = tempY;
GLfloat newZ = (tempX * sin(angle)) - (tempZ * cos(angle));

// log the new point
cout << "(" << newX << ", " << newY << ", " << newZ << ")\n";

// render the new point
glVertex3d(newX, newY, newZ);
}


This produces no screen output, but console output of:

(0.048, -0.296, 0.0) by 0 radians = (0.048, -0.296, 0)
(0.376, -0.508, 0.0) by 0 radians = (0.376, -0.508, 0)
(0.72, -0.204, 0.0) by 0 radians = (0.72, -0.204, 0)
(0.652, 0.176, 0.0) by 0 radians = (0.652, 0.176, 0)
(0.368, 0.504, 0.0) by 0 radians = (0.368, 0.504, 0)

(0.048, -0.296, 0.0) by 0.628319 radians = (0.0388328, -0.296, 0.0282137)
(0.376, -0.508, 0.0) by 0.628319 radians = (0.30419, -0.508, 0.221007)
(0.72, -0.204, 0.0) by 0.628319 radians = (0.582492, -0.204, 0.423205)
(0.652, 0.176, 0.0) by 0.628319 radians = (0.527479, 0.176, 0.383236)
(0.368, 0.504, 0.0) by 0.628319 radians = (0.297718, 0.504, 0.216305)

(0.048, -0.296, 0.0) by 1.25664 radians = (0.0148328, -0.296, 0.0456507)
(0.376, -0.508, 0.0) by 1.25664 radians = (0.11619, -0.508, 0.357597)
(0.72, -0.204, 0.0) by 1.25664 radians = (0.222492, -0.204, 0.684761)
(0.652, 0.176, 0.0) by 1.25664 radians = (0.201479, 0.176, 0.620089)
(0.368, 0.504, 0.0) by 1.25664 radians = (0.113718, 0.504, 0.349989)

...

(0.048, -0.296, 0.0) by 6.28319 radians = (0.048, -0.296, -1.17566e-17)
(0.376, -0.508, 0.0) by 6.28319 radians = (0.376, -0.508, -9.20934e-17)
(0.72, -0.204, 0.0) by 6.28319 radians = (0.72, -0.204, -1.76349e-16)
(0.652, 0.176, 0.0) by 6.28319 radians = (0.652, 0.176, -1.59694e-16)
(0.368, 0.504, 0.0) by 6.28319 radians = (0.368, 0.504, -9.0134e-17)


I'm not sure what exactly is going on here.

EDIT 2: Updated loop to use radians.

FINAL EDIT (for future generations!):

Here is what I finally got working, after discussing some linear algebra with a teacher at college:

void displayPersp(void)
{
glClear(GL_COLOR_BUFFER_BIT);

gluLookAt (-2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);

glMatrixMode (GL_MODELVIEW);

// draw the axis
glBegin(GL_LINES);
// x
glVertex3f(500.0, 0.0, 0.0);
glVertex3f(-500.0, 0.0, 0.0);
// y
glVertex3f(0.0, -500.0, 0.0);
glVertex3f(0.0, 500.0, 0.0);
// z
glVertex3f(0.0, 0.0, -500.0);
glVertex3f(0.0, 0.0, 500.0);

glEnd();

cout << endl;

double previousTheta = 0.0;

for( int i=0; i<=sweepResolutionMod; i++ )
{
double theta = i>0 ? (360/sweepResolutionMod)*i : 0;

theta = theta * (M_PI/180);

if( clickedPoints.size() > 1 )
{
// the 'vertical' piece
glBegin(GL_LINE_STRIP);

for(int i=0; i<clickedPoints.size(); i++ )
{
// normalize
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;

// new points
GLfloat newX = ( tempX * cos(theta) ) + ( tempZ * sin(theta) );
GLfloat newY = tempY;
GLfloat newZ = ( tempZ * cos(theta) ) - ( tempX * sin(theta) );

glVertex3f(newX, newY, newZ);
}

glEnd();

// the 'horizontal' piece
if( previousTheta != theta )
{
glBegin(GL_LINES);

for(int i=0; i<clickedPoints.size(); i++ )
{
// normalize
GLfloat tempX = (clickedPoints[i].x-250)/250;
GLfloat tempY = (clickedPoints[i].y-250)/250;
GLfloat tempZ = 0.0;

// new points
GLfloat newX = ( tempX * cos(theta) ) + ( tempZ * sin(theta) );
GLfloat newY = tempY;
GLfloat newZ = ( tempZ * cos(theta) ) - ( tempX * sin(theta) );

// previous points
GLfloat previousX = ( tempX * cos(previousTheta) ) + ( tempZ * sin(previousTheta) );
GLfloat previousY = tempY;
GLfloat previousZ = ( tempZ * cos(previousTheta) ) - ( tempX * sin(previousTheta) );

// horizontal component
glVertex3f(newX, newY, newZ);
glVertex3f(previousX, previousY, previousZ);
}

glEnd();
}
}

previousTheta = theta;
}

glutSwapBuffers();
}

-
Are these points supposed to be in the same horizontal plane as the original? In that case it's still a 2D problem ($y$ is constant). – AMPerrine Oct 26 '11 at 2:29
@AMPerrine, No. I should have clarified. The left subwindow is a 2 dimensional x/y grid. The right window is a 3D perspective view. So you define a profile curve in terms of x and y (z=0), and I then wrap that curve around the y axis every 360/n degrees, in 3D space. Essentially creating a solid object from a profile curve. Think a single slice of the right mirrored half of a wine glass. – Josh Oct 26 '11 at 2:32
Rotating by 360 degrees is supposed to be the same as "do nothing"... – J. M. Oct 26 '11 at 14:43
@J.M.: I know that, however, it is not doing that. – Josh Oct 26 '11 at 14:55
I think I'd need to see those results to try to diagnose the problem. However if you are not converting to radians it has no chance of working at all--GIGO and all that. – AMPerrine Oct 26 '11 at 15:41

Each point in the curve can be rotated about the $y$-axis by an angle $\theta$ using the following:

$x'=x\cos\theta-z\sin\theta$

$y'=y$

$z'=x\sin\theta+z\cos\theta$

But if $z$ is always zero this of course becomes even simpler.

-
This is in 3D space, so Z is not always zero. So this will go directly from (x, y, z) to a rotated (x, y, z)? No intermediaries? I ask because elsewhere it was suggested that I convert to cylindrical coordinates to do the rotation, then back to euclidean coordinates to render, and I just wanted to make sure your answer here does indeed maintain the point in the manner of (x, y, z). – Josh Oct 26 '11 at 3:01
The formula given will work for rotating around the $y$-axis, and will give the same results as those conversions. I was originally going to suggest converting to polar before thinking about it further. From my understanding the original point is always of the form $(x,y,0)$. In that case you can drop off the $z$ terms. – AMPerrine Oct 26 '11 at 3:06
I'm confused as to why the Z coordinate is irrelevant. If my point starts at (1, 1, 0), and I rotate it, say, 45 degrees around the Y axis, my new point should most definitely have a change in Z, right? – Josh Oct 26 '11 at 3:09
Your new point will have a $z$-coordinate of $x\sin\theta$. If you choose to rotate that point again, you will need the full formula. But I would prefer to rotate the original point by 36, 72, 108, etc. degrees to generate the full set of points (for precision reasons). – AMPerrine Oct 26 '11 at 3:12
Ah, so you're saying it will only yield a Z of zero on the first iteration. Which makes sense, because the first point would be on the z=0. And yes, I definitely plan on calculating the points off of the initial point with an incremented $\theta$ to preserve accuracy. I'll give this a go in a bit, and report back. Thanks! – Josh Oct 26 '11 at 3:17