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);
}

其他

其他涉及比较多的技术,我们下次再说。直到我们真实建立场景。

猜你喜欢

转载自blog.csdn.net/qianbo042311/article/details/127372598