如何使用圆柱体绘制完美的 3D Spring
How to draw a perfect 3D Spring using Cylinders
我正在尝试仅使用圆柱体绘制 Spring。
void spring(GLfloat rounds, GLfloat height, GLfloat thickness, GLfloat radius) {
glColor3f(1.0, 1.0, 1.0);
GLfloat j = 0;
for (GLfloat i = 0; i <= rounds * 360; i += 5) {
glPushMatrix();
glRotatef(i, 0, 1, 0);
glTranslatef(0, j, radius);
gluCylinder(qobj, thickness, thickness, radius, 50, 50);
glPopMatrix();
j += height / (rounds * 360);
}
}
spring(4, 2.5, 0.03, 0.1);
用这段代码绘制的spring并不完美。此外,当半径增加时,spring 的形状会变形。
我该如何解决这个问题?
A spring 是在 3 个维度上弯曲的形状。圆柱体不能完美地粘在一起形成 spring。为什么不使用 OpenGL 创建自己的网格 primitives?
例如:使用 TRINGLESTRIP
将长丝带缠绕在弯曲成 spring 的管子上:
#include <vector>
#include <algorithm>
void createSpring(
GLfloat rounds, GLfloat height, GLfloat thickness, GLfloat radius,
std::vector<GLfloat> &vertices, std::vector<GLuint> &indices)
{
const int slices = 32;
const int step = 5;
for (int i = -slices; i <= rounds * 360 + step; i += step)
{
for (int j = 0; j < slices; j ++)
{
GLfloat t = (GLfloat)i / 360 + (GLfloat)j / slices * step / 360;
t = std::max(0.0f, std::min(rounds, t));
GLfloat a1 = t * M_PI * 2;
GLfloat a2 = (GLfloat)j / slices * M_PI * 2;
GLfloat d = radius + thickness * cos(a2);
vertices.push_back(d * cos(a1));
vertices.push_back(d * sin(a1));
vertices.push_back(thickness * sin(a2) + height * t / rounds);
}
}
for (GLuint i = 0; i < (GLuint)vertices.size() / 3 - slices; ++i)
{
indices.push_back(i);
indices.push_back(i + slices);
}
}
void drawSpring(
const std::vector<GLfloat>& vertices, const std::vector<GLuint>& indices)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // just to see the mesh (delete later)
glColor4f(1, 1, 1, 1);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices.data());
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, indices.data());
glDisableClientState(GL_VERTEX_ARRAY);
}
std::vector<GLfloat> springVertices;
std::vector<GLuint> springIndices;
void init()
{
createSpring(1.5, 0.25, 0.03, 0.1, springVertices, springIndices);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(20.0, 1.0f, 0.1f, 1000);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, -1, 0.125, 0, 0.0, 0.125, 0, 0, 1);
glEnable(GL_DEPTH_TEST);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawSpring(springVertices, springIndices);
glutPostRedisplay();
glutSwapBuffers();
}
我正在尝试仅使用圆柱体绘制 Spring。
void spring(GLfloat rounds, GLfloat height, GLfloat thickness, GLfloat radius) {
glColor3f(1.0, 1.0, 1.0);
GLfloat j = 0;
for (GLfloat i = 0; i <= rounds * 360; i += 5) {
glPushMatrix();
glRotatef(i, 0, 1, 0);
glTranslatef(0, j, radius);
gluCylinder(qobj, thickness, thickness, radius, 50, 50);
glPopMatrix();
j += height / (rounds * 360);
}
}
spring(4, 2.5, 0.03, 0.1);
用这段代码绘制的spring并不完美。此外,当半径增加时,spring 的形状会变形。
我该如何解决这个问题?
A spring 是在 3 个维度上弯曲的形状。圆柱体不能完美地粘在一起形成 spring。为什么不使用 OpenGL 创建自己的网格 primitives?
例如:使用 TRINGLESTRIP
将长丝带缠绕在弯曲成 spring 的管子上:
#include <vector>
#include <algorithm>
void createSpring(
GLfloat rounds, GLfloat height, GLfloat thickness, GLfloat radius,
std::vector<GLfloat> &vertices, std::vector<GLuint> &indices)
{
const int slices = 32;
const int step = 5;
for (int i = -slices; i <= rounds * 360 + step; i += step)
{
for (int j = 0; j < slices; j ++)
{
GLfloat t = (GLfloat)i / 360 + (GLfloat)j / slices * step / 360;
t = std::max(0.0f, std::min(rounds, t));
GLfloat a1 = t * M_PI * 2;
GLfloat a2 = (GLfloat)j / slices * M_PI * 2;
GLfloat d = radius + thickness * cos(a2);
vertices.push_back(d * cos(a1));
vertices.push_back(d * sin(a1));
vertices.push_back(thickness * sin(a2) + height * t / rounds);
}
}
for (GLuint i = 0; i < (GLuint)vertices.size() / 3 - slices; ++i)
{
indices.push_back(i);
indices.push_back(i + slices);
}
}
void drawSpring(
const std::vector<GLfloat>& vertices, const std::vector<GLuint>& indices)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // just to see the mesh (delete later)
glColor4f(1, 1, 1, 1);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertices.data());
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, indices.data());
glDisableClientState(GL_VERTEX_ARRAY);
}
std::vector<GLfloat> springVertices;
std::vector<GLuint> springIndices;
void init()
{
createSpring(1.5, 0.25, 0.03, 0.1, springVertices, springIndices);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(20.0, 1.0f, 0.1f, 1000);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, -1, 0.125, 0, 0.0, 0.125, 0, 0, 1);
glEnable(GL_DEPTH_TEST);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawSpring(springVertices, springIndices);
glutPostRedisplay();
glutSwapBuffers();
}