Compare commits

...

27 Commits

Author SHA1 Message Date
64d5584698 Update 'README.md' 2021-04-26 21:07:42 +00:00
Anakin
7e87b14fe1 made all path relative now 2017-04-30 15:05:21 +02:00
Anakin
da0b7e3c5f new release version,
Features:
- fixed overexposed specular bug,
- most settings are saved after each session
Bugs:
-nothing known
2017-02-08 14:32:48 +01:00
Anakin
fa75e17d58 most settings are saved and restored 2017-02-08 14:29:22 +01:00
Anakin
49585945c3 fixed too high specular,
updated preview.jpg
2017-02-06 16:53:27 +01:00
Anakin
67657061b6 new release version,
Features:
- normal map support,
- added specular support for cloth,
- "glow" support,
Bugs:
- normal mapping looks a bit drizzly depending on the angle of view
2017-02-06 14:59:46 +01:00
Anakin
06d403d546 support normal map now,
support "glow" now,
update preview.jpg
2017-02-06 14:53:05 +01:00
Anakin
541a975624 added preview imange,
passed data to shader,
need to process data in shader
2017-02-05 20:10:05 +01:00
Anakin
30f1a1e627 passing poylNormal, tangent, bitangent to shader 2017-02-05 16:57:12 +01:00
Anakin
cdf19911f6 calculate polygon normal, tangent, and bitangent,
next step, use them for calculation
2017-02-05 16:39:37 +01:00
Anakin
4c40d140a9 cloth now has specular 2017-02-05 15:25:59 +01:00
Anakin
f47e1cc76a new release version,
Features:
- extreme performance improvement when loading files,
- new camera controls (free, orbital, move),
- using ogl 4.5 again since 2.0 causes problems on some pc,
Bugs:
- nothing known
2017-02-05 12:38:32 +01:00
Anakin
2d335474bf fixed camera control,
removed test exe
2017-02-05 12:34:24 +01:00
Anakin
a07d8acbec update gui for camera mods 2017-02-04 17:42:44 +01:00
Anakin
800a6a50f8 doesn't work for ggctuk since i use ogl 2.0 instead of 4.5
trying to figure out the problem
2017-02-04 15:57:15 +01:00
Anakin
94a2fa59ec added MoveCamera but isn't working well
updated about text,
2017-02-04 15:48:10 +01:00
Anakin
648b805daf forget to save file 2017-02-03 15:55:04 +01:00
Anakin
92245be302 finished OrbitCamera 2017-02-03 15:54:45 +01:00
Anakin
333eca25eb use class for camera handling,
orbit does not work. Need to figure out why
2017-02-02 18:01:08 +01:00
Anakin
b17ab3f8e9 fixed out of file check order 2017-02-02 15:26:40 +01:00
Anakin
ff08ee7cea error handling when out of file 2017-02-02 15:10:48 +01:00
Anakin
8346e5916d changed everything from std to qt 2017-02-02 14:44:48 +01:00
Anakin
5372838420 further performance improvement 2017-02-02 11:14:16 +01:00
Anakin
a14229aa71 further improvement on tga import 2017-02-01 17:53:42 +01:00
Anakin
1c5631a5e0 improve image load performance,
can be improved more, but scanline has wrong results
2017-02-01 17:41:29 +01:00
Anakin
bc5bfc62bc fixed a bug 2017-02-01 16:34:43 +01:00
Anakin
4cb070c8c5 removed files from repo that are not needed in the release folder 2017-01-30 17:24:21 +01:00
63 changed files with 1560 additions and 595 deletions

View File

@ -19,7 +19,9 @@
<property name="windowTitle"> <property name="windowTitle">
<string>MainWindow</string> <string>MainWindow</string>
</property> </property>
<widget class="QWidget" name="centralWidget"/> <widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout"/>
</widget>
<widget class="QToolBar" name="mainToolBar"> <widget class="QToolBar" name="mainToolBar">
<property name="allowedAreas"> <property name="allowedAreas">
<set>Qt::LeftToolBarArea|Qt::RightToolBarArea|Qt::TopToolBarArea</set> <set>Qt::LeftToolBarArea|Qt::RightToolBarArea|Qt::TopToolBarArea</set>
@ -32,6 +34,72 @@
</attribute> </attribute>
</widget> </widget>
<widget class="QStatusBar" name="statusBar"/> <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> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<resources> <resources>

View File

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

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <QOpenGlTexture> #include <QOpenGlTexture>
#include <fstream> #include <QFile>
#include <QVector> #include <QVector>
#include <QVector2D> #include <QVector2D>
#include <QMatrix4x4> #include <QMatrix4x4>
@ -18,20 +18,23 @@ struct VertexData
QVector3D position; QVector3D position;
QVector2D texCoord; QVector2D texCoord;
QVector3D vertexNormal; QVector3D vertexNormal;
QVector3D polygonNormal;
QVector3D tangent;
QVector3D bitangent;
}; };
struct Segment { struct Segment {
std::uint32_t textureIndex = 0; quint32 textureIndex = 0;
QVector<VertexData> vertices; QVector<VertexData> vertices;
QVector<GLuint> indices; QVector<GLuint> indices;
}; };
struct Model { struct Model {
std::string name = ""; QString name = "";
std::string parent = ""; QString parent = "";
QMatrix4x4 m4x4Translation; QMatrix4x4 m4x4Translation;
QQuaternion quadRotation; QQuaternion quadRotation;
std::vector<Segment*> segmList; QVector<Segment*> segmList;
}; };
struct Material { struct Material {
@ -42,14 +45,14 @@ struct Material {
QString tx3d; QString tx3d;
QOpenGLTexture* texture0 = Q_NULLPTR; QOpenGLTexture* texture0 = Q_NULLPTR;
QOpenGLTexture* texture1 = 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 diffuseColor = { 1.0, 0.0, 0.0, 1.0 };
QVector4D ambientColor = { 1.0, 1.0, 1.0, 1.0 }; QVector4D ambientColor = { 1.0, 1.0, 1.0, 1.0 };
float shininess = 80; float shininess = 1;
bool flags[8] = { false }; bool flags[8] = { false };
bool transparent = false; bool transparent = false;
std::uint8_t rendertype = 0; quint8 rendertype = 0;
std::uint8_t dataValues[2] = { 0 }; quint8 dataValues[2] = { 0 };
}; };
class FileInterface class FileInterface
@ -61,9 +64,9 @@ public:
, m_materials(new QVector<Material>) , m_materials(new QVector<Material>)
{ {
//open file //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()); throw std::invalid_argument(std::string("ERROR: file not found: ") += path.toStdString());
m_filepath = path.left(path.lastIndexOf(QRegExp("/|\\\\"))); m_filepath = path.left(path.lastIndexOf(QRegExp("/|\\\\")));
@ -94,7 +97,7 @@ public:
protected: protected:
QVector<Model*>* m_models; QVector<Model*>* m_models;
std::fstream m_file; QFile m_file;
QVector<Material>* m_materials; QVector<Material>* m_materials;
BoundingBox m_sceneBbox; BoundingBox m_sceneBbox;
QString m_filepath; QString m_filepath;

View File

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

View File

@ -34,6 +34,7 @@ private:
// functions // functions
private: private:
void clearData(); void clearData();
void setupPipeline(QOpenGLShaderProgram * program);
public: public:
void drawGeometry(QOpenGLShaderProgram *program); void drawGeometry(QOpenGLShaderProgram *program);

View File

@ -30,6 +30,8 @@ private:
// functions // functions
private: private:
void setupWidgets(); void setupWidgets();
void getAssetLibrary();
void searchMeshFiles(QString path);
void openFile(); void openFile();
void takeScreenShot(); void takeScreenShot();
void aboutTool(); void aboutTool();

View File

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

View File

@ -1,11 +1,11 @@
#pragma once #pragma once
#include "..\Header\FileInterface.h" #include "..\Header\FileInterface.h"
#include <QList>
struct ChunkHeader { struct ChunkHeader {
char name[5]; QString name;
std::uint32_t size; quint32 size;
std::streampos position; qint64 position;
}; };
enum ModelTyp { enum ModelTyp {
@ -29,22 +29,22 @@ private:
virtual void import() Q_DECL_OVERRIDE Q_DECL_FINAL; 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 analyseModlChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void analyseGeomChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); void analyseGeomChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void analyseSegmChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); void analyseSegmChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void analyseClthChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList); void analyseClthChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void readVertex(Segment* dataDestination, std::streampos position); void readVertex(Segment* dataDestination, qint64 position);
void readUV(Segment* dataDestination, std::streampos position); void readUV(Segment* dataDestination, qint64 position);
void loadTexture(QOpenGLTexture*& destination, QString filepath, QString& filename); void loadTexture(QOpenGLTexture*& destination, QString filepath, QString& filename);
QMatrix4x4 getParentMatrix(std::string parent) const; QMatrix4x4 getParentMatrix(QString parent) const;
QQuaternion getParentRotation(std::string parent) const; QQuaternion getParentRotation(QString parent) const;
}; };

