assimp/tools/assimp_qt_viewer/glview.hpp

385 lines
16 KiB
C++

/// \file glview.hpp
/// \brief OpenGL visualisation.
/// \author smal.root@gmail.com
/// \date 2016
#pragma once
// Header files, Qt.
#include <QtOpenGL>
// Header files Assimp
#include <assimp/scene.h>
/// \class CGLView
/// Class which hold and render scene.
class CGLView : public QGLWidget
{
Q_OBJECT
/**********************************/
/************* Types **************/
/**********************************/
private:
/// \struct SBBox
/// Bounding box for object.
struct SBBox
{
aiVector3D Minimum;///< Minimum values of coordinates.
aiVector3D Maximum;///< Maximum values of coordinates.
};
/// \struct SHelper_Mesh
/// Helper object for fast rendering of mesh (\ref aiMesh).
struct SHelper_Mesh
{
const size_t Quantity_Point;///< Quantity of points.
const size_t Quantity_Line;///< Quantity of lines.
const size_t Quantity_Triangle;///< Quantity of triangles.
GLuint* Index_Point;///< Array of indices for drawing points.
GLuint* Index_Line;///< Array of indices for drawing lines.
GLuint* Index_Triangle;///< Array of indices for drawing triangles.
const SBBox BBox;///< BBox of mesh.
/// \fn explicit SHelper_Mesh(const size_t pQuantity_Point, const size_t pQuantity_Line, const size_t pQuantity_Triangle, const SBBox& pBBox = {{0, 0, 0}, {0, 0, 0}})
/// Constructor.
/// \param [in] pQuantity_Point - quantity of points.
/// \param [in] pQuantity_Line - quantity of lines.
/// \param [in] pQuantity_Triangle - quantity of triangles.
/// \param [in] pBBox - BBox of mesh.
explicit SHelper_Mesh(const size_t pQuantity_Point, const size_t pQuantity_Line, const size_t pQuantity_Triangle, const SBBox& pBBox = {{0, 0, 0}, {0, 0, 0}});
/// \fn ~SHelper_Mesh()
/// Destructor.
~SHelper_Mesh();
};
/// \struct SHelper_Camera
/// Information about position of the camera in space.
struct SHelper_Camera
{
aiVector3D Position;///< Coordinates of the camera.
aiVector3D Target;///< Target point of the camera.
// Transformation path:
// set Camera -> Rotation_AroundCamera -> Translation_ToScene -> Rotation_Scene -> draw Scene
aiMatrix4x4 Rotation_AroundCamera;///< Rotation matrix which set rotation angles of the scene around camera.
aiMatrix4x4 Rotation_Scene;///< Rotation matrix which set rotation angles of the scene around own center.
aiVector3D Translation_ToScene;///< Translation vector from camera to the scene.
/// \fn void SetDefault()
/// Set default parameters of camera.
void SetDefault();
};
public:
/// \enum ELightType
/// Type of light source.
enum class ELightType { Directional, Point, Spot };
/// \struct SLightParameters
/// Parameters of light source.
struct SLightParameters
{
aiLightSourceType Type;///< Type of light source.
aiColor4D Ambient;///< Ambient RGBA intensity of the light.
aiColor4D Diffuse;///< Diffuse RGBA intensity of the light.
aiColor4D Specular;///< Specular RGBA intensity of the light.
union UFor
{
/// \struct SDirectional
/// Parameters of directional light source.
struct SDirectional
{
aiVector3D Direction;
SDirectional() {}
} Directional;
/// \struct SPoint
/// Parameters of point light source.
struct SPoint
{
aiVector3D Position;
GLfloat Attenuation_Constant;
GLfloat Attenuation_Linear;
GLfloat Attenuation_Quadratic;
SPoint() {}
} Point;
/// \struct SSpot
/// Parameters of spot light source.
struct SSpot
{
aiVector3D Position;
GLfloat Attenuation_Constant;
GLfloat Attenuation_Linear;
GLfloat Attenuation_Quadratic;
aiVector3D Direction;
GLfloat CutOff;
SSpot() {}
} Spot;
UFor() {}
} For;
SLightParameters() {}
};
/**********************************/
/************ Variables ***********/
/**********************************/
private:
// Scene
const aiScene* mScene = nullptr;///< Copy of pointer to scene (\ref aiScene).
SBBox mScene_BBox;///< Bounding box of scene.
aiVector3D mScene_Center;///< Coordinates of center of the scene.
bool mScene_DrawBBox = false;///< Flag which control drawing scene BBox.
// Meshes
size_t mHelper_Mesh_Quantity = 0;///< Quantity of meshes in scene.
SHelper_Mesh** mHelper_Mesh = nullptr;///< Array of pointers to helper objects for drawing mesh. Sequence of meshes are equivalent to \ref aiScene::mMeshes.
// Cameras
SHelper_Camera mHelper_Camera;///< Information about current camera placing in space.
SHelper_Camera mHelper_CameraDefault;///< Information about default camera initial placing in space.
bool mCamera_DefaultAdded = true;///< If true then scene has no defined cameras and default was added, if false - scene has defined cameras.
GLdouble mCamera_FOVY = 45.0;///< Specifies the field of view angle, in degrees, in the y direction.
GLdouble mCamera_Viewport_AspectRatio;///< Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
// Lighting
bool mLightingEnabled = false;///< If true then OpenGL lighting is enabled (glEnable(GL_LIGHTING)), if false - disabled.
// Textures
///TODO: map is goooood, but not for case when one image can be used in different materials with difference in: texture transformation, targeting of the
/// texture (ambient or emission, or even height map), texture properties.
QMap<QString, GLuint> mTexture_IDMap;///< Map image filenames to textures ID's.
/**********************************/
/************ Functions ***********/
/**********************************/
private:
// Why in some cases pointers are used? Because: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
template<typename TArg> void AssignIfLesser(TArg* pBaseValue, const TArg pTestValue) { if(pTestValue < *pBaseValue) *pBaseValue = pTestValue; }
template<typename TArg> void AssignIfGreater(TArg* pBaseValue, const TArg pTestValue) { if(pTestValue > *pBaseValue) *pBaseValue = pTestValue; }
template<typename TArg> void AssignIfLesser(TArg& pBaseValue, const TArg pTestValue) { if(pTestValue < pBaseValue) pBaseValue = pTestValue; }
template<typename TArg> void AssignIfGreater(TArg& pBaseValue, const TArg pTestValue) { if(pTestValue > pBaseValue) pBaseValue = pTestValue; }
/// \fn void Material_Apply(const aiMaterial* pMaterial)
/// Enable pointed material.
/// \param [in] pMaterial - pointer to material which must be used.
void Material_Apply(const aiMaterial* pMaterial);
/// \fn void Matrix_NodeToRoot(const aiNode* pNode, aiMatrix4x4& pOutMatrix)
/// Calculate matrix for transforming coordinates from pointed node to root node (read as "global coordinate system").
/// \param [in] pNode - pointer initial node from which relative coordintaes will be taken,
/// \param [out] pOutMatrix - matrix for transform relative coordinates in \ref pNode to coordinates in root node (\ref aiScene::mRootNode).
void Matrix_NodeToRoot(const aiNode* pNode, aiMatrix4x4& pOutMatrix);
/// \fn void ImportTextures()
/// Import textures.
/// \param [in] pScenePath - path to the file of the scene.
void ImportTextures(const QString& pScenePath);
/// \fn void BBox_GetForNode(const aiNode& pNode, const aiMatrix4x4& pParentNode_TransformationMatrix, SBBox& pNodeBBox, bool& pFirstAssign)
/// Calculate BBox for pointed node. Function walk thru child nodes and apply all transformations.
/// \param [in] pNode - reference to node for which needed BBox.
/// \param [in] pParent_TransformationMatrix - reference to parent (parent for pNode) transformation matrix.
/// \param [in,out] pNodeBBox - reference to where pNode BBox will be placed. It will expanded by child nodes BBoxes.
/// \param [in] pFirstAssign - means that pNodeBBox not contain valid BBox at now and assign ('=') will used for setting new value, If
/// false then \ref BBox_Extend will be used for setting new BBox.
void BBox_GetForNode(const aiNode& pNode, const aiMatrix4x4& pParent_TransformationMatrix, SBBox& pNodeBBox, bool& pFirstAssign);
/// \fn void BBox_Extend(const SBBox& pChild, SBBox& pParent)
/// Check and if need - extend current node BBox with BBox of child node.
/// \param [in] pChild - reference to BBox which used for extend parent BBox.
/// \param [in.out] pParent - BBox which will be extended using child BBox.
void BBox_Extend(const SBBox& pChild, SBBox& pParent);
/// \fn void BBox_GetVertices(const SBBox& pBBox, aiVector3D pVertices[8])
/// Get vertices of a parallelepiped which is described by BBox.
/// \param [in] pBBox - input BBox.
/// \param [out] pVertices - array of vertices.
void BBox_GetVertices(const SBBox& pBBox, aiVector3D pVertices[8]);
/// \fn void BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVerticesQuantity, SBBox& pBBox)
/// Calculate BBox for vertices array.
/// \param [in] pVertices - vertices array.
/// \param [in] pVerticesQuantity - quantity of vertices in array. If 0 then pBBox will be assigned with {{0, 0, 0}, {0, 0, 0}}.
/// \param [out] pBBox - calculated BBox.
void BBox_GetFromVertices(const aiVector3D* pVertices, const size_t pVerticesQuantity, SBBox& pBBox);
/********************************************************************/
/************************ Logging functions *************************/
/********************************************************************/
/// \fn void LogInfo(const QString& pMessage)
/// Add message with severity "Warning" to log.
void LogInfo(const QString& pMessage);
/// \fn void LogError(const QString& pMessage)
/// Add message with severity "Error" to log.
void LogError(const QString& pMessage);
/********************************************************************/
/************************** Draw functions **************************/
/********************************************************************/
/// \fn void Draw_Node(const aiNode* pNode)
/// Apply node transformation and draw meshes assigned to this node.
/// \param [in] pNode - pointer to node for drawing (\ref aiNode).
void Draw_Node(const aiNode* pNode);
/// \fn void Draw_Mesh(const size_t pMesh_Index)
/// Draw mesh.
/// \param [in] pMesh_Index - index of mesh which must be drawn. Index point to mesh in \ref mHelper_Mesh.
void Draw_Mesh(const size_t pMesh_Index);
/// \fn void Draw_BBox(const SBBox& pBBox)
/// Draw bounding box using lines.
/// \param [in] pBBox - bounding box for drawing.
void Draw_BBox(const SBBox& pBBox);
/********************************************************************/
/*********************** Overrided functions ************************/
/********************************************************************/
protected:
void drawCoordSystem();
/// \fn void initializeGL() override
/// Overrided function for initialise OpenGL.
void initializeGL() override;
/// \fn void resizeGL(int pWidth, int pHeight) override
/// \param [in] pWidth - new width of viewport.
/// \param [in] pHeight - new height of viewport.
void resizeGL(int pWidth, int pHeight) override;
/// \fn void paintGL() override
/// Overrided function for rendering.
void paintGL() override;
public:
/********************************************************************/
/********************** Constructor/Destructor **********************/
/********************************************************************/
/// \fn explicit CGLView(QWidget* pParent)
/// Constructor.
/// \param [in] pParent - parent widget.
explicit CGLView(QWidget* pParent);
/// \fn virtual ~CGLView()
/// Destructor.
virtual ~CGLView();
/********************************************************************/
/********************* Scene control functions **********************/
/********************************************************************/
/// \fn void FreeScene()
/// Free all helper objects data.
void FreeScene();
/// \fn void SetScene(const aiScene* pScene)
/// Set scene for rendering.
/// \param [in] pScene - pointer to scene.
/// \param [in] pScenePath - path to the file of the scene.
void SetScene(const aiScene* pScene, const QString& pScenePath);
/// \fn void Enable_SceneBBox(const bool pEnable)
/// Enable drawing scene bounding box.
/// \param [in] pEnable - if true then bbox will be drawing, if false - will not be drawing.
void Enable_SceneBBox(const bool pEnable) { mScene_DrawBBox = pEnable; }
/// \fn void Enable_Textures(const bool pEnable)
/// Control textures drawing.
/// \param [in] pEnable - if true then enable textures, false - disable textures.
void Enable_Textures(const bool pEnable);
/********************************************************************/
/******************** Lighting control functions ********************/
/********************************************************************/
/// \fn void Lighting_Enable()
/// Enable OpenGL lighting.
void Lighting_Enable();
/// \fn void Lighting_Disable()
/// Disable OpenGL lighting.
void Lighting_Disable();
/// \fn void Lighting_EditSource(const size_t pLightNumber, const SLightParameters& pLightParameters)
/// Edit light source properties.
/// \param [in] pLightNumber - light source number. \ref aiScene::mLights.
/// \param [in] pLightParameters - light source parameters.
void Lighting_EditSource(const size_t pLightNumber, const SLightParameters& pLightParameters);///TODO: function set
/// \fn void Lighting_EnableSource(const size_t pLightNumber)
/// Enable light source.
/// \param [in] pLightNumber - light source number. \ref aiScene::mLights.
void Lighting_EnableSource(const size_t pLightNumber);
///void Lighting_DisableSource(const size_t pLightNumber)
/// Disable light source,
/// \param [in] pLightNumber - light source number. \ref aiScene::mLights.
void Lighting_DisableSource(const size_t pLightNumber);
/********************************************************************/
/******************** Cameras control functions *********************/
/********************************************************************/
/// \fn void Camera_Set(const size_t pCameraNumber)
/// Set view from pointed camera.
/// \param [in] pCamera_Index - index of the camera (\ref aiScene::mCameras).
void Camera_Set(const size_t pCameraNumber);
/// \fn void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
/// Rotate scene around axisees.
/// \param [in] pAngle_X - specifies the angle of rotation around axis oX, in degrees.
/// \param [in] pAngle_Y - specifies the angle of rotation around axis oY, in degrees.
/// \param [in] pAngle_Z - specifies the angle of rotation around axis oZ, in degrees.
void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z);
/// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z)
/// Rotate camera around axisees.
/// \param [in] pAngle_X - specifies the angle of rotation around axis oX, in degrees.
/// \param [in] pAngle_Y - specifies the angle of rotation around axis oY, in degrees.
/// \param [in] pAngle_Z - specifies the angle of rotation around axis oZ, in degrees.
void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z);
/// \fn void Camera_Translate(const size_t pTranslate_X, const size_t pTranslate_Y, const size_t pTranslate_Z)
/// Translate camera along axises. In local coordinates.
/// \param [in] pTranslate_X - specifies the X coordinate of translation vector.
/// \param [in] pTranslate_Y - specifies the Y coordinate of translation vector.
/// \param [in] pTranslate_Z - specifies the Z coordinate of translation vector.
void Camera_Translate(const GLfloat pTranslate_X, const GLfloat pTranslate_Y, const GLfloat pTranslate_Z);
signals:
/// \fn void Paint_Finished(const size_t pPaintTime, const GLfloat pDistance)
///< Signal. Emits when execution of \ref paintGL is end.
/// \param [out] pPaintTime_ms - time spent for rendering, in milliseconds.
/// \param [out] pDistance - distance between current camera and center of the scene. \sa SHelper_Camera::Translation_ToScene.
void Paint_Finished(const size_t pPaintTime_ms, const GLfloat pDistance);
/// \fn void SceneObject_Camera(const QString& pName)
/// Signal. Emit for every camera found in scene. Also for default camera.
/// \param [out] pName - name of the camera.
void SceneObject_Camera(const QString& pName);
/// \fn void SceneObject_LightSource(const QString& pName)
/// Signal. Emit for every light source found in scene. Also for default light source.
/// \param [out] pName - name of the light source.
void SceneObject_LightSource(const QString& pName);
};// class CGLView