Take the 2-minute tour ×
Mathematics Stack Exchange is a question and answer site for people studying math at any level and professionals in related fields. It's 100% free, no registration required.

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);
   glLoadIdentity ();  

   // 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();
}
share|improve this question
    
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
1  
@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
1  
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
show 5 more comments

1 Answer

up vote 2 down vote accepted

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.

share|improve this answer
    
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
show 4 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.