Compare commits
27 Commits
Version_1.
...
master
Author | SHA1 | Date |
---|---|---|
itdominator | 64d5584698 | |
Anakin | 7e87b14fe1 | |
Anakin | da0b7e3c5f | |
Anakin | fa75e17d58 | |
Anakin | 49585945c3 | |
Anakin | 67657061b6 | |
Anakin | 06d403d546 | |
Anakin | 541a975624 | |
Anakin | 30f1a1e627 | |
Anakin | cdf19911f6 | |
Anakin | 4c40d140a9 | |
Anakin | f47e1cc76a | |
Anakin | 2d335474bf | |
Anakin | a07d8acbec | |
Anakin | 800a6a50f8 | |
Anakin | 94a2fa59ec | |
Anakin | 648b805daf | |
Anakin | 92245be302 | |
Anakin | 333eca25eb | |
Anakin | b17ab3f8e9 | |
Anakin | ff08ee7cea | |
Anakin | 8346e5916d | |
Anakin | 5372838420 | |
Anakin | a14229aa71 | |
Anakin | 1c5631a5e0 | |
Anakin | bc5bfc62bc | |
Anakin | 4cb070c8c5 |
|
@ -19,7 +19,9 @@
|
|||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget"/>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="mainToolBar">
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::LeftToolBarArea|Qt::RightToolBarArea|Qt::TopToolBarArea</set>
|
||||
|
@ -32,6 +34,72 @@
|
|||
</attribute>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<widget class="QDockWidget" name="dockWidget">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="features">
|
||||
<set>QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable</set>
|
||||
</property>
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::RightDockWidgetArea</set>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Asset library</string>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>2</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContents">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectItems</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include <QMatrix4x4>
|
||||
|
||||
class CameraInterface
|
||||
{
|
||||
public:
|
||||
explicit CameraInterface() {};
|
||||
virtual ~CameraInterface() {};
|
||||
|
||||
// attributes
|
||||
protected:
|
||||
QMatrix4x4 m_matrix;
|
||||
double m_zSpeed = 1.0;
|
||||
|
||||
// functions
|
||||
public:
|
||||
virtual void setZoomSpeed(int percent) { m_zSpeed = (double) percent / 100; };
|
||||
|
||||
virtual void rotateAction(QVector2D diff) = 0;
|
||||
virtual void moveAction(QVector2D diff) = 0;
|
||||
virtual void wheelAction(double value) = 0;
|
||||
virtual void resetView() { m_matrix = QMatrix4x4(); };
|
||||
|
||||
virtual void recalculateMatrix() = 0;
|
||||
virtual QMatrix4x4 getMatrix() { recalculateMatrix(); return m_matrix; };
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
#include <QOpenGlTexture>
|
||||
#include <fstream>
|
||||
#include <QFile>
|
||||
#include <QVector>
|
||||
#include <QVector2D>
|
||||
#include <QMatrix4x4>
|
||||
|
@ -18,20 +18,23 @@ struct VertexData
|
|||
QVector3D position;
|
||||
QVector2D texCoord;
|
||||
QVector3D vertexNormal;
|
||||
QVector3D polygonNormal;
|
||||
QVector3D tangent;
|
||||
QVector3D bitangent;
|
||||
};
|
||||
|
||||
struct Segment {
|
||||
std::uint32_t textureIndex = 0;
|
||||
quint32 textureIndex = 0;
|
||||
QVector<VertexData> vertices;
|
||||
QVector<GLuint> indices;
|
||||
};
|
||||
|
||||
struct Model {
|
||||
std::string name = "";
|
||||
std::string parent = "";
|
||||
QString name = "";
|
||||
QString parent = "";
|
||||
QMatrix4x4 m4x4Translation;
|
||||
QQuaternion quadRotation;
|
||||
std::vector<Segment*> segmList;
|
||||
QVector<Segment*> segmList;
|
||||
};
|
||||
|
||||
struct Material {
|
||||
|
@ -42,14 +45,14 @@ struct Material {
|
|||
QString tx3d;
|
||||
QOpenGLTexture* texture0 = Q_NULLPTR;
|
||||
QOpenGLTexture* texture1 = Q_NULLPTR;
|
||||
QVector4D specularColor = { 1.0, 1.0, 1.0, 1.0 };
|
||||
QVector4D specularColor = { 0.1f, 0.1f, 0.1f, 1.0 };
|
||||
QVector4D diffuseColor = { 1.0, 0.0, 0.0, 1.0 };
|
||||
QVector4D ambientColor = { 1.0, 1.0, 1.0, 1.0 };
|
||||
float shininess = 80;
|
||||
float shininess = 1;
|
||||
bool flags[8] = { false };
|
||||
bool transparent = false;
|
||||
std::uint8_t rendertype = 0;
|
||||
std::uint8_t dataValues[2] = { 0 };
|
||||
quint8 rendertype = 0;
|
||||
quint8 dataValues[2] = { 0 };
|
||||
};
|
||||
|
||||
class FileInterface
|
||||
|
@ -61,9 +64,9 @@ public:
|
|||
, m_materials(new QVector<Material>)
|
||||
{
|
||||
//open file
|
||||
m_file.open(path.toStdString().c_str(), std::ios::in | std::ios::binary);
|
||||
m_file.setFileName(path);
|
||||
|
||||
if (!m_file.is_open())
|
||||
if (!m_file.open(QIODevice::ReadOnly))
|
||||
throw std::invalid_argument(std::string("ERROR: file not found: ") += path.toStdString());
|
||||
|
||||
m_filepath = path.left(path.lastIndexOf(QRegExp("/|\\\\")));
|
||||
|
@ -94,7 +97,7 @@ public:
|
|||
|
||||
protected:
|
||||
QVector<Model*>* m_models;
|
||||
std::fstream m_file;
|
||||
QFile m_file;
|
||||
QVector<Material>* m_materials;
|
||||
BoundingBox m_sceneBbox;
|
||||
QString m_filepath;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
#include "CameraInterface.h"
|
||||
|
||||
|
||||
class FreeCamera : public CameraInterface
|
||||
{
|
||||
public:
|
||||
explicit FreeCamera();
|
||||
virtual ~FreeCamera();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
QVector3D m_translation;
|
||||
QQuaternion m_rotation;
|
||||
|
||||
// functions
|
||||
public:
|
||||
virtual void rotateAction(QVector2D diff) Q_DECL_OVERRIDE;
|
||||
virtual void moveAction(QVector2D diff) Q_DECL_OVERRIDE;
|
||||
virtual void wheelAction(double value) Q_DECL_OVERRIDE;
|
||||
virtual void recalculateMatrix() Q_DECL_OVERRIDE;
|
||||
virtual void resetView() Q_DECL_OVERRIDE;
|
||||
};
|
|
@ -34,6 +34,7 @@ private:
|
|||
// functions
|
||||
private:
|
||||
void clearData();
|
||||
void setupPipeline(QOpenGLShaderProgram * program);
|
||||
|
||||
public:
|
||||
void drawGeometry(QOpenGLShaderProgram *program);
|
||||
|
|
|
@ -30,6 +30,8 @@ private:
|
|||
// functions
|
||||
private:
|
||||
void setupWidgets();
|
||||
void getAssetLibrary();
|
||||
void searchMeshFiles(QString path);
|
||||
void openFile();
|
||||
void takeScreenShot();
|
||||
void aboutTool();
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
#include "CameraInterface.h"
|
||||
|
||||
|
||||
class MoveCamera : public CameraInterface
|
||||
{
|
||||
public:
|
||||
explicit MoveCamera();
|
||||
virtual ~MoveCamera();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
QVector3D m_position;
|
||||
double m_phi;
|
||||
double m_theta;
|
||||
int m_forwardSpeed;
|
||||
int m_sidewardSpeed;
|
||||
|
||||
// functions
|
||||
public:
|
||||
virtual void rotateAction(QVector2D diff) Q_DECL_OVERRIDE;
|
||||
virtual void moveAction(QVector2D diff) Q_DECL_OVERRIDE;
|
||||
virtual void wheelAction(double value) Q_DECL_OVERRIDE;
|
||||
virtual void recalculateMatrix() Q_DECL_OVERRIDE;
|
||||
virtual void resetView() Q_DECL_OVERRIDE;
|
||||
};
|
|
@ -1,11 +1,11 @@
|
|||
#pragma once
|
||||
#include "..\Header\FileInterface.h"
|
||||
|
||||
#include <QList>
|
||||
|
||||
struct ChunkHeader {
|
||||
char name[5];
|
||||
std::uint32_t size;
|
||||
std::streampos position;
|
||||
QString name;
|
||||
quint32 size;
|
||||
qint64 position;
|
||||
};
|
||||
|
||||
enum ModelTyp {
|
||||
|
@ -29,22 +29,22 @@ private:
|
|||
|
||||
virtual void import() Q_DECL_OVERRIDE Q_DECL_FINAL;
|
||||
|
||||
void loadChunks(std::list<ChunkHeader*> &destination, std::streampos start, const std::uint32_t length);
|
||||
void loadChunks(QList<ChunkHeader*> &destination, qint64 start, const quint32 length);
|
||||
|
||||
void analyseMsh2Chunks(std::list<ChunkHeader*> &chunkList);
|
||||
void analyseMsh2Chunks(QList<ChunkHeader*> &chunkList);
|
||||
|
||||
void analyseMatdChunks(std::list<ChunkHeader*> &chunkList);
|
||||
void analyseMatdChunks(QList<ChunkHeader*> &chunkList);
|
||||
|
||||
void analyseModlChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
|
||||
void analyseGeomChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
|
||||
void analyseSegmChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
|
||||
void analyseClthChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
|
||||
void analyseModlChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
|
||||
void analyseGeomChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
|
||||
void analyseSegmChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
|
||||
void analyseClthChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
|
||||
|
||||
void readVertex(Segment* dataDestination, std::streampos position);
|
||||
void readUV(Segment* dataDestination, std::streampos position);
|
||||
void readVertex(Segment* dataDestination, qint64 position);
|
||||
void readUV(Segment* dataDestination, qint64 position);
|
||||
|
||||
void loadTexture(QOpenGLTexture*& destination, QString filepath, QString& filename);
|
||||
|
||||
QMatrix4x4 getParentMatrix(std::string parent) const;
|
||||
QQuaternion getParentRotation(std::string parent) const;
|
||||
QMatrix4x4 getParentMatrix(QString parent) const;
|
||||
QQuaternion getParentRotation(QString parent) const;
|
||||
};
|
|
@ -5,6 +5,7 @@
|
|||
#include <QMatrix4x4>
|
||||
#include "GeometryEngine.h"
|
||||
#include "SettingsWindow.h"
|
||||
#include "CameraInterface.h"
|
||||
|
||||
|
||||
class GeometryEngine;
|
||||
|
@ -22,43 +23,35 @@ private:
|
|||
QOpenGLShaderProgram m_program;
|
||||
GeometryEngine *m_dataEngine;
|
||||
|
||||
QVector4D m_backgroundColorOn = { 0.02f, 0.02f, 0.02f, 1.0f };
|
||||
QVector4D m_backgroundColorOff = { 0.5f, 0.8f, 1.0f, 1.0f };
|
||||
QVector4D m_backgroundColorOn;
|
||||
QVector4D m_backgroundColorOff;
|
||||
|
||||
bool m_wireframe = false;
|
||||
bool m_lightOn = false;
|
||||
bool m_backfaceCulling = false;
|
||||
bool m_wireframe;
|
||||
bool m_lightOn;
|
||||
bool m_backfaceCulling;
|
||||
|
||||
struct {
|
||||
QVector4D position = { 1,1,1,0 };
|
||||
QVector3D intensities = { 1.0,1.0,1.0 };
|
||||
float attenuationFactor = 0.0f;
|
||||
float ambientCoefficient = 0.005f;
|
||||
bool headlight = false;
|
||||
QVector4D position;
|
||||
QVector3D intensities;
|
||||
float attenuationFactor;
|
||||
float ambientCoefficient;
|
||||
bool headlight;
|
||||
} m_light;
|
||||
|
||||
SettingsWindow* m_settings;
|
||||
|
||||
struct {
|
||||
bool left = false;
|
||||
bool right = false;
|
||||
QVector2D position;
|
||||
} m_mouse;
|
||||
|
||||
struct {
|
||||
bool x = true;
|
||||
bool y = true;
|
||||
bool z = true;
|
||||
} m_rotDirections;
|
||||
|
||||
QMatrix4x4 m_projection;
|
||||
QVector3D m_translation;
|
||||
QQuaternion m_rotation;
|
||||
CameraInterface* m_camera;
|
||||
|
||||
double m_zSpeed = 1.0;
|
||||
SettingsWindow* m_settings;
|
||||
|
||||
// functions
|
||||
private:
|
||||
void setDefaultValues();
|
||||
void initShaders();
|
||||
void resetView();
|
||||
void updateLightPosition();
|
||||
|
@ -74,6 +67,7 @@ protected:
|
|||
void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE;
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
|
||||
void keyReleaseEvent(QKeyEvent *e) Q_DECL_OVERRIDE;
|
||||
|
||||
void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE;
|
||||
void dropEvent(QDropEvent * event) Q_DECL_OVERRIDE;
|
||||
|
@ -81,10 +75,13 @@ protected:
|
|||
// slots
|
||||
public slots:
|
||||
void loadFile(QString name);
|
||||
void toggleAxis(int axis);
|
||||
void useFreeCamera();
|
||||
void useOrbitCamera();
|
||||
void useMoveCamera();
|
||||
void toggleWireframe();
|
||||
void toggleLight();
|
||||
void showSettings();
|
||||
|
||||
void setBGColorOff(QVector3D value);
|
||||
void setBGColorOn(QVector3D value);
|
||||
void setLightColor(QVector3D value);
|
||||
|
@ -92,7 +89,11 @@ public slots:
|
|||
void setAmbCoef(double value);
|
||||
void setHeadlight(bool value);
|
||||
void setBackfaceCulling(bool value);
|
||||
void setZoomSpeed(int percent);
|
||||
|
||||
// signals
|
||||
signals:
|
||||
void lightChanged(bool value);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "CameraInterface.h"
|
||||
|
||||
|
||||
class OrbitCamera : public CameraInterface
|
||||
{
|
||||
public:
|
||||
explicit OrbitCamera();
|
||||
virtual ~OrbitCamera();
|
||||
|
||||
// attributes
|
||||
private:
|
||||
double m_phi;
|
||||
double m_theta;
|
||||
double m_roh;
|
||||
|
||||
// functions
|
||||
public:
|
||||
virtual void rotateAction(QVector2D diff) Q_DECL_OVERRIDE;
|
||||
virtual void moveAction(QVector2D diff) Q_DECL_OVERRIDE;
|
||||
virtual void wheelAction(double value) Q_DECL_OVERRIDE;
|
||||
virtual void recalculateMatrix() Q_DECL_OVERRIDE;
|
||||
virtual void resetView() Q_DECL_OVERRIDE;
|
||||
};
|
|
@ -0,0 +1,72 @@
|
|||
#pragma once
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QVector3D>
|
||||
#include <QVector4D>
|
||||
|
||||
|
||||
class SettingsManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
SettingsManager(QObject *parent = Q_NULLPTR);
|
||||
|
||||
public:
|
||||
SettingsManager(SettingsManager const&) = delete;
|
||||
void operator=(SettingsManager const&) = delete;
|
||||
|
||||
~SettingsManager();
|
||||
|
||||
static SettingsManager* getInstance(QObject *parent = Q_NULLPTR);
|
||||
|
||||
// attributes
|
||||
private:
|
||||
QFile file;
|
||||
|
||||
QVector3D m_bgColorOn = { 5, 5, 5 };
|
||||
QVector3D m_bgColorOff = { 128, 204, 255 };
|
||||
bool m_bfCulling = false;
|
||||
bool m_light = false;
|
||||
|
||||
int m_lightType = 1; // 1 = direct, 2 = point
|
||||
QVector3D m_lightColor = { 255,255,255 };
|
||||
float m_attenuation = 0.0f;
|
||||
float m_ambient = 0.005f;
|
||||
bool m_headlight = false;
|
||||
bool m_autoColor = true;
|
||||
|
||||
// functions
|
||||
private:
|
||||
void readFromFile();
|
||||
void writeToFile();
|
||||
|
||||
public:
|
||||
QVector3D getBgColorOn() const;
|
||||
QVector3D getBgColorOff() const;
|
||||
bool isBfCulling() const;
|
||||
bool isLight() const;
|
||||
|
||||
int getLightType() const;
|
||||
QVector3D getLightColor() const;
|
||||
float getAttenuation() const;
|
||||
float getAmbient() const;
|
||||
bool isHeadlight() const;
|
||||
bool isAutoColor() const;
|
||||
|
||||
|
||||
// slots
|
||||
public:
|
||||
void setBgColorOn(QVector3D value);
|
||||
void setBgColorOff(QVector3D value);
|
||||
void setBfCulling(bool value);
|
||||
void setLight(bool value);
|
||||
|
||||
void setLightType(int value);
|
||||
void setLightColor(QVector3D value);
|
||||
void setAttenuation(double value);
|
||||
void setAmbient(double value);
|
||||
void setHeadlight(bool value);
|
||||
void setAutoColor(int value);
|
||||
|
||||
};
|
|
@ -9,7 +9,7 @@ class SettingsWindow : public QWidget
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVector3D lightColor, bool autoColor, double ambCoef, double attFac, int lightType, QWidget * parent = Q_NULLPTR);
|
||||
SettingsWindow(QWidget * parent = Q_NULLPTR);
|
||||
~SettingsWindow();
|
||||
|
||||
private:
|
||||
|
@ -33,5 +33,6 @@ signals:
|
|||
void sendHeadlight(bool value);
|
||||
void sendBackfaceCulling(bool value);
|
||||
void sendZommSpeed(int percent);
|
||||
void changeLightType(int value);
|
||||
|
||||
};
|
|
@ -1,138 +1,128 @@
|
|||
#pragma once
|
||||
#include <fstream>
|
||||
#include "OutputDevice.h"
|
||||
#include <QImage>
|
||||
#include <QColor>
|
||||
#include <QVector>
|
||||
#include <QFile>
|
||||
|
||||
|
||||
QImage loadTga(QString filePath, bool &success)
|
||||
{
|
||||
QImage img;
|
||||
success = true;
|
||||
|
||||
// open the file
|
||||
std::fstream fsPicture(filePath.toStdString().c_str(), std::ios::in | std::ios::binary);
|
||||
QFile file(filePath);
|
||||
|
||||
if (!fsPicture.is_open())
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
img = QImage(1, 1, QImage::Format_RGB32);
|
||||
img.fill(Qt::red);
|
||||
success = false;
|
||||
return img;
|
||||
}
|
||||
|
||||
// read in the header
|
||||
std::uint8_t ui8x18Header[19] = { 0 };
|
||||
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
|
||||
|
||||
//get variables
|
||||
std::uint32_t ui32BpP;
|
||||
std::uint32_t ui32Width;
|
||||
std::uint32_t ui32Height;
|
||||
std::uint32_t ui32IDLength;
|
||||
std::uint32_t ui32PicType;
|
||||
std::uint32_t ui32PaletteLength;
|
||||
std::uint32_t ui32Size;
|
||||
|
||||
// extract all information from header
|
||||
ui32IDLength = ui8x18Header[0];
|
||||
ui32PicType = ui8x18Header[2];
|
||||
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
|
||||
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
|
||||
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
|
||||
ui32BpP = ui8x18Header[16];
|
||||
|
||||
// calculate some more information
|
||||
ui32Size = ui32Width * ui32Height * ui32BpP / 8;
|
||||
|
||||
// jump to the data block
|
||||
fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);
|
||||
|
||||
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
|
||||
|
||||
// uncompressed
|
||||
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
|
||||
{
|
||||
std::vector<std::uint8_t> vui8Pixels;
|
||||
vui8Pixels.resize(ui32Size);
|
||||
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
|
||||
|
||||
for (unsigned int y = 0; y < ui32Height; y++)
|
||||
{
|
||||
for (unsigned int x = 0; x < ui32Width; x++)
|
||||
{
|
||||
int valr = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 2);
|
||||
int valg = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 1);
|
||||
int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8);
|
||||
int vala = 255;
|
||||
if (ui32BpP == 32)
|
||||
vala = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 3);
|
||||
|
||||
QColor value(valr, valg, valb, vala);
|
||||
img.setPixel(x, ui32Width - 1 - y, value.rgba());
|
||||
}
|
||||
}
|
||||
}
|
||||
// else if compressed 24 or 32 bit
|
||||
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
|
||||
{
|
||||
std::uint8_t tempChunkHeader;
|
||||
std::uint8_t tempData[5];
|
||||
unsigned int tmp_pixelIndex = 0;
|
||||
|
||||
do {
|
||||
fsPicture.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
|
||||
|
||||
if (tempChunkHeader >> 7) // repeat count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
|
||||
|
||||
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
else // data count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
} while (tmp_pixelIndex < (ui32Width * ui32Height));
|
||||
}
|
||||
// not useable format
|
||||
else
|
||||
{
|
||||
fsPicture.close();
|
||||
success = false;
|
||||
return img;
|
||||
|
||||
// read in the header
|
||||
quint8 ui8x18Header[19] = { 0 };
|
||||
file.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
|
||||
|
||||
//get variables
|
||||
quint32 ui32BpP;
|
||||
quint32 ui32Width;
|
||||
quint32 ui32Height;
|
||||
quint32 ui32IDLength;
|
||||
quint32 ui32PicType;
|
||||
quint32 ui32PaletteLength;
|
||||
quint32 ui32Size;
|
||||
|
||||
// extract all information from header
|
||||
ui32IDLength = ui8x18Header[0];
|
||||
ui32PicType = ui8x18Header[2];
|
||||
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
|
||||
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
|
||||
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
|
||||
ui32BpP = ui8x18Header[16];
|
||||
|
||||
// calculate some more information
|
||||
ui32Size = ui32Width * ui32Height * ui32BpP / 8;
|
||||
|
||||
// jump to the data block
|
||||
file.seek(ui32IDLength + ui32PaletteLength + 18);
|
||||
|
||||
// uncompressed
|
||||
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
|
||||
{
|
||||
img = QImage(ui32Width, ui32Height, ui32BpP == 32 ? QImage::Format_RGBA8888 : QImage::Format_RGB888);
|
||||
int lineWidth = ui32Width * ui32BpP / 8;
|
||||
|
||||
for (int i = ui32Height - 1; i >= 0; --i)
|
||||
file.read(reinterpret_cast<char*>(img.scanLine(i)), lineWidth);
|
||||
|
||||
}
|
||||
// else if compressed 24 or 32 bit
|
||||
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
|
||||
{
|
||||
OutputDevice::getInstance()->print("compressed tga is not supported by SWBF", 1);
|
||||
|
||||
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
|
||||
|
||||
quint8 tempChunkHeader;
|
||||
quint8 tempData[5];
|
||||
unsigned int tmp_pixelIndex = 0;
|
||||
|
||||
do {
|
||||
file.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
|
||||
|
||||
if (tempChunkHeader >> 7) // repeat count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (quint8(tempChunkHeader << 1) >> 1);
|
||||
|
||||
file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
else // data count
|
||||
{
|
||||
// just use the first 7 bits
|
||||
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
|
||||
|
||||
for (int i = 0; i <= tempChunkHeader; i++)
|
||||
{
|
||||
file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
|
||||
|
||||
QColor color;
|
||||
|
||||
if (ui32BpP == 32)
|
||||
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], tempData[3]));
|
||||
else
|
||||
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], 255));
|
||||
|
||||
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
|
||||
tmp_pixelIndex++;
|
||||
}
|
||||
}
|
||||
} while (tmp_pixelIndex < (ui32Width * ui32Height));
|
||||
}
|
||||
// not useable format
|
||||
else
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
fsPicture.close();
|
||||
success = true;
|
||||
return img;
|
||||
if (file.isOpen())
|
||||
file.close();
|
||||
return qMove(img).rgbSwapped();
|
||||
|
||||
}
|
||||
|
|
|
@ -15,17 +15,14 @@
|
|||
<file>info.png</file>
|
||||
<file>about.png</file>
|
||||
<file>open.png</file>
|
||||
<file>X.png</file>
|
||||
<file>Y.png</file>
|
||||
<file>Z.png</file>
|
||||
<file>screenshot.png</file>
|
||||
<file>wireframe.png</file>
|
||||
<file>light_off.png</file>
|
||||
<file>light_on.png</file>
|
||||
<file>solid.png</file>
|
||||
<file>X_disabled.png</file>
|
||||
<file>Y_disabled.png</file>
|
||||
<file>Z_disabled.png</file>
|
||||
<file>settings.png</file>
|
||||
<file>freeCamera.png</file>
|
||||
<file>orbitalCamera.png</file>
|
||||
<file>walkCamera.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -37,28 +37,16 @@ QToolButton#screenshot {
|
|||
image: url(:/images/toolbar/screenshot.png);
|
||||
}
|
||||
|
||||
QToolButton#x {
|
||||
image: url(:/images/toolbar/X_disabled.png);
|
||||
QToolButton#freeCamera {
|
||||
image: url(:/images/toolbar/freeCamera.png);
|
||||
}
|
||||
|
||||
QToolButton#x:checked {
|
||||
image: url(:/images/toolbar/X.png);
|
||||
QToolButton#orbitalCamera {
|
||||
image: url(:/images/toolbar/orbitalCamera.png);
|
||||
}
|
||||
|
||||
QToolButton#y {
|
||||
image: url(:/images/toolbar/Y_disabled.png);
|
||||
}
|
||||
|
||||
QToolButton#y:checked {
|
||||
image: url(:/images/toolbar/Y.png);
|
||||
}
|
||||
|
||||
QToolButton#z {
|
||||
image: url(:/images/toolbar/Z_disabled.png);
|
||||
}
|
||||
|
||||
QToolButton#z:checked {
|
||||
image: url(:/images/toolbar/Z.png);
|
||||
QToolButton#walkCamera {
|
||||
image: url(:/images/toolbar/walkCamera.png);
|
||||
}
|
||||
|
||||
QToolButton#wireframe {
|
||||
|
|
|
@ -4,9 +4,22 @@ source code: https://git.rwth-aachen.de/carstenf/OpenGL/tree/master/QtMeshViewer
|
|||
|
||||
===============================================================
|
||||
Controll:
|
||||
|
||||
Free Camera: static view position and you rotate and move the object
|
||||
left mouse - rotate
|
||||
right mouse - move
|
||||
scroll - zoom
|
||||
|
||||
Orbit Camera: static object and you move around it like a satalite
|
||||
left mouse - rotate
|
||||
scroll - zoom
|
||||
|
||||
Move Camera: static object and you can walk through the scene
|
||||
w/s - forward/backward
|
||||
a/d - left/right
|
||||
left mouse - look around
|
||||
|
||||
General:
|
||||
space - reset view
|
||||
L - set light to current position
|
||||
esc - close
|
||||
|
|
After Width: | Height: | Size: 964 B |
|
@ -4,16 +4,22 @@ precision mediump int;
|
|||
precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform mat3 n_matrix;
|
||||
uniform mat3 normalMatrix;
|
||||
uniform vec3 cameraPosition;
|
||||
|
||||
uniform sampler2D texture;
|
||||
uniform float materialShininess;
|
||||
uniform vec3 materialSpecularColor;
|
||||
uniform sampler2D tx0;
|
||||
uniform sampler2D tx1;
|
||||
|
||||
uniform bool b_transparent;
|
||||
uniform bool b_specular;
|
||||
uniform bool b_light;
|
||||
uniform struct Material {
|
||||
float shininess;
|
||||
vec3 specularColor;
|
||||
bool isTransparent;
|
||||
bool hasSpecularmap;
|
||||
bool hasNormalmap;
|
||||
bool isGlow;
|
||||
} material;
|
||||
|
||||
uniform bool useLight;
|
||||
|
||||
uniform struct Light {
|
||||
vec4 position;
|
||||
|
@ -25,67 +31,96 @@ uniform struct Light {
|
|||
varying vec2 v_surfaceUV;
|
||||
varying vec3 v_surfacePosition;
|
||||
varying vec3 v_surfaceNormal;
|
||||
varying vec3 v_polyNorm;
|
||||
varying vec3 v_polyTan;
|
||||
varying vec3 v_polyBiTan;
|
||||
|
||||
void main()
|
||||
{
|
||||
if(b_light)
|
||||
if(useLight && !material.isGlow)
|
||||
{
|
||||
// some values
|
||||
vec3 normalWorld = normalize(n_matrix * v_surfaceNormal);
|
||||
|
||||
vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV));
|
||||
// get the color and undo gamma correction
|
||||
vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV));
|
||||
surfaceColor.rgb = pow(surfaceColor.rgb, vec3(2.2));
|
||||
|
||||
vec3 surfaceToLight;
|
||||
float attenuation;
|
||||
// directional light
|
||||
if(light.position.w == 0.0f)
|
||||
{
|
||||
surfaceToLight = normalize(light.position.xyz);
|
||||
}
|
||||
// point light
|
||||
else
|
||||
{
|
||||
surfaceToLight = normalize(light.position.xyz - v_surfacePosition);
|
||||
}
|
||||
|
||||
float distanceToLight = length(light.position.xyz - v_surfacePosition);
|
||||
attenuation = 1.0 / (1.0 + light.attenuationFactor * pow(distanceToLight, 2));
|
||||
|
||||
// attenutation depending on the distance to the light
|
||||
float distanceToLight = length(light.position.xyz - v_surfacePosition);
|
||||
float attenuation = 1.0 / (1.0 + light.attenuationFactor * pow(distanceToLight, 2));
|
||||
|
||||
// normal vector
|
||||
vec3 normal = normalize(normalMatrix * v_surfaceNormal);
|
||||
|
||||
// direction from surface to light depending on the light type
|
||||
vec3 surfaceToLight;
|
||||
if(light.position.w == 0.0) // directional light
|
||||
surfaceToLight = normalize(light.position.xyz);
|
||||
else // point light
|
||||
surfaceToLight = normalize(light.position.xyz - v_surfacePosition);
|
||||
|
||||
// direction from surface to camera
|
||||
vec3 surfaceToCamera = normalize(cameraPosition - v_surfacePosition);
|
||||
|
||||
// ambient
|
||||
// adjust the values if material has normal map
|
||||
if(material.hasNormalmap)
|
||||
{
|
||||
vec3 surfaceTangent = normalize(normalMatrix * v_polyTan);
|
||||
vec3 surfaceBitangent = normalize(normalMatrix * -v_polyBiTan);
|
||||
vec3 surfaceNormal = normalize(normalMatrix * v_surfaceNormal);
|
||||
mat3 tbn = transpose(mat3(surfaceTangent, surfaceBitangent, surfaceNormal));
|
||||
normal = texture2D(tx1, v_surfaceUV).rgb;
|
||||
normal = normalize(normal * 2.0 -1.0);
|
||||
surfaceToLight = normalize(tbn * surfaceToLight);
|
||||
surfaceToCamera = normalize(tbn * surfaceToCamera);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// ambient component
|
||||
|
||||
vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;
|
||||
|
||||
// diffuse
|
||||
float diffuseCoefficient = max(0.0, dot(normalWorld, surfaceToLight));
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// diffuse component
|
||||
|
||||
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
|
||||
vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
|
||||
|
||||
// specular
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// specular component
|
||||
|
||||
float specularCoefficient = 0.0;
|
||||
if(diffuseCoefficient > 0.0)
|
||||
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normalWorld))), materialShininess);
|
||||
vec3 specColor;
|
||||
if(b_specular)
|
||||
specColor = vec3(surfaceColor.a);
|
||||
else
|
||||
specColor = materialSpecularColor;
|
||||
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), material.shininess);
|
||||
|
||||
float specularWeight = 1;
|
||||
if(material.hasSpecularmap)
|
||||
specularWeight = surfaceColor.a;
|
||||
vec3 specColor = specularWeight * 1/255 * material.specularColor;
|
||||
|
||||
vec3 specular = specularCoefficient * specColor * light.intensities;
|
||||
|
||||
// linear color before gamma correction)
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// linear color before gamma correction
|
||||
vec3 linearColor = ambient + attenuation * (diffuse + specular);
|
||||
|
||||
// final color after gama correction
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// gama correction
|
||||
vec3 gamma = vec3(1.0/2.2);
|
||||
if(!b_transparent)
|
||||
surfaceColor.a = 1.0f;
|
||||
|
||||
if(!material.isTransparent)
|
||||
surfaceColor.a = 1.0;
|
||||
|
||||
gl_FragColor = vec4(pow(linearColor, gamma), surfaceColor.a);
|
||||
}
|
||||
// don't use light
|
||||
else
|
||||
{
|
||||
vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV));
|
||||
if(!b_transparent)
|
||||
surfaceColor.a = 1.0f;
|
||||
vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV));
|
||||
|
||||
if(!material.isTransparent)
|
||||
surfaceColor.a = 1.0;
|
||||
|
||||
gl_FragColor = surfaceColor;
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 993 B |
|
@ -4,26 +4,35 @@ precision mediump int;
|
|||
precision mediump float;
|
||||
#endif
|
||||
|
||||
uniform mat4 vp_matrix;
|
||||
uniform mat4 norm_matrix;
|
||||
uniform mat4 m_matrix;
|
||||
uniform mat4 viewProjection;
|
||||
uniform mat4 normalizeModel;
|
||||
uniform mat4 modelMatrix;
|
||||
|
||||
attribute vec4 a_position;
|
||||
attribute vec2 a_texcoord;
|
||||
attribute vec3 a_normal;
|
||||
attribute vec3 a_polyNorm;
|
||||
attribute vec3 a_polyTan;
|
||||
attribute vec3 a_polyBiTan;
|
||||
|
||||
varying vec2 v_surfaceUV;
|
||||
varying vec3 v_surfacePosition;
|
||||
varying vec3 v_surfaceNormal;
|
||||
varying vec3 v_polyNorm;
|
||||
varying vec3 v_polyTan;
|
||||
varying vec3 v_polyBiTan;
|
||||
|
||||
void main()
|
||||
{
|
||||
// Calculate vertex position in screen space
|
||||
gl_Position = vp_matrix * norm_matrix * m_matrix * a_position;
|
||||
gl_Position = viewProjection * normalizeModel * modelMatrix * a_position;
|
||||
|
||||
// Pass data to fragment shader
|
||||
// Value will be automatically interpolated to fragments inside polygon faces
|
||||
v_surfaceUV = a_texcoord;
|
||||
v_surfacePosition = vec3(norm_matrix * m_matrix * a_position);
|
||||
v_surfacePosition = vec3(normalizeModel * modelMatrix * a_position);
|
||||
v_surfaceNormal = a_normal;
|
||||
v_polyNorm = a_polyNorm;
|
||||
v_polyTan = a_polyTan;
|
||||
v_polyBiTan = a_polyBiTan;
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 924 B |
|
@ -0,0 +1,53 @@
|
|||
#include "..\Header\FreeCamera.h"
|
||||
#include <QVector2D>
|
||||
#include <QVector3D>
|
||||
#include <QQuaternion>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// constructor/destructor
|
||||
|
||||
FreeCamera::FreeCamera()
|
||||
{
|
||||
resetView();
|
||||
}
|
||||
|
||||
FreeCamera::~FreeCamera()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// functions
|
||||
|
||||
void FreeCamera::rotateAction(QVector2D diff)
|
||||
{
|
||||
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation;
|
||||
}
|
||||
|
||||
void FreeCamera::moveAction(QVector2D diff)
|
||||
{
|
||||
m_translation += {(float)(diff.x() * 0.01), (float)(diff.y() * -0.01), 0.0};
|
||||
}
|
||||
|
||||
void FreeCamera::wheelAction(double value)
|
||||
{
|
||||
m_translation += {0.0, 0.0, (float) (m_zSpeed * value / 240)};
|
||||
}
|
||||
|
||||
void FreeCamera::recalculateMatrix()
|
||||
{
|
||||
m_matrix = QMatrix4x4();
|
||||
|
||||
m_matrix.translate(m_translation);
|
||||
m_matrix.rotate(m_rotation);
|
||||
}
|
||||
|
||||
void FreeCamera::resetView()
|
||||
{
|
||||
m_translation = { 0, 0, -4 };
|
||||
m_rotation = QQuaternion();
|
||||
|
||||
CameraInterface::resetView();
|
||||
}
|
|
@ -51,26 +51,8 @@ void GeometryEngine::clearData()
|
|||
m_drawList.clear();
|
||||
}
|
||||
|
||||
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
|
||||
void GeometryEngine::setupPipeline(QOpenGLShaderProgram *program)
|
||||
{
|
||||
if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
|
||||
return;
|
||||
|
||||
// Setup
|
||||
// Tell OpenGL which VBOs to use
|
||||
m_arrayBuf.bind();
|
||||
m_indexBuf.bind();
|
||||
|
||||
// Allways normalize by this
|
||||
QMatrix4x4 normMatrix;
|
||||
float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
|
||||
normMatrix.scale(1 / maxExtent);
|
||||
normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
|
||||
program->setUniformValue("norm_matrix", normMatrix);
|
||||
|
||||
// Allways use texture unit 0
|
||||
program->setUniformValue("texture", 0);
|
||||
|
||||
// Offset for position
|
||||
quintptr offset = 0;
|
||||
|
||||
|
@ -87,50 +69,115 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
|
|||
program->enableAttributeArray(texcoordLocation);
|
||||
program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));
|
||||
|
||||
//Offset for normal
|
||||
//Offset for vertexNormal
|
||||
offset += sizeof(QVector2D);
|
||||
|
||||
// Tell OpenGL programmable pipeline how to locate vertex normal data
|
||||
int normLocation = program->attributeLocation("a_normal");
|
||||
program->enableAttributeArray(normLocation);
|
||||
program->setAttributeBuffer(normLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
|
||||
int vertNormLocation = program->attributeLocation("a_normal");
|
||||
program->enableAttributeArray(vertNormLocation);
|
||||
program->setAttributeBuffer(vertNormLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
|
||||
|
||||
//Offset for polygonNormal
|
||||
offset += sizeof(QVector3D);
|
||||
|
||||
// Tell OpenGL programmable pipeline how to locate polygon normal data
|
||||
int polyNormLocation = program->attributeLocation("a_polyNorm");
|
||||
program->enableAttributeArray(polyNormLocation);
|
||||
program->setAttributeBuffer(polyNormLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
|
||||
|
||||
//Offset for polygonTangent
|
||||
offset += sizeof(QVector3D);
|
||||
|
||||
// Tell OpenGL programmable pipeline how to locate polygon tangent data
|
||||
int polyTanLocation = program->attributeLocation("a_polyTan");
|
||||
program->enableAttributeArray(polyTanLocation);
|
||||
program->setAttributeBuffer(polyTanLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
|
||||
|
||||
//Offset for polygonBitangent
|
||||
offset += sizeof(QVector3D);
|
||||
|
||||
// Tell OpenGL programmable pipeline how to locate polygon bitangent data
|
||||
int polyBiTanLocation = program->attributeLocation("a_polyBiTan");
|
||||
program->enableAttributeArray(polyBiTanLocation);
|
||||
program->setAttributeBuffer(polyBiTanLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
|
||||
|
||||
}
|
||||
|
||||
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
|
||||
{
|
||||
if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
|
||||
return;
|
||||
|
||||
// Setup
|
||||
// Tell OpenGL which VBOs to use
|
||||
m_arrayBuf.bind();
|
||||
m_indexBuf.bind();
|
||||
|
||||
// Allways normalize by this
|
||||
QMatrix4x4 normMatrix;
|
||||
float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
|
||||
normMatrix.scale(1 / maxExtent);
|
||||
normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
|
||||
program->setUniformValue("normalizeModel", normMatrix);
|
||||
|
||||
// Allways use texture unit 0 and 1
|
||||
program->setUniformValue("tx0", 0);
|
||||
program->setUniformValue("tx1", 1);
|
||||
|
||||
//setup the pipeline
|
||||
setupPipeline(program);
|
||||
|
||||
// Paint
|
||||
|
||||
for (auto& it : m_drawList)
|
||||
{
|
||||
bool tmp_transparent(false);
|
||||
bool tmp_specular(false);
|
||||
bool tmp_normalmap(false);
|
||||
bool tmp_glow(false);
|
||||
float shininess(0.0);
|
||||
QVector3D specularColor;
|
||||
|
||||
// bind the correct texture
|
||||
if (it.textureIndex < (unsigned)m_materials->size() && m_materials->at(it.textureIndex).texture0 != Q_NULLPTR)
|
||||
{
|
||||
m_materials->at(it.textureIndex).texture0->bind();
|
||||
m_materials->at(it.textureIndex).texture0->bind(0);
|
||||
tmp_transparent = m_materials->at(it.textureIndex).transparent;
|
||||
tmp_specular = m_materials->at(it.textureIndex).flags[7];
|
||||
shininess = m_materials->at(it.textureIndex).shininess;
|
||||
specularColor = m_materials->at(it.textureIndex).specularColor.toVector3D();
|
||||
|
||||
if (m_materials->at(it.textureIndex).rendertype == 27 || m_materials->at(it.textureIndex).rendertype == 28)
|
||||
{
|
||||
if (m_materials->at(it.textureIndex).texture1 != Q_NULLPTR)
|
||||
{
|
||||
tmp_normalmap = true;
|
||||
m_materials->at(it.textureIndex).texture1->bind(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_materials->at(it.textureIndex).flags[0] || m_materials->at(it.textureIndex).flags[1] || m_materials->at(it.textureIndex).rendertype == 1)
|
||||
tmp_glow = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_defaultMaterial->texture0->bind();
|
||||
m_defaultMaterial->texture0->bind(0);
|
||||
tmp_transparent = m_defaultMaterial->transparent;
|
||||
}
|
||||
|
||||
// Set model matrix
|
||||
program->setUniformValue("m_matrix", it.modelMatrix);
|
||||
program->setUniformValue("modelMatrix", it.modelMatrix);
|
||||
|
||||
// Set normal matrix
|
||||
program->setUniformValue("n_matrix", (normMatrix * it.modelMatrix).normalMatrix());
|
||||
|
||||
// set some more values
|
||||
program->setUniformValue("b_transparent", tmp_transparent);
|
||||
program->setUniformValue("b_specular", tmp_specular);
|
||||
program->setUniformValue("normalMatrix", (normMatrix * it.modelMatrix).normalMatrix());
|
||||
|
||||
// set some material attributes
|
||||
program->setUniformValue("materialShininess", shininess);
|
||||
program->setUniformValue("materialSpecularColor", specularColor);
|
||||
program->setUniformValue("material.shininess", shininess);
|
||||
program->setUniformValue("material.specularColor", specularColor);
|
||||
program->setUniformValue("material.isTransparent", tmp_transparent);
|
||||
program->setUniformValue("material.hasSpecularmap", tmp_specular);
|
||||
program->setUniformValue("material.hasNormalmap", tmp_normalmap);
|
||||
program->setUniformValue("material.isGlow", tmp_glow);
|
||||
|
||||
// Draw cube geometry using indices from VBO 1
|
||||
glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint)));
|
||||
|
|
|
@ -36,9 +36,6 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
// setup opengl things
|
||||
QSurfaceFormat format;
|
||||
format.setDepthBufferSize(24);
|
||||
format.setMajorVersion(2);
|
||||
format.setMinorVersion(0);
|
||||
format.setProfile(QSurfaceFormat::NoProfile);
|
||||
QSurfaceFormat::setDefaultFormat(format);
|
||||
|
||||
// set default text to file info
|
||||
|
@ -52,6 +49,8 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
styleSheet.open(QIODevice::ReadOnly);
|
||||
this->setStyleSheet(styleSheet.readAll());
|
||||
|
||||
getAssetLibrary();
|
||||
|
||||
printMessage("MeshViewer by Anakin", 0);
|
||||
}
|
||||
|
||||
|
@ -90,41 +89,26 @@ void MainWindow::setupWidgets()
|
|||
//////////////////////////////////////////////////
|
||||
ui->mainToolBar->addSeparator();
|
||||
|
||||
QSignalMapper* signalMapper = new QSignalMapper(this);
|
||||
// Free Camera
|
||||
QToolButton *freeCamera = new QToolButton(this);
|
||||
freeCamera->setObjectName("freeCamera");
|
||||
freeCamera->setToolTip("free camera");
|
||||
connect(freeCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useFreeCamera);
|
||||
ui->mainToolBar->addWidget(freeCamera);
|
||||
|
||||
// X
|
||||
QToolButton *x = new QToolButton(this);
|
||||
x->setObjectName("x");
|
||||
x->setToolTip("x-direction");
|
||||
x->setCheckable(true);
|
||||
x->setChecked(true);
|
||||
ui->mainToolBar->addWidget(x);
|
||||
// Orbital Camera
|
||||
QToolButton *orbitCamera = new QToolButton(this);
|
||||
orbitCamera->setObjectName("orbitalCamera");
|
||||
orbitCamera->setToolTip("orbital camera");
|
||||
connect(orbitCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useOrbitCamera);
|
||||
ui->mainToolBar->addWidget(orbitCamera);
|
||||
|
||||
// Y
|
||||
QToolButton *y = new QToolButton(this);
|
||||
y->setObjectName("y");
|
||||
y->setToolTip("y-direction");
|
||||
y->setCheckable(true);
|
||||
y->setChecked(true);
|
||||
ui->mainToolBar->addWidget(y);
|
||||
|
||||
// Z
|
||||
QToolButton *z = new QToolButton(this);
|
||||
z->setObjectName("z");
|
||||
z->setToolTip("z-direction");
|
||||
z->setCheckable(true);
|
||||
z->setChecked(true);
|
||||
ui->mainToolBar->addWidget(z);
|
||||
|
||||
connect(x, SIGNAL(pressed()), signalMapper, SLOT(map()));
|
||||
connect(y, SIGNAL(pressed()), signalMapper, SLOT(map()));
|
||||
connect(z, SIGNAL(pressed()), signalMapper, SLOT(map()));
|
||||
|
||||
signalMapper->setMapping(x, 1);
|
||||
signalMapper->setMapping(y, 2);
|
||||
signalMapper->setMapping(z, 3);
|
||||
|
||||
connect(signalMapper, SIGNAL(mapped(int)), viewer, SLOT(toggleAxis(int)));
|
||||
// Move Camera
|
||||
QToolButton *walkCamera = new QToolButton(this);
|
||||
walkCamera->setObjectName("walkCamera");
|
||||
walkCamera->setToolTip("walk camera");
|
||||
connect(walkCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useMoveCamera);
|
||||
ui->mainToolBar->addWidget(walkCamera);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
ui->mainToolBar->addSeparator();
|
||||
|
@ -179,6 +163,33 @@ void MainWindow::setupWidgets()
|
|||
|
||||
}
|
||||
|
||||
void MainWindow::getAssetLibrary()
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem;
|
||||
item->setData(0, Qt::DisplayRole, "Wuhu");
|
||||
ui->treeWidget->addTopLevelItem(item);
|
||||
|
||||
searchMeshFiles("D:/workspaces/Visual Studio 2015/Projects/OpenGL/Release");
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::searchMeshFiles(QString path)
|
||||
{
|
||||
QDir directory(path);
|
||||
directory.setNameFilters(QStringList("*.msh"));
|
||||
|
||||
QStringList childDirectories = directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||
|
||||
QStringList fileNames = directory.entryList(QDir::Files);
|
||||
|
||||
for (auto &it : childDirectories)
|
||||
qDebug() << it;
|
||||
|
||||
for (auto &it : fileNames)
|
||||
qDebug() << it;
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::openFile()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Mesh (*.msh)");
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#include "..\Header\MoveCamera.h"
|
||||
#include <QVector2D>
|
||||
#include <qmath.h>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// constructor/destructor
|
||||
|
||||
MoveCamera::MoveCamera()
|
||||
{
|
||||
resetView();
|
||||
}
|
||||
|
||||
MoveCamera::~MoveCamera()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// functions
|
||||
|
||||
void MoveCamera::rotateAction(QVector2D diff)
|
||||
{
|
||||
m_phi -= diff.x() * 0.01;
|
||||
m_theta += diff.y() * 0.01;
|
||||
|
||||
m_theta = qMax(qMin(M_PI - 0.0001, m_theta), 0.0001);
|
||||
}
|
||||
|
||||
void MoveCamera::moveAction(QVector2D diff)
|
||||
{
|
||||
if (diff.y() > 0)
|
||||
m_sidewardSpeed = 1;
|
||||
else if (diff.y() < 0)
|
||||
m_sidewardSpeed = -1;
|
||||
else
|
||||
m_sidewardSpeed = 0;
|
||||
}
|
||||
|
||||
void MoveCamera::wheelAction(double value)
|
||||
{
|
||||
if (value > 0)
|
||||
m_forwardSpeed = 1;
|
||||
else if (value < 0)
|
||||
m_forwardSpeed = -1;
|
||||
else
|
||||
m_forwardSpeed = 0;
|
||||
}
|
||||
|
||||
void MoveCamera::recalculateMatrix()
|
||||
{
|
||||
m_matrix = QMatrix4x4();
|
||||
|
||||
// different coordinate (spherical -> world) X->Z | Y->X | Z->Y
|
||||
QVector3D tmpdirection(
|
||||
qSin(m_theta) * qSin(m_phi),
|
||||
qCos(m_theta),
|
||||
qSin(m_theta) * qCos(m_phi)
|
||||
);
|
||||
|
||||
QVector3D tmpRight(
|
||||
qSin(m_phi - M_PI_2),
|
||||
0,
|
||||
qCos(m_phi - M_PI_2)
|
||||
);
|
||||
|
||||
m_position += m_forwardSpeed * m_zSpeed * 0.1 * tmpdirection;
|
||||
m_position += m_sidewardSpeed * m_zSpeed * 0.1 * tmpRight;
|
||||
|
||||
m_matrix.lookAt(m_position, m_position + tmpdirection, QVector3D::crossProduct(tmpRight, tmpdirection));
|
||||
}
|
||||
|
||||
void MoveCamera::resetView()
|
||||
{
|
||||
m_position = { 0,0,4 };
|
||||
m_phi = M_PI;
|
||||
m_theta = M_PI_2;
|
||||
m_forwardSpeed = 0;
|
||||
m_sidewardSpeed = 0;
|
||||
CameraInterface::resetView();
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
#include "..\Header\MshFile.h"
|
||||
#include "..\Header\tga.h"
|
||||
#include "..\Header\OutputDevice.h"
|
||||
#include <QColor>
|
||||
#include <QVector3D>
|
||||
|
||||
|
||||
// helper function to save data from file to any variable type
|
||||
|
@ -28,22 +28,22 @@ MshFile::~MshFile()
|
|||
void MshFile::import()
|
||||
{
|
||||
// go to file size information
|
||||
m_file.seekg(4);
|
||||
m_file.seek(4);
|
||||
|
||||
std::uint32_t tmp_fileSize;
|
||||
std::list<ChunkHeader*> tmp_mainChunks;
|
||||
quint32 tmp_fileSize;
|
||||
QList<ChunkHeader*> tmp_mainChunks;
|
||||
|
||||
// get all chunks under HEDR
|
||||
m_file.read(F2V(tmp_fileSize), sizeof(tmp_fileSize));
|
||||
loadChunks(tmp_mainChunks, m_file.tellg(), tmp_fileSize);
|
||||
loadChunks(tmp_mainChunks, m_file.pos(), tmp_fileSize);
|
||||
|
||||
// evaulate HEDR subchunks (= find MSH2)
|
||||
for (ChunkHeader* it : tmp_mainChunks)
|
||||
{
|
||||
if (!strcmp("MSH2", it->name))
|
||||
if ("MSH2" == it->name)
|
||||
{
|
||||
// get all subchunks
|
||||
std::list<ChunkHeader*> tmp_msh2Chunks;
|
||||
QList<ChunkHeader*> tmp_msh2Chunks;
|
||||
loadChunks(tmp_msh2Chunks, it->position, it->size);
|
||||
|
||||
// evaluate MSH2 subchunks
|
||||
|
@ -68,54 +68,57 @@ void MshFile::import()
|
|||
}
|
||||
}
|
||||
|
||||
void MshFile::loadChunks(std::list<ChunkHeader*>& destination, std::streampos start, const std::uint32_t length)
|
||||
void MshFile::loadChunks(QList<ChunkHeader*>& destination, qint64 start, const quint32 length)
|
||||
{
|
||||
// jump to first chunk
|
||||
m_file.seekg(start);
|
||||
m_file.seek(start);
|
||||
|
||||
do
|
||||
{
|
||||
// out of file. Maybe a size information is corrupted
|
||||
if (m_file.atEnd() || m_file.error() != QFileDevice::NoError)
|
||||
{
|
||||
OutputDevice::getInstance()->print("WARNING: corrupted file. Trying to continue..", 1);
|
||||
m_file.unsetError();
|
||||
m_file.seek(0);
|
||||
break;
|
||||
}
|
||||
|
||||
ChunkHeader* tmp_header = new ChunkHeader();
|
||||
|
||||
// get information
|
||||
m_file.read(F2V(tmp_header->name[0]), sizeof(tmp_header->name) - 1);
|
||||
char tmpName[5] = { 0 };
|
||||
m_file.read(F2V(tmpName[0]), sizeof(tmpName) -1);
|
||||
tmp_header->name = QString(tmpName);
|
||||
m_file.read(F2V(tmp_header->size), sizeof(tmp_header->size));
|
||||
tmp_header->position = m_file.tellg();
|
||||
tmp_header->position = m_file.pos();
|
||||
|
||||
// store information
|
||||
destination.push_back(tmp_header);
|
||||
|
||||
// jump to next header
|
||||
m_file.seekg(tmp_header->size, std::ios_base::cur);
|
||||
m_file.seek(tmp_header->size + m_file.pos());
|
||||
|
||||
// out of file. Maybe a size information is corrupted
|
||||
if (!m_file.good())
|
||||
{
|
||||
OutputDevice::getInstance()->print("WARNING: corrupted file. Trying to continue..", 1);
|
||||
m_file.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
} while (m_file.tellg() - start != length);
|
||||
} while (m_file.pos() - start != length);
|
||||
}
|
||||
|
||||
void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
|
||||
void MshFile::analyseMsh2Chunks(QList<ChunkHeader*>& chunkList)
|
||||
{
|
||||
for (auto& it : chunkList)
|
||||
{
|
||||
// scene information
|
||||
if (!strcmp("SINF", it->name))
|
||||
if ("SINF" == it->name)
|
||||
{
|
||||
// get SINF subchunks
|
||||
std::list<ChunkHeader*> tmp_sinfChunks;
|
||||
QList<ChunkHeader*> tmp_sinfChunks;
|
||||
loadChunks(tmp_sinfChunks, it->position, it->size);
|
||||
|
||||
// evaluate SINF subchunks
|
||||
for (auto& it : tmp_sinfChunks)
|
||||
{
|
||||
if (!strcmp("BBOX", it->name))
|
||||
if ("BBOX" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
|
||||
// read in the quaternion
|
||||
float tmp_quat[4];
|
||||
|
@ -143,24 +146,25 @@ void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// material list
|
||||
else if (!strcmp("MATL", it->name))
|
||||
else if ("MATL" == it->name)
|
||||
{
|
||||
OutputDevice::getInstance()->print("loading materials..", 0);
|
||||
// "useless" information how many MATD follow, jump over it
|
||||
m_file.seekg(it->position);
|
||||
m_file.seekg(sizeof(std::uint32_t), std::ios_base::cur);
|
||||
m_file.seek(it->position);
|
||||
m_file.seek(sizeof(quint32) + m_file.pos());
|
||||
|
||||
// get all MATL subchunk
|
||||
std::list<ChunkHeader*> tmp_matlChunks;
|
||||
loadChunks(tmp_matlChunks, m_file.tellg(), it->size - 4);
|
||||
QList<ChunkHeader*> tmp_matlChunks;
|
||||
loadChunks(tmp_matlChunks, m_file.pos(), it->size - 4);
|
||||
|
||||
// evaluate MATL subchunks
|
||||
for (auto& it : tmp_matlChunks)
|
||||
{
|
||||
// This shouldn't be anything else than MATD
|
||||
if (!strcmp("MATD", it->name))
|
||||
if ("MATD" == it->name)
|
||||
{
|
||||
// get all subchunks from MATD
|
||||
std::list<ChunkHeader*> tmp_matdChunks;
|
||||
QList<ChunkHeader*> tmp_matdChunks;
|
||||
loadChunks(tmp_matdChunks, it->position, it->size);
|
||||
|
||||
m_materials->push_back(Material());
|
||||
|
@ -188,14 +192,15 @@ void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// model
|
||||
else if (!strcmp("MODL", it->name))
|
||||
else if ("MODL" == it->name)
|
||||
{
|
||||
OutputDevice::getInstance()->print("loading model..", 0);
|
||||
Model* new_model = new Model;
|
||||
m_currentType = ModelTyp::null;
|
||||
m_currentRenderFlag = -1;
|
||||
|
||||
// get all MODL subchunks
|
||||
std::list<ChunkHeader*> tmp_chunks;
|
||||
QList<ChunkHeader*> tmp_chunks;
|
||||
loadChunks(tmp_chunks, it->position, it->size);
|
||||
|
||||
// evaluate MODL subchunks
|
||||
|
@ -215,14 +220,14 @@ void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
}
|
||||
|
||||
void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
||||
void MshFile::analyseMatdChunks(QList<ChunkHeader*>& chunkList)
|
||||
{
|
||||
for (auto& it : chunkList)
|
||||
{
|
||||
// name
|
||||
if (!strcmp("NAME", it->name))
|
||||
if ("NAME" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -231,9 +236,9 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// data
|
||||
else if(!strcmp("DATA", it->name))
|
||||
else if("DATA" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
|
||||
// diffuse
|
||||
for (unsigned int i = 0; i < 4; i++)
|
||||
|
@ -252,18 +257,18 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// attributes
|
||||
else if (!strcmp("ATRB", it->name))
|
||||
else if ("ATRB" == it->name)
|
||||
{
|
||||
// get pointer to current material
|
||||
Material* curMat = &m_materials->back();
|
||||
|
||||
// read the attributes
|
||||
m_file.seekg(it->position);
|
||||
std::uint8_t flag;
|
||||
m_file.seek(it->position);
|
||||
quint8 flag;
|
||||
m_file.read(F2V(flag), sizeof(flag));
|
||||
m_file.read(F2V(curMat->rendertype), sizeof(std::uint8_t));
|
||||
m_file.read(F2V(curMat->dataValues[0]), sizeof(std::uint8_t));
|
||||
m_file.read(F2V(curMat->dataValues[1]), sizeof(std::uint8_t));
|
||||
m_file.read(F2V(curMat->rendertype), sizeof(quint8));
|
||||
m_file.read(F2V(curMat->dataValues[0]), sizeof(quint8));
|
||||
m_file.read(F2V(curMat->dataValues[1]), sizeof(quint8));
|
||||
|
||||
// flags
|
||||
// 0: emissive
|
||||
|
@ -276,16 +281,16 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
// 7: specular
|
||||
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
curMat->flags[i] = (std::uint8_t)(flag << (7 - i)) >> 7;
|
||||
curMat->flags[i] = (quint8)(flag << (7 - i)) >> 7;
|
||||
|
||||
curMat->transparent = curMat->flags[2] || curMat->flags[3] || curMat->flags[4] || curMat->flags[6] || curMat->rendertype == 4;
|
||||
}
|
||||
|
||||
// texture 0
|
||||
else if (!strcmp("TX0D", it->name))
|
||||
else if ("TX0D" == it->name)
|
||||
{
|
||||
// get the texture name
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -298,10 +303,10 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// texture 1
|
||||
else if (!strcmp("TX1D", it->name))
|
||||
else if ("TX1D" == it->name)
|
||||
{
|
||||
// get the texture name
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -313,10 +318,10 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// texture 2
|
||||
else if (!strcmp("TX2D", it->name))
|
||||
else if ("TX2D" == it->name)
|
||||
{
|
||||
// get the texture name
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -325,10 +330,10 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
|
||||
// texture 3
|
||||
else if (!strcmp("TX3D", it->name))
|
||||
else if ("TX3D" == it->name)
|
||||
{
|
||||
// get the texture name
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -338,23 +343,23 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
|
|||
}
|
||||
}
|
||||
|
||||
void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
|
||||
void MshFile::analyseModlChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
|
||||
{
|
||||
for (auto& it : chunkList)
|
||||
{
|
||||
// model type
|
||||
if (!strcmp("MTYP", it->name))
|
||||
if ("MTYP" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
std::uint32_t tmp_type;
|
||||
m_file.seek(it->position);
|
||||
quint32 tmp_type;
|
||||
m_file.read(F2V(tmp_type), sizeof(tmp_type));
|
||||
m_currentType = (ModelTyp)tmp_type;
|
||||
}
|
||||
|
||||
// parent name
|
||||
else if (!strcmp("PRNT", it->name))
|
||||
else if ("PRNT" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -363,9 +368,9 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
|
||||
// model name
|
||||
else if (!strcmp("NAME", it->name))
|
||||
else if ("NAME" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -374,20 +379,20 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
|
||||
// render flags
|
||||
else if (!strcmp("FLGS", it->name))
|
||||
else if ("FLGS" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
m_file.read(F2V(m_currentRenderFlag), sizeof(m_currentRenderFlag));
|
||||
}
|
||||
|
||||
// translation
|
||||
else if (!strcmp("TRAN", it->name))
|
||||
else if ("TRAN" == it->name)
|
||||
{
|
||||
float tmp_scale[3];
|
||||
float tmp_rotation[4];
|
||||
float tmp_trans[3];
|
||||
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
|
||||
// read in the data
|
||||
for (int i = 0; i < 3; i++)
|
||||
|
@ -410,14 +415,14 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
|
||||
// geometry data
|
||||
else if (!strcmp("GEOM", it->name))
|
||||
else if ("GEOM" == it->name)
|
||||
{
|
||||
// don't get null, bone, shadowMesh and hidden mesh indices
|
||||
if (m_currentType == null || m_currentType == bone || m_currentType == shadowMesh || m_currentRenderFlag == 1)
|
||||
continue;
|
||||
|
||||
// get all GEOM subchunks
|
||||
std::list<ChunkHeader*> tmp_geomChunks;
|
||||
QList<ChunkHeader*> tmp_geomChunks;
|
||||
loadChunks(tmp_geomChunks, it->position, it->size);
|
||||
|
||||
// evaluate GEOM subchunks
|
||||
|
@ -434,15 +439,15 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
}
|
||||
|
||||
void MshFile::analyseGeomChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
|
||||
void MshFile::analyseGeomChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
|
||||
{
|
||||
for (auto& it : chunkList)
|
||||
{
|
||||
// segment
|
||||
if (!strcmp("SEGM", it->name))
|
||||
if ("SEGM" == it->name)
|
||||
{
|
||||
// get all SEGM subchunks
|
||||
std::list<ChunkHeader*> tmp_segmChunks;
|
||||
QList<ChunkHeader*> tmp_segmChunks;
|
||||
loadChunks(tmp_segmChunks, it->position, it->size);
|
||||
|
||||
// evaluate SEGM subchunks
|
||||
|
@ -458,10 +463,10 @@ void MshFile::analyseGeomChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
|
||||
// cloth
|
||||
else if (!strcmp("CLTH", it->name))
|
||||
else if ("CLTH" == it->name)
|
||||
{
|
||||
// get all CLTH subchunks
|
||||
std::list<ChunkHeader*> tmp_clthChunks;
|
||||
QList<ChunkHeader*> tmp_clthChunks;
|
||||
loadChunks(tmp_clthChunks, it->position, it->size);
|
||||
|
||||
// evaluate CLTH subchunks
|
||||
|
@ -478,30 +483,30 @@ void MshFile::analyseGeomChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
}
|
||||
|
||||
void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
|
||||
void MshFile::analyseSegmChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
|
||||
{
|
||||
Segment* new_segment = new Segment;
|
||||
|
||||
for (auto& it : chunkList)
|
||||
{
|
||||
// material index
|
||||
if (!strcmp("MATI", it->name))
|
||||
if ("MATI" == it->name)
|
||||
{
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
m_file.read(F2V(new_segment->textureIndex), sizeof(new_segment->textureIndex));
|
||||
}
|
||||
|
||||
// position list (vertex)
|
||||
else if (!strcmp("POSL", it->name))
|
||||
else if ("POSL" == it->name)
|
||||
{
|
||||
readVertex(new_segment, it->position);
|
||||
}
|
||||
|
||||
// normals
|
||||
else if (!strcmp("NRML", it->name))
|
||||
else if ("NRML" == it->name)
|
||||
{
|
||||
std::uint32_t tmp_size;
|
||||
m_file.seekg(it->position);
|
||||
quint32 tmp_size;
|
||||
m_file.seek(it->position);
|
||||
m_file.read(F2V(tmp_size), sizeof(tmp_size));
|
||||
|
||||
if (tmp_size < (unsigned) new_segment->vertices.size())
|
||||
|
@ -525,18 +530,18 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
|
||||
// uv
|
||||
else if (!strcmp("UV0L", it->name))
|
||||
else if ("UV0L" == it->name)
|
||||
{
|
||||
readUV(new_segment, it->position);
|
||||
}
|
||||
|
||||
// polygons (indices into vertex/uv list)
|
||||
else if (!strcmp("STRP", it->name))
|
||||
else if ("STRP" == it->name)
|
||||
{
|
||||
|
||||
// jump to the data section and read the size;
|
||||
std::uint32_t tmp_size;
|
||||
m_file.seekg(it->position);
|
||||
quint32 tmp_size;
|
||||
m_file.seek(it->position);
|
||||
m_file.read(F2V(tmp_size), sizeof(tmp_size));
|
||||
|
||||
int highBitCount(0);
|
||||
|
@ -545,7 +550,7 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
for (unsigned int i = 0; i < tmp_size; i++)
|
||||
{
|
||||
// ReadData
|
||||
std::uint16_t tmp_value;
|
||||
quint16 tmp_value;
|
||||
m_file.read(F2V(tmp_value), sizeof(tmp_value));
|
||||
|
||||
// Check if highbit is set
|
||||
|
@ -553,7 +558,7 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
{
|
||||
highBitCount++;
|
||||
// remove the high bit, to get the actually value
|
||||
tmp_value = (std::uint16_t(tmp_value << 1) >> 1);
|
||||
tmp_value = (quint16(tmp_value << 1) >> 1);
|
||||
}
|
||||
|
||||
// save data
|
||||
|
@ -567,18 +572,106 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
|
||||
if (tmp_buffer.size() == 5)
|
||||
{
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
new_segment->indices.push_back(tmp_buffer.takeFirst());
|
||||
// calculate poylgon normal, tangent and bitangent
|
||||
QVector3D vec1, vec2, norm, tan, bi;
|
||||
QVector2D uv1, uv2;
|
||||
float f;
|
||||
|
||||
vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position;
|
||||
vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position;
|
||||
uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord;
|
||||
uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord;
|
||||
f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y());
|
||||
|
||||
norm = QVector3D::crossProduct(vec1, vec2).normalized();
|
||||
|
||||
tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x()));
|
||||
tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y()));
|
||||
tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z()));
|
||||
tan.normalize();
|
||||
|
||||
bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x()));
|
||||
bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y()));
|
||||
bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z()));
|
||||
bi.normalize();
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
// polygon normal wasn't calculated before
|
||||
if (new_segment->vertices[tmp_buffer[k]].polygonNormal == QVector3D(0, 0, 0))
|
||||
{
|
||||
new_segment->vertices[tmp_buffer[k]].polygonNormal = norm;
|
||||
new_segment->vertices[tmp_buffer[k]].tangent = tan;
|
||||
new_segment->vertices[tmp_buffer[k]].bitangent = bi;
|
||||
|
||||
new_segment->indices.push_back(tmp_buffer[k]);
|
||||
}
|
||||
// polygon normal already calculated so duplicate the vertex
|
||||
else
|
||||
{
|
||||
new_segment->vertices.push_back(new_segment->vertices[tmp_buffer[k]]);
|
||||
new_segment->vertices.back().polygonNormal = norm;
|
||||
new_segment->vertices.back().tangent = tan;
|
||||
new_segment->vertices.back().bitangent = bi;
|
||||
new_segment->indices.push_back(new_segment->vertices.size() - 1);
|
||||
}
|
||||
}
|
||||
tmp_buffer.remove(0, 3);
|
||||
}
|
||||
else if (tmp_buffer.size() > 5)
|
||||
{
|
||||
unsigned int tmp_multiPolySize = tmp_buffer.size() - 2;
|
||||
|
||||
// calculate poylgon normal, tangent and bitangent
|
||||
QVector3D vec1, vec2, norm, tan, bi;
|
||||
QVector2D uv1, uv2;
|
||||
float f;
|
||||
|
||||
vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position;
|
||||
vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position;
|
||||
uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord;
|
||||
uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord;
|
||||
f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y());
|
||||
|
||||
norm = QVector3D::crossProduct(vec1, vec2).normalized();
|
||||
|
||||
tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x()));
|
||||
tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y()));
|
||||
tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z()));
|
||||
tan.normalize();
|
||||
|
||||
bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x()));
|
||||
bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y()));
|
||||
bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z()));
|
||||
bi.normalize();
|
||||
|
||||
// for every triangle of the multi polygon..
|
||||
for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++)
|
||||
{
|
||||
// ..calculate the edge indices
|
||||
for (int triEdge = 0; triEdge < 3; triEdge++)
|
||||
new_segment->indices.push_back(tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))]);
|
||||
{
|
||||
int curIndi = tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))];
|
||||
|
||||
// polygon normal wasn't calculated before
|
||||
if (new_segment->vertices[curIndi].polygonNormal == QVector3D(0, 0, 0))
|
||||
{
|
||||
new_segment->vertices[curIndi].polygonNormal = norm;
|
||||
new_segment->vertices[curIndi].tangent = tan;
|
||||
new_segment->vertices[curIndi].bitangent = bi;
|
||||
new_segment->indices.push_back(curIndi);
|
||||
}
|
||||
// polygon normal already calculated so duplicate the vertex
|
||||
else
|
||||
{
|
||||
new_segment->vertices.push_back(new_segment->vertices[curIndi]);
|
||||
new_segment->vertices.back().polygonNormal = norm;
|
||||
new_segment->vertices.back().tangent = tan;
|
||||
new_segment->vertices.back().bitangent = bi;
|
||||
new_segment->indices.push_back(new_segment->vertices.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
tmp_buffer.remove(0, tmp_multiPolySize);
|
||||
}
|
||||
|
||||
|
@ -589,17 +682,106 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
// save the last polygon (no 2 high bit followed)
|
||||
if (tmp_buffer.size() == 3)
|
||||
{
|
||||
for (size_t i = 0; i < 3; i++)
|
||||
new_segment->indices.push_back(tmp_buffer.takeFirst());
|
||||
// calculate poylgon normal, tangent and bitangent
|
||||
QVector3D vec1, vec2, norm, tan, bi;
|
||||
QVector2D uv1, uv2;
|
||||
float f;
|
||||
|
||||
vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position;
|
||||
vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position;
|
||||
uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord;
|
||||
uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord;
|
||||
f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y());
|
||||
|
||||
norm = QVector3D::crossProduct(vec1, vec2).normalized();
|
||||
|
||||
tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x()));
|
||||
tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y()));
|
||||
tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z()));
|
||||
tan.normalize();
|
||||
|
||||
bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x()));
|
||||
bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y()));
|
||||
bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z()));
|
||||
bi.normalize();
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
// polygon normal wasn't calculated before
|
||||
if (new_segment->vertices[tmp_buffer[k]].polygonNormal == QVector3D(0, 0, 0))
|
||||
{
|
||||
new_segment->vertices[tmp_buffer[k]].polygonNormal = norm;
|
||||
new_segment->vertices[tmp_buffer[k]].tangent = tan;
|
||||
new_segment->vertices[tmp_buffer[k]].bitangent = bi;
|
||||
|
||||
new_segment->indices.push_back(tmp_buffer[k]);
|
||||
}
|
||||
// polygon normal already calculated so duplicate the vertex
|
||||
else
|
||||
{
|
||||
new_segment->vertices.push_back(new_segment->vertices[tmp_buffer[k]]);
|
||||
new_segment->vertices.back().polygonNormal = norm;
|
||||
new_segment->vertices.back().tangent = tan;
|
||||
new_segment->vertices.back().bitangent = bi;
|
||||
new_segment->indices.push_back(new_segment->vertices.size() - 1);
|
||||
}
|
||||
}
|
||||
tmp_buffer.remove(0, 3);
|
||||
}
|
||||
else if (tmp_buffer.size() > 3)
|
||||
{
|
||||
unsigned int tmp_multiPolySize = tmp_buffer.size();
|
||||
|
||||
// calculate poylgon normal, tangent and bitangent
|
||||
QVector3D vec1, vec2, norm, tan, bi;
|
||||
QVector2D uv1, uv2;
|
||||
float f;
|
||||
|
||||
vec1 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[1]].position;
|
||||
vec2 = new_segment->vertices[tmp_buffer[0]].position - new_segment->vertices[tmp_buffer[2]].position;
|
||||
uv1 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[1]].texCoord;
|
||||
uv2 = new_segment->vertices[tmp_buffer[0]].texCoord - new_segment->vertices[tmp_buffer[2]].texCoord;
|
||||
f = 1.0f / (uv1.x() * uv2.y() - uv2.x() * uv1.y());
|
||||
|
||||
norm = QVector3D::crossProduct(vec1, vec2).normalized();
|
||||
|
||||
tan.setX(f * (uv2.y() * vec1.x() - uv1.y() * vec2.x()));
|
||||
tan.setY(f * (uv2.y() * vec1.y() - uv1.y() * vec2.y()));
|
||||
tan.setZ(f * (uv2.y() * vec1.z() - uv1.y() * vec2.z()));
|
||||
tan.normalize();
|
||||
|
||||
bi.setX(f * (-uv2.x() * vec1.x() + uv1.x() * vec2.x()));
|
||||
bi.setY(f * (-uv2.x() * vec1.y() + uv1.x() * vec2.y()));
|
||||
bi.setZ(f * (-uv2.x() * vec1.z() + uv1.x() * vec2.z()));
|
||||
bi.normalize();
|
||||
|
||||
// for every triangle of the multi polygon..
|
||||
for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++)
|
||||
{
|
||||
// ..calculate the edge indices
|
||||
for (int triEdge = 0; triEdge < 3; triEdge++)
|
||||
new_segment->indices.push_back(tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))]);
|
||||
{
|
||||
int curIndi = tmp_buffer[(tri + triEdge - ((tri % 2) * (triEdge - 1) * 2))];
|
||||
|
||||
// polygon normal wasn't calculated before
|
||||
if (new_segment->vertices[curIndi].polygonNormal == QVector3D(0, 0, 0))
|
||||
{
|
||||
new_segment->vertices[curIndi].polygonNormal = norm;
|
||||
new_segment->vertices[curIndi].tangent = tan;
|
||||
new_segment->vertices[curIndi].bitangent = bi;
|
||||
new_segment->indices.push_back(curIndi);
|
||||
}
|
||||
// polygon normal already calculated so duplicate the vertex
|
||||
else
|
||||
{
|
||||
new_segment->vertices.push_back(new_segment->vertices[curIndi]);
|
||||
new_segment->vertices.back().polygonNormal = norm;
|
||||
new_segment->vertices.back().tangent = tan;
|
||||
new_segment->vertices.back().bitangent = bi;
|
||||
new_segment->indices.push_back(new_segment->vertices.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -607,17 +789,17 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
dataDestination->segmList.push_back(new_segment);
|
||||
}
|
||||
|
||||
void MshFile::analyseClthChunks(Model * dataDestination, std::list<ChunkHeader*>& chunkList)
|
||||
void MshFile::analyseClthChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
|
||||
{
|
||||
Segment* new_segment = new Segment;
|
||||
|
||||
for (auto& it : chunkList)
|
||||
{
|
||||
// texture name
|
||||
if (!strcmp("CTEX", it->name))
|
||||
if ("CTEX" == it->name)
|
||||
{
|
||||
// read the texture name
|
||||
m_file.seekg(it->position);
|
||||
m_file.seek(it->position);
|
||||
char* buffer = new char[it->size + 1];
|
||||
*buffer = { 0 };
|
||||
m_file.read(buffer, it->size);
|
||||
|
@ -638,32 +820,46 @@ void MshFile::analyseClthChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
}
|
||||
|
||||
// position list (vertex)
|
||||
else if (!strcmp("CPOS", it->name))
|
||||
else if ("CPOS" == it->name)
|
||||
{
|
||||
readVertex(new_segment, it->position);
|
||||
}
|
||||
|
||||
// uv
|
||||
else if (!strcmp("CUV0", it->name))
|
||||
else if ("CUV0" == it->name)
|
||||
{
|
||||
readUV(new_segment, it->position);
|
||||
}
|
||||
|
||||
// triangles (indices into vertex/uv list)
|
||||
else if (!strcmp("CMSH", it->name))
|
||||
else if ("CMSH" == it->name)
|
||||
{
|
||||
// jump to the data section and read the size;
|
||||
std::uint32_t tmp_size;
|
||||
m_file.seekg(it->position);
|
||||
quint32 tmp_size;
|
||||
m_file.seek(it->position);
|
||||
m_file.read(F2V(tmp_size), sizeof(tmp_size));
|
||||
|
||||
// for every triangle..
|
||||
for (unsigned int i = 0; i < tmp_size * 3; i++)
|
||||
for (unsigned int i = 0; i < tmp_size; i++)
|
||||
{
|
||||
std::uint32_t tmp_value;
|
||||
m_file.read(F2V(tmp_value), sizeof(std::uint32_t));
|
||||
quint32 tmp_value[3];
|
||||
for (unsigned int j = 0; j < 3; j++)
|
||||
{
|
||||
m_file.read(F2V(tmp_value[j]), sizeof(quint32));
|
||||
new_segment->indices.push_back((GLuint)tmp_value[j]);
|
||||
}
|
||||
|
||||
new_segment->indices.push_back((GLuint)tmp_value);
|
||||
QVector3D vec1, vec2, norm;
|
||||
|
||||
vec1 = new_segment->vertices[new_segment->indices[i * 3]].position - new_segment->vertices[new_segment->indices[i * 3 + 1]].position;
|
||||
vec2 = new_segment->vertices[new_segment->indices[i * 3]].position - new_segment->vertices[new_segment->indices[i * 3 + 2]].position;
|
||||
norm = QVector3D::crossProduct(vec1, vec2);
|
||||
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
new_segment->vertices[new_segment->indices[i * 3 + k]].vertexNormal += norm;
|
||||
new_segment->vertices[new_segment->indices[i * 3 + k]].vertexNormal.normalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -671,10 +867,10 @@ void MshFile::analyseClthChunks(Model * dataDestination, std::list<ChunkHeader*>
|
|||
dataDestination->segmList.push_back(new_segment);
|
||||
}
|
||||
|
||||
void MshFile::readVertex(Segment * dataDestination, std::streampos position)
|
||||
void MshFile::readVertex(Segment * dataDestination, qint64 position)
|
||||
{
|
||||
std::uint32_t tmp_size;
|
||||
m_file.seekg(position);
|
||||
quint32 tmp_size;
|
||||
m_file.seek(position);
|
||||
m_file.read(F2V(tmp_size), sizeof(tmp_size));
|
||||
|
||||
for (unsigned int i = 0; i < tmp_size; i++)
|
||||
|
@ -690,10 +886,10 @@ void MshFile::readVertex(Segment * dataDestination, std::streampos position)
|
|||
}
|
||||
}
|
||||
|
||||
void MshFile::readUV(Segment * dataDestination, std::streampos position)
|
||||
void MshFile::readUV(Segment * dataDestination, qint64 position)
|
||||
{
|
||||
std::uint32_t tmp_size;
|
||||
m_file.seekg(position);
|
||||
quint32 tmp_size;
|
||||
m_file.seek(position);
|
||||
m_file.read(F2V(tmp_size), sizeof(tmp_size));
|
||||
|
||||
if (tmp_size < (unsigned) dataDestination->vertices.size())
|
||||
|
@ -724,7 +920,7 @@ void MshFile::loadTexture(QOpenGLTexture *& destination, QString filepath, QStri
|
|||
if (!loadSuccess)
|
||||
{
|
||||
OutputDevice::getInstance()->print("WARNING: texture not found or corrupted: " + filename, 1);
|
||||
|
||||
//TODO: cloth use the wrong diffuse color. should be null
|
||||
img = QImage(1, 1, QImage::Format_RGB32);
|
||||
img.fill(QColor(m_materials->back().diffuseColor[0] * 255, m_materials->back().diffuseColor[1] * 255, m_materials->back().diffuseColor[2] * 255));
|
||||
filename += " *";
|
||||
|
@ -746,13 +942,13 @@ void MshFile::loadTexture(QOpenGLTexture *& destination, QString filepath, QStri
|
|||
destination = new_texture;
|
||||
}
|
||||
|
||||
QMatrix4x4 MshFile::getParentMatrix(std::string parent) const
|
||||
QMatrix4x4 MshFile::getParentMatrix(QString parent) const
|
||||
{
|
||||
QMatrix4x4 matrix;
|
||||
|
||||
for (auto& it : *m_models)
|
||||
{
|
||||
if (!strcmp(parent.c_str(), it->name.c_str()))
|
||||
if (parent == it->name)
|
||||
{
|
||||
matrix = getParentMatrix(it->parent) * it->m4x4Translation;
|
||||
break;
|
||||
|
@ -762,13 +958,13 @@ QMatrix4x4 MshFile::getParentMatrix(std::string parent) const
|
|||
return matrix;
|
||||
}
|
||||
|
||||
QQuaternion MshFile::getParentRotation(std::string parent) const
|
||||
QQuaternion MshFile::getParentRotation(QString parent) const
|
||||
{
|
||||
QQuaternion rotation;
|
||||
|
||||
for (auto& it : *m_models)
|
||||
{
|
||||
if (!strcmp(parent.c_str(), it->name.c_str()))
|
||||
if (parent == it->name)
|
||||
{
|
||||
rotation = getParentRotation(it->parent) * it->quadRotation;
|
||||
break;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include "..\Header\OglViewerWidget.h"
|
||||
#include "..\Header\MainWindow.h"
|
||||
#include "..\Header\FreeCamera.h"
|
||||
#include "..\Header\OrbitCamera.h"
|
||||
#include "..\Header\MoveCamera.h"
|
||||
#include "..\Header\SettingsManager.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QDropEvent>
|
||||
#include <QMimeData>
|
||||
|
@ -14,13 +18,15 @@
|
|||
|
||||
OglViewerWidget::OglViewerWidget(QWidget *parent)
|
||||
: QOpenGLWidget(parent)
|
||||
, m_dataEngine(0)
|
||||
, m_dataEngine(Q_NULLPTR)
|
||||
, m_camera(new FreeCamera)
|
||||
{
|
||||
setFocus();
|
||||
setAcceptDrops(true);
|
||||
|
||||
// settings window
|
||||
m_settings = new SettingsWindow(m_backgroundColorOff.toVector3D() * 255, m_backgroundColorOn.toVector3D() * 255, m_light.intensities * 255, true, m_light.ambientCoefficient, m_light.attenuationFactor, 1, this);
|
||||
setDefaultValues();
|
||||
m_settings = new SettingsWindow(this);
|
||||
|
||||
connect(m_settings, &SettingsWindow::updateBGColorOff, this, &OglViewerWidget::setBGColorOff);
|
||||
connect(m_settings, &SettingsWindow::updateBGColorOn, this, &OglViewerWidget::setBGColorOn);
|
||||
|
@ -29,7 +35,7 @@ OglViewerWidget::OglViewerWidget(QWidget *parent)
|
|||
connect(m_settings, &SettingsWindow::updateAmbCoef, this, &OglViewerWidget::setAmbCoef);
|
||||
connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight);
|
||||
connect(m_settings, &SettingsWindow::sendBackfaceCulling, this, &OglViewerWidget::setBackfaceCulling);
|
||||
connect(m_settings, &SettingsWindow::sendZommSpeed, this, &OglViewerWidget::setZoomSpeed);
|
||||
connect(m_settings, &SettingsWindow::sendZommSpeed, [this](int value) {m_camera->setZoomSpeed(value); });
|
||||
}
|
||||
|
||||
OglViewerWidget::~OglViewerWidget()
|
||||
|
@ -40,6 +46,7 @@ OglViewerWidget::~OglViewerWidget()
|
|||
delete m_dataEngine;
|
||||
doneCurrent();
|
||||
|
||||
delete m_camera;
|
||||
delete m_settings;
|
||||
}
|
||||
|
||||
|
@ -47,6 +54,30 @@ OglViewerWidget::~OglViewerWidget()
|
|||
/////////////////////////////////////////////////////////////////////////
|
||||
// functions
|
||||
|
||||
void OglViewerWidget::setDefaultValues()
|
||||
{
|
||||
SettingsManager* sm = SettingsManager::getInstance(this);
|
||||
|
||||
m_backgroundColorOn = QVector4D(sm->getBgColorOn() / 255, 1.0f);
|
||||
m_backgroundColorOff = QVector4D(sm->getBgColorOff() / 255, 1.0f);
|
||||
|
||||
m_wireframe = false;
|
||||
m_lightOn = sm->isLight();
|
||||
m_backfaceCulling = sm->isBfCulling();
|
||||
|
||||
if (sm->getLightType() == 1) // directional
|
||||
m_light.position = { 0.0,0.0,0.0,0.0 };
|
||||
else // point
|
||||
m_light.position = { 0.0,0.0,0.0,1.0 };
|
||||
m_light.intensities = sm->getLightColor() / 255;
|
||||
m_light.attenuationFactor = sm->getAttenuation();
|
||||
m_light.ambientCoefficient = sm->getAmbient();
|
||||
m_light.headlight = sm->isHeadlight();
|
||||
|
||||
connect(this, &OglViewerWidget::lightChanged, sm, &SettingsManager::setLight);
|
||||
|
||||
}
|
||||
|
||||
void OglViewerWidget::initShaders()
|
||||
{
|
||||
// Compile vertex shader
|
||||
|
@ -68,9 +99,7 @@ void OglViewerWidget::initShaders()
|
|||
|
||||
void OglViewerWidget::resetView()
|
||||
{
|
||||
m_rotation = QQuaternion();
|
||||
m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE };
|
||||
m_zSpeed = 1;
|
||||
m_camera->resetView();
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
|
@ -79,13 +108,13 @@ void OglViewerWidget::resetView()
|
|||
|
||||
void OglViewerWidget::updateLightPosition()
|
||||
{
|
||||
QMatrix4x4 rotateBack;
|
||||
rotateBack.rotate(m_rotation.inverted());
|
||||
QVector3D cameraPosition = rotateBack * (-m_translation);
|
||||
QVector4D lightPosition = { 0,0,0,1 };
|
||||
|
||||
m_light.position.setX(cameraPosition.x());
|
||||
m_light.position.setY(cameraPosition.y());
|
||||
m_light.position.setZ(cameraPosition.z());
|
||||
lightPosition = m_camera->getMatrix().inverted() * lightPosition;
|
||||
|
||||
m_light.position.setX(lightPosition.x());
|
||||
m_light.position.setY(lightPosition.y());
|
||||
m_light.position.setZ(lightPosition.z());
|
||||
}
|
||||
|
||||
// OpenGL ///////////////////////////////////////////////////////////////
|
||||
|
@ -139,25 +168,18 @@ void OglViewerWidget::paintGL()
|
|||
// Clear color and depth buffer
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Calculate view transformation
|
||||
QMatrix4x4 view;
|
||||
view.translate(m_translation);
|
||||
view.rotate(m_rotation);
|
||||
|
||||
// Set view-projection matrix
|
||||
m_program.setUniformValue("vp_matrix", m_projection * view);
|
||||
m_program.setUniformValue("viewProjection", m_projection * m_camera->getMatrix());
|
||||
|
||||
// Set Light values
|
||||
m_program.setUniformValue("b_light", m_lightOn);
|
||||
m_program.setUniformValue("useLight", m_lightOn);
|
||||
m_program.setUniformValue("light.position", m_light.position);
|
||||
m_program.setUniformValue("light.intensities", m_light.intensities);
|
||||
m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor);
|
||||
m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient);
|
||||
|
||||
// Set camera position
|
||||
QMatrix4x4 rotateBack;
|
||||
rotateBack.rotate(m_rotation.inverted());
|
||||
m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation));
|
||||
m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D());
|
||||
|
||||
// Draw cube geometry
|
||||
if (m_backfaceCulling)
|
||||
|
@ -199,76 +221,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
|
|||
if (m_mouse.left)
|
||||
{
|
||||
// get the difference between last press and now
|
||||
QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;
|
||||
m_camera->rotateAction(QVector2D(e->localPos()) - m_mouse.position);
|
||||
|
||||
// update the new position
|
||||
m_mouse.position = QVector2D(e->localPos());
|
||||
|
||||
// calculate the rotations depending on the active axis
|
||||
// XYZ
|
||||
if (m_rotDirections.x && m_rotDirections.y && m_rotDirections.z)
|
||||
{
|
||||
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation;
|
||||
}
|
||||
// XY
|
||||
else if (m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z)
|
||||
{
|
||||
|
||||
float pitch, yaw, roll;
|
||||
m_rotation.getEulerAngles(&pitch, &yaw, &roll);
|
||||
|
||||
pitch += diff.y() * 0.5;
|
||||
yaw += diff.x() * 0.5;
|
||||
|
||||
if (pitch > 89)
|
||||
pitch = 89;
|
||||
else if (pitch < -89)
|
||||
pitch = -89;
|
||||
|
||||
m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
|
||||
|
||||
}
|
||||
// X
|
||||
else if (m_rotDirections.x && !m_rotDirections.y && !m_rotDirections.z)
|
||||
{
|
||||
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0).normalized(), diff.x() * 0.5) * m_rotation;
|
||||
}
|
||||
// Y
|
||||
else if (!m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z)
|
||||
{
|
||||
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0).normalized(), diff.y() * 0.5) * m_rotation;
|
||||
}
|
||||
// Z
|
||||
else if (!m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z)
|
||||
{
|
||||
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 0.0, 1.0).normalized(), diff.x() * 0.5) * m_rotation;
|
||||
}
|
||||
// XZ
|
||||
else if (m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z)
|
||||
{
|
||||
float pitch, yaw, roll;
|
||||
m_rotation.getEulerAngles(&pitch, &yaw, &roll);
|
||||
roll -= diff.y() * 0.5;
|
||||
yaw += diff.x() * 0.5;
|
||||
|
||||
m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
|
||||
}
|
||||
// YZ
|
||||
else if (!m_rotDirections.x && m_rotDirections.y && m_rotDirections.z)
|
||||
{
|
||||
float pitch, yaw, roll;
|
||||
m_rotation.getEulerAngles(&pitch, &yaw, &roll);
|
||||
pitch += diff.y() * 0.5;
|
||||
roll += diff.x() * 0.5;
|
||||
|
||||
if (pitch > 89)
|
||||
pitch = 89;
|
||||
else if (pitch < -89)
|
||||
pitch = -89;
|
||||
|
||||
m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
|
||||
}
|
||||
|
||||
// request an update
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
|
@ -277,14 +234,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
|
|||
else if (m_mouse.right)
|
||||
{
|
||||
// get the difference between last press and now
|
||||
QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;
|
||||
m_camera->moveAction(QVector2D(e->localPos()) - m_mouse.position);
|
||||
|
||||
// update the new position
|
||||
m_mouse.position = QVector2D(e->localPos());
|
||||
|
||||
// calculate the translation
|
||||
m_translation += {(float)(diff.x() * 0.01), (float)(diff.y() * -0.01), 0.0};
|
||||
|
||||
// request an update
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
|
@ -294,7 +248,7 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
|
|||
|
||||
void OglViewerWidget::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
m_translation += {0.0, 0.0, (float)m_zSpeed * e->angleDelta().y() / 240};
|
||||
m_camera->wheelAction(e->angleDelta().y());
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
|
@ -307,6 +261,38 @@ void OglViewerWidget::keyPressEvent(QKeyEvent *e)
|
|||
{
|
||||
resetView();
|
||||
}
|
||||
else if (e->key() == Qt::Key_W)
|
||||
{
|
||||
emit m_camera->wheelAction(1);
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
else if (e->key() == Qt::Key_S)
|
||||
{
|
||||
emit m_camera->wheelAction(-1);
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
else if (e->key() == Qt::Key_A)
|
||||
{
|
||||
emit m_camera->moveAction(QVector2D(0, -1));
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
else if (e->key() == Qt::Key_D)
|
||||
{
|
||||
emit m_camera->moveAction(QVector2D(0, 1));
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
else if (e->key() == Qt::Key_Escape)
|
||||
{
|
||||
parentWidget()->close();
|
||||
|
@ -318,6 +304,26 @@ void OglViewerWidget::keyPressEvent(QKeyEvent *e)
|
|||
}
|
||||
}
|
||||
|
||||
void OglViewerWidget::keyReleaseEvent(QKeyEvent *e)
|
||||
{
|
||||
if (e->key() == Qt::Key_W || e->key() == Qt::Key_S)
|
||||
{
|
||||
emit m_camera->wheelAction(0);
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
else if (e->key() == Qt::Key_A || e->key() == Qt::Key_D)
|
||||
{
|
||||
emit m_camera->moveAction(QVector2D(0, 0));
|
||||
|
||||
if (m_light.headlight)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e)
|
||||
{
|
||||
if (e->mimeData()->hasUrls())
|
||||
|
@ -341,20 +347,34 @@ void OglViewerWidget::loadFile(QString name)
|
|||
m_dataEngine->loadFile(name);
|
||||
}
|
||||
|
||||
void OglViewerWidget::toggleAxis(int axis)
|
||||
void OglViewerWidget::useFreeCamera()
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case 1:
|
||||
m_rotDirections.x = !m_rotDirections.x;
|
||||
break;
|
||||
case 2:
|
||||
m_rotDirections.y = !m_rotDirections.y;
|
||||
break;
|
||||
case 3:
|
||||
m_rotDirections.z = !m_rotDirections.z;
|
||||
break;
|
||||
}
|
||||
delete m_camera;
|
||||
m_camera = new FreeCamera;
|
||||
|
||||
if (m_lightOn)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
|
||||
void OglViewerWidget::useOrbitCamera()
|
||||
{
|
||||
delete m_camera;
|
||||
m_camera = new OrbitCamera;
|
||||
|
||||
if (m_lightOn)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
|
||||
void OglViewerWidget::useMoveCamera()
|
||||
{
|
||||
delete m_camera;
|
||||
m_camera = new MoveCamera;
|
||||
|
||||
if (m_lightOn)
|
||||
updateLightPosition();
|
||||
update();
|
||||
}
|
||||
|
||||
void OglViewerWidget::toggleWireframe()
|
||||
|
@ -377,6 +397,8 @@ void OglViewerWidget::toggleLight()
|
|||
m_backgroundColorOff[3] = 1.0;
|
||||
}
|
||||
|
||||
emit lightChanged(m_lightOn);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
@ -441,8 +463,3 @@ void OglViewerWidget::setBackfaceCulling(bool value)
|
|||
m_backfaceCulling = value;
|
||||
update();
|
||||
}
|
||||
|
||||
void OglViewerWidget::setZoomSpeed(int percent)
|
||||
{
|
||||
m_zSpeed = (double) percent / 100;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
#include "..\Header\OrbitCamera.h"
|
||||
#include <QVector2D>
|
||||
#include <qmath.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// constructor/destructor
|
||||
|
||||
OrbitCamera::OrbitCamera()
|
||||
{
|
||||
resetView();
|
||||
}
|
||||
|
||||
OrbitCamera::~OrbitCamera()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// functions
|
||||
|
||||
void OrbitCamera::rotateAction(QVector2D diff)
|
||||
{
|
||||
m_phi -= diff.x() * 0.01;
|
||||
m_theta -= diff.y() * 0.01;
|
||||
|
||||
//m_theta = qMax(qMin(M_PI - 0.0001, m_theta), 0.0001);
|
||||
}
|
||||
|
||||
void OrbitCamera::moveAction(QVector2D diff)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OrbitCamera::wheelAction(double value)
|
||||
{
|
||||
m_roh -= m_zSpeed * value / 240;
|
||||
m_roh = qMax(m_roh, 0.0);
|
||||
}
|
||||
|
||||
void OrbitCamera::recalculateMatrix()
|
||||
{
|
||||
m_matrix = QMatrix4x4();
|
||||
|
||||
// different coordinate (spherical -> world) X->Z | Y->X | Z->Y
|
||||
QVector3D tmpPosition(
|
||||
qSin(m_theta) * qSin(m_phi),
|
||||
qCos(m_theta),
|
||||
qSin(m_theta) * qCos(m_phi)
|
||||
);
|
||||
|
||||
QVector3D tmpRight(
|
||||
qSin(m_phi - M_PI_2),
|
||||
0,
|
||||
qCos(m_phi - M_PI_2)
|
||||
);
|
||||
|
||||
m_matrix.lookAt(m_roh * tmpPosition, QVector3D(0,0,0), QVector3D::crossProduct(tmpRight, tmpPosition));
|
||||
}
|
||||
|
||||
void OrbitCamera::resetView()
|
||||
{
|
||||
m_roh = 4;
|
||||
m_phi = 0;
|
||||
m_theta = M_PI_2;
|
||||
CameraInterface::resetView();
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
#include "..\Header\SettingsManager.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// constructor/destructor
|
||||
|
||||
SettingsManager::SettingsManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
file.setFileName("meshviewer.config");
|
||||
readFromFile();
|
||||
}
|
||||
|
||||
SettingsManager::~SettingsManager()
|
||||
{
|
||||
writeToFile();
|
||||
}
|
||||
|
||||
SettingsManager* SettingsManager::getInstance(QObject *parent)
|
||||
{
|
||||
static SettingsManager* instance = new SettingsManager(parent);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// functions
|
||||
|
||||
void SettingsManager::readFromFile()
|
||||
{
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
|
||||
QByteArray stream = file.readAll();
|
||||
QList<QByteArray> lines = stream.split('\n');
|
||||
|
||||
for (auto& it : lines)
|
||||
{
|
||||
if (it.startsWith("<bgOn>"))
|
||||
{
|
||||
QList<QByteArray> values = it.right(it.size() - it.indexOf('>') - 1).split(';');
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
m_bgColorOn[i] = values[i].toFloat();
|
||||
}
|
||||
else if (it.startsWith("<bgOff>"))
|
||||
{
|
||||
QList<QByteArray> values = it.right(it.size() - it.indexOf('>') - 1).split(';');
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
m_bgColorOff[i] = values[i].toFloat();
|
||||
}
|
||||
else if (it.startsWith("<liCo>"))
|
||||
{
|
||||
QList<QByteArray> values = it.right(it.size() - it.indexOf('>') - 1).split(';');
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
m_lightColor[i] = values[i].toFloat();
|
||||
}
|
||||
else if (it.startsWith("<bfCul>"))
|
||||
{
|
||||
m_bfCulling = it.right(it.size() - it.indexOf('>') - 1).toInt();
|
||||
}
|
||||
else if (it.startsWith("<liOn>"))
|
||||
{
|
||||
m_light = it.right(it.size() - it.indexOf('>') - 1).toInt();
|
||||
}
|
||||
else if (it.startsWith("<heLi>"))
|
||||
{
|
||||
m_headlight = it.right(it.size() - it.indexOf('>') - 1).toInt();
|
||||
}
|
||||
else if (it.startsWith("<auCo>"))
|
||||
{
|
||||
m_autoColor = it.right(it.size() - it.indexOf('>') - 1).toInt();
|
||||
}
|
||||
else if (it.startsWith("<liTy>"))
|
||||
{
|
||||
m_lightType = it.right(it.size() - it.indexOf('>') - 1).toInt();
|
||||
}
|
||||
else if (it.startsWith("<atFa>"))
|
||||
{
|
||||
m_attenuation = it.right(it.size() - it.indexOf('>') - 1).toFloat();
|
||||
}
|
||||
else if (it.startsWith("<amCo>"))
|
||||
{
|
||||
m_ambient = it.right(it.size() - it.indexOf('>') - 1).toFloat();
|
||||
}
|
||||
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void SettingsManager::writeToFile()
|
||||
{
|
||||
file.open(QIODevice::WriteOnly);
|
||||
|
||||
file.write(QString("<bgOn>%1;%2;%3\n").arg(m_bgColorOn.x()).arg(m_bgColorOn.y()).arg(m_bgColorOn.z()).toUtf8());
|
||||
file.write(QString("<bgOff>%1;%2;%3\n").arg(m_bgColorOff.x()).arg(m_bgColorOff.y()).arg(m_bgColorOff.z()).toUtf8());
|
||||
file.write(QString("<liCo>%1;%2;%3\n").arg(m_lightColor.x()).arg(m_lightColor.y()).arg(m_lightColor.z()).toUtf8());
|
||||
|
||||
file.write(QString("<bfCul>%1\n").arg(m_bfCulling).toUtf8());
|
||||
file.write(QString("<liOn>%1\n").arg(m_light).toUtf8());
|
||||
file.write(QString("<heLi>%1\n").arg(m_headlight).toUtf8());
|
||||
file.write(QString("<auCo>%1\n").arg(m_autoColor).toUtf8());
|
||||
|
||||
file.write(QString("<liTy>%1\n").arg(m_lightType).toUtf8());
|
||||
file.write(QString("<atFa>%1\n").arg(m_attenuation).toUtf8());
|
||||
file.write(QString("<amCo>%1\n").arg(m_ambient).toUtf8());
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
// getter ///////////////////////////////////////////////////////////////
|
||||
|
||||
QVector3D SettingsManager::getBgColorOn() const
|
||||
{
|
||||
return m_bgColorOn;
|
||||
}
|
||||
|
||||
QVector3D SettingsManager::getBgColorOff() const
|
||||
{
|
||||
return m_bgColorOff;
|
||||
}
|
||||
|
||||
bool SettingsManager::isBfCulling() const
|
||||
{
|
||||
return m_bfCulling;
|
||||
}
|
||||
|
||||
bool SettingsManager::isLight() const
|
||||
{
|
||||
return m_light;
|
||||
}
|
||||
|
||||
int SettingsManager::getLightType() const
|
||||
{
|
||||
return m_lightType;
|
||||
}
|
||||
|
||||
QVector3D SettingsManager::getLightColor() const
|
||||
{
|
||||
return m_lightColor;
|
||||
}
|
||||
|
||||
float SettingsManager::getAttenuation() const
|
||||
{
|
||||
return m_attenuation;
|
||||
}
|
||||
|
||||
float SettingsManager::getAmbient() const
|
||||
{
|
||||
return m_ambient;
|
||||
}
|
||||
|
||||
bool SettingsManager::isHeadlight() const
|
||||
{
|
||||
return m_headlight;
|
||||
}
|
||||
|
||||
bool SettingsManager::isAutoColor() const
|
||||
{
|
||||
return m_autoColor;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// slots
|
||||
|
||||
void SettingsManager::setBgColorOn(QVector3D value)
|
||||
{
|
||||
m_bgColorOn = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setBgColorOff(QVector3D value)
|
||||
{
|
||||
m_bgColorOff = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setBfCulling(bool value)
|
||||
{
|
||||
m_bfCulling = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setLight(bool value)
|
||||
{
|
||||
m_light = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setLightType(int value)
|
||||
{
|
||||
m_lightType = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setLightColor(QVector3D value)
|
||||
{
|
||||
m_lightColor = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setAttenuation(double value)
|
||||
{
|
||||
m_attenuation = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setAmbient(double value)
|
||||
{
|
||||
m_ambient = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setHeadlight(bool value)
|
||||
{
|
||||
m_headlight = value;
|
||||
}
|
||||
|
||||
void SettingsManager::setAutoColor(int value)
|
||||
{
|
||||
if (value == 0)
|
||||
m_autoColor = false;
|
||||
else
|
||||
m_autoColor = true;
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
#include "..\Header\SettingsWindow.h"
|
||||
#include "..\Header\SettingsManager.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// constructor/destructor
|
||||
|
||||
SettingsWindow::SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVector3D lightColor, bool autoColor, double ambCoef, double attFac, int lightType, QWidget * parent)
|
||||
SettingsWindow::SettingsWindow(QWidget * parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::SettingsWindow)
|
||||
{
|
||||
|
@ -15,24 +16,41 @@ SettingsWindow::SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVecto
|
|||
setupConnections();
|
||||
|
||||
// set default values
|
||||
ui->lightOff_R_SB->setValue((int)bgOffColor[0]);
|
||||
ui->lightOff_G_SB->setValue((int)bgOffColor[1]);
|
||||
ui->lightOff_B_SB->setValue((int)bgOffColor[2]);
|
||||
SettingsManager* sm = SettingsManager::getInstance(this);
|
||||
|
||||
ui->lightOn_R_SB->setValue((int)bgOnColor[0]);
|
||||
ui->lightOn_G_SB->setValue((int)bgOnColor[1]);
|
||||
ui->lightOn_B_SB->setValue((int)bgOnColor[2]);
|
||||
ui->lightOff_R_SB->setValue((int)(sm->getBgColorOff()[0]));
|
||||
ui->lightOff_G_SB->setValue((int)(sm->getBgColorOff()[1]));
|
||||
ui->lightOff_B_SB->setValue((int)(sm->getBgColorOff()[2]));
|
||||
|
||||
ui->light_R_SB->setValue((int)lightColor[0]);
|
||||
ui->light_G_SB->setValue((int)lightColor[1]);
|
||||
ui->light_B_SB->setValue((int)lightColor[2]);
|
||||
ui->lightOn_R_SB->setValue((int)(sm->getBgColorOn()[0]));
|
||||
ui->lightOn_G_SB->setValue((int)(sm->getBgColorOn()[1]));
|
||||
ui->lightOn_B_SB->setValue((int)(sm->getBgColorOn()[2]));
|
||||
|
||||
ui->ambCoef->setValue(ambCoef);
|
||||
ui->attFac->setValue(attFac);
|
||||
ui->light_R_SB->setValue((int)(sm->getLightColor()[0]));
|
||||
ui->light_G_SB->setValue((int)(sm->getLightColor()[1]));
|
||||
ui->light_B_SB->setValue((int)(sm->getLightColor()[2]));
|
||||
|
||||
ui->checkAutoColor->setChecked(autoColor);
|
||||
if (lightType == 1)
|
||||
ui->ambCoef->setValue(sm->getAmbient());
|
||||
ui->attFac->setValue(sm->getAttenuation());
|
||||
|
||||
ui->checkBackfaceCulling->setChecked(sm->isBfCulling());
|
||||
ui->checkAutoColor->setChecked(sm->isAutoColor());
|
||||
ui->checkHeadlight->setChecked(sm->isHeadlight());
|
||||
|
||||
if (sm->getLightType() == 1)
|
||||
ui->radioDirectLight->setChecked(true);
|
||||
else
|
||||
ui->radioPointLight->setChecked(true);
|
||||
|
||||
connect(this, &SettingsWindow::updateBGColorOff, sm, &SettingsManager::setBgColorOff);
|
||||
connect(this, &SettingsWindow::updateBGColorOn, sm, &SettingsManager::setBgColorOn);
|
||||
connect(this, &SettingsWindow::updateLightColor, sm, &SettingsManager::setLightColor);
|
||||
connect(this, &SettingsWindow::updateAttFac, sm, &SettingsManager::setAttenuation);
|
||||
connect(this, &SettingsWindow::updateAmbCoef, sm, &SettingsManager::setAmbient);
|
||||
connect(this, &SettingsWindow::sendHeadlight, sm, &SettingsManager::setHeadlight);
|
||||
connect(this, &SettingsWindow::sendBackfaceCulling, sm, &SettingsManager::setBfCulling);
|
||||
connect(ui->checkAutoColor, &QCheckBox::stateChanged, sm, &SettingsManager::setAutoColor);
|
||||
connect(this, &SettingsWindow::changeLightType, sm, &SettingsManager::setLightType);
|
||||
|
||||
}
|
||||
|
||||
|
@ -133,10 +151,12 @@ void SettingsWindow::radioToggled()
|
|||
{
|
||||
ui->attFac->setValue(0.0);
|
||||
ui->attFac->setEnabled(false);
|
||||
emit changeLightType(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->attFac->setEnabled(true);
|
||||
emit changeLightType(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
17
README.md
|
@ -1,3 +1,12 @@
|
|||
|
||||
https://git.rwth-aachen.de/carstenf/OpenGL
|
||||
|
||||
Pulled from here as backup of work that I did under the develop branch. I hope to come back to this and port to Python using this as a reference for logic and how-to.
|
||||
|
||||
Below is original README text.
|
||||
|
||||
|
||||
|
||||
# MshViewer
|
||||
|
||||
I started to learn OpenGL. Therefore i decided to implement a .msh viewer for SWBFII assets, since the old one
|
||||
|
@ -12,10 +21,4 @@ So far it is just me. If you wanna help me, let me know :D
|
|||
Feel free to use my code the way you like. But remember i used some public libraries. Make sure you read their
|
||||
licence, too.
|
||||
|
||||
### To Do
|
||||
- normal map,
|
||||
- list all msh in a directory
|
||||
- glow/emissive
|
||||
- optional display bones, shadow, collision
|
||||
- change pose
|
||||
- animation
|
||||
|
||||
|
|
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 48 KiB |
|
@ -1,14 +0,0 @@
|
|||
#version 450 core
|
||||
|
||||
// Input
|
||||
in vec2 UV;
|
||||
|
||||
// Ouput data
|
||||
out vec3 color;
|
||||
|
||||
uniform sampler2D textureSampler;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = texture(textureSampler, UV).rgb;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#version 450 core
|
||||
|
||||
// Input vertex data, different for all executions of this shader.
|
||||
layout(location = 0) in vec3 vertexPosition_modelspace;
|
||||
layout(location = 1) in vec2 vertexUV;
|
||||
|
||||
// Output
|
||||
out vec2 UV;
|
||||
|
||||
// Values that stay constant for the whole mesh.
|
||||
uniform mat4 MVP;
|
||||
|
||||
void main(){
|
||||
|
||||
// Output position of the vertex, in clip space : MVP * position
|
||||
gl_Position = MVP * vec4(vertexPosition_modelspace, 1);
|
||||
|
||||
UV = vertexUV;
|
||||
|
||||
}
|
After Width: | Height: | Size: 46 KiB |