この記事では、OpenGLのみ、記録を作成するには、この中の3D数学、ベクトルや行列の使用を学習する過程で個人のためです。
1.OpenGL行列、ベクトル
- >ベクトルの方向と量:のOpenGLの三次元座標において、三つの値(X、Y、Z)は、2つの重要な値を表すために結合されます。
math3dはmath3dライブラリは、データの2種類があり表現することができる⼀3次元や4次元ベクトルを、OpenGLライブラリにあります。M3DVector3f
⼀は、3次元ベクトル(x、y、z)を表してもよく、そして
M3DVector4f
それは、4次元ベクトル(X、Y、Z、Wを表すことができます )。典型的なケースでは、W座標が1.0に設定します。X、Y、Zの値がWで割ることによってスケーリングします。Xは本質1.0、Y、Z値を変更せずに分割されます。
typedef float M3DVector3f[3];
typedef float M3DVector4f[4];
声明⼀个三分量向量操作:
M3DVector3f vVector;
类似,声明⼀个四分量的操作:
M3DVector4f vVectro= {0.0f,0.0f,1.0f,1.0f};
声明一个三分量顶点数组,例如⽣成⼀个三⻆形
M3DVector3f vVerts[] = {
-1.0f,0.0f,0.0f,
0.5f,0.0f,0.0f,
0.0f,1.0f,0.0f
};
复制代码
2.ドット:
2つのベクトル間の角度を返すように小数点乗算
//实现点乘方法:
//⽅法1: 返回的是-1,1之间的值。它代表这个2个向量量的余弦值。
float m3dDotProduct3(const M3DVector3f u,const
M3DVector3f v);
//方法2:返回2个向量之间的弧度值。
float m3dGetAngleBetweenVector3(const M3DVector3f u,const M3DVector3f v);
复制代码
3.外積:
クロス乗算の結果は、新しいベクター、新規ベクター及び2元に垂直なベクトルを返します
void m3dCrossProduct3(M3DVector3f result,const M3DVector3f u ,const M3DVector3f v);
复制代码
4.モデル変換
OpenGLで変換を初めて目:
コンバート | アプリケーション | 説明コメント |
---|---|---|
ビュー | オブザーバーやカメラの位置を開発 | ビュー変換は、私たちが所望の位置に任意のポイントを観察するために、および任意の方向にシーンを見てできるようにすることができます。カメラがシーン内に配置されるようビュー変換を決定し、特定の方向に指します。 |
モデル | シーンにおける移動物体 | モデル変換モデルおよびその中の特定のオブジェクトを操作します。これらの変換は、所望の位置にオブジェクトを移動し、それらは、回転、ズーム。 |
ビューモデル | ビューとモデル変換の説明二重性 | はるかに便利である実際には、(ビュー変換)カメラを動かすが、同じ効果を達成するための二つの方法、時には別の変換を用いた変換率のいずれかを使用することができ、このオブジェクト(モデル変換)を、移動することにより、対象物を観察する必要はありません。これはまた、ビューは、変換され、モデル変換は、統一されたモデルビュー行列の理由です。 |
投影 | 視野ボリュームのサイズを変更したり、その形状をリセット、トリミングされるか錐台の外側に位置する投影された2次元のスクリーン座標の三次元座標 | 射影変換は、頂点を変換、モデルビューに適用された後、それは(すべてのモデルが完了した変換)指定されたシーンを完了し、画面上にどのように最終画像に投影されています。正射:すべてのポリゴンは指定された相対的な大きさに応じて画面上に正確に描かれています。透視投影:透視投影の特性、遠くのオブジェクトは、同じサイズのうちのオブジェクトの数よりも小さく見えるように、このような特性をフォアショートニングされます。 |
ビューポート | これは、擬似変換であるが、ズームウィンドウの最終的な出力 | すべての完了変換した後、あなたはシーンの2次元投影を取得し、それはどこか、画面上のウィンドウにマップされます。このマップは、ビューポート変換と呼ばれる、我々は変換物理的な傷最後の対象となります。 |
5.マトリックス
文のマトリックス
声明一个三维矩阵:
typedef float M3DMatrix33f[9];
声明一个四维矩阵:
typedef float M3DMatrix44f[16];
复制代码
OpenGLのは、4×4行列は、浮動小数点値の2次元配列として表現されていないが、それは16の浮動小数点値の単一の配列として表されます。
最初の3つの列は、x軸、y軸、z軸方向に対応します。カラムマトリックスは、特にマークされている、行列の最後の行がゼロであり、最後の要素が1です。4×4行列が存在する場合、座標系の異なる位置及び向きを含み、(カラムマトリックスまたはベクトルとして表される)元の座標系のベクトル表現は、この行列を乗じ、次いで、その結果を新しい座標系に変換されます。新しいベクトル。これは、宇宙のどこか、あなたが望む任意の方向には、一意4X4行列によって決定することができることを意味し、この行列を乗じたオブジェクトを持つすべてのベクトルは、その後、我々は与えられたスペースにオブジェクト全体を変えていく場合位置と方向。マトリックス:対角線上の要素の集合に加えてマトリクス、他の要素がゼロです。行列によるベクトル/行列、これは、任意の変更が発生していない、1によってベクトル/行列と等価です。行列の6.
モデルビュー行列モデルビュー行列は、座標系の変換を表す4×4行列であり、オブジェクトを配置するために使用することができ、我々は、オブジェクトの向きを決定します。マトリックスは、新しい視覚座標となり、モデルビュー行列を乗じた単一の頂点データを含みます。我々は、モデルビュー変換行列を使用してmath3dライブラリm3dTranslationMatrix44関数を呼び出します。
1.平移
void m3dTranslationMatrix44(M3DMatrix44f m,float x,float y,float z);
2.旋转
m3dRotationMatrix44(M3DMatrix44f m,float angle,float x,float y,float z);
3.缩放
void m3dScaleMatrix44(M3DMatrix44f m,float xScale,float yScale,float zScale);
4.综合(math3d库函数m3dMatrixMultiply44用来将两个矩阵相乘并返回运算结果)
void m3dMatrixMultiply44(M3DMatrix44f product,const M3DMatrix44f a,const M3DMatrix44f b);
eg:
M3DMatrix44f mFinalTransform, mTranslationMatrix, mRotationMatrix;
//平移 xPos,yPos
m3dTranslationMatrix44(mTranslationMatrix, xPos, yPos, 0.0f);
// 每次重绘时,旋转5度
static float yRot = 0.0f;
yRot += 5.0f;
m3dRotationMatrix44(mRotationMatrix, m3dDegToRad(yRot), 0.0f, 0.0f, 1.0f);
//将旋转和移动的结果合并到mFinalTransform 中
m3dMatrixMultiply44(mFinalTransform, mTranslationMatrix, mRotationMatrix);
复制代码
投影ビュー行列
1.正投影
GLFrustum::SetOrthographic(GLfloat xMin,GLfloat xMax,GLfloat yMin,GLfloat yMax,GLfloat zMin,GLfloat zMax);
2.透视投影
GLFrustum::SetPerspective(float fFov,float fAspect,float fNear,float fFar);
// 参数1:从顶点方向看去的视场角度值
// 参数2:宽和高的纵横比
// 参数3:近裁剪面的距离
// 参数4:远裁剪面的距离
复制代码
行列スタックコンストラクタGLMatrixStackクラスの最大深さはスタックの深さが、これは初期化時に行列スタックに含まれているデフォルトの行列スタック64である、あなたがスタックを指定することができます。(マトリックススタックの最後のアウト)
GLMatrixStack::GLMatrixStack(int iStackDepth=64);
复制代码
使用のマトリックススタック:
1.矩阵堆栈顶部载入单元矩阵
void GLMatrixStack::LoadIdentity(void);
2.矩阵堆栈顶部载入任何矩阵
void GLMatrixStack::LoadMatrix(const M3DMatrix44f m);
3.用一个矩阵乘以矩阵堆栈的顶部矩阵,相乘得到的结果随后将存储在堆栈的顶部
void GLMatrixStack::MultMatrix(const M3DMatrix44f);
4.获取矩阵堆栈顶部的值
const M3DMatrix44f& GLMatrixStack::GetMatrix(void);
void GLMatrixStack::GetMatrix(M3DMatrix44f mMatrix);
5.压栈和出栈
void GLMatrixStack::PushMatrix(void);
void PushMatrix(const M3DMatrix44f mMatrix);
void PushMatrix(GLFrame& frame);
void GLMatrixStack::PopMatrix(void);
6.仿射变换
GLMatrixStack类也有对创建旋转、平移和缩放矩阵的支持。
void MatrixStack::Rotate(GLfloat angle,GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Translate(GLfloat x,GLfloat y,GLfloat z);
void MatrixStack::Scale(GLfloat x,GLfloat y,GLfloat z);
复制代码
我々は、ビューのグラフィカルな点を複数描画することにより、マトリックスコードおよびマトリックススタックの使用を見て:第一のヘッダファイルをインポートします。
#include "GLTools.h" // OpenGL toolkit
#include "GLMatrixStack.h" //矩阵堆栈工具类
#include "GLFrame.h" //矩阵位置工具类
#include "GLFrustum.h" // 透视投影矩阵类
#include "GLBatch.h" //三角形批次类
#include "GLGeometryTransform.h" //变换管道
#include "StopWatch.h"
#include <math.h> // 数学类
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
复制代码
グローバル変数を宣言します。
GLShaderManager shaderManager; //存储着色器管理
GLMatrixStack modelViewMatrix;//模型视图矩阵堆栈
GLMatrixStack projectionMatrix;// 投影视图矩阵堆栈
GLFrame cameraFrame;//观察者位置
GLFrame objectFrame;//世界坐标位置
GLFrustum viewFrustum;//视景体,用来构造投影矩阵
GLTriangleBatch CC_Triangle;//三角形批次类
//每一种图形都需要一个单独的三角形批次类:
GLTriangleBatch sphereBatch;//球
GLTriangleBatch torusBatch;//环
GLTriangleBatch cylinderBatch;//圆柱
GLTriangleBatch coneBatch;//锥
GLTriangleBatch diskBatch;//磁盘
GLGeometryTransform transformPipeline;//变换管道,用来管理模型,投影矩阵
M3DMatrix44f shadowMatrix;
GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f }; //定义颜色:绿色
GLfloat vBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };//定义颜色:黑色
int nStep = 0; //定义第几个图形
复制代码
プログラムエントリmain()関数:
int main(int argc, char* argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
//设置GLUT窗口大小、窗口标题
glutInitWindowSize(800, 600);
glutCreateWindow("Sphere");
//注册重塑函数---设置视口
glutReshapeFunc(ChangeSize);
//注册空格函数---切换图形
glutKeyboardFunc(KeyPressFunc);
//注册移动函数---上下左右移动图形
glutSpecialFunc(SpecialKeys);
//注册显示函数
glutDisplayFunc(RenderScene);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
return 1;
}
//设置渲染环境
SetupRC();
glutMainLoop();
return 0;
}
复制代码
リモデリング関数ChangeSize():ウィンドウが最初に表示される、または改造するとき、窓関数のサイズを変更する再と呼ばれる、時間値、Wニューを受信します。
void ChangeSize(int w, int h)
{
//1.视口
if(h == 0){ // 防止h变为0
h = 1;
}
glViewport(0, 0, w, h); //设置视口坐标,大小,一般情况下视口的坐标都是窗口的左下角,故设置为(0,0);
//2.设置透视投影
//创建透视投影矩阵
viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);
//projectionMatrix 投影视图矩阵堆栈---加载透视投影矩阵
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//3.modelViewMatrix 模型视图矩阵堆栈 ----加载一个单元矩阵
modelViewMatrix.LoadIdentity();
//4.通过GLGeometryTransform管理矩阵堆栈
//使用transformPipeline 管道管理模型视图矩阵堆栈 和 投影视图矩阵堆栈
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
复制代码
レンダリング環境SetupRC()関数を設定します。
// 将上下文中,进行必要的初始化
void SetupRC()
{
//1.设置背景颜色值
glClearColor(0.7f, 0.7f, 0.7f, 1.0f );
//2.初始化存储着色器管理
shaderManager.InitializeStockShaders();
//3.开启深度测试(无论绘制什么图形,都开启深度测试)
glEnable(GL_DEPTH_TEST);
//4.将观察者坐标位置Z移动往屏幕里移动15个单位位置
//表示离屏幕之间的距离。
//负数,是往屏幕后面移动
//正数,是往屏幕前面移动
cameraFrame.MoveForward(-15.0f);
//5.利用三角形批次类构造图形对象
// 球
/*
gltMakeSphere(GLTriangleBatch& sphereBatch, GLfloat fRadius, GLint iSlices, GLint iStacks);
参数1:sphereBatch,三角形批次类对象
参数2:fRadius,球体半径
参数3:iSlices,从球体底部堆叠到顶部的三角形带的数量;其实球体是一圈一圈三角形带组成
参数4:iStacks,围绕球体一圈排列的三角形对数
建议:一个对称较好的球体的片段数量是堆叠数量的2倍,就是iStacks = 2 * iSlices;
绘制球体都是围绕Z轴,这样+z就是球体的顶点,-z就是球体的底部。
*/
gltMakeSphere(sphereBatch, 3.0, 10, 20);
// 环面
/*
gltMakeTorus(GLTriangleBatch& torusBatch, GLfloat majorRadius, GLfloat minorRadius, GLint numMajor, GLint numMinor);
参数1:torusBatch,三角形批次类对象
参数2:majorRadius,甜甜圈中心到外边缘的半径
参数3:minorRadius,甜甜圈中心到内边缘的半径
参数4:numMajor,沿着主半径的三角形数量
参数5:numMinor,沿着内部较小半径的三角形数量
*/
gltMakeTorus(torusBatch, 3.0f, 0.75f, 15, 15);
// 圆柱
/*
void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
参数1:cylinderBatch,三角形批次类对象
参数2:baseRadius,底部半径
参数3:topRadius,头部半径
参数4:fLength,圆形长度
参数5:numSlices,围绕Z轴的三角形对的数量
参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
*/
gltMakeCylinder(cylinderBatch, 2.0f, 2.0f, 3.0f, 15, 2);
//锥
/*
void gltMakeCylinder(GLTriangleBatch& cylinderBatch, GLfloat baseRadius, GLfloat topRadius, GLfloat fLength, GLint numSlices, GLint numStacks);
参数1:cylinderBatch,三角形批次类对象
参数2:baseRadius,底部半径
参数3:topRadius,头部半径
参数4:fLength,圆形长度
参数5:numSlices,围绕Z轴的三角形对的数量
参数6:numStacks,圆柱底部堆叠到顶部圆环的三角形数量
*/
//圆柱体,从0开始向Z轴正方向延伸。
//圆锥体,是一端的半径为0,另一端半径可指定。
gltMakeCylinder(coneBatch, 2.0f, 0.0f, 3.0f, 13, 2);
// 磁盘
/*
void gltMakeDisk(GLTriangleBatch& diskBatch, GLfloat innerRadius, GLfloat outerRadius, GLint nSlices, GLint nStacks);
参数1:diskBatch,三角形批次类对象
参数2:innerRadius,内圆半径
参数3:outerRadius,外圆半径
参数4:nSlices,圆盘围绕Z轴的三角形对的数量
参数5:nStacks,圆盘外网到内围的三角形数量
*/
gltMakeDisk(diskBatch, 1.5f, 3.0f, 13, 3);
}
复制代码
RenderSceneは、シーン()関数を表示します。
//召唤场景
void RenderScene(void)
{
//1.清除当前缓存,防止在渲染过程中出现错误
//GL_COLOR_BUFFER_BIT :指当前激活的用来进行颜色写入缓冲区
//GL_DEPTH_BUFFER_BIT :指深度缓存区
//GL_STENCIL_BUFFER_BIT:指模板缓冲区
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
//2.模型视图矩阵栈堆,压栈
modelViewMatrix.PushMatrix();
//3.创建摄像头矩阵
M3DMatrix44f mCamera;
//从camereaFrame中获取矩阵到mCamera
cameraFrame.GetCameraMatrix(mCamera);
//模型视图堆栈的 矩阵与mCamera矩阵 相乘之后,存储到modelViewMatrix矩阵堆栈中
modelViewMatrix.MultMatrix(mCamera);
//4.创建矩阵mObjectFrame
M3DMatrix44f mObjectFrame;
//从ObjectFrame 获取矩阵到mOjectFrame中
objectFrame.GetMatrix(mObjectFrame);
//将modelViewMatrix 的堆栈中的矩阵 与 mOjbectFrame 矩阵相乘,存储到modelViewMatrix矩阵堆栈中
modelViewMatrix.MultMatrix(mObjectFrame);
//5.判断你目前是绘制第几个图形
switch(nStep) {
case 0:
DrawWireFramedBatch(&sphereBatch);
break;
case 1:
DrawWireFramedBatch(&torusBatch);
break;
case 2:
DrawWireFramedBatch(&cylinderBatch);
break;
case 3:
DrawWireFramedBatch(&coneBatch);
break;
case 4:
DrawWireFramedBatch(&diskBatch);
break;
}
//6. pop绘制完成之后,把栈顶矩阵pop出去,不要影响下一次的绘制。(还原到以前的模型视图矩阵 (单位矩阵))
modelViewMatrix.PopMatrix();
//7. 进行缓冲区交换
glutSwapBuffers();
}
复制代码
以下のハイライトは、このコードでマークを付けます。
- modelViewMatrix.PushMatrix();ここで、モデルビュー発現プッシュ、PushMatrix()は括弧空であるコンテンツプッシュが空であることを示していないが、マトリックススタックコピーの上部要素がプッシュであるものとします、スタックの最上部まで。ブラケットが空でない場合は、代わりに、スタックする行列スタックの行列に圧入。
- M3DMatrix44f mCamera;ステートメント観測行列; cameraFrame.GetCameraMatrix(mCamera)は、座標系cameraFrame視聴者からの行列を取得する手段、及びその後mCameraに割り当てられます。
- modelViewMatrix.MultMatrix(mCamera)は、マトリックスとマトリックスは、結果マトリックスで乗算トップオブザーバ行列(mCamera)を積層することを意味し、マトリックス(すなわち、単にマトリックススタックスタックを交換するバックスタックの最上位にスタックトップ行列)。
- M3DMatrix44f mObjectFrame;世界オブジェクトマトリックスの座標位置を宣言しました。objectFrame.GetMatrix(mObjectFrame);ワールド座標系、そして次いでmObjectFrameに割り当てobjectFrameから取得行列を意味します。
- modelViewMatrix.MultMatrix(mObjectFrame); modelViewMatrixは、スタック内のスタックは、結果マトリックススタックmodelViewMatrixスタックを得るために、マトリクスコピーmOjbectFrameマトリックス、マトリックスと乗算。(ここで注意:マトリックス乗算は可換ではないので、場合スタック行列乗算の上面、及び第mObjectFrameで、次いでmCameraであることができません)
- modelViewMatrix.PopMatrix();スタックのスタックアレイの上面は、元の行列にスタックに戻り、それはその後の描画に影響を及ぼさないことを意味します。
ここに約レコード:SetupRCで()このメソッドは、我々は、観察者の位置Zは、モバイル位置にスクリーン15点の座標単位に向かっcameraFrame.MoveForward(-15.0f)に移動する。実際には、我々は、視聴者を移動させることができず、その結果観察者にobjectFrame.MoveForward(15.0f)を移動物体、この場合RenderScene()このメソッドは、
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.MultMatrix(mCamera);
M3DMatrix44f mObjectFrame;
objectFrame.GetMatrix(mObjectFrame);
modelViewMatrix.MultMatrix(mObjectFrame);
复制代码
このコードは、モデルビュー行列スタックプッシュ動作、modelViewMatrix.PushMatrix()、いくつかの単語を追加する必要があります。objectFrame modelViewMatrix.PushMatrix(objectFrame)に押し込まれ、これはなぜ起こるのですか?我々SetupRC()メソッドので、オブザーバの状態へのオブジェクトの動きを記録objectFrameながらspecialKeys()メソッド、(objectFrame.RotateWorld(m3dDegToRad(-5.0f)、1.0F、は0.0f、は0.0f) ;)objectFrame世界と同じレコードは、システム移動状態、レンダリング時間の最後の座標(RenderScene())、modelViewMatrix.PushMatrix(objectFrame)は、行列スタックに結合変化と運動の回転を変化させることです。
この図は、スタック理解フローチャート行列のスタック上に描画されます。
()関数DrawWireFramedBatchをグラフ化:
void DrawWireFramedBatch(GLTriangleBatch* pBatch)
{
//----绘制图形----
//1.平面着色器,绘制三角形
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
//参数1:着色器类型
//参数2:通过transformPipeline获取模型视图投影矩阵
//参数3:颜色
//传过来的参数,对应不同的图形Batch
pBatch->Draw();
//2.开启多边形偏移
glEnable(GL_POLYGON_OFFSET_LINE);
//多边形模型(背面、线) 将多边形背面设为线框模式
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//开启多边形偏移(设置偏移数量)
glPolygonOffset(-1.0f, -1.0f);
//线条宽度
glLineWidth(2.5f);
//3.开启混合功能(颜色混合&抗锯齿功能)
glEnable(GL_BLEND);
//开启处理线段抗锯齿功能
glEnable(GL_LINE_SMOOTH);
//设置颜色混合因子
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//4.平面着色器绘制线条
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw();
//5.恢复多边形模式和深度测试
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}
复制代码
グラフィックス機能のSpecialKeysの移動():
//点击键盘的上下左右,来移动世界坐标系从而移动图形
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
//移动世界坐标系,而不是去移动物体。
//将世界坐标系在X方向移动-5.0
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_DOWN)
objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
if(key == GLUT_KEY_LEFT)
objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
if(key == GLUT_KEY_RIGHT)
objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
// 通知GLUT在进行一次同样操作
glutPostRedisplay();
}
复制代码
グラフィックス機能をKeyPressFunc(スイッチング):
//点击键盘空格,切换渲染的图形
void KeyPressFunc(unsigned char key, int x, int y)
{
if(key == 32)
{
nStep++;
if(nStep > 4)
nStep = 0;
}
switch(nStep)
{
case 0:
glutSetWindowTitle("Sphere");
break;
case 1:
glutSetWindowTitle("Torus");
break;
case 2:
glutSetWindowTitle("Cylinder");
break;
case 3:
glutSetWindowTitle("Cone");
break;
case 4:
glutSetWindowTitle("Disk");
break;
}
glutPostRedisplay();
}
复制代码
そして、コード実行のグラフィカルな結果を見てみましょう。
ます。https://juejin.im/post/5d09fbf75188252b8d1d454dで再現