gpt4 book ai didi

c++ - OpenGL - 围绕 Y 轴旋转 'Curve'

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:05:11 27 4
gpt4 key购买 nike

根据我在 Math Stackexchange 上的 question:

我正在为我的 3D 图形类(class)做一个项目。该项目是用 C++ 和 OpenGL/Glut 构建的。基本上,我创建了一个水平矩形窗口, segmentation 为两个正方形。在左侧,我有一个二维坐标平面,它允许用户指向并单击并定义轮廓“曲线”。然后我需要将这条曲线围绕 Y 轴绕 n 次。

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

(1, 1, 0)

并且它们的扫描分辨率 (n) 设置为 10,然后我需要围绕 Y 轴每 36 (360/10) 度重绘该点。

我假设三角函数会在这方面对我有帮助,我的假设是否正确?如果是这样,有人可以告诉我如何计算 3D 空间中翻译点的位置吗?自从我使用 Trig 以来已经有一段时间了,我不相信我们曾经离开过 2D 空间。

编辑:我尝试使用:

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

y'=y

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

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

// 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:这是我的透视 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();
}

编辑 3:这是一个糟糕的插图,说明了我需要做什么。我知道视角似乎不对,但我试图获得的是右侧 subview 中的绿色“水平”(这是使用上面注释掉的 glRotatef() 代码):

Pic

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

在与一位大学老师讨论了一些线性代数之后,这是我最终得到的结果:

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

最佳答案

编辑 2:好的,我明白你遇到的问题了——这是一个我忘记的限制(所以我之前发布的代码是完全错误的,根本无法工作)。问题是您不允许在 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();
}

关于c++ - OpenGL - 围绕 Y 轴旋转 'Curve',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7904281/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com