View File

@ -5,6 +5,7 @@
#include <QMatrix4x4> #include <QMatrix4x4>
#include "GeometryEngine.h" #include "GeometryEngine.h"
#include "SettingsWindow.h" #include "SettingsWindow.h"
#include "CameraInterface.h"
class GeometryEngine; class GeometryEngine;
@ -22,43 +23,35 @@ private:
QOpenGLShaderProgram m_program; QOpenGLShaderProgram m_program;
GeometryEngine *m_dataEngine; GeometryEngine *m_dataEngine;
QVector4D m_backgroundColorOn = { 0.02f, 0.02f, 0.02f, 1.0f }; QVector4D m_backgroundColorOn;
QVector4D m_backgroundColorOff = { 0.5f, 0.8f, 1.0f, 1.0f }; QVector4D m_backgroundColorOff;
bool m_wireframe = false; bool m_wireframe;
bool m_lightOn = false; bool m_lightOn;
bool m_backfaceCulling = false; bool m_backfaceCulling;
struct { struct {
QVector4D position = { 1,1,1,0 }; QVector4D position;
QVector3D intensities = { 1.0,1.0,1.0 }; QVector3D intensities;
float attenuationFactor = 0.0f; float attenuationFactor;
float ambientCoefficient = 0.005f; float ambientCoefficient;
bool headlight = false; bool headlight;
} m_light; } m_light;
SettingsWindow* m_settings;
struct { struct {
bool left = false; bool left = false;
bool right = false; bool right = false;
QVector2D position; QVector2D position;
} m_mouse; } m_mouse;
struct {
bool x = true;
bool y = true;
bool z = true;
} m_rotDirections;
QMatrix4x4 m_projection; QMatrix4x4 m_projection;
QVector3D m_translation; CameraInterface* m_camera;
QQuaternion m_rotation;
double m_zSpeed = 1.0; SettingsWindow* m_settings;
// functions // functions
private: private:
void setDefaultValues();
void initShaders(); void initShaders();
void resetView(); void resetView();
void updateLightPosition(); void updateLightPosition();
@ -74,6 +67,7 @@ protected:
void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE; void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent *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 dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE;
void dropEvent(QDropEvent * event) Q_DECL_OVERRIDE; void dropEvent(QDropEvent * event) Q_DECL_OVERRIDE;
@ -81,10 +75,13 @@ protected:
// slots // slots
public slots: public slots:
void loadFile(QString name); void loadFile(QString name);
void toggleAxis(int axis); void useFreeCamera();
void useOrbitCamera();
void useMoveCamera();
void toggleWireframe(); void toggleWireframe();
void toggleLight(); void toggleLight();
void showSettings(); void showSettings();
void setBGColorOff(QVector3D value); void setBGColorOff(QVector3D value);
void setBGColorOn(QVector3D value); void setBGColorOn(QVector3D value);
void setLightColor(QVector3D value); void setLightColor(QVector3D value);
@ -92,7 +89,11 @@ public slots:
void setAmbCoef(double value); void setAmbCoef(double value);
void setHeadlight(bool value); void setHeadlight(bool value);
void setBackfaceCulling(bool value); void setBackfaceCulling(bool value);
void setZoomSpeed(int percent);
// signals
signals:
void lightChanged(bool value);
}; };

View File

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

View File

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

View File

@ -9,7 +9,7 @@ class SettingsWindow : public QWidget
Q_OBJECT Q_OBJECT
public: 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(); ~SettingsWindow();
private: private:
@ -33,5 +33,6 @@ signals:
void sendHeadlight(bool value); void sendHeadlight(bool value);
void sendBackfaceCulling(bool value); void sendBackfaceCulling(bool value);
void sendZommSpeed(int percent); void sendZommSpeed(int percent);
void changeLightType(int value);
}; };

View File

