OpenGL -绕Y轴旋转“曲线”

hjqgdpho  于 12个月前  发布在  其他
关注(0)|答案(3)|浏览(171)
  • 根据我在Math Stackexchange上的question:*

我正在为我的3D图形类做一个项目。这个项目是用C++和OpenGL / Glut构建的。基本上,我创建了一个水平的矩形窗口,细分为两个正方形。在左边,我有一个二维坐标平面,它允许用户指向并单击并定义一个剖面“曲线”。然后我需要将这个曲线绕Y轴缠绕n次。
那么,有人能指导我如何使用三角函数来计算连续点的X和Z值吗?例如,如果用户单击并创建点:
(1,1,0)
并且它们的扫描分辨率(n)设置为,比如说,10,那么我需要围绕Y轴每隔36(360/10)度重新绘制该点。
我假设三角学可以帮助我吗?如果是这样,有人能告诉我一点关于如何计算在3D空间中平移点的位置吗?自从我学习三角学以来已经有一段时间了,我不相信我们曾经离开过2D空间。

编辑:尝试用途:

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

y'=y

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

字符串
根据我对安培瑞恩的回答的理解,我不认为它像我希望的那样起作用:

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


这不会产生屏幕输出,但会产生控制台输出:

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


我不知道到底是怎么回事,但我有一个可怕的时间试图弄清楚,所以请不要认为我试图获得双重声誉或任何东西,我只是真的卡住了。

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

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


编辑3:这里有一个很糟糕的例子来说明我需要做什么。我知道透视图看起来不对,但我试图在右边的子视图中获取绿色的“水平线”(这是使用上面注解掉的glRotatef()代码):
x1c 0d1x的数据

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

这是我在大学里和一位老师讨论了一些线性代数之后,最终得到的工作:

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

rbpvctlc

rbpvctlc1#

看起来你正在尝试构造一个surface of revolution/solid of revolution/"lathe object"
一个工作示例:
x1c 0d1x的数据

#include <GL/glut.h>
#include <glm/glm.hpp>
#include <vector>
#include <cmath>

using namespace std;
using namespace glm;

struct Vertex
{
    Vertex( const vec3& position, const vec3& normal )
        : position( position )
        , normal( normal ) 
    {}
    vec3 position;
    vec3 normal;
};

// spin the pts array around the Z axis.
// pts.x will become the radius, and pts.y will become the height
// pts should be sorted by y-coordinate
vector< Vertex > Lathe( const vector< vec2 >& pts, unsigned int segments = 32 )
{
    // precalculate circle points
    vector< vec2 > circlePts;
    for( unsigned int i = 0; i <= segments; ++i )
    {
        float angle = ( i / (float)segments ) * 3.14159f * 2.0f;
        circlePts.push_back( vec2( cos( angle ), sin( angle ) ) );
    }

    // fill each layer
    typedef vector< vec3 > Layer;
    typedef vector< Layer > Layers;
    Layers layers( pts.size(), Layer( circlePts.size() ) );
    for( size_t i = 0; i < pts.size(); ++i )
    {
        for( unsigned int j = 0; j < circlePts.size(); ++j )
        {
            layers[i][j] = vec3( circlePts[j] * pts[i].x, pts[i].y );
        }
    }

    // move through layers generating triangles
    vector< Vertex > verts;
    for( size_t i = 1; i < layers.size(); ++i )
    {
        const Layer& prvLayer = layers[ i-1 ];
        const Layer& curLayer = layers[ i-0 ];
        for( size_t j = 1; j < circlePts.size(); ++j )
        {
            //    upper = cur layer
            //        UL -- UR  
            // left   | 0 /  |  right 
            // = j-1  |  / 1 |  = j-0
            //        LL -- LR  
            //    lower = prv layer
            const vec3& LL = prvLayer[ j-1 ]; // lower-left
            const vec3& LR = prvLayer[ j-0 ]; // lower-right
            const vec3& UL = curLayer[ j-1 ]; // upper-left
            const vec3& UR = curLayer[ j-0 ]; // upper-right

            // triangle0: LL -> UR -> UL
            const vec3 normal0 = normalize( cross( UR - LL, UL - LL ) );
            verts.push_back( Vertex( LL, normal0 ) );
            verts.push_back( Vertex( UR, normal0 ) );
            verts.push_back( Vertex( UL, normal0 ) );

            // triangle1: LL -> LR -> UR
            const vec3 normal1 = normalize( cross( LR - LL, UL - LL ) );
            verts.push_back( Vertex( LL, normal1 ) );
            verts.push_back( Vertex( LR, normal1 ) );
            verts.push_back( Vertex( UR, normal1 ) );
        }
    }

    return verts;
}

// mouse state
int btn;
ivec2 startMouse;
ivec2 startRot, curRot;

void mouse(int button, int state, int x, int y )
{
    if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
    {
        btn = button;
        startMouse = ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
        startRot = curRot;
    }
}

void motion( int x, int y )
{
    ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
    if( btn == GLUT_LEFT_BUTTON )
    {
        curRot = startRot + ( curMouse - startMouse );
    }
    glutPostRedisplay();
}

vector< Vertex > model;
void display()
{
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double w = glutGet( GLUT_WINDOW_WIDTH );
    double h = glutGet( GLUT_WINDOW_HEIGHT );
    double ar = w / h;
    gluPerspective( 60, ar, 0.1, 40 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glTranslatef( 0, 0, -10 );

    glPushMatrix();
    glRotatef( curRot.x % 360, 0, 1, 0 );
    glRotatef( -curRot.y % 360, 1, 0, 0 );

    // draw model
    if( !model.empty() )
    {
        glColor3ub( 255, 0, 0 );
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_NORMAL_ARRAY );
        glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
        glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
        glDrawArrays( GL_TRIANGLES, 0, model.size() );
        glDisableClientState( GL_VERTEX_ARRAY );
        glDisableClientState( GL_NORMAL_ARRAY );
    }

    // draw bounding cube
    glDisable( GL_LIGHTING );
    glColor3ub( 255, 255, 255 );
    glutWireCube( 7 );
    glEnable( GL_LIGHTING );

    glPopMatrix();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    vector< vec2 > pts;
    pts.push_back( vec2( 0.1, -3 ) );
    pts.push_back( vec2( 2, -2 ) );
    pts.push_back( vec2( 3, -1 ) );
    pts.push_back( vec2( 1, 0 ) );
    pts.push_back( vec2( 3, 1 ) );
    pts.push_back( vec2( 4, 2 ) );
    pts.push_back( vec2( 4, 3 ) );
    model = Lathe( pts );

    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
    glutInitWindowSize( 640, 480 );
    glutCreateWindow( "GLUT" );
    glutDisplayFunc( display );
    glutMouseFunc( mouse );
    glutMotionFunc( motion );

    glEnable( GL_DEPTH_TEST );

    // set up lighting
    glShadeModel( GL_SMOOTH );
    glEnable( GL_COLOR_MATERIAL );
    glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
    glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
    glEnable( GL_LIGHTING );

    // set up "headlamp"-like light
    glEnable( GL_LIGHT0 );
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    GLfloat position[] = { 0, 0, 1, 0 };
    glLightfv( GL_LIGHT0, GL_POSITION, position );

    glPolygonMode( GL_FRONT, GL_FILL );
    glPolygonMode( GL_BACK, GL_LINE );

    glutMainLoop();
    return 0;
}

字符串

vmpqdwk3

vmpqdwk32#

编辑二:好吧,我知道你遇到的问题了--这是一个我忘记的限制(所以我之前发布的代码是完全错误的,根本不能工作)。问题是不允许在glBegin/glEnd对之间调用glRotate--如果你这样做了,它会设置一个错误标志,并且不会再进行绘制。
这意味着你必须自己处理旋转。幸运的是,这比你试图做的要简单一些:

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作为旋转中心,你可以随意移动它,但是剪切截头体之外的任何东西都不会显示。
还要注意的是,要得到一个线框,你必须分别绘制“垂直”和“水平”线,所以代码看起来像这样:

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

vd2z7a6w

vd2z7a6w3#

函数的Angular 单位是弧度,而不是度。
我还怀疑你的视口设置不正确,这解释了为什么你在屏幕上看不到任何东西。通常当我认为东西没有渲染时,它通常是,然而,我没有正确配置相机,灯光和其他东西。

相关问题