OpenGL-绕Y轴旋转“曲线" [英] OpenGL - Rotate a 'Curve' About the Y-Axis

查看:100
本文介绍了OpenGL-绕Y轴旋转“曲线"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据我对Math Stackexchange的问题:

我正在为我的3D图形课程设计一个项目.该项目使用C ++和OpenGL/Glut构建.基本上,我创建了一个水平矩形窗口,分为两个正方形.在左侧,我有一个二维坐标平面,允许用户指向和单击并定义轮廓曲线".然后,我需要将此曲线绕Y轴缠绕n次.

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.

那么,有谁能指导我如何使用三角函数来计算连续点的X和Z值?例如,如果用户单击并创建该点:

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)

并将其扫描分辨率(n)设置为10,然后我需要绕Y轴每36(360/10)度重画一次该点.

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.

我是否可以假设三角学在这里对我有帮助?如果是这样,有人可以请我启发一下如何计算平移点在3D空间中的位置吗?自从上手Trig以来已经有一段时间了,我不相信我们曾经离开过2D空间.

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.

编辑:我尝试使用:

x'=xcos(theta)-zsin(theta)

y'=y

z'=xsin(theta)+zcos(theta)

,根据我对AMPerrine的 answer 的理解,而且我认为它不像我希望的那样工作:

, 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, but I'm having a terrible time trying to figure it out, so please don't think I'm trying to get double reputation or anything, I'm just really stuck.

编辑:这是我的透视图子视图的整个显示例程:

EDIT 2: Here is my whole display routine for my perspective subview:

void displayPersp(void)
{
    glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();  

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

    // 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;

    // loop as many number of times as we are going to draw the points around the Y-Axis
    for( int i=0; i<=sweepResolutionMod; i++ )
    {
        cout << endl;

        // 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++ )
        {
            GLfloat tempX = (clickedPoints[i].x-250)/250;
            GLfloat tempY = (clickedPoints[i].y-250)/250;
            GLfloat tempZ = 0.0;

            cout << "(" << tempX << ", " << tempY << ", 0.0) by " << angle << " degrees = ";

            GLfloat newX = (tempX * cos(angle)) - (tempZ * sin(angle));
            GLfloat newY = tempY;
            GLfloat newZ = (tempX * sin(angle)) - (tempZ * cos(angle));

            cout << "(" << newX << ", " << newY << ", " << newZ << ")\n";

            glVertex3d(newX, newY, newZ);
        }

        // the following was my old solution, using OpenGL's rotate(), but that
        // didn't allow me to get back the new point's coordinates.

        /*
        glRotatef(angle, 0.0, 1.0, 0.0);

        // draw a line?
        if( clickedPoints.size() > 1 )
        {
            glBegin(GL_LINE_STRIP);

            for(int i=0; i<clickedPoints.size(); i++ )
            {     
                glVertex3f((clickedPoints[i].x-250)/250, (clickedPoints[i].y-250)/250, 0.0);     
            }

            glEnd();
        }

        // everyone gets points
        glBegin(GL_POINTS);

        for(int i=0; i<clickedPoints.size(); i++ )
        { 
            glVertex3f((clickedPoints[i].x-250)/250, (clickedPoints[i].y-250)/250, 0.0);     
        }

        glEnd();
        */
    }


    glutSwapBuffers();
}

这是一个可怕的插图,阐明了我需要做的事情.我知道透视图似乎不对,但是我试图获取的是右侧子视图中的绿色水平线"(这是使用上面注释掉的glRotatef()代码):

EDIT 3: Here is a terrible illustration that illustrates what I need to do. I know the perspective seems off, but what I'm attempting to acquire is the green 'horizontals' in the right subview (this is using the commented out glRotatef() code above):

最终编辑(为子孙后代!):

在与大学老师讨论了线性代数之后,我终于开始工作了:

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

推荐答案

好的,我看到了您遇到的问题-这是我忘记的限制(因此,我之前发布的代码完全错误,根本无法使用).问题是您不允许在glBegin/glEnd对之间调用glRotate -如果这样做,它将设置一个错误标志,并且将不再进行绘制.

Edit 2: Okay, I see the problem you're running into -- it's a limitation I'd forgotten about (so the code I'd posted previously was dead wrong and wouldn't work at all). The problem is that you're not allowed to call glRotate between a glBegin/glEnd pair -- if you do, it'll set an error flag, and no more drawing will be done.

那确实意味着您几乎必须自己处理旋转.幸运的是,这要比您尝试的要简单一些:

That does mean you pretty much have to handle the rotation yourself. Fortunately, that's a bit simpler than you've tried to make it:

static const double pi = 3.1416;

for (int point=0; point<NUM_POINTS; point++) {
    glBegin(GL_LINE_STRIP);
    for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
        double x = cos(theta);
        double z = sin(theta);
        glVertex3d(points[point][0]*x, points[point][1], -1.0-points[point][0]*z);
    }
    glEnd();
}   

按原样,此代码沿Z轴使用-1.0作为旋转中心.显然,您可以将其移动到所需的位置,尽管截头锥体之外的任何内容显然都不会显示.

As-is, this code uses -1.0 along the Z axis as the center of rotation. You can obviously move that where you wish, though anything outside your clipping frustum obviously won't display.

还要注意,要获得线框,您必须分别绘制垂直"线和水平"线,因此代码如下所示:

Also note that to get a wireframe, you'll have to draw both your "vertical", and your "horizontal" lines separately, so the code will look something like this:

for (int point=0; point<NUM_POINTS; point++) {
    glBegin(GL_LINE_STRIP);
    for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
        double x = cos(theta);
        double z = sin(theta);
        glVertex3d(points[point][0]*x, points[point][1], -1.0 - points[point][0]*z);
    }
    glEnd();
}

for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
    glBegin(GL_LINE_STRIP);
    for (int point=0; point<NUM_POINTS; point++) {
        double x = cos(theta);
        double z = sin(theta);
        glVertex3d(points[point][0]*x, points[point][1], -1.0 - points[point][0]*z);
    }
    glEnd();
}

这篇关于OpenGL-绕Y轴旋转“曲线"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