@ -1,36 +1,38 @@
#pragma once #pragma once
#include <fstream> #include "OutputDevice.h"
#include <QImage> #include <QImage>
#include <QColor> #include <QColor>
#include <QVector>
#include <QFile>
QImage loadTga(QString filePath, bool &success) QImage loadTga(QString filePath, bool &success)
{ {
QImage img; QImage img;
success = true;
// open the file // 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; success = false;
return img;
} }
else
{
// read in the header // read in the header
std::uint8_t ui8x18Header[19] = { 0 }; quint8 ui8x18Header[19] = { 0 };
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1); file.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
//get variables //get variables
std::uint32_t ui32BpP; quint32 ui32BpP;
std::uint32_t ui32Width; quint32 ui32Width;
std::uint32_t ui32Height; quint32 ui32Height;
std::uint32_t ui32IDLength; quint32 ui32IDLength;
std::uint32_t ui32PicType; quint32 ui32PicType;
std::uint32_t ui32PaletteLength; quint32 ui32PaletteLength;
std::uint32_t ui32Size; quint32 ui32Size;
// extract all information from header // extract all information from header
ui32IDLength = ui8x18Header[0]; ui32IDLength = ui8x18Header[0];
@ -44,58 +46,47 @@ QImage loadTga(QString filePath, bool &success)
ui32Size = ui32Width * ui32Height * ui32BpP / 8; ui32Size = ui32Width * ui32Height * ui32BpP / 8;
// jump to the data block // jump to the data block
fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur); file.seek(ui32IDLength + ui32PaletteLength + 18);
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
// uncompressed // uncompressed
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32)) if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
{ {
std::vector<std::uint8_t> vui8Pixels; img = QImage(ui32Width, ui32Height, ui32BpP == 32 ? QImage::Format_RGBA8888 : QImage::Format_RGB888);
vui8Pixels.resize(ui32Size); int lineWidth = ui32Width * ui32BpP / 8;
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
for (unsigned int y = 0; y < ui32Height; y++) for (int i = ui32Height - 1; i >= 0; --i)
{ file.read(reinterpret_cast<char*>(img.scanLine(i)), lineWidth);
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 compressed 24 or 32 bit
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
{ {
std::uint8_t tempChunkHeader; OutputDevice::getInstance()->print("compressed tga is not supported by SWBF", 1);
std::uint8_t tempData[5];
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
quint8 tempChunkHeader;
quint8 tempData[5];
unsigned int tmp_pixelIndex = 0; unsigned int tmp_pixelIndex = 0;
do { do {
fsPicture.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader)); file.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
if (tempChunkHeader >> 7) // repeat count if (tempChunkHeader >> 7) // repeat count
{ {
// just use the first 7 bits // just use the first 7 bits
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1); tempChunkHeader = (quint8(tempChunkHeader << 1) >> 1);
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8); file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
for (int i = 0; i <= tempChunkHeader; i++) for (int i = 0; i <= tempChunkHeader; i++)
{ {
QColor color; QColor color;
if (ui32BpP == 32) if (ui32BpP == 32)
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3])); color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], tempData[3]));
else else
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255)); color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], 255));
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba()); img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
tmp_pixelIndex++; tmp_pixelIndex++;
@ -108,14 +99,14 @@ QImage loadTga(QString filePath, bool &success)
for (int i = 0; i <= tempChunkHeader; i++) for (int i = 0; i <= tempChunkHeader; i++)
{ {
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8); file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
QColor color; QColor color;
if (ui32BpP == 32) if (ui32BpP == 32)
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3])); color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], tempData[3]));
else else
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255)); color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], 255));
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba()); img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
tmp_pixelIndex++; tmp_pixelIndex++;
@ -126,13 +117,12 @@ QImage loadTga(QString filePath, bool &success)
// not useable format // not useable format
else else
{ {
fsPicture.close();
success = false; success = false;
return img; }
} }
fsPicture.close(); if (file.isOpen())
success = true; file.close();
return img; return qMove(img).rgbSwapped();
} }

View File

@ -15,17 +15,14 @@
<file>info.png</file> <file>info.png</file>
<file>about.png</file> <file>about.png</file>
<file>open.png</file> <file>open.png</file>
<file>X.png</file>
<file>Y.png</file>
<file>Z.png</file>
<file>screenshot.png</file> <file>screenshot.png</file>
<file>wireframe.png</file> <file>wireframe.png</file>
<file>light_off.png</file> <file>light_off.png</file>
<file>light_on.png</file> <file>light_on.png</file>
<file>solid.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>settings.png</file>
<file>freeCamera.png</file>
<file>orbitalCamera.png</file>
<file>walkCamera.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -37,28 +37,16 @@ QToolButton#screenshot {
image: url(:/images/toolbar/screenshot.png); image: url(:/images/toolbar/screenshot.png);
} }
QToolButton#x { QToolButton#freeCamera {
image: url(:/images/toolbar/X_disabled.png); image: url(:/images/toolbar/freeCamera.png);
} }
QToolButton#x:checked { QToolButton#orbitalCamera {
image: url(:/images/toolbar/X.png); image: url(:/images/toolbar/orbitalCamera.png);
} }
QToolButton#y { QToolButton#walkCamera {
image: url(:/images/toolbar/Y_disabled.png); image: url(:/images/toolbar/walkCamera.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#wireframe { QToolButton#wireframe {

View File

@ -4,9 +4,22 @@ source code: https://git.rwth-aachen.de/carstenf/OpenGL/tree/master/QtMeshViewer
=============================================================== ===============================================================
Controll: Controll:
Free Camera: static view position and you rotate and move the object
left mouse - rotate left mouse - rotate
right mouse - move right mouse - move
scroll - zoom 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 space - reset view
L - set light to current position L - set light to current position
esc - close esc - close

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

View File

@ -4,16 +4,22 @@ precision mediump int;
precision mediump float; precision mediump float;
#endif #endif
uniform mat3 n_matrix; uniform mat3 normalMatrix;
uniform vec3 cameraPosition; uniform vec3 cameraPosition;
uniform sampler2D texture; uniform sampler2D tx0;
uniform float materialShininess; uniform sampler2D tx1;
uniform vec3 materialSpecularColor;
uniform bool b_transparent; uniform struct Material {
uniform bool b_specular; float shininess;
uniform bool b_light; vec3 specularColor;
bool isTransparent;
bool hasSpecularmap;
bool hasNormalmap;
bool isGlow;
} material;
uniform bool useLight;
uniform struct Light { uniform struct Light {
vec4 position; vec4 position;
@ -25,67 +31,96 @@ uniform struct Light {
varying vec2 v_surfaceUV; varying vec2 v_surfaceUV;
varying vec3 v_surfacePosition; varying vec3 v_surfacePosition;
varying vec3 v_surfaceNormal; varying vec3 v_surfaceNormal;
varying vec3 v_polyNorm;
varying vec3 v_polyTan;
varying vec3 v_polyBiTan;
void main() void main()
{ {
if(b_light) if(useLight && !material.isGlow)
{ {
// some values // get the color and undo gamma correction
vec3 normalWorld = normalize(n_matrix * v_surfaceNormal); vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV));
vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV));
surfaceColor.rgb = pow(surfaceColor.rgb, vec3(2.2)); surfaceColor.rgb = pow(surfaceColor.rgb, vec3(2.2));
vec3 surfaceToLight; // attenutation depending on the distance to the light
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); float distanceToLight = length(light.position.xyz - v_surfacePosition);
attenuation = 1.0 / (1.0 + light.attenuationFactor * pow(distanceToLight, 2)); 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); 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; 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; vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
// specular
/////////////////////////////////////////////////////////////////////////////////////
// specular component
float specularCoefficient = 0.0; float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0) if(diffuseCoefficient > 0.0)
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normalWorld))), materialShininess); specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), material.shininess);
vec3 specColor;
if(b_specular) float specularWeight = 1;
specColor = vec3(surfaceColor.a); if(material.hasSpecularmap)
else specularWeight = surfaceColor.a;
specColor = materialSpecularColor; vec3 specColor = specularWeight * 1/255 * material.specularColor;
vec3 specular = specularCoefficient * specColor * light.intensities; vec3 specular = specularCoefficient * specColor * light.intensities;
// linear color before gamma correction) /////////////////////////////////////////////////////////////////////////////////////
// linear color before gamma correction
vec3 linearColor = ambient + attenuation * (diffuse + specular); vec3 linearColor = ambient + attenuation * (diffuse + specular);
// final color after gama correction /////////////////////////////////////////////////////////////////////////////////////
// gama correction
vec3 gamma = vec3(1.0/2.2); 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); gl_FragColor = vec4(pow(linearColor, gamma), surfaceColor.a);
} }
// don't use light
else else
{ {
vec4 surfaceColor = vec4(texture2D(texture, v_surfaceUV)); vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV));
if(!b_transparent)
surfaceColor.a = 1.0f; if(!material.isTransparent)
surfaceColor.a = 1.0;
gl_FragColor = surfaceColor; gl_FragColor = surfaceColor;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

View File

@ -4,26 +4,35 @@ precision mediump int;
precision mediump float; precision mediump float;
#endif #endif
uniform mat4 vp_matrix; uniform mat4 viewProjection;
uniform mat4 norm_matrix; uniform mat4 normalizeModel;
uniform mat4 m_matrix; uniform mat4 modelMatrix;
attribute vec4 a_position; attribute vec4 a_position;
attribute vec2 a_texcoord; attribute vec2 a_texcoord;
attribute vec3 a_normal; attribute vec3 a_normal;
attribute vec3 a_polyNorm;
attribute vec3 a_polyTan;
attribute vec3 a_polyBiTan;
varying vec2 v_surfaceUV; varying vec2 v_surfaceUV;
varying vec3 v_surfacePosition; varying vec3 v_surfacePosition;
varying vec3 v_surfaceNormal; varying vec3 v_surfaceNormal;
varying vec3 v_polyNorm;
varying vec3 v_polyTan;
varying vec3 v_polyBiTan;
void main() void main()
{ {
// Calculate vertex position in screen space // 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 // Pass data to fragment shader
// Value will be automatically interpolated to fragments inside polygon faces // Value will be automatically interpolated to fragments inside polygon faces
v_surfaceUV = a_texcoord; 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_surfaceNormal = a_normal;
v_polyNorm = a_polyNorm;
v_polyTan = a_polyTan;
v_polyBiTan = a_polyBiTan;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

View File

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

View File

@ -51,26 +51,8 @@ void GeometryEngine::clearData()
m_drawList.clear(); 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 // Offset for position
quintptr offset = 0; quintptr offset = 0;
@ -87,13 +69,63 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
program->enableAttributeArray(texcoordLocation); program->enableAttributeArray(texcoordLocation);
program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData)); program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));
//Offset for normal //Offset for vertexNormal
offset += sizeof(QVector2D); offset += sizeof(QVector2D);
// Tell OpenGL programmable pipeline how to locate vertex normal data // Tell OpenGL programmable pipeline how to locate vertex normal data
int normLocation = program->attributeLocation("a_normal"); int vertNormLocation = program->attributeLocation("a_normal");
program->enableAttributeArray(normLocation); program->enableAttributeArray(vertNormLocation);
program->setAttributeBuffer(normLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); 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 // Paint
@ -101,36 +133,51 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
{ {
bool tmp_transparent(false); bool tmp_transparent(false);
bool tmp_specular(false); bool tmp_specular(false);
bool tmp_normalmap(false);
bool tmp_glow(false);
float shininess(0.0); float shininess(0.0);
QVector3D specularColor; QVector3D specularColor;
// bind the correct texture // bind the correct texture
if (it.textureIndex < (unsigned)m_materials->size() && m_materials->at(it.textureIndex).texture0 != Q_NULLPTR) 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_transparent = m_materials->at(it.textureIndex).transparent;
tmp_specular = m_materials->at(it.textureIndex).flags[7]; tmp_specular = m_materials->at(it.textureIndex).flags[7];
shininess = m_materials->at(it.textureIndex).shininess; shininess = m_materials->at(it.textureIndex).shininess;
specularColor = m_materials->at(it.textureIndex).specularColor.toVector3D(); 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 else
{ {
m_defaultMaterial->texture0->bind(); m_defaultMaterial->texture0->bind(0);
tmp_transparent = m_defaultMaterial->transparent; tmp_transparent = m_defaultMaterial->transparent;
} }
// Set model matrix // Set model matrix
program->setUniformValue("m_matrix", it.modelMatrix); program->setUniformValue("modelMatrix", it.modelMatrix);
// Set normal matrix // Set normal matrix
program->setUniformValue("n_matrix", (normMatrix * it.modelMatrix).normalMatrix()); program->setUniformValue("normalMatrix", (normMatrix * it.modelMatrix).normalMatrix());
// set some more values
program->setUniformValue("b_transparent", tmp_transparent);
program->setUniformValue("b_specular", tmp_specular);
// set some material attributes // set some material attributes
program->setUniformValue("materialShininess", shininess); program->setUniformValue("material.shininess", shininess);
program->setUniformValue("materialSpecularColor", specularColor); 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 // Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint))); glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint)));

View File

@ -36,9 +36,6 @@ MainWindow::MainWindow(QWidget *parent)
// setup opengl things // setup opengl things
QSurfaceFormat format; QSurfaceFormat format;
format.setDepthBufferSize(24); format.setDepthBufferSize(24);
format.setMajorVersion(2);
format.setMinorVersion(0);
format.setProfile(QSurfaceFormat::NoProfile);
QSurfaceFormat::setDefaultFormat(format); QSurfaceFormat::setDefaultFormat(format);
// set default text to file info // set default text to file info
@ -52,6 +49,8 @@ MainWindow::MainWindow(QWidget *parent)
styleSheet.open(QIODevice::ReadOnly); styleSheet.open(QIODevice::ReadOnly);
this->setStyleSheet(styleSheet.readAll()); this->setStyleSheet(styleSheet.readAll());
getAssetLibrary();
printMessage("MeshViewer by Anakin", 0); printMessage("MeshViewer by Anakin", 0);
} }
@ -90,41 +89,26 @@ void MainWindow::setupWidgets()
////////////////////////////////////////////////// //////////////////////////////////////////////////
ui->mainToolBar->addSeparator(); 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 // Orbital Camera
QToolButton *x = new QToolButton(this); QToolButton *orbitCamera = new QToolButton(this);
x->setObjectName("x"); orbitCamera->setObjectName("orbitalCamera");
x->setToolTip("x-direction"); orbitCamera->setToolTip("orbital camera");
x->setCheckable(true); connect(orbitCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useOrbitCamera);
x->setChecked(true); ui->mainToolBar->addWidget(orbitCamera);
ui->mainToolBar->addWidget(x);
// Y // Move Camera
QToolButton *y = new QToolButton(this); QToolButton *walkCamera = new QToolButton(this);
y->setObjectName("y"); walkCamera->setObjectName("walkCamera");
y->setToolTip("y-direction"); walkCamera->setToolTip("walk camera");
y->setCheckable(true); connect(walkCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useMoveCamera);
y->setChecked(true); ui->mainToolBar->addWidget(walkCamera);
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)));
////////////////////////////////////////////////// //////////////////////////////////////////////////
ui->mainToolBar->addSeparator(); 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() void MainWindow::openFile()
{ {
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Mesh (*.msh)"); QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Mesh (*.msh)");

View File

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

View File

@ -1,7 +1,7 @@
#include "..\Header\MshFile.h" #include "..\Header\MshFile.h"
#include "..\Header\tga.h" #include "..\Header\tga.h"
#include "..\Header\OutputDevice.h" #include "..\Header\OutputDevice.h"
#include <QColor> #include <QVector3D>
// helper function to save data from file to any variable type // helper function to save data from file to any variable type
@ -28,22 +28,22 @@ MshFile::~MshFile()
void MshFile::import() void MshFile::import()
{ {
// go to file size information // go to file size information
m_file.seekg(4); m_file.seek(4);
std::uint32_t tmp_fileSize; quint32 tmp_fileSize;
std::list<ChunkHeader*> tmp_mainChunks; QList<ChunkHeader*> tmp_mainChunks;
// get all chunks under HEDR // get all chunks under HEDR
m_file.read(F2V(tmp_fileSize), sizeof(tmp_fileSize)); 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) // evaulate HEDR subchunks (= find MSH2)
for (ChunkHeader* it : tmp_mainChunks) for (ChunkHeader* it : tmp_mainChunks)
{ {
if (!strcmp("MSH2", it->name)) if ("MSH2" == it->name)
{ {
// get all subchunks // get all subchunks
std::list<ChunkHeader*> tmp_msh2Chunks; QList<ChunkHeader*> tmp_msh2Chunks;
loadChunks(tmp_msh2Chunks, it->position, it->size); loadChunks(tmp_msh2Chunks, it->position, it->size);
// evaluate MSH2 subchunks // 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 // jump to first chunk
m_file.seekg(start); m_file.seek(start);
do 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(); ChunkHeader* tmp_header = new ChunkHeader();
// get information // 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)); 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 // store information
destination.push_back(tmp_header); destination.push_back(tmp_header);
// jump to next 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 } while (m_file.pos() - start != length);
if (!m_file.good())
{
OutputDevice::getInstance()->print("WARNING: corrupted file. Trying to continue..", 1);
m_file.clear();
break;
} }
} while (m_file.tellg() - start != length); void MshFile::analyseMsh2Chunks(QList<ChunkHeader*>& chunkList)
}
void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
{ {
for (auto& it : chunkList) for (auto& it : chunkList)
{ {
// scene information // scene information
if (!strcmp("SINF", it->name)) if ("SINF" == it->name)
{ {
// get SINF subchunks // get SINF subchunks
std::list<ChunkHeader*> tmp_sinfChunks; QList<ChunkHeader*> tmp_sinfChunks;
loadChunks(tmp_sinfChunks, it->position, it->size); loadChunks(tmp_sinfChunks, it->position, it->size);
// evaluate SINF subchunks // evaluate SINF subchunks
for (auto& it : tmp_sinfChunks) 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 // read in the quaternion
float tmp_quat[4]; float tmp_quat[4];
@ -143,24 +146,25 @@ void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
} }
// material list // 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 // "useless" information how many MATD follow, jump over it
m_file.seekg(it->position); m_file.seek(it->position);
m_file.seekg(sizeof(std::uint32_t), std::ios_base::cur); m_file.seek(sizeof(quint32) + m_file.pos());
// get all MATL subchunk // get all MATL subchunk
std::list<ChunkHeader*> tmp_matlChunks; QList<ChunkHeader*> tmp_matlChunks;
loadChunks(tmp_matlChunks, m_file.tellg(), it->size - 4); loadChunks(tmp_matlChunks, m_file.pos(), it->size - 4);
// evaluate MATL subchunks // evaluate MATL subchunks
for (auto& it : tmp_matlChunks) for (auto& it : tmp_matlChunks)
{ {
// This shouldn't be anything else than MATD // This shouldn't be anything else than MATD
if (!strcmp("MATD", it->name)) if ("MATD" == it->name)
{ {
// get all subchunks from MATD // get all subchunks from MATD
std::list<ChunkHeader*> tmp_matdChunks; QList<ChunkHeader*> tmp_matdChunks;
loadChunks(tmp_matdChunks, it->position, it->size); loadChunks(tmp_matdChunks, it->position, it->size);
m_materials->push_back(Material()); m_materials->push_back(Material());
@ -188,14 +192,15 @@ void MshFile::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
} }
// model // model
else if (!strcmp("MODL", it->name)) else if ("MODL" == it->name)
{ {
OutputDevice::getInstance()->print("loading model..", 0);
Model* new_model = new Model; Model* new_model = new Model;
m_currentType = ModelTyp::null; m_currentType = ModelTyp::null;
m_currentRenderFlag = -1; m_currentRenderFlag = -1;
// get all MODL subchunks // get all MODL subchunks
std::list<ChunkHeader*> tmp_chunks; QList<ChunkHeader*> tmp_chunks;
loadChunks(tmp_chunks, it->position, it->size); loadChunks(tmp_chunks, it->position, it->size);
// evaluate MODL subchunks // 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) for (auto& it : chunkList)
{ {
// name // 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]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -231,9 +236,9 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
} }
// data // data
else if(!strcmp("DATA", it->name)) else if("DATA" == it->name)
{ {
m_file.seekg(it->position); m_file.seek(it->position);
// diffuse // diffuse
for (unsigned int i = 0; i < 4; i++) for (unsigned int i = 0; i < 4; i++)
@ -252,18 +257,18 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
} }
// attributes // attributes
else if (!strcmp("ATRB", it->name)) else if ("ATRB" == it->name)
{ {
// get pointer to current material // get pointer to current material
Material* curMat = &m_materials->back(); Material* curMat = &m_materials->back();
// read the attributes // read the attributes
m_file.seekg(it->position); m_file.seek(it->position);
std::uint8_t flag; quint8 flag;
m_file.read(F2V(flag), sizeof(flag)); m_file.read(F2V(flag), sizeof(flag));
m_file.read(F2V(curMat->rendertype), sizeof(std::uint8_t)); m_file.read(F2V(curMat->rendertype), sizeof(quint8));
m_file.read(F2V(curMat->dataValues[0]), sizeof(std::uint8_t)); m_file.read(F2V(curMat->dataValues[0]), sizeof(quint8));
m_file.read(F2V(curMat->dataValues[1]), sizeof(std::uint8_t)); m_file.read(F2V(curMat->dataValues[1]), sizeof(quint8));
// flags // flags
// 0: emissive // 0: emissive
@ -276,16 +281,16 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
// 7: specular // 7: specular
for (unsigned int i = 0; i < 8; i++) 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; curMat->transparent = curMat->flags[2] || curMat->flags[3] || curMat->flags[4] || curMat->flags[6] || curMat->rendertype == 4;
} }
// texture 0 // texture 0
else if (!strcmp("TX0D", it->name)) else if ("TX0D" == it->name)
{ {
// get the texture name // get the texture name
m_file.seekg(it->position); m_file.seek(it->position);
char* buffer = new char[it->size + 1]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -298,10 +303,10 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
} }
// texture 1 // texture 1
else if (!strcmp("TX1D", it->name)) else if ("TX1D" == it->name)
{ {
// get the texture name // get the texture name
m_file.seekg(it->position); m_file.seek(it->position);
char* buffer = new char[it->size + 1]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -313,10 +318,10 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
} }
// texture 2 // texture 2
else if (!strcmp("TX2D", it->name)) else if ("TX2D" == it->name)
{ {
// get the texture name // get the texture name
m_file.seekg(it->position); m_file.seek(it->position);
char* buffer = new char[it->size + 1]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -325,10 +330,10 @@ void MshFile::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
} }
// texture 3 // texture 3
else if (!strcmp("TX3D", it->name)) else if ("TX3D" == it->name)
{ {
// get the texture name // get the texture name
m_file.seekg(it->position); m_file.seek(it->position);
char* buffer = new char[it->size + 1]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); 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) for (auto& it : chunkList)
{ {
// model type // model type
if (!strcmp("MTYP", it->name)) if ("MTYP" == it->name)
{ {
m_file.seekg(it->position); m_file.seek(it->position);
std::uint32_t tmp_type; quint32 tmp_type;
m_file.read(F2V(tmp_type), sizeof(tmp_type)); m_file.read(F2V(tmp_type), sizeof(tmp_type));
m_currentType = (ModelTyp)tmp_type; m_currentType = (ModelTyp)tmp_type;
} }
// parent name // 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]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -363,9 +368,9 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
} }
// model name // 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]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -374,20 +379,20 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
} }
// render flags // 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)); m_file.read(F2V(m_currentRenderFlag), sizeof(m_currentRenderFlag));
} }
// translation // translation
else if (!strcmp("TRAN", it->name)) else if ("TRAN" == it->name)
{ {
float tmp_scale[3]; float tmp_scale[3];
float tmp_rotation[4]; float tmp_rotation[4];
float tmp_trans[3]; float tmp_trans[3];
m_file.seekg(it->position); m_file.seek(it->position);
// read in the data // read in the data
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
@ -410,14 +415,14 @@ void MshFile::analyseModlChunks(Model * dataDestination, std::list<ChunkHeader*>
} }
// geometry data // geometry data
else if (!strcmp("GEOM", it->name)) else if ("GEOM" == it->name)
{ {
// don't get null, bone, shadowMesh and hidden mesh indices // don't get null, bone, shadowMesh and hidden mesh indices
if (m_currentType == null || m_currentType == bone || m_currentType == shadowMesh || m_currentRenderFlag == 1) if (m_currentType == null || m_currentType == bone || m_currentType == shadowMesh || m_currentRenderFlag == 1)
continue; continue;
// get all GEOM subchunks // get all GEOM subchunks
std::list<ChunkHeader*> tmp_geomChunks; QList<ChunkHeader*> tmp_geomChunks;
loadChunks(tmp_geomChunks, it->position, it->size); loadChunks(tmp_geomChunks, it->position, it->size);
// evaluate GEOM subchunks // 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) for (auto& it : chunkList)
{ {
// segment // segment
if (!strcmp("SEGM", it->name)) if ("SEGM" == it->name)
{ {
// get all SEGM subchunks // get all SEGM subchunks
std::list<ChunkHeader*> tmp_segmChunks; QList<ChunkHeader*> tmp_segmChunks;
loadChunks(tmp_segmChunks, it->position, it->size); loadChunks(tmp_segmChunks, it->position, it->size);
// evaluate SEGM subchunks // evaluate SEGM subchunks
@ -458,10 +463,10 @@ void MshFile::analyseGeomChunks(Model * dataDestination, std::list<ChunkHeader*>
} }
// cloth // cloth
else if (!strcmp("CLTH", it->name)) else if ("CLTH" == it->name)
{ {
// get all CLTH subchunks // get all CLTH subchunks
std::list<ChunkHeader*> tmp_clthChunks; QList<ChunkHeader*> tmp_clthChunks;
loadChunks(tmp_clthChunks, it->position, it->size); loadChunks(tmp_clthChunks, it->position, it->size);
// evaluate CLTH subchunks // 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; Segment* new_segment = new Segment;
for (auto& it : chunkList) for (auto& it : chunkList)
{ {
// material index // 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)); m_file.read(F2V(new_segment->textureIndex), sizeof(new_segment->textureIndex));
} }
// position list (vertex) // position list (vertex)
else if (!strcmp("POSL", it->name)) else if ("POSL" == it->name)
{ {
readVertex(new_segment, it->position); readVertex(new_segment, it->position);
} }
// normals // normals
else if (!strcmp("NRML", it->name)) else if ("NRML" == it->name)
{ {
std::uint32_t tmp_size; quint32 tmp_size;
m_file.seekg(it->position); m_file.seek(it->position);
m_file.read(F2V(tmp_size), sizeof(tmp_size)); m_file.read(F2V(tmp_size), sizeof(tmp_size));
if (tmp_size < (unsigned) new_segment->vertices.size()) if (tmp_size < (unsigned) new_segment->vertices.size())
@ -525,18 +530,18 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
} }
// uv // uv
else if (!strcmp("UV0L", it->name)) else if ("UV0L" == it->name)
{ {
readUV(new_segment, it->position); readUV(new_segment, it->position);
} }
// polygons (indices into vertex/uv list) // 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; // jump to the data section and read the size;
std::uint32_t tmp_size; quint32 tmp_size;
m_file.seekg(it->position); m_file.seek(it->position);
m_file.read(F2V(tmp_size), sizeof(tmp_size)); m_file.read(F2V(tmp_size), sizeof(tmp_size));
int highBitCount(0); int highBitCount(0);
@ -545,7 +550,7 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
for (unsigned int i = 0; i < tmp_size; i++) for (unsigned int i = 0; i < tmp_size; i++)
{ {
// ReadData // ReadData
std::uint16_t tmp_value; quint16 tmp_value;
m_file.read(F2V(tmp_value), sizeof(tmp_value)); m_file.read(F2V(tmp_value), sizeof(tmp_value));
// Check if highbit is set // Check if highbit is set
@ -553,7 +558,7 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
{ {
highBitCount++; highBitCount++;
// remove the high bit, to get the actually value // 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 // save data
@ -567,18 +572,106 @@ void MshFile::analyseSegmChunks(Model * dataDestination, std::list<ChunkHeader*>
if (tmp_buffer.size() == 5) if (tmp_buffer.size() == 5)
{ {
for (size_t i = 0; i < 3; i++) // calculate poylgon normal, tangent and bitangent
new_segment->indices.push_back(tmp_buffer.takeFirst()); 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) else if (tmp_buffer.size() > 5)
{ {
unsigned int tmp_multiPolySize = tmp_buffer.size() - 2; 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 every triangle of the multi polygon..
for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++) for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++)
{
// ..calculate the edge indices // ..calculate the edge indices
for (int triEdge = 0; triEdge < 3; triEdge++) 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); 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) // save the last polygon (no 2 high bit followed)
if (tmp_buffer.size() == 3) if (tmp_buffer.size() == 3)
{ {
for (size_t i = 0; i < 3; i++) // calculate poylgon normal, tangent and bitangent
new_segment->indices.push_back(tmp_buffer.takeFirst()); 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) else if (tmp_buffer.size() > 3)
{ {
unsigned int tmp_multiPolySize = tmp_buffer.size(); 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 every triangle of the multi polygon..
for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++) for (unsigned int tri = 0; tri < tmp_multiPolySize - 2; tri++)
{
// ..calculate the edge indices // ..calculate the edge indices
for (int triEdge = 0; triEdge < 3; triEdge++) 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); 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; Segment* new_segment = new Segment;
for (auto& it : chunkList) for (auto& it : chunkList)
{ {
// texture name // texture name
if (!strcmp("CTEX", it->name)) if ("CTEX" == it->name)
{ {
// read the texture name // read the texture name
m_file.seekg(it->position); m_file.seek(it->position);
char* buffer = new char[it->size + 1]; char* buffer = new char[it->size + 1];
*buffer = { 0 }; *buffer = { 0 };
m_file.read(buffer, it->size); m_file.read(buffer, it->size);
@ -638,32 +820,46 @@ void MshFile::analyseClthChunks(Model * dataDestination, std::list<ChunkHeader*>
} }
// position list (vertex) // position list (vertex)
else if (!strcmp("CPOS", it->name)) else if ("CPOS" == it->name)
{ {
readVertex(new_segment, it->position); readVertex(new_segment, it->position);
} }
// uv // uv
else if (!strcmp("CUV0", it->name)) else if ("CUV0" == it->name)
{ {
readUV(new_segment, it->position); readUV(new_segment, it->position);
} }
// triangles (indices into vertex/uv list) // 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; // jump to the data section and read the size;
std::uint32_t tmp_size; quint32 tmp_size;
m_file.seekg(it->position); m_file.seek(it->position);
m_file.read(F2V(tmp_size), sizeof(tmp_size)); m_file.read(F2V(tmp_size), sizeof(tmp_size));
// for every triangle.. // 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; quint32 tmp_value[3];
m_file.read(F2V(tmp_value), sizeof(std::uint32_t)); 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); 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; quint32 tmp_size;
m_file.seekg(position); m_file.seek(position);
m_file.read(F2V(tmp_size), sizeof(tmp_size)); m_file.read(F2V(tmp_size), sizeof(tmp_size));
for (unsigned int i = 0; i < tmp_size; i++) 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; quint32 tmp_size;
m_file.seekg(position); m_file.seek(position);
m_file.read(F2V(tmp_size), sizeof(tmp_size)); m_file.read(F2V(tmp_size), sizeof(tmp_size));
if (tmp_size < (unsigned) dataDestination->vertices.size()) if (tmp_size < (unsigned) dataDestination->vertices.size())
@ -724,7 +920,7 @@ void MshFile::loadTexture(QOpenGLTexture *& destination, QString filepath, QStri
if (!loadSuccess) if (!loadSuccess)
{ {
OutputDevice::getInstance()->print("WARNING: texture not found or corrupted: " + filename, 1); 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 = 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)); img.fill(QColor(m_materials->back().diffuseColor[0] * 255, m_materials->back().diffuseColor[1] * 255, m_materials->back().diffuseColor[2] * 255));
filename += " *"; filename += " *";
@ -746,13 +942,13 @@ void MshFile::loadTexture(QOpenGLTexture *& destination, QString filepath, QStri
destination = new_texture; destination = new_texture;
} }
QMatrix4x4 MshFile::getParentMatrix(std::string parent) const QMatrix4x4 MshFile::getParentMatrix(QString parent) const
{ {
QMatrix4x4 matrix; QMatrix4x4 matrix;
for (auto& it : *m_models) for (auto& it : *m_models)
{ {
if (!strcmp(parent.c_str(), it->name.c_str())) if (parent == it->name)
{ {
matrix = getParentMatrix(it->parent) * it->m4x4Translation; matrix = getParentMatrix(it->parent) * it->m4x4Translation;
break; break;
@ -762,13 +958,13 @@ QMatrix4x4 MshFile::getParentMatrix(std::string parent) const
return matrix; return matrix;
} }
QQuaternion MshFile::getParentRotation(std::string parent) const QQuaternion MshFile::getParentRotation(QString parent) const
{ {
QQuaternion rotation; QQuaternion rotation;
for (auto& it : *m_models) for (auto& it : *m_models)
{ {
if (!strcmp(parent.c_str(), it->name.c_str())) if (parent == it->name)
{ {
rotation = getParentRotation(it->parent) * it->quadRotation; rotation = getParentRotation(it->parent) * it->quadRotation;
break; break;

View File

@ -1,5 +1,9 @@
#include "..\Header\OglViewerWidget.h" #include "..\Header\OglViewerWidget.h"
#include "..\Header\MainWindow.h" #include "..\Header\MainWindow.h"
#include "..\Header\FreeCamera.h"
#include "..\Header\OrbitCamera.h"
#include "..\Header\MoveCamera.h"
#include "..\Header\SettingsManager.h"
#include <QMouseEvent> #include <QMouseEvent>
#include <QDropEvent> #include <QDropEvent>
#include <QMimeData> #include <QMimeData>
@ -14,13 +18,15 @@
OglViewerWidget::OglViewerWidget(QWidget *parent) OglViewerWidget::OglViewerWidget(QWidget *parent)
: QOpenGLWidget(parent) : QOpenGLWidget(parent)
, m_dataEngine(0) , m_dataEngine(Q_NULLPTR)
, m_camera(new FreeCamera)
{ {
setFocus(); setFocus();
setAcceptDrops(true); setAcceptDrops(true);
// settings window // 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::updateBGColorOff, this, &OglViewerWidget::setBGColorOff);
connect(m_settings, &SettingsWindow::updateBGColorOn, this, &OglViewerWidget::setBGColorOn); 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::updateAmbCoef, this, &OglViewerWidget::setAmbCoef);
connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight); connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight);
connect(m_settings, &SettingsWindow::sendBackfaceCulling, this, &OglViewerWidget::setBackfaceCulling); 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() OglViewerWidget::~OglViewerWidget()
@ -40,6 +46,7 @@ OglViewerWidget::~OglViewerWidget()
delete m_dataEngine; delete m_dataEngine;
doneCurrent(); doneCurrent();
delete m_camera;
delete m_settings; delete m_settings;
} }
@ -47,6 +54,30 @@ OglViewerWidget::~OglViewerWidget()
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// functions // 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() void OglViewerWidget::initShaders()
{ {
// Compile vertex shader // Compile vertex shader
@ -68,9 +99,7 @@ void OglViewerWidget::initShaders()
void OglViewerWidget::resetView() void OglViewerWidget::resetView()
{ {
m_rotation = QQuaternion(); m_camera->resetView();
m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE };
m_zSpeed = 1;
if (m_light.headlight) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -79,13 +108,13 @@ void OglViewerWidget::resetView()
void OglViewerWidget::updateLightPosition() void OglViewerWidget::updateLightPosition()
{ {
QMatrix4x4 rotateBack; QVector4D lightPosition = { 0,0,0,1 };
rotateBack.rotate(m_rotation.inverted());
QVector3D cameraPosition = rotateBack * (-m_translation);
m_light.position.setX(cameraPosition.x()); lightPosition = m_camera->getMatrix().inverted() * lightPosition;
m_light.position.setY(cameraPosition.y());
m_light.position.setZ(cameraPosition.z()); m_light.position.setX(lightPosition.x());
m_light.position.setY(lightPosition.y());
m_light.position.setZ(lightPosition.z());
} }
// OpenGL /////////////////////////////////////////////////////////////// // OpenGL ///////////////////////////////////////////////////////////////
@ -139,25 +168,18 @@ void OglViewerWidget::paintGL()
// Clear color and depth buffer // Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 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 // Set view-projection matrix
m_program.setUniformValue("vp_matrix", m_projection * view); m_program.setUniformValue("viewProjection", m_projection * m_camera->getMatrix());
// Set Light values // 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.position", m_light.position);
m_program.setUniformValue("light.intensities", m_light.intensities); m_program.setUniformValue("light.intensities", m_light.intensities);
m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor); m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor);
m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient); m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient);
// Set camera position // Set camera position
QMatrix4x4 rotateBack; m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D());
rotateBack.rotate(m_rotation.inverted());
m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation));
// Draw cube geometry // Draw cube geometry
if (m_backfaceCulling) if (m_backfaceCulling)
@ -199,76 +221,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
if (m_mouse.left) if (m_mouse.left)
{ {
// get the difference between last press and now // 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 // update the new position
m_mouse.position = QVector2D(e->localPos()); 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 // request an update
if (m_light.headlight) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -277,14 +234,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
else if (m_mouse.right) else if (m_mouse.right)
{ {
// get the difference between last press and now // 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 // update the new position
m_mouse.position = QVector2D(e->localPos()); 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 // request an update
if (m_light.headlight) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -294,7 +248,7 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
void OglViewerWidget::wheelEvent(QWheelEvent *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) if (m_light.headlight)
updateLightPosition(); updateLightPosition();
@ -307,6 +261,38 @@ void OglViewerWidget::keyPressEvent(QKeyEvent *e)
{ {
resetView(); 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) else if (e->key() == Qt::Key_Escape)
{ {
parentWidget()->close(); 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) void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e)
{ {
if (e->mimeData()->hasUrls()) if (e->mimeData()->hasUrls())
@ -341,20 +347,34 @@ void OglViewerWidget::loadFile(QString name)
m_dataEngine->loadFile(name); m_dataEngine->loadFile(name);
} }
void OglViewerWidget::toggleAxis(int axis) void OglViewerWidget::useFreeCamera()
{ {
switch (axis) delete m_camera;
{ m_camera = new FreeCamera;
case 1:
m_rotDirections.x = !m_rotDirections.x; if (m_lightOn)
break; updateLightPosition();
case 2: update();
m_rotDirections.y = !m_rotDirections.y;
break;
case 3:
m_rotDirections.z = !m_rotDirections.z;
break;
} }
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() void OglViewerWidget::toggleWireframe()
@ -377,6 +397,8 @@ void OglViewerWidget::toggleLight()
m_backgroundColorOff[3] = 1.0; m_backgroundColorOff[3] = 1.0;
} }
emit lightChanged(m_lightOn);
update(); update();
} }
@ -441,8 +463,3 @@ void OglViewerWidget::setBackfaceCulling(bool value)
m_backfaceCulling = value; m_backfaceCulling = value;
update(); update();
} }
void OglViewerWidget::setZoomSpeed(int percent)
{
m_zSpeed = (double) percent / 100;
}

View File

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

View File

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

View File

@ -1,10 +1,11 @@
#include "..\Header\SettingsWindow.h" #include "..\Header\SettingsWindow.h"
#include "..\Header\SettingsManager.h"
///////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////
// constructor/destructor // 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) : QWidget(parent)
, ui(new Ui::SettingsWindow) , ui(new Ui::SettingsWindow)
{ {
@ -15,24 +16,41 @@ SettingsWindow::SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVecto
setupConnections(); setupConnections();
// set default values // set default values
ui->lightOff_R_SB->setValue((int)bgOffColor[0]); SettingsManager* sm = SettingsManager::getInstance(this);
ui->lightOff_G_SB->setValue((int)bgOffColor[1]);
ui->lightOff_B_SB->setValue((int)bgOffColor[2]);
ui->lightOn_R_SB->setValue((int)bgOnColor[0]); ui->lightOff_R_SB->setValue((int)(sm->getBgColorOff()[0]));
ui->lightOn_G_SB->setValue((int)bgOnColor[1]); ui->lightOff_G_SB->setValue((int)(sm->getBgColorOff()[1]));
ui->lightOn_B_SB->setValue((int)bgOnColor[2]); ui->lightOff_B_SB->setValue((int)(sm->getBgColorOff()[2]));
ui->light_R_SB->setValue((int)lightColor[0]); ui->lightOn_R_SB->setValue((int)(sm->getBgColorOn()[0]));
ui->light_G_SB->setValue((int)lightColor[1]); ui->lightOn_G_SB->setValue((int)(sm->getBgColorOn()[1]));
ui->light_B_SB->setValue((int)lightColor[2]); ui->lightOn_B_SB->setValue((int)(sm->getBgColorOn()[2]));
ui->ambCoef->setValue(ambCoef); ui->light_R_SB->setValue((int)(sm->getLightColor()[0]));
ui->attFac->setValue(attFac); ui->light_G_SB->setValue((int)(sm->getLightColor()[1]));
ui->light_B_SB->setValue((int)(sm->getLightColor()[2]));
ui->checkAutoColor->setChecked(autoColor); ui->ambCoef->setValue(sm->getAmbient());
if (lightType == 1) 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); 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->setValue(0.0);
ui->attFac->setEnabled(false); ui->attFac->setEnabled(false);
emit changeLightType(1);
} }
else else
{ {
ui->attFac->setEnabled(true); ui->attFac->setEnabled(true);
emit changeLightType(2);
} }
} }

View File

@ -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 # MshViewer
I started to learn OpenGL. Therefore i decided to implement a .msh viewer for SWBFII assets, since the old one 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 Feel free to use my code the way you like. But remember i used some public libraries. Make sure you read their
licence, too. licence, too.
### To Do
- normal map,
- list all msh in a directory
- glow/emissive
- optional display bones, shadow, collision
- change pose
- animation

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

View File

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

Binary file not shown.

Binary file not shown.

BIN
preview.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB