3d引擎制作
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3d引擎制作相关的知识,希望对你有一定的参考价值。
3d引擎包含 照相机 camera,shader,视窗window ,对于界面这一块,如果在windows里面,可以选择mfc,不过为了跨平台,我们的选择就比较少了。
1 sdl
2 imgui
3 qt
4 sfml
5 glfw
其实五者都是可以的,要看读者自己熟悉程度,或者想做得程度。
摄像机
对于摄像机的计算,可以使用glm 来计算,这就相当于使用wsad四个键来在场景中漫游,如下所示:
void Camera::ProcessInput(unsigned int key)
switch (key)
case KEY_W :
this->_position += this->_direction * _speed;
break;
case KEY_A:
this->_position -= glm::cross(this->_direction, this->_up) * _speed;
break;
case KEY_S:
this->_position -= this->_direction * _speed;
break;
case KEY_D:
this->_position += glm::cross(this->_direction, this->_up) * _speed;
break;
default:
return;
UpdateMatrix();
摄像机在处理点击转动,实际上就是在点击鼠标过后的转动摄像机行为
void Camera::ProcessCursorPos(double xpos, double ypos)
static bool bFirstCall = true;
static glm::dvec2 lastCursorPos;
const glm::dvec2 cursorPos(xpos, ypos);
if (bFirstCall)
lastCursorPos = cursorPos;
bFirstCall = false;
constexpr float sensitivity = 8e-2f;
const float xoffset = static_cast<float>(lastCursorPos.x - cursorPos.x) * sensitivity;
const float yoffset = static_cast<float>(lastCursorPos.y - cursorPos.y) * sensitivity;
lastCursorPos = cursorPos;
//! create quaternion matrix with up vector and yaw angle.
auto yawQuat = glm::angleAxis(glm::radians(xoffset), this->_up);
//! create quaternion matrix with right vector and pitch angle.
auto pitchQuat = glm::angleAxis(glm::radians(yoffset), glm::cross(this->_direction, this->_up));
this->_direction = glm::normalize(yawQuat * pitchQuat) * this->_direction;
UpdateMatrix();
渲染器
3d引擎比较重要的就是渲染器
class Renderer
public:
//! Default constructor
Renderer();
//! Default desctrutor
virtual ~Renderer();
//! Initialize the Renderer
bool Initialize(const cxxopts::ParseResult& configure);
//! Add application implementation
bool AddApplication(std::shared_ptr<Application> app, const cxxopts::ParseResult& configure);
//! Update the application with delta time.
void UpdateFrame(double dt);
//! Draw the one frame of the application.
void DrawFrame();
//! Clean up the all resources.
void CleanUp();
//! Returns the current bound application
std::shared_ptr< GL3::Application > GetCurrentApplication() const;
//! Returns the current application's window
std::shared_ptr< GL3::Window > GetWindow() const;
//! Returns whether this renderer should exit or not.
bool GetRendererShouldExit() const;
//! Switch the current app to the next given application
void SwitchApplication(std::shared_ptr< GL3::Application > app);
void SwitchApplication(size_t index);
protected:
virtual bool OnInitialize(const cxxopts::ParseResult& configure) = 0;
virtual void OnCleanUp() = 0;
virtual void OnUpdateFrame(double dt) = 0;
virtual void OnBeginDraw() = 0;
virtual void OnEndDraw() = 0;
virtual void OnProcessInput(unsigned int key) = 0;
virtual void OnProcessResize(int width, int height) = 0;
//! Begin of GPU Time measurement
void BeginGPUMeasure();
//! End of GPU Time measurement and returns elapsed time
size_t EndGPUMeasure();
std::weak_ptr< GL3::Application > _currentApp;
std::vector< std::shared_ptr< GL3::Application > > _applications;
std::shared_ptr< GL3::Window > _mainWindow;
std::vector< std::shared_ptr< GL3::Window > > _sharedWindows;
std::unique_ptr< PostProcessing > _postProcessing;
private:
//! Process the input key
void ProcessInput(unsigned int key);
//!Process the mouse cursor positions
void ProcessCursorPos(double xpos, double ypos);
//!Resize the renderer resources
void ProcessResize(int width, int height);
DebugUtils _debug;
GLuint _queryID;
bool _bMeasureGPUTime;
;
;
加载模型文件
我们使用assimp来加载模型文件,比如obj,mtl,gltf等等文件,如果有必要,我们可以加载ifc文件,ifc是bim所用文件标准
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "stb_image.h"
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include "model.h"
#include "mesh.h"
Model::Model()
Model::~Model()
void Model::loadModel(std::string path)
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
if(!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
std::cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << std::endl;
return;
this->directory = path.substr(0, path.find_last_of('/'));
this->processNode(scene->mRootNode, scene);
void Model::Draw()
for(GLuint i = 0; i < this->meshes.size(); i++)
this->meshes[i].Draw();
void Model::processNode(aiNode* node, const aiScene* scene)
for(GLuint i = 0; i < node->mNumMeshes; i++)
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
this->meshes.push_back(this->processMesh(mesh, scene));
for(GLuint i = 0; i < node->mNumChildren; i++)
this->processNode(node->mChildren[i], scene);
Mesh Model::processMesh(aiMesh* mesh, const aiScene* scene)
std::vector<Vertex> vertices;
std::vector<GLuint> indices;
for(GLuint i = 0; i < mesh->mNumVertices; i++)
Vertex vertex;
glm::vec3 vector;
vector.x = mesh->mVertices[i].x;
vector.y = mesh->mVertices[i].y;
vector.z = mesh->mVertices[i].z;
vertex.Position = vector;
vector.x = mesh->mNormals[i].x;
vector.y = mesh->mNormals[i].y;
vector.z = mesh->mNormals[i].z;
vertex.Normal = vector;
if(mesh->mTextureCoords[0])
glm::vec2 vec;
vec.x = mesh->mTextureCoords[0][i].x;
vec.y = mesh->mTextureCoords[0][i].y;
vertex.TexCoords = vec;
else
vertex.TexCoords = glm::vec2(0.0f, 0.0f);
vertices.push_back(vertex);
for(GLuint i = 0; i < mesh->mNumFaces; i++)
aiFace face = mesh->mFaces[i];
for(GLuint j = 0; j < face.mNumIndices; j++)
indices.push_back(face.mIndices[j]);
return Mesh(vertices, indices);
其他
其他涉及比较多的技术,我们下次再说。直到我们真实建立场景。
以上是关于3d引擎制作的主要内容,如果未能解决你的问题,请参考以下文章