如何使用 OpenGL 创建一个或多个球体?
Posted
技术标签:
【中文标题】如何使用 OpenGL 创建一个或多个球体?【英文标题】:How to create one or more spheres using OpenGL? 【发布时间】:2015-05-15 14:03:57 【问题描述】:我们必须创造一个球类游戏。然而,在将我们的代码实现到图形中之前,我们得到了 3 种图形的 3 个代码。一个立方体的代码,一个不移动的随机球体的代码,一个移动的立方体的代码,如果我没记错的话(也许我是)。
立方体的第一个代码如下:
#include "vue_opengl.h"
#include "vertex_shader.h"
#include "contenu.h"
// ======================================================================
void VueOpenGL::dessine(Contenu const& a_dessiner)
Q_UNUSED(a_dessiner);
draw first cube (at origin)
dessineCube();
QMatrix4x4 matrice;
// Dessine le 2e cube
matrice.translate(0.0, 1.5, 0.0);
matrice.scale(0.25);
dessineCube(matrice);
// Dessine le 3e cube
matrice.setToIdentity();
matrice.translate(0.0, 0.0, 1.5);
matrice.scale(0.25);
matrice.rotate(45.0, 0.0, 1.0, 0.0);
dessineCube(matrice);
// ======================================================================
void VueOpenGL::init()
prog.addShaderFromSourceFile(QGLShader::Vertex, ":/vertex_shader.glsl");
prog.addShaderFromSourceFile(QGLShader::Fragment, ":/fragment_shader.glsl");
prog.bindAttributeLocation("sommet", SommetId);
prog.bindAttributeLocation("couleur", CouleurId);
// Compilation of the shader openGL
prog.link();
// Activation of the shader
prog.bind();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
initializePosition();
// ======================================================================
void VueOpenGL::initializePosition()
// position initiale
matrice_vue.setToIdentity();
matrice_vue.translate(0.0, 0.0, -4.0);
matrice_vue.rotate(60.0, 0.0, 1.0, 0.0);
matrice_vue.rotate(45.0, 0.0, 0.0, 1.0);
// ======================================================================
void VueOpenGL::translate(double x, double y, double z)
QMatrix4x4 translation_supplementaire;
translation_supplementaire.translate(x, y, z);
matrice_vue = translation_supplementaire * matrice_vue;
// ======================================================================
void VueOpenGL::rotate(double angle, double dir_x, double dir_y, double dir_z)
// Multiplie la matrice de vue par LA GAUCHE
QMatrix4x4 rotation_supplementaire;
rotation_supplementaire.rotate(angle, dir_x, dir_y, dir_z);
matrice_vue = rotation_supplementaire * matrice_vue;
// ======================================================================
void VueOpenGL::dessineCube (QMatrix4x4 const& point_de_vue)
prog.setUniformValue("vue_modele", matrice_vue * point_de_vue);
glBegin(GL_QUADS);
// side X = +1
prog.setAttributeValue(CouleurId, 1.0, 0.0, 0.0); // red
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
// sides X = -1
prog.setAttributeValue(CouleurId, 0.0, 1.0, 0.0); // green
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
// side Y = +1
prog.setAttributeValue(CouleurId, 0.0, 0.0, 1.0); // blue
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
//side Y = -1
prog.setAttributeValue(CouleurId, 0.0, 1.0, 1.0); // cyan
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
// side Z = +1
prog.setAttributeValue(CouleurId, 1.0, 1.0, 0.0); // yellow
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
// side Z = -1
prog.setAttributeValue(CouleurId, 1.0, 0.0, 1.0); // magenta
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
glEnd();
现在他们给了我们一个球体的代码:
#include "vue_opengl.h"
#include "vertex_shader.h"
#include "contenu.h"
// ======================================================================
void VueOpenGL::dessine(Contenu const& a_dessiner)
Q_UNUSED(a_dessiner); //
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
QMatrix4x4 matrice;
matrice.translate(-0.5, 0.0, -2.0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // passe en mode "fil de fer"
dessineSphere(matrice, 0.0, 0.0); // bleu
matrice.scale(1.5); // taille des axes (1.5 pour qu'ils dépassent un peu)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // repasse en mode "plein"
// ======================================================================
void VueOpenGL::init()
prog.addShaderFromSourceFile(QGLShader::Vertex, ":/vertex_shader.glsl");
prog.addShaderFromSourceFile(QGLShader::Fragment, ":/fragment_shader.glsl");
prog.bindAttributeLocation("sommet", SommetId);
prog.bindAttributeLocation("couleur", CouleurId);
prog.link();
// Activation du shader
prog.bind();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
sphere.initialize(); // initialise la sphère
initializePosition();
// ======================================================================
void VueOpenGL::initializePosition()
// position initial
matrice_vue.setToIdentity();
matrice_vue.translate(0.0, 0.0, -4.0);
matrice_vue.rotate(60.0, 0.0, 1.0, 0.0);
matrice_vue.rotate(45.0, 0.0, 0.0, 1.0);
// ======================================================================
void VueOpenGL::translate(double x, double y, double z)
QMatrix4x4 translation_supplementaire;
translation_supplementaire.translate(x, y, z);
matrice_vue = translation_supplementaire * matrice_vue;
// ======================================================================
void VueOpenGL::rotate(double angle, double dir_x, double dir_y, double dir_z)
//
QMatrix4x4 rotation_supplementaire;
rotation_supplementaire.rotate(angle, dir_x, dir_y, dir_z);
matrice_vue = rotation_supplementaire * matrice_vue;
// ======================================================================
void VueOpenGL::dessineCube (QMatrix4x4 const& point_de_vue)
prog.setUniformValue("vue_modele", matrice_vue * point_de_vue);
glBegin(GL_QUADS);
// side X = +1
prog.setAttributeValue(CouleurId, 1.0, 0.0, 0.0); // rouge
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
// side X = -1
prog.setAttributeValue(CouleurId, 0.0, 1.0, 0.0); // vert
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
// face coté Y = +1
prog.setAttributeValue(CouleurId, 0.0, 0.0, 1.0); // bleu
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
// side Y = -1
prog.setAttributeValue(CouleurId, 0.0, 1.0, 1.0); // cyan
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
// side Z = +1
prog.setAttributeValue(CouleurId, 1.0, 1.0, 0.0); // jaune
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
//side Z = -1
prog.setAttributeValue(CouleurId, 1.0, 0.0, 1.0); // magenta
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
glEnd();
// ======================================================================
void VueOpenGL::dessineSphere (QMatrix4x4 const& point_de_vue,
double rouge, double vert, double bleu)
prog.setUniformValue("vue_modele", matrice_vue * point_de_vue);
prog.setAttributeValue(CouleurId, rouge, vert, bleu); // met la couleur
sphere.draw(prog, SommetId); // dessine la sphère
// ======================================================================
void VueOpenGL::dessineAxes (QMatrix4x4 const& point_de_vue, bool en_couleur)
prog.setUniformValue("vue_modele", matrice_vue * point_de_vue);
glBegin(GL_LINES);
// axe X
if (en_couleur)
prog.setAttributeValue(CouleurId, 1.0, 0.0, 0.0); // rouge
else
prog.setAttributeValue(CouleurId, 1.0, 1.0, 1.0); // blanc
prog.setAttributeValue(SommetId, 0.0, 0.0, 0.0);
prog.setAttributeValue(SommetId, 1.0, 0.0, 0.0);
// axe Y
if (en_couleur) prog.setAttributeValue(CouleurId, 0.0, 1.0, 0.0); // green
prog.setAttributeValue(SommetId, 0.0, 0.0, 0.0);
prog.setAttributeValue(SommetId, 0.0, 1.0, 0.0);
// axe Z
if (en_couleur) prog.setAttributeValue(CouleurId, 0.0, 0.0, 1.0); // blue
prog.setAttributeValue(SommetId, 0.0, 0.0, 0.0);
prog.setAttributeValue(SommetId, 0.0, 0.0, 1.0);
glEnd();
最后的代码:移动立方体:-我假设我们必须将球体放在这段代码中以便它移动:
#include "vue_opengl.h"
#include "vertex_shader.h" // Identifiants Qt de nos différents attributs
#include "contenu.h"
// ======================================================================
void VueOpenGL::dessine(Contenu const& a_dessiner)
// Dessine le 1er cube (à l'origine)
dessineCube();
QMatrix4x4 matrice;
// Dessine le 4e cube
matrice.setToIdentity();
matrice.rotate(a_dessiner.infos(), 1.0, 0.0, 0.0);
matrice.translate(0.0, 2.3, 0.0);
matrice.scale(0.2);
dessineCube(matrice);
// ======================================================================
void VueOpenGL::init()
prog.addShaderFromSourceFile(QGLShader::Vertex, ":/vertex_shader.glsl");
prog.addShaderFromSourceFile(QGLShader::Fragment, ":/fragment_shader.glsl");
prog.bindAttributeLocation("sommet", SommetId);
prog.bindAttributeLocation("couleur", CouleurId);
// Compilation du shader OpenGL
prog.link();
// Activation du shader
prog.bind();
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
initializePosition();
// ======================================================================
void VueOpenGL::initializePosition()
// position initiale
matrice_vue.setToIdentity();
matrice_vue.translate(0.0, 0.0, -4.0);
matrice_vue.rotate(60.0, 0.0, 1.0, 0.0);
matrice_vue.rotate(45.0, 0.0, 0.0, 1.0);
// ======================================================================
void VueOpenGL::translate(double x, double y, double z)
QMatrix4x4 translation_supplementaire;
translation_supplementaire.translate(x, y, z);
matrice_vue = translation_supplementaire * matrice_vue;
// ======================================================================
void VueOpenGL::rotate(double angle, double dir_x, double dir_y, double dir_z)
QMatrix4x4 rotation_supplementaire;
rotation_supplementaire.rotate(angle, dir_x, dir_y, dir_z);
matrice_vue = rotation_supplementaire * matrice_vue;
// ======================================================================
void VueOpenGL::dessineCube (QMatrix4x4 const& point_de_vue)
prog.setUniformValue("vue_modele", matrice_vue * point_de_vue);
glBegin(GL_QUADS);
// face coté X = +1
prog.setAttributeValue(CouleurId, 1.0, 0.0, 0.0); // rouge
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
// face coté X = -1
prog.setAttributeValue(CouleurId, 0.0, 1.0, 0.0); // vert
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
// face coté Y = +1
prog.setAttributeValue(CouleurId, 0.0, 0.0, 1.0); // bleu
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
// face coté Y = -1
prog.setAttributeValue(CouleurId, 0.0, 1.0, 1.0); // cyan
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
// face coté Z = +1
prog.setAttributeValue(CouleurId, 1.0, 1.0, 0.0); // jaune
prog.setAttributeValue(SommetId, -1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, +1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, +1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, +1.0);
// face coté Z = -1
prog.setAttributeValue(CouleurId, 1.0, 0.0, 1.0); // magenta
prog.setAttributeValue(SommetId, -1.0, -1.0, -1.0);
prog.setAttributeValue(SommetId, -1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, +1.0, -1.0);
prog.setAttributeValue(SommetId, +1.0, -1.0, -1.0);
glEnd();
我如何实现所有这 3 个代码来显示一个正在移动并且是一种纯色的球体?
【问题讨论】:
抱歉,部分代码是法语,但 dessine 的意思是绘图 我在这里的回答解释了绘制球体的一些选项:***.com/questions/24137198/opengl-es-2-0-sphere。 【参考方案1】:你可以使用 GLU 库吗? GLU 有一个 Sphere 的原始类型。这里是documentation
使用示例:
二次初始化:
quadratic = gluNewQuadric();
gluQuadricNormals(quadratic, GLU_SMOOTH);
绘制函数:
glPushMatrix();
glTranslatef("TranslateX here","TranslateY here","TranslateZ here");
gluSphere(quadratic,"Sphere Radius here", 32, 32);
glPopMatrix();
【讨论】:
以上是关于如何使用 OpenGL 创建一个或多个球体?的主要内容,如果未能解决你的问题,请参考以下文章