配置GoogleTest
採用TDD(Test-Driven-Development)方式開發引擎,使用GoogleTest進行程序測試,便於開發過程中發現錯誤。
GoogleTest
-
下載:Github
-
環境搭建
- 拷貝googletest目錄中的src與include中gtest文件夾,放置於Middleware/gtest
- 建立新項目engineTester,將gtest/src/gtest-all.cc添加至項目中(此cpp爲所有程序代碼的集合)
- 添加myMain.cpp,編譯成功
-
使用方法
- 新建MyTempTestFile.cpp,包含gtest/test.h
#include <gtest/gtest.h>
TEST(MyTestSuiteName, MyTestName) {
int a = 1, b = 2, c = a + b;
EXPECT_EQ(c, 3);
EXPECT_TRUE(c == 3);
}
初步編寫Vector2D
//Vector2D.h
namespace Math {
struct Vector2D {
float x;
float y;
explicit Vector2D(const float& x = 0.0f, const float& y = 0.0f) :x(x), y(y) {}
};
inline Vector2D operator + (const Vector2D& a, const Vector2D& b);
inline Vector2D operator * (const Vector2D& a, const float& b);
inline Vector2D operator * (const float& a, const Vector2D& b);
#include "Vector2D.inl"
}
//Vector2D.inl
Vector2D operator + (const Vector2D& a, const Vector2D& b) {
return Vector2D(a.x + b.x, a.y + b.y);
}
Vector2D operator * (const Vector2D & a, const float& b) {
return Vector2D(a.x * b, a.y * b);
}
Vector2D operator *(const float& a, const Vector2D & b) {
return Vector2D(a * b.x, a * b.y);
}
實現openGL多幀繪製
-
QTimer && Q_OBJECT
- QTimer主要實現設定時間或立即觸發某一個槽,這裏用來觸發myUpdate
- connect(&myTimer,SIGNAL(timeout()),this,SLOT(myUpdate));
- 這裏需要myUpdate是一個槽信號,所以需要加private slots:
- 當對象需要信號槽時,需要令其爲Q_OBJECT,在類內添加Q_OBJECT宏
- 此時還需要利用QT程序中的moc.exe對Q_OBJECT程序進行重新編譯
- 查找到moc.exe後執行" moc.exe MyGlWindow.h > MyGlWindow_moc.cpp"到項目中
- 最後編譯成功,循環繪製
#ifndef SANDBOX_MY_GL_WINDOW
#define SANDBOX_MY_GL_WINDOW
#include <QtOpenGL/qgl.h>
#include <QtCore/qtimer.h>
class MyGlWindow : public QGLWidget
{
Q_OBJECT
QTimer myTimer;
protected:
void initializeGL();
void paintGL();
void resizeGL(int, int);
private slots:
void myUpdate();
};
#endif
簡易的圖形移動
- glBufferData不傳遞verts內容,只開闢verts大小內存,並設置爲GL_DYNAMIC_DRAW
- 在每次繪製前對verts進行矢量位移,通過glBufferSubData傳遞修改後的verts
- update中設置移動速度,迭代位移矢量,重繪圖像
#include <GL/glew.h>
#include "MyGlWindow.h"
#include <cassert>
#include <Math/Vector2D.h>
using Math::Vector2D;
namespace {
Vector2D verts[] = {
Vector2D(+0.1f,-0.1f),
Vector2D(+0.0f,+0.1f),
Vector2D(-0.1f,-0.1f),
};
Vector2D shipPosition(0.0f, 0.0f);
const int VERTS_NUM = sizeof(verts) / sizeof(*verts);
}
void MyGlWindow::initializeGL() {
GLenum errorCode = glewInit();
assert(errorCode == 0);
GLuint myBufferID;
glGenBuffers(1, &myBufferID);
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof verts, NULL,
GL_DYNAMIC_DRAW);
connect(&myTimer, SIGNAL(timeout()), this, SLOT(myUpdate()));
myTimer.start(0);
}
void MyGlWindow::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBufferData(GL_ARRAY_BUFFER, sizeof verts, verts, GL_DYNAMIC_DRAW);
Vector2D transVerts[VERTS_NUM];
for (int i = 0; i < VERTS_NUM; i++)
transVerts[i] = verts[i] + shipPosition;
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof transVerts, transVerts);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
void MyGlWindow::myUpdate() {
Vector2D velocity(0.001f,0.001f);
shipPosition = shipPosition + velocity;
repaint();
}
void MyGlWindow::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
}