OpenGL -绕Y轴旋转“曲线”

hjqgdpho  于 2024-01-07  发布在  其他
关注(0)|答案(3)|浏览(234)
  • 根据我在Math Stackexchange上的question:*

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

编辑:尝试用途:

  1. x'=xcos(theta)-zsin(theta)
  2. y'=y
  3. z'=xsin(theta)+zcos(theta)

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

  1. // this is in a loop
  2. // setup the new angle
  3. double angle = i>0 ? (360/sweepResolutionMod)*i : 0;
  4. angle = angle * (M_PI/180);
  5. // for each point...
  6. for( int i=0; i<clickedPoints.size(); i++ )
  7. {
  8. // initial point, normalized
  9. GLfloat tempX = (clickedPoints[i].x-250)/250;
  10. GLfloat tempY = (clickedPoints[i].y-250)/250;
  11. GLfloat tempZ = 0.0;
  12. // log the initial point
  13. cout << "(" << tempX << ", " << tempY << ", 0.0) by " << angle << " radians = ";
  14. // generate the new point
  15. GLfloat newX = (tempX * cos(angle)) - (tempZ * sin(angle));
  16. GLfloat newY = tempY;
  17. GLfloat newZ = (tempX * sin(angle)) - (tempZ * cos(angle));
  18. // log the new point
  19. cout << "(" << newX << ", " << newY << ", " << newZ << ")\n";
  20. // render the new point
  21. glVertex3d(newX, newY, newZ);
  22. }


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

  1. (0.048, -0.296, 0.0) by 0 radians = (0.048, -0.296, 0)
  2. (0.376, -0.508, 0.0) by 0 radians = (0.376, -0.508, 0)
  3. (0.72, -0.204, 0.0) by 0 radians = (0.72, -0.204, 0)
  4. (0.652, 0.176, 0.0) by 0 radians = (0.652, 0.176, 0)
  5. (0.368, 0.504, 0.0) by 0 radians = (0.368, 0.504, 0)
  6. (0.048, -0.296, 0.0) by 0.628319 radians = (0.0388328, -0.296, 0.0282137)
  7. (0.376, -0.508, 0.0) by 0.628319 radians = (0.30419, -0.508, 0.221007)
  8. (0.72, -0.204, 0.0) by 0.628319 radians = (0.582492, -0.204, 0.423205)
  9. (0.652, 0.176, 0.0) by 0.628319 radians = (0.527479, 0.176, 0.383236)
  10. (0.368, 0.504, 0.0) by 0.628319 radians = (0.297718, 0.504, 0.216305)
  11. (0.048, -0.296, 0.0) by 1.25664 radians = (0.0148328, -0.296, 0.0456507)
  12. (0.376, -0.508, 0.0) by 1.25664 radians = (0.11619, -0.508, 0.357597)
  13. (0.72, -0.204, 0.0) by 1.25664 radians = (0.222492, -0.204, 0.684761)
  14. (0.652, 0.176, 0.0) by 1.25664 radians = (0.201479, 0.176, 0.620089)
  15. (0.368, 0.504, 0.0) by 1.25664 radians = (0.113718, 0.504, 0.349989)
  16. ...
  17. (0.048, -0.296, 0.0) by 6.28319 radians = (0.048, -0.296, -1.17566e-17)
  18. (0.376, -0.508, 0.0) by 6.28319 radians = (0.376, -0.508, -9.20934e-17)
  19. (0.72, -0.204, 0.0) by 6.28319 radians = (0.72, -0.204, -1.76349e-16)
  20. (0.652, 0.176, 0.0) by 6.28319 radians = (0.652, 0.176, -1.59694e-16)
  21. (0.368, 0.504, 0.0) by 6.28319 radians = (0.368, 0.504, -9.0134e-17)


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

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

  1. void displayPersp(void)
  2. {
  3. glClear(GL_COLOR_BUFFER_BIT);
  4. glMatrixMode (GL_MODELVIEW);
  5. glLoadIdentity ();
  6. gluLookAt (-2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
  7. // draw the axis
  8. glBegin(GL_LINES);
  9. // x
  10. glVertex3f(500.0, 0.0, 0.0);
  11. glVertex3f(-500.0, 0.0, 0.0);
  12. // y
  13. glVertex3f(0.0, -500.0, 0.0);
  14. glVertex3f(0.0, 500.0, 0.0);
  15. // z
  16. glVertex3f(0.0, 0.0, -500.0);
  17. glVertex3f(0.0, 0.0, 500.0);
  18. glEnd();
  19. cout << endl;
  20. // loop as many number of times as we are going to draw the points around the Y-Axis
  21. for( int i=0; i<=sweepResolutionMod; i++ )
  22. {
  23. cout << endl;
  24. // setup the new angle
  25. double angle = i>0 ? (360/sweepResolutionMod)*i : 0;
  26. angle = angle * (M_PI/180);
  27. // for each point...
  28. for( int i=0; i<clickedPoints.size(); i++ )
  29. {
  30. GLfloat tempX = (clickedPoints[i].x-250)/250;
  31. GLfloat tempY = (clickedPoints[i].y-250)/250;
  32. GLfloat tempZ = 0.0;
  33. cout << "(" << tempX << ", " << tempY << ", 0.0) by " << angle << " degrees = ";
  34. GLfloat newX = (tempX * cos(angle)) - (tempZ * sin(angle));
  35. GLfloat newY = tempY;
  36. GLfloat newZ = (tempX * sin(angle)) - (tempZ * cos(angle));
  37. cout << "(" << newX << ", " << newY << ", " << newZ << ")\n";
  38. glVertex3d(newX, newY, newZ);
  39. }
  40. // the following was my old solution, using OpenGL's rotate(), but that
  41. // didn't allow me to get back the new point's coordinates.
  42. /*
  43. glRotatef(angle, 0.0, 1.0, 0.0);
  44. // draw a line?
  45. if( clickedPoints.size() > 1 )
  46. {
  47. glBegin(GL_LINE_STRIP);
  48. for(int i=0; i<clickedPoints.size(); i++ )
  49. {
  50. glVertex3f((clickedPoints[i].x-250)/250, (clickedPoints[i].y-250)/250, 0.0);
  51. }
  52. glEnd();
  53. }
  54. // everyone gets points
  55. glBegin(GL_POINTS);
  56. for(int i=0; i<clickedPoints.size(); i++ )
  57. {
  58. glVertex3f((clickedPoints[i].x-250)/250, (clickedPoints[i].y-250)/250, 0.0);
  59. }
  60. glEnd();
  61. */
  62. }
  63. glutSwapBuffers();
  64. }


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

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

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

  1. void displayPersp(void)
  2. {
  3. glClear(GL_COLOR_BUFFER_BIT);
  4. gluLookAt (-2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
  5. glMatrixMode (GL_MODELVIEW);
  6. glLoadIdentity ();
  7. // draw the axis
  8. glBegin(GL_LINES);
  9. // x
  10. glVertex3f(500.0, 0.0, 0.0);
  11. glVertex3f(-500.0, 0.0, 0.0);
  12. // y
  13. glVertex3f(0.0, -500.0, 0.0);
  14. glVertex3f(0.0, 500.0, 0.0);
  15. // z
  16. glVertex3f(0.0, 0.0, -500.0);
  17. glVertex3f(0.0, 0.0, 500.0);
  18. glEnd();
  19. cout << endl;
  20. double previousTheta = 0.0;
  21. for( int i=0; i<=sweepResolutionMod; i++ )
  22. {
  23. double theta = i>0 ? (360/sweepResolutionMod)*i : 0;
  24. theta = theta * (M_PI/180);
  25. if( clickedPoints.size() > 1 )
  26. {
  27. // the 'vertical' piece
  28. glBegin(GL_LINE_STRIP);
  29. for(int i=0; i<clickedPoints.size(); i++ )
  30. {
  31. // normalize
  32. GLfloat tempX = (clickedPoints[i].x-250)/250;
  33. GLfloat tempY = (clickedPoints[i].y-250)/250;
  34. GLfloat tempZ = 0.0;
  35. // new points
  36. GLfloat newX = ( tempX * cos(theta) ) + ( tempZ * sin(theta) );
  37. GLfloat newY = tempY;
  38. GLfloat newZ = ( tempZ * cos(theta) ) - ( tempX * sin(theta) );
  39. glVertex3f(newX, newY, newZ);
  40. }
  41. glEnd();
  42. // the 'horizontal' piece
  43. if( previousTheta != theta )
  44. {
  45. glBegin(GL_LINES);
  46. for(int i=0; i<clickedPoints.size(); i++ )
  47. {
  48. // normalize
  49. GLfloat tempX = (clickedPoints[i].x-250)/250;
  50. GLfloat tempY = (clickedPoints[i].y-250)/250;
  51. GLfloat tempZ = 0.0;
  52. // new points
  53. GLfloat newX = ( tempX * cos(theta) ) + ( tempZ * sin(theta) );
  54. GLfloat newY = tempY;
  55. GLfloat newZ = ( tempZ * cos(theta) ) - ( tempX * sin(theta) );
  56. // previous points
  57. GLfloat previousX = ( tempX * cos(previousTheta) ) + ( tempZ * sin(previousTheta) );
  58. GLfloat previousY = tempY;
  59. GLfloat previousZ = ( tempZ * cos(previousTheta) ) - ( tempX * sin(previousTheta) );
  60. // horizontal component
  61. glVertex3f(newX, newY, newZ);
  62. glVertex3f(previousX, previousY, previousZ);
  63. }
  64. glEnd();
  65. }
  66. }
  67. previousTheta = theta;
  68. }
  69. glutSwapBuffers();
  70. }

rbpvctlc

rbpvctlc1#

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

  1. #include <GL/glut.h>
  2. #include <glm/glm.hpp>
  3. #include <vector>
  4. #include <cmath>
  5. using namespace std;
  6. using namespace glm;
  7. struct Vertex
  8. {
  9. Vertex( const vec3& position, const vec3& normal )
  10. : position( position )
  11. , normal( normal )
  12. {}
  13. vec3 position;
  14. vec3 normal;
  15. };
  16. // spin the pts array around the Z axis.
  17. // pts.x will become the radius, and pts.y will become the height
  18. // pts should be sorted by y-coordinate
  19. vector< Vertex > Lathe( const vector< vec2 >& pts, unsigned int segments = 32 )
  20. {
  21. // precalculate circle points
  22. vector< vec2 > circlePts;
  23. for( unsigned int i = 0; i <= segments; ++i )
  24. {
  25. float angle = ( i / (float)segments ) * 3.14159f * 2.0f;
  26. circlePts.push_back( vec2( cos( angle ), sin( angle ) ) );
  27. }
  28. // fill each layer
  29. typedef vector< vec3 > Layer;
  30. typedef vector< Layer > Layers;
  31. Layers layers( pts.size(), Layer( circlePts.size() ) );
  32. for( size_t i = 0; i < pts.size(); ++i )
  33. {
  34. for( unsigned int j = 0; j < circlePts.size(); ++j )
  35. {
  36. layers[i][j] = vec3( circlePts[j] * pts[i].x, pts[i].y );
  37. }
  38. }
  39. // move through layers generating triangles
  40. vector< Vertex > verts;
  41. for( size_t i = 1; i < layers.size(); ++i )
  42. {
  43. const Layer& prvLayer = layers[ i-1 ];
  44. const Layer& curLayer = layers[ i-0 ];
  45. for( size_t j = 1; j < circlePts.size(); ++j )
  46. {
  47. // upper = cur layer
  48. // UL -- UR
  49. // left | 0 / | right
  50. // = j-1 | / 1 | = j-0
  51. // LL -- LR
  52. // lower = prv layer
  53. const vec3& LL = prvLayer[ j-1 ]; // lower-left
  54. const vec3& LR = prvLayer[ j-0 ]; // lower-right
  55. const vec3& UL = curLayer[ j-1 ]; // upper-left
  56. const vec3& UR = curLayer[ j-0 ]; // upper-right
  57. // triangle0: LL -> UR -> UL
  58. const vec3 normal0 = normalize( cross( UR - LL, UL - LL ) );
  59. verts.push_back( Vertex( LL, normal0 ) );
  60. verts.push_back( Vertex( UR, normal0 ) );
  61. verts.push_back( Vertex( UL, normal0 ) );
  62. // triangle1: LL -> LR -> UR
  63. const vec3 normal1 = normalize( cross( LR - LL, UL - LL ) );
  64. verts.push_back( Vertex( LL, normal1 ) );
  65. verts.push_back( Vertex( LR, normal1 ) );
  66. verts.push_back( Vertex( UR, normal1 ) );
  67. }
  68. }
  69. return verts;
  70. }
  71. // mouse state
  72. int btn;
  73. ivec2 startMouse;
  74. ivec2 startRot, curRot;
  75. void mouse(int button, int state, int x, int y )
  76. {
  77. if( button == GLUT_LEFT_BUTTON && state == GLUT_DOWN )
  78. {
  79. btn = button;
  80. startMouse = ivec2( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
  81. startRot = curRot;
  82. }
  83. }
  84. void motion( int x, int y )
  85. {
  86. ivec2 curMouse( x, glutGet( GLUT_WINDOW_HEIGHT ) - y );
  87. if( btn == GLUT_LEFT_BUTTON )
  88. {
  89. curRot = startRot + ( curMouse - startMouse );
  90. }
  91. glutPostRedisplay();
  92. }
  93. vector< Vertex > model;
  94. void display()
  95. {
  96. glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
  97. glMatrixMode( GL_PROJECTION );
  98. glLoadIdentity();
  99. double w = glutGet( GLUT_WINDOW_WIDTH );
  100. double h = glutGet( GLUT_WINDOW_HEIGHT );
  101. double ar = w / h;
  102. gluPerspective( 60, ar, 0.1, 40 );
  103. glMatrixMode( GL_MODELVIEW );
  104. glLoadIdentity();
  105. glTranslatef( 0, 0, -10 );
  106. glPushMatrix();
  107. glRotatef( curRot.x % 360, 0, 1, 0 );
  108. glRotatef( -curRot.y % 360, 1, 0, 0 );
  109. // draw model
  110. if( !model.empty() )
  111. {
  112. glColor3ub( 255, 0, 0 );
  113. glEnableClientState( GL_VERTEX_ARRAY );
  114. glEnableClientState( GL_NORMAL_ARRAY );
  115. glVertexPointer( 3, GL_FLOAT, sizeof(Vertex), &model[0].position );
  116. glNormalPointer( GL_FLOAT, sizeof(Vertex), &model[0].normal );
  117. glDrawArrays( GL_TRIANGLES, 0, model.size() );
  118. glDisableClientState( GL_VERTEX_ARRAY );
  119. glDisableClientState( GL_NORMAL_ARRAY );
  120. }
  121. // draw bounding cube
  122. glDisable( GL_LIGHTING );
  123. glColor3ub( 255, 255, 255 );
  124. glutWireCube( 7 );
  125. glEnable( GL_LIGHTING );
  126. glPopMatrix();
  127. glutSwapBuffers();
  128. }
  129. int main( int argc, char **argv )
  130. {
  131. vector< vec2 > pts;
  132. pts.push_back( vec2( 0.1, -3 ) );
  133. pts.push_back( vec2( 2, -2 ) );
  134. pts.push_back( vec2( 3, -1 ) );
  135. pts.push_back( vec2( 1, 0 ) );
  136. pts.push_back( vec2( 3, 1 ) );
  137. pts.push_back( vec2( 4, 2 ) );
  138. pts.push_back( vec2( 4, 3 ) );
  139. model = Lathe( pts );
  140. glutInit( &argc, argv );
  141. glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE );
  142. glutInitWindowSize( 640, 480 );
  143. glutCreateWindow( "GLUT" );
  144. glutDisplayFunc( display );
  145. glutMouseFunc( mouse );
  146. glutMotionFunc( motion );
  147. glEnable( GL_DEPTH_TEST );
  148. // set up lighting
  149. glShadeModel( GL_SMOOTH );
  150. glEnable( GL_COLOR_MATERIAL );
  151. glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE ) ;
  152. glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE );
  153. glEnable( GL_LIGHTING );
  154. // set up "headlamp"-like light
  155. glEnable( GL_LIGHT0 );
  156. glMatrixMode( GL_MODELVIEW );
  157. glLoadIdentity();
  158. GLfloat position[] = { 0, 0, 1, 0 };
  159. glLightfv( GL_LIGHT0, GL_POSITION, position );
  160. glPolygonMode( GL_FRONT, GL_FILL );
  161. glPolygonMode( GL_BACK, GL_LINE );
  162. glutMainLoop();
  163. return 0;
  164. }

