457 lines
20 KiB
C++
457 lines
20 KiB
C++
/*
|
|
---------------------------------------------------------------------------
|
|
Open Asset Import Library (assimp)
|
|
---------------------------------------------------------------------------
|
|
|
|
Copyright (c) 2006-2018, assimp team
|
|
|
|
|
|
|
|
All rights reserved.
|
|
|
|
Redistribution and use of this software in source and binary forms,
|
|
with or without modification, are permitted provided that the following
|
|
conditions are met:
|
|
|
|
* Redistributions of source code must retain the above
|
|
copyright notice, this list of conditions and the
|
|
following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above
|
|
copyright notice, this list of conditions and the
|
|
following disclaimer in the documentation and/or other
|
|
materials provided with the distribution.
|
|
|
|
* Neither the name of the assimp team, nor the names of its
|
|
contributors may be used to endorse or promote products
|
|
derived from this software without specific prior
|
|
written permission of the assimp team.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
---------------------------------------------------------------------------
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
// Header files, Qt.
|
|
#include <QMap>
|
|
#if ASSIMP_QT4_VIEWER
|
|
# include <QtOpenGL>
|
|
#else
|
|
# include <QOpenGLWidget>
|
|
# include <QOpenGLFunctions>
|
|
#endif // ASSIMP_QT4_VIEWER
|
|
|
|
// Header files Assimp
|
|
#include <assimp/scene.h>
|
|
|
|
/// \class CGLView
|
|
/// Class which hold and render scene.
|
|
#if ASSIMP_QT4_VIEWER
|
|
class CGLView : public QGLWidget
|
|
#else
|
|
class CGLView : public QOpenGLWidget, protected QOpenGLFunctions
|
|
#endif // ASSIMP_QT4_VIEWER
|
|
{
|
|
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:
|
|
|
|
#if !ASSIMP_QT4_VIEWER
|
|
// Qt5 widget has another behavior, so you must to know that you already made context are current. Yes, its a dirty hack. Better decision are welcome.
|
|
bool mGLContext_Current;///< Widget's GL-context made current.
|
|
#endif // ASSIMP_QT4_VIEWER
|
|
// 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.
|
|
bool mScene_AxesEnabled = true;///< Flag which control drawing axes of the coordinate system.
|
|
// 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.
|
|
///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);
|
|
|
|
/********************************************************************/
|
|
/*********************** Override functions ************************/
|
|
/********************************************************************/
|
|
|
|
protected:
|
|
|
|
/// \fn void drawCoordSystem()
|
|
/// Draw axes of the coordinate system.
|
|
void drawCoordSystem();
|
|
|
|
/// \fn void initializeGL() override
|
|
/// Override function to 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
|
|
/// Override 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);
|
|
|
|
/// \fn void Enable_Axes(const bool pEnable)
|
|
/// Control axes drawing.
|
|
/// \param [in] pEnable - if true then enable axes, false - disable axes.
|
|
void Enable_Axes(const bool pEnable) { this->mScene_AxesEnabled = 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, const aiMatrix4x4* pMatrix_Rotation_Initial)
|
|
/// 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.
|
|
/// \param [in] pMatrix_Rotation_Initial - matrix from which calculates new transformation matrix. If not set (equal to nullptr) then current transformation matrix
|
|
/// will be used.
|
|
void Camera_RotateScene(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr);
|
|
|
|
/// \fn void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr)
|
|
/// 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.
|
|
/// \param [in] pMatrix_Rotation_Initial - matrix from which calculates new transformation matrix. If not set (equal to nullptr) then current transformation matrix
|
|
/// will be used.
|
|
void Camera_Rotate(const GLfloat pAngle_X, const GLfloat pAngle_Y, const GLfloat pAngle_Z, const aiMatrix4x4* pMatrix_Rotation_Initial = nullptr);
|
|
|
|
/// \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);
|
|
|
|
/// \fn void Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera)
|
|
/// Return data about camera position in world.
|
|
/// \param [out] pRotation_Camera - rotation matrix which set rotation angles of the scene around camera.
|
|
/// \param [out] pRotation_Scene - rotation matrix which set rotation angles of the scene around own center.
|
|
/// \param [out] pTranslation_Camera - translation vector from camera to the scene.
|
|
void Camera_Matrix(aiMatrix4x4& pRotation_Camera, aiMatrix4x4& pRotation_Scene, aiVector3D& pTranslation_Camera);
|
|
|
|
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
|