初心者にとって、小規模なプロジェクトには、glut で十分です。その定義は、単純なプログラムや初心者が使い方を学ぶには、シンプル、簡単、小規模です。
vs2015 で空のプロジェクトを作成します。
次に、glut のインクルード パスをプロジェクトに追加します。
まず、glut.h を呼び出す大きなフレームワークを作成します。
#include <GL/glut.h>
// 创建图形窗口的基本宏
#define WINDOW_X_POS 50
#define WINDOW_Y_POS 50
#define WIDTH 700
#define HEIGHT 700
// 用于注册 GLUT 的回调
void onDisplay(void);
void onUpdate(void);
void onKeyboard(unsigned char key, int x, int y);
int main(int argc, char* argv[]) {
// 对 GLUT 进行初始化,并处理所有的命令行参数
glutInit(&argc, argv);
// 这个函数指定了使用 RGBA 模式还是颜色索引模式。另外还可以
// 指定是使用单缓冲还是双缓冲窗口。这里我们使用 RGBA 和 双缓冲窗口
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
// 设置窗口被创建时左上角位于屏幕上的位置
glutInitWindowPosition(WINDOW_X_POS, WINDOW_Y_POS);
// 设置窗口被创建时的宽高, 为了简便起见
glutInitWindowSize(WIDTH, HEIGHT);
// 创建一个窗口,输入的字符串为窗口的标题
glutCreateWindow("SolarSystem at Shiyanlou");
// glutDisplayFunc 的函数原型为 glutDisplayFunc(void (*func)(void))
// 这是一个回调函数,每当 GLUT 确定一个窗口的内容需要更新显示的时候,
// glutDisplayFunc 注册的回调函数就会被执行.
//
// glutIdleFunc(void (*func)(void)) 将指定一个函数,用于处理当事件循环
// 处于空闲的时候,就执行这个函数。这个回调函数接受一个函数指针作为它的唯一参数
//
// glutKeyboardFunc(void (*func)(unsigned char key, int x, int y))
// 会将键盘上的键与一个函数关联,当这个键被按下或者释放时,函数就会调用
//
// 因此下面的三行实际上是在向 GLUT 注册关键的三个回调函数
glutDisplayFunc(onDisplay);
glutIdleFunc(onUpdate);
glutKeyboardFunc(onKeyboard);
glutMainLoop();
return 0;
}
必要な変更を加えます。
//
// main.cpp
// solarsystem
//
#include <GL/glut.h>//glut基本头文件
#include "solarsystem.h"
//创建图形窗口的基本宏
#define WINDOW_X_POS 50
#define WINDOW_Y_POS 50
#define WIDTH 700
#define HEIGHT 700
SolarSystem solarsystem;
//用于注册glut的回调
void onDisplay(void) {
solarsystem.onDisplay();
}
void onUpdate(void) {
solarsystem.onUpdate();
}
void onKeyboard(unsigned char key, int x, int y) {
solarsystem.onKeyboard(key, x, y);
}
int main(int argc, char* argv[]) {
glutInit(&argc, argv);//对GLUT初始化,并处理所有命令行参数
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
//指定使用RGBA模式
//另外指定了双缓冲窗口
glutInitWindowPosition(WINDOW_X_POS, WINDOW_Y_POS);
//指定窗口创建时左上角位于屏幕的位置
glutCreateWindow("SolarSystem");
//指定创建的窗口标题为SolarSystem
glutDisplayFunc(onDisplay);
//回调函数,当GLUT确定窗口内容需要更新时
//指定函数onDisplay就会被执行
glutIdleFunc(onUpdate);
//指定函数onUpdate
//当事件循环处于空闲,执行此函数
glutKeyboardFunc(onKeyboard);
//将键盘上的键与函数相关联,按键被按下或者释放,函数调用
glutMainLoop();
return 0;
}
基本知識:
シングル バッファリング: すべての命令をウィンドウ上で直接実行します (つまり、描画)。ただし、非効率的であり、コンピュータのパフォーマンスによって制限されます。パソコンの性能が低いとちらつきが発生します。
ダブルバッファリング: 描画命令はバッファ内で完了し、完了後に交換命令を経て完成したグラフィックスを出力するため、視覚効果が良く、シングルバッファリングより効率が高くなります。
ダブルバッファリングはフロントバッファリングとバックグラウンドバッファリングに分けられ、フロントバッファリングは肉眼で見る画面、バックバッファリングはメモリ内にバッファリングされます。後者の操作では、完成したイメージが画面にコピーされます。描画操作はグラフィックス カードでリアルタイムに実行されるため、タスクと IO 操作が複雑になり、表示効果が非常に低くなります。交換バッファに描画すると、効果をグラフィックスに直接送信できます。後でレンダリングするためのカード。
C++ なので、当然オブジェクト指向の操作が必要ですが、私のプロジェクトの名前が見えますか? あ、リリースしてないですよ、ハハハ。ここでは実験棟で太陽系を描いた記録をもとに、実際にパソコン上で操作を行っています。
- クラス設計:
基本的な設定を行う まず、太陽系は天体系なので、概念的な天体系を抽出します。天体システムでは、最も基本的な物体は天体(星)であり、その上に、熱を発する星(fixed_star)、様々な星が捕らえた特定の軌道を持つ惑星(planet)、もう 1 つは、これら 2 つの普遍的な要素以外の天体です。ここでは (星星、特別な星) と呼びます。通常の設定をいくつか設定します。惑星
の軌道は円形です。
回転速度は同じにします。
更新間隔は 1 日に設定します。 、ある日の終わり、リフレッシュを開始
初期化は次のとおりです:
OpenGL エンジンを初期化し、onDraw と onUpdate を実装します。
惑星には独自の属性、軌道関係、および変換関連の描画があるため、惑星クラスを設計するときは、回転用のdraw() メソッドを提供する必要があります。 update() メソッドは更新を制御するために使用されます。
各惑星のdraw() メソッドは onDraw() で呼び出される必要があります。
各惑星の update() メソッドは onUpdate で呼び出される必要があります。 ();
キーボードは、onKeyboard() で太陽系全体の表示を調整します。
特定の属性:
色 color
回転半径 半径
回転速度 RotationSp
回転速度 RevolutionSp
太陽の中心からの距離
親星の周りを周回する惑星の距離
現在の回転角度 Rotation_angle
現在の回転角度 Revolution_angle
さて、基本的なスタイルは次のとおりです。
- 対応するヘッダー ファイル
スター ヘッダー ファイルを書き込む
class Star {
public:
// 星球的运行半径
GLfloat radius;
// 星球的公转、自传速度
GLfloat rotationSp, revolutionSp;
// 星球的中心与父节点星球中心的距离
GLfloat distance;
// 星球的颜色
GLfloat rgbaColor[4];
// 父节点星球
Star* parentStar;
// 构造函数,构造一颗星球时必须提供
// 旋转半径、旋转速度、自转速度、绕行(父节点)星球
Star(GLfloat radius, GLfloat distance,
GLfloat revolutionSp, GLfloat rotationSp,
Star* parentStar);
// 对一般的星球的移动、旋转等活动进行绘制
void drawStar();
// 提供默认实现,负责调用 drawStar()
virtual void draw() {
drawStar(); }
// 参数为每次刷新画面时的时间跨度
virtual void update(long timeSpan);
protected:
GLfloat rotationang, revolution_angle;
};
class Planet : public Star {
public:
// 构造函数
Planet(GLfloat radius, GLfloat distance,
GLfloat revolutionSp, GLfloat rotationSp,
Star* parentStar, GLfloat rgbColor[3]);
// 增加对具备自身材质的行星绘制材质
void drawPlanet();
// 继续向其子类开放重写功能
virtual void draw() {
drawPlanet(); drawStar(); }
};
class Fixed_star : public Planet {
public:
Fixed_star(GLfloat Radius, GLfloat Distance,
GLfloat revolutionSp, GLfloat rotationSp,
Star* ParentStar, GLfloat rgbColor[]);
// 增加对提供光源的恒星绘制光照
void drawsun();
virtual void draw() {
drawsun(); drawPlanet(); drawStar(); }
};
次に、太陽系の設計です。
#include"stars.h"
#include<GL/glut.h>
#define STARS_NUM 10
class SolarSystem {
public:
SolarSystem();
~SolarSystem();
void onDisplay();
void onUpdate();
void onKeyboard(unsigned char key, int x, int y);
private:
Star *stars[STARS_NUM];
// 定义观察视角的参数
GLdouble viewX, viewY, viewZ;
GLdouble centerX, centerY, centerZ;
GLdouble upX, upY, upZ;
};
太陽系には、
星を基本天体とする 9 つの内部メンバー (冥王星を除く) があります。
#define STARS_NUM 10
enum STARS {
Sun, // 太阳
Mercury, // 水星
Venus, // 金星
Earth, // 地球
Moon, // 月球
Mars, // 火星
Jupiter, // 木星
Saturn, // 土星
Uranus, // 天王星
Neptune // 海王星
};
Star * stars[STARS_NUM];
//相同自转速度
#define TIMEPAST 1
#define SELFROTATE 3
- クラスメソッドの実装
//
// stars.cpp
// solarsystem
//
#include "stars.h"
#define PI 3.1415926535
Star::Star(GLfloat radius, GLfloat distance,
GLfloat revolutionSp, GLfloat rotationSp,
Star* parentStar) {
// TODO:
}
void Star::drawStar() {
// TODO:
}
void Star::update(long timeSpan) {
// TODO:
}
Planet::Planet(GLfloat radius, GLfloat distance,
GLfloat revolutionSp, GLfloat rotationSp,
Star* parentStar, GLfloat rgbColor[3]):Star(radius,distance,revolutionSp,rotationSp,parentStar){
// TODO:
}
void Planet::drawPlanet() {
// TODO:
}
Fixed_star::Fixed_star(GLfloat Radius, GLfloat Distance,
GLfloat revolutionSp, GLfloat rotationSp,
Star* ParentStar, GLfloat rgbColor[]):
Planet(radius, distance, revolutionSp,rotationSp, parentStar, rgbColor) {
// TODO:
}
void Fixed_star::drawsun() {
// TODO:
}
//
//
// solarsystem
//
#include "solarsystem.h"
#define TIMEPAST 1
#define SELFROTATE 3
enum STARS {
Sun, Mercury, Venus, Earth, Moon,
Mars, Jupiter, Saturn, Uranus, Neptune
};
void SolarSystem::onDisplay() {
// TODO:
}
void SolarSystem::onUpdate() {
// TODO:
}
void SolarSystem::onKeyboard(unsigned char key, int x, int y) {
// TODO:
}
SolarSystem::SolarSystem() {
// TODO:
}
SolarSystem::~SolarSystem() {
// TODO:
}
- 最初にこのフレームワークの実現可能性をテストしたいため、メソッド宣言は完了していません。そのため、最初にコンパイルします。結果は次のとおりです
エラー LNK1104 では、ファイル「glut32.lib」を開くことができません。solarsystem
これは、接続エラーです。glut をダウンロードしたときに、glut32.lib やその他のファイルが見つからなかったため、プロジェクトを作成したときにダイナミック ライブラリに含めなかったためです。今すぐ解決する必要があります。これが問題です。
- glut32.lib
Baiduをリンクした結果、オリジナルのglutは古すぎて放棄されており、代替バージョンのfreeglutが存在します。ここでは、
多くの便利な開発ライブラリの推奨ダウンロード
ソースを
紹介しますが、最新バージョンに対応しています。そして古いバージョンには lib ディレクトリがありません。ああ、ははは、解決策を探し続けましたが
、最終的には方法がありませんでした。リソースは他の人がお金を稼ぐ方法として使用していたか、私のネットワークがリソースに接続できなかったかのどちらかです。そのため、特定のパッケージを探す必要がありました(お金を稼ぎたいという人々の欲求と資源の貴重さを深く理解する)。 - 考え方を変え
、Windows で挫折の連続だった私は、実験棟のシステムを真似して Unix システムで実験したくて仕方がありませんでした。とにかく使い方を覚え、Linux を学ぶことです。仮想マシンも例外ではありません。
centos7を使用しているため、研究室棟のように直接コマンドを使うことができません。
sudo apt-get update && sudo apt-get install freeglut3 freeglut3-dev
centos7 で実行すると sudo コマンドが見つからないため、centos7 は引き続き yum を使用してインストールします。
# yum list mesa*
# yum install -y mesa*
# yum install -y freeglut*
# yum install -y *glew*
インストール後、以前のプログラムをテストしましたが、問題が発生しました。vs2015 で以前編集したため、フォーマットの問題が多すぎたので、それを解決する良い方法があれば、教えてください。ありがとうございます (つまり、私は古い方法を使用しました!それに応じてスペースを削除してください!) ああ、ちなみに、別の方法もあります。つまり、vim でドキュメントを作成し、保存して、編集せずに直接終了します。。。。。。この方法を覚えるまでに 2 ~ 3 回の試行が必要でした。
次のステップはメイクファイルを作成することです
CXX = g++
EXEC = solarsystem
SOURCES = main.cpp stars.cpp solarsystem.cpp
OBJECTS = main.o stars.o solarsystem.o
LDFLAGS = -lglut -lGL -lGLU
all :
$(CXX) $(SOURCES) $(LDFLAGS) -o $(EXEC)
clean:
rm -f $(EXEC) *.gdb *.o
ここで make をコンパイルすると、次のエラーが発生します。
make: *** makefile: 是一个目录。 停止。
Baidu が取得した結果:
特殊変数 VPATH の書き込みエラーが発生しました. VPATH は makefile 内の特殊変数であり, ターゲット ファイルと依存ファイルをマークするために使用されます. 定義されていない場合は, で検索されますそれが置かれているディレクトリ。ここまで来るのはかなり面倒なので、しばらく放置して、続きは明日にします。
ああ、忘れていましたが、直接コンパイルして実行することもできます。
g++ solarsystem.cpp stars.cpp main.cpp -o solarsystem
その後、エラーが発生しました。。。。。。
問題は次のようになります。
/tmp/ccn3DYud.o:在函数‘main’中:
main.cpp:(.text+0x69):对‘glutInit’未定义的引用
main.cpp:(.text+0x73):对‘glutInitDisplayMode’未定义的引用
main.cpp:(.text+0x82):对‘glutInitWindowPosition’未定义的引用
main.cpp:(.text+0x8c):对‘glutCreateWindow’未定义的引用
main.cpp:(.text+0x96):对‘glutDisplayFunc’未定义的引用
main.cpp:(.text+0xa0):对‘glutIdleFunc’未定义的引用
main.cpp:(.text+0xaa):对‘glutKeyboardFunc’未定义的引用
main.cpp:(.text+0xaf):对‘glutMainLoop’未定义的引用
collect2: 错误:ld 返回 1
まだリンクもコンパイルもされていないことが分かり、学習を諦めたので、もう一度勉強してみます!
g++ main.cpp stars.cpp solarsystem.cpp -lglut -lGL -lGLU -o solarsystem
すると、生成されました!
楽しそうに走っていましたが、顔は真っ黒でした。。。。。。結局のところ、上記のメンバー関数はまだ完成されていないので、満足してください。メイクファイルもうまく書けません(残念)。
フォローアップは次のとおりです:
openGL の学習 太陽系 天体系の描画