字符串

展开查看全部
vmpqdwk3

vmpqdwk32#

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

  1. static const double pi = 3.1416;
  2. for (int point=0; point<NUM_POINTS; point++) {
  3. glBegin(GL_LINE_STRIP);
  4. for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
  5. double x = cos(theta);
  6. double z = sin(theta);
  7. glVertex3d(points[point][0]*x, points[point][1], -1.0-points[point][0]*z);
  8. }
  9. glEnd();
  10. }

字符串
这段代码使用沿着Z轴的-1.0作为旋转中心,你可以随意移动它,但是剪切截头体之外的任何东西都不会显示。
还要注意的是,要得到一个线框,你必须分别绘制“垂直”和“水平”线,所以代码看起来像这样:

  1. for (int point=0; point<NUM_POINTS; point++) {
  2. glBegin(GL_LINE_STRIP);
  3. for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
  4. double x = cos(theta);
  5. double z = sin(theta);
  6. glVertex3d(points[point][0]*x, points[point][1], -1.0 - points[point][0]*z);
  7. }
  8. glEnd();
  9. }
  10. for (double theta = 0.0; theta < 2.0 * pi; theta += pi/6.0) {
  11. glBegin(GL_LINE_STRIP);
  12. for (int point=0; point<NUM_POINTS; point++) {
  13. double x = cos(theta);
  14. double z = sin(theta);
  15. glVertex3d(points[point][0]*x, points[point][1], -1.0 - points[point][0]*z);
  16. }
  17. glEnd();
  18. }

展开查看全部
vd2z7a6w

vd2z7a6w3#

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

相关问题