Compare commits

...

27 Commits

Author SHA1 Message Date
itdominator 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">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QWidget" name="centralWidget">
<layout class="QHBoxLayout" name="horizontalLayout"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<property name="allowedAreas">
<set>Qt::LeftToolBarArea|Qt::RightToolBarArea|Qt::TopToolBarArea</set>
@ -32,6 +34,72 @@
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<widget class="QDockWidget" name="dockWidget">
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="features">
<set>QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetFloatable</set>
</property>
<property name="allowedAreas">
<set>Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Asset library</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectItems</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

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

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
private:
void clearData();
void setupPipeline(QOpenGLShaderProgram * program);
public:
void drawGeometry(QOpenGLShaderProgram *program);

View File

@ -30,6 +30,8 @@ private:
// functions
private:
void setupWidgets();
void getAssetLibrary();
void searchMeshFiles(QString path);
void openFile();
void takeScreenShot();
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
#include "..\Header\FileInterface.h"
#include <QList>
struct ChunkHeader {
char name[5];
std::uint32_t size;
std::streampos position;
QString name;
quint32 size;
qint64 position;
};
enum ModelTyp {
@ -29,22 +29,22 @@ private:
virtual void import() Q_DECL_OVERRIDE Q_DECL_FINAL;
void loadChunks(std::list<ChunkHeader*> &destination, std::streampos start, const std::uint32_t length);
void loadChunks(QList<ChunkHeader*> &destination, qint64 start, const quint32 length);
void analyseMsh2Chunks(std::list<ChunkHeader*> &chunkList);
void analyseMsh2Chunks(QList<ChunkHeader*> &chunkList);
void analyseMatdChunks(std::list<ChunkHeader*> &chunkList);
void analyseMatdChunks(QList<ChunkHeader*> &chunkList);
void analyseModlChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
void analyseGeomChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
void analyseSegmChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
void analyseClthChunks(Model* dataDestination, std::list<ChunkHeader*> &chunkList);
void analyseModlChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void analyseGeomChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void analyseSegmChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void analyseClthChunks(Model* dataDestination, QList<ChunkHeader*> &chunkList);
void readVertex(Segment* dataDestination, std::streampos position);
void readUV(Segment* dataDestination, std::streampos position);
void readVertex(Segment* dataDestination, qint64 position);
void readUV(Segment* dataDestination, qint64 position);
void loadTexture(QOpenGLTexture*& destination, QString filepath, QString& filename);
QMatrix4x4 getParentMatrix(std::string parent) const;
QQuaternion getParentRotation(std::string parent) const;
QMatrix4x4 getParentMatrix(QString parent) const;
QQuaternion getParentRotation(QString parent) const;
};

View File

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

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
public:
SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVector3D lightColor, bool autoColor, double ambCoef, double attFac, int lightType, QWidget * parent = Q_NULLPTR);
SettingsWindow(QWidget * parent = Q_NULLPTR);
~SettingsWindow();
private:
@ -33,5 +33,6 @@ signals:
void sendHeadlight(bool value);
void sendBackfaceCulling(bool value);
void sendZommSpeed(int percent);
void changeLightType(int value);
};

View File

@ -1,138 +1,128 @@
#pragma once
#include <fstream>
#include "OutputDevice.h"
#include <QImage>
#include <QColor>
#include <QVector>
#include <QFile>
QImage loadTga(QString filePath, bool &success)
{
QImage img;
success = true;
// open the file
std::fstream fsPicture(filePath.toStdString().c_str(), std::ios::in | std::ios::binary);
QFile file(filePath);
if (!fsPicture.is_open())
if (!file.open(QIODevice::ReadOnly))
{
img = QImage(1, 1, QImage::Format_RGB32);
img.fill(Qt::red);
success = false;
return img;
}
// read in the header
std::uint8_t ui8x18Header[19] = { 0 };
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
//get variables
std::uint32_t ui32BpP;
std::uint32_t ui32Width;
std::uint32_t ui32Height;
std::uint32_t ui32IDLength;
std::uint32_t ui32PicType;
std::uint32_t ui32PaletteLength;
std::uint32_t ui32Size;
// extract all information from header
ui32IDLength = ui8x18Header[0];
ui32PicType = ui8x18Header[2];
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
ui32BpP = ui8x18Header[16];
// calculate some more information
ui32Size = ui32Width * ui32Height * ui32BpP / 8;
// jump to the data block
fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
// uncompressed
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
{
std::vector<std::uint8_t> vui8Pixels;
vui8Pixels.resize(ui32Size);
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
for (unsigned int y = 0; y < ui32Height; y++)
{
for (unsigned int x = 0; x < ui32Width; x++)
{
int valr = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 2);
int valg = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 1);
int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8);
int vala = 255;
if (ui32BpP == 32)
vala = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8 + 3);
QColor value(valr, valg, valb, vala);
img.setPixel(x, ui32Width - 1 - y, value.rgba());
}
}
}
// else if compressed 24 or 32 bit
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
{
std::uint8_t tempChunkHeader;
std::uint8_t tempData[5];
unsigned int tmp_pixelIndex = 0;
do {
fsPicture.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
if (tempChunkHeader >> 7) // repeat count
{
// just use the first 7 bits
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
for (int i = 0; i <= tempChunkHeader; i++)
{
QColor color;
if (ui32BpP == 32)
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
else
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
tmp_pixelIndex++;
}
}
else // data count
{
// just use the first 7 bits
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
for (int i = 0; i <= tempChunkHeader; i++)
{
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
QColor color;
if (ui32BpP == 32)
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], tempData[3]));
else
color.setRgba(qRgba(tempData[2], tempData[1], tempData[0], 255));
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
tmp_pixelIndex++;
}
}
} while (tmp_pixelIndex < (ui32Width * ui32Height));
}
// not useable format
else
{
fsPicture.close();
success = false;
return img;
// read in the header
quint8 ui8x18Header[19] = { 0 };
file.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header) - 1);
//get variables
quint32 ui32BpP;
quint32 ui32Width;
quint32 ui32Height;
quint32 ui32IDLength;
quint32 ui32PicType;
quint32 ui32PaletteLength;
quint32 ui32Size;
// extract all information from header
ui32IDLength = ui8x18Header[0];
ui32PicType = ui8x18Header[2];
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
ui32BpP = ui8x18Header[16];
// calculate some more information
ui32Size = ui32Width * ui32Height * ui32BpP / 8;
// jump to the data block
file.seek(ui32IDLength + ui32PaletteLength + 18);
// uncompressed
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
{
img = QImage(ui32Width, ui32Height, ui32BpP == 32 ? QImage::Format_RGBA8888 : QImage::Format_RGB888);
int lineWidth = ui32Width * ui32BpP / 8;
for (int i = ui32Height - 1; i >= 0; --i)
file.read(reinterpret_cast<char*>(img.scanLine(i)), lineWidth);
}
// else if compressed 24 or 32 bit
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
{
OutputDevice::getInstance()->print("compressed tga is not supported by SWBF", 1);
img = QImage(ui32Width, ui32Height, QImage::Format_RGBA8888);
quint8 tempChunkHeader;
quint8 tempData[5];
unsigned int tmp_pixelIndex = 0;
do {
file.read(reinterpret_cast<char*>(&tempChunkHeader), sizeof(tempChunkHeader));
if (tempChunkHeader >> 7) // repeat count
{
// just use the first 7 bits
tempChunkHeader = (quint8(tempChunkHeader << 1) >> 1);
file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
for (int i = 0; i <= tempChunkHeader; i++)
{
QColor color;
if (ui32BpP == 32)
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], tempData[3]));
else
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], 255));
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
tmp_pixelIndex++;
}
}
else // data count
{
// just use the first 7 bits
tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1);
for (int i = 0; i <= tempChunkHeader; i++)
{
file.read(reinterpret_cast<char*>(&tempData), ui32BpP / 8);
QColor color;
if (ui32BpP == 32)
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], tempData[3]));
else
color.setRgba(qRgba(tempData[0], tempData[1], tempData[2], 255));
img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba());
tmp_pixelIndex++;
}
}
} while (tmp_pixelIndex < (ui32Width * ui32Height));
}
// not useable format
else
{
success = false;
}
}
fsPicture.close();
success = true;
return img;
if (file.isOpen())
file.close();
return qMove(img).rgbSwapped();
}

View File

@ -15,17 +15,14 @@
<file>info.png</file>
<file>about.png</file>
<file>open.png</file>
<file>X.png</file>
<file>Y.png</file>
<file>Z.png</file>
<file>screenshot.png</file>
<file>wireframe.png</file>
<file>light_off.png</file>
<file>light_on.png</file>
<file>solid.png</file>
<file>X_disabled.png</file>
<file>Y_disabled.png</file>
<file>Z_disabled.png</file>
<file>settings.png</file>
<file>freeCamera.png</file>
<file>orbitalCamera.png</file>
<file>walkCamera.png</file>
</qresource>
</RCC>

View File

@ -37,28 +37,16 @@ QToolButton#screenshot {
image: url(:/images/toolbar/screenshot.png);
}
QToolButton#x {
image: url(:/images/toolbar/X_disabled.png);
QToolButton#freeCamera {
image: url(:/images/toolbar/freeCamera.png);
}
QToolButton#x:checked {
image: url(:/images/toolbar/X.png);
QToolButton#orbitalCamera {
image: url(:/images/toolbar/orbitalCamera.png);
}
QToolButton#y {
image: url(:/images/toolbar/Y_disabled.png);
}
QToolButton#y:checked {
image: url(:/images/toolbar/Y.png);
}
QToolButton#z {
image: url(:/images/toolbar/Z_disabled.png);
}
QToolButton#z:checked {
image: url(:/images/toolbar/Z.png);
QToolButton#walkCamera {
image: url(:/images/toolbar/walkCamera.png);
}
QToolButton#wireframe {

View File

@ -4,9 +4,22 @@ source code: https://git.rwth-aachen.de/carstenf/OpenGL/tree/master/QtMeshViewer
===============================================================
Controll:
Free Camera: static view position and you rotate and move the object
left mouse - rotate
right mouse - move
scroll - zoom
Orbit Camera: static object and you move around it like a satalite
left mouse - rotate
scroll - zoom
Move Camera: static object and you can walk through the scene
w/s - forward/backward
a/d - left/right
left mouse - look around
General:
space - reset view
L - set light to current position
esc - close

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

View File

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

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();
}
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
void GeometryEngine::setupPipeline(QOpenGLShaderProgram *program)
{
if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
return;
// Setup
// Tell OpenGL which VBOs to use
m_arrayBuf.bind();
m_indexBuf.bind();
// Allways normalize by this
QMatrix4x4 normMatrix;
float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
normMatrix.scale(1 / maxExtent);
normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
program->setUniformValue("norm_matrix", normMatrix);
// Allways use texture unit 0
program->setUniformValue("texture", 0);
// Offset for position
quintptr offset = 0;
@ -87,50 +69,115 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
program->enableAttributeArray(texcoordLocation);
program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));
//Offset for normal
//Offset for vertexNormal
offset += sizeof(QVector2D);
// Tell OpenGL programmable pipeline how to locate vertex normal data
int normLocation = program->attributeLocation("a_normal");
program->enableAttributeArray(normLocation);
program->setAttributeBuffer(normLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
int vertNormLocation = program->attributeLocation("a_normal");
program->enableAttributeArray(vertNormLocation);
program->setAttributeBuffer(vertNormLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
//Offset for polygonNormal
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate polygon normal data
int polyNormLocation = program->attributeLocation("a_polyNorm");
program->enableAttributeArray(polyNormLocation);
program->setAttributeBuffer(polyNormLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
//Offset for polygonTangent
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate polygon tangent data
int polyTanLocation = program->attributeLocation("a_polyTan");
program->enableAttributeArray(polyTanLocation);
program->setAttributeBuffer(polyTanLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
//Offset for polygonBitangent
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate polygon bitangent data
int polyBiTanLocation = program->attributeLocation("a_polyBiTan");
program->enableAttributeArray(polyBiTanLocation);
program->setAttributeBuffer(polyBiTanLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
}
void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program)
{
if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated())
return;
// Setup
// Tell OpenGL which VBOs to use
m_arrayBuf.bind();
m_indexBuf.bind();
// Allways normalize by this
QMatrix4x4 normMatrix;
float maxExtent = std::max(std::max(m_boundings.extents[0], m_boundings.extents[1]), m_boundings.extents[2]);
normMatrix.scale(1 / maxExtent);
normMatrix.translate(-m_boundings.center[0], -m_boundings.center[1], -m_boundings.center[2]);
program->setUniformValue("normalizeModel", normMatrix);
// Allways use texture unit 0 and 1
program->setUniformValue("tx0", 0);
program->setUniformValue("tx1", 1);
//setup the pipeline
setupPipeline(program);
// Paint
for (auto& it : m_drawList)
{
bool tmp_transparent(false);
bool tmp_specular(false);
bool tmp_normalmap(false);
bool tmp_glow(false);
float shininess(0.0);
QVector3D specularColor;
// bind the correct texture
if (it.textureIndex < (unsigned)m_materials->size() && m_materials->at(it.textureIndex).texture0 != Q_NULLPTR)
{
m_materials->at(it.textureIndex).texture0->bind();
m_materials->at(it.textureIndex).texture0->bind(0);
tmp_transparent = m_materials->at(it.textureIndex).transparent;
tmp_specular = m_materials->at(it.textureIndex).flags[7];
shininess = m_materials->at(it.textureIndex).shininess;
specularColor = m_materials->at(it.textureIndex).specularColor.toVector3D();
if (m_materials->at(it.textureIndex).rendertype == 27 || m_materials->at(it.textureIndex).rendertype == 28)
{
if (m_materials->at(it.textureIndex).texture1 != Q_NULLPTR)
{
tmp_normalmap = true;
m_materials->at(it.textureIndex).texture1->bind(1);
}
}
if (m_materials->at(it.textureIndex).flags[0] || m_materials->at(it.textureIndex).flags[1] || m_materials->at(it.textureIndex).rendertype == 1)
tmp_glow = true;
}
else
{
m_defaultMaterial->texture0->bind();
m_defaultMaterial->texture0->bind(0);
tmp_transparent = m_defaultMaterial->transparent;
}
// Set model matrix
program->setUniformValue("m_matrix", it.modelMatrix);
program->setUniformValue("modelMatrix", it.modelMatrix);
// Set normal matrix
program->setUniformValue("n_matrix", (normMatrix * it.modelMatrix).normalMatrix());
// set some more values
program->setUniformValue("b_transparent", tmp_transparent);
program->setUniformValue("b_specular", tmp_specular);
program->setUniformValue("normalMatrix", (normMatrix * it.modelMatrix).normalMatrix());
// set some material attributes
program->setUniformValue("materialShininess", shininess);
program->setUniformValue("materialSpecularColor", specularColor);
program->setUniformValue("material.shininess", shininess);
program->setUniformValue("material.specularColor", specularColor);
program->setUniformValue("material.isTransparent", tmp_transparent);
program->setUniformValue("material.hasSpecularmap", tmp_specular);
program->setUniformValue("material.hasNormalmap", tmp_normalmap);
program->setUniformValue("material.isGlow", tmp_glow);
// Draw cube geometry using indices from VBO 1
glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint)));

View File

@ -36,9 +36,6 @@ MainWindow::MainWindow(QWidget *parent)
// setup opengl things
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setMajorVersion(2);
format.setMinorVersion(0);
format.setProfile(QSurfaceFormat::NoProfile);
QSurfaceFormat::setDefaultFormat(format);
// set default text to file info
@ -52,6 +49,8 @@ MainWindow::MainWindow(QWidget *parent)
styleSheet.open(QIODevice::ReadOnly);
this->setStyleSheet(styleSheet.readAll());
getAssetLibrary();
printMessage("MeshViewer by Anakin", 0);
}
@ -90,41 +89,26 @@ void MainWindow::setupWidgets()
//////////////////////////////////////////////////
ui->mainToolBar->addSeparator();
QSignalMapper* signalMapper = new QSignalMapper(this);
// Free Camera
QToolButton *freeCamera = new QToolButton(this);
freeCamera->setObjectName("freeCamera");
freeCamera->setToolTip("free camera");
connect(freeCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useFreeCamera);
ui->mainToolBar->addWidget(freeCamera);
// X
QToolButton *x = new QToolButton(this);
x->setObjectName("x");
x->setToolTip("x-direction");
x->setCheckable(true);
x->setChecked(true);
ui->mainToolBar->addWidget(x);
// Orbital Camera
QToolButton *orbitCamera = new QToolButton(this);
orbitCamera->setObjectName("orbitalCamera");
orbitCamera->setToolTip("orbital camera");
connect(orbitCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useOrbitCamera);
ui->mainToolBar->addWidget(orbitCamera);
// Y
QToolButton *y = new QToolButton(this);
y->setObjectName("y");
y->setToolTip("y-direction");
y->setCheckable(true);
y->setChecked(true);
ui->mainToolBar->addWidget(y);
// Z
QToolButton *z = new QToolButton(this);
z->setObjectName("z");
z->setToolTip("z-direction");
z->setCheckable(true);
z->setChecked(true);
ui->mainToolBar->addWidget(z);
connect(x, SIGNAL(pressed()), signalMapper, SLOT(map()));
connect(y, SIGNAL(pressed()), signalMapper, SLOT(map()));
connect(z, SIGNAL(pressed()), signalMapper, SLOT(map()));
signalMapper->setMapping(x, 1);
signalMapper->setMapping(y, 2);
signalMapper->setMapping(z, 3);
connect(signalMapper, SIGNAL(mapped(int)), viewer, SLOT(toggleAxis(int)));
// Move Camera
QToolButton *walkCamera = new QToolButton(this);
walkCamera->setObjectName("walkCamera");
walkCamera->setToolTip("walk camera");
connect(walkCamera, &QToolButton::pressed, viewer, &OglViewerWidget::useMoveCamera);
ui->mainToolBar->addWidget(walkCamera);
//////////////////////////////////////////////////
ui->mainToolBar->addSeparator();
@ -179,6 +163,33 @@ void MainWindow::setupWidgets()
}
void MainWindow::getAssetLibrary()
{
QTreeWidgetItem* item = new QTreeWidgetItem;
item->setData(0, Qt::DisplayRole, "Wuhu");
ui->treeWidget->addTopLevelItem(item);
searchMeshFiles("D:/workspaces/Visual Studio 2015/Projects/OpenGL/Release");
}
void MainWindow::searchMeshFiles(QString path)
{
QDir directory(path);
directory.setNameFilters(QStringList("*.msh"));
QStringList childDirectories = directory.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
QStringList fileNames = directory.entryList(QDir::Files);
for (auto &it : childDirectories)
qDebug() << it;
for (auto &it : fileNames)
qDebug() << it;
}
void MainWindow::openFile()
{
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Mesh (*.msh)");

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

View File

@ -1,5 +1,9 @@
#include "..\Header\OglViewerWidget.h"
#include "..\Header\MainWindow.h"
#include "..\Header\FreeCamera.h"
#include "..\Header\OrbitCamera.h"
#include "..\Header\MoveCamera.h"
#include "..\Header\SettingsManager.h"
#include <QMouseEvent>
#include <QDropEvent>
#include <QMimeData>
@ -14,13 +18,15 @@
OglViewerWidget::OglViewerWidget(QWidget *parent)
: QOpenGLWidget(parent)
, m_dataEngine(0)
, m_dataEngine(Q_NULLPTR)
, m_camera(new FreeCamera)
{
setFocus();
setAcceptDrops(true);
// settings window
m_settings = new SettingsWindow(m_backgroundColorOff.toVector3D() * 255, m_backgroundColorOn.toVector3D() * 255, m_light.intensities * 255, true, m_light.ambientCoefficient, m_light.attenuationFactor, 1, this);
setDefaultValues();
m_settings = new SettingsWindow(this);
connect(m_settings, &SettingsWindow::updateBGColorOff, this, &OglViewerWidget::setBGColorOff);
connect(m_settings, &SettingsWindow::updateBGColorOn, this, &OglViewerWidget::setBGColorOn);
@ -29,7 +35,7 @@ OglViewerWidget::OglViewerWidget(QWidget *parent)
connect(m_settings, &SettingsWindow::updateAmbCoef, this, &OglViewerWidget::setAmbCoef);
connect(m_settings, &SettingsWindow::sendHeadlight, this, &OglViewerWidget::setHeadlight);
connect(m_settings, &SettingsWindow::sendBackfaceCulling, this, &OglViewerWidget::setBackfaceCulling);
connect(m_settings, &SettingsWindow::sendZommSpeed, this, &OglViewerWidget::setZoomSpeed);
connect(m_settings, &SettingsWindow::sendZommSpeed, [this](int value) {m_camera->setZoomSpeed(value); });
}
OglViewerWidget::~OglViewerWidget()
@ -40,6 +46,7 @@ OglViewerWidget::~OglViewerWidget()
delete m_dataEngine;
doneCurrent();
delete m_camera;
delete m_settings;
}
@ -47,6 +54,30 @@ OglViewerWidget::~OglViewerWidget()
/////////////////////////////////////////////////////////////////////////
// functions
void OglViewerWidget::setDefaultValues()
{
SettingsManager* sm = SettingsManager::getInstance(this);
m_backgroundColorOn = QVector4D(sm->getBgColorOn() / 255, 1.0f);
m_backgroundColorOff = QVector4D(sm->getBgColorOff() / 255, 1.0f);
m_wireframe = false;
m_lightOn = sm->isLight();
m_backfaceCulling = sm->isBfCulling();
if (sm->getLightType() == 1) // directional
m_light.position = { 0.0,0.0,0.0,0.0 };
else // point
m_light.position = { 0.0,0.0,0.0,1.0 };
m_light.intensities = sm->getLightColor() / 255;
m_light.attenuationFactor = sm->getAttenuation();
m_light.ambientCoefficient = sm->getAmbient();
m_light.headlight = sm->isHeadlight();
connect(this, &OglViewerWidget::lightChanged, sm, &SettingsManager::setLight);
}
void OglViewerWidget::initShaders()
{
// Compile vertex shader
@ -68,9 +99,7 @@ void OglViewerWidget::initShaders()
void OglViewerWidget::resetView()
{
m_rotation = QQuaternion();
m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE };
m_zSpeed = 1;
m_camera->resetView();
if (m_light.headlight)
updateLightPosition();
@ -79,13 +108,13 @@ void OglViewerWidget::resetView()
void OglViewerWidget::updateLightPosition()
{
QMatrix4x4 rotateBack;
rotateBack.rotate(m_rotation.inverted());
QVector3D cameraPosition = rotateBack * (-m_translation);
QVector4D lightPosition = { 0,0,0,1 };
m_light.position.setX(cameraPosition.x());
m_light.position.setY(cameraPosition.y());
m_light.position.setZ(cameraPosition.z());
lightPosition = m_camera->getMatrix().inverted() * lightPosition;
m_light.position.setX(lightPosition.x());
m_light.position.setY(lightPosition.y());
m_light.position.setZ(lightPosition.z());
}
// OpenGL ///////////////////////////////////////////////////////////////
@ -139,25 +168,18 @@ void OglViewerWidget::paintGL()
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Calculate view transformation
QMatrix4x4 view;
view.translate(m_translation);
view.rotate(m_rotation);
// Set view-projection matrix
m_program.setUniformValue("vp_matrix", m_projection * view);
m_program.setUniformValue("viewProjection", m_projection * m_camera->getMatrix());
// Set Light values
m_program.setUniformValue("b_light", m_lightOn);
m_program.setUniformValue("useLight", m_lightOn);
m_program.setUniformValue("light.position", m_light.position);
m_program.setUniformValue("light.intensities", m_light.intensities);
m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor);
m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient);
// Set camera position
QMatrix4x4 rotateBack;
rotateBack.rotate(m_rotation.inverted());
m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation));
m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D());
// Draw cube geometry
if (m_backfaceCulling)
@ -199,76 +221,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
if (m_mouse.left)
{
// get the difference between last press and now
QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;
m_camera->rotateAction(QVector2D(e->localPos()) - m_mouse.position);
// update the new position
m_mouse.position = QVector2D(e->localPos());
// calculate the rotations depending on the active axis
// XYZ
if (m_rotDirections.x && m_rotDirections.y && m_rotDirections.z)
{
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation;
}
// XY
else if (m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z)
{
float pitch, yaw, roll;
m_rotation.getEulerAngles(&pitch, &yaw, &roll);
pitch += diff.y() * 0.5;
yaw += diff.x() * 0.5;
if (pitch > 89)
pitch = 89;
else if (pitch < -89)
pitch = -89;
m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
}
// X
else if (m_rotDirections.x && !m_rotDirections.y && !m_rotDirections.z)
{
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0).normalized(), diff.x() * 0.5) * m_rotation;
}
// Y
else if (!m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z)
{
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0).normalized(), diff.y() * 0.5) * m_rotation;
}
// Z
else if (!m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z)
{
m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 0.0, 1.0).normalized(), diff.x() * 0.5) * m_rotation;
}
// XZ
else if (m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z)
{
float pitch, yaw, roll;
m_rotation.getEulerAngles(&pitch, &yaw, &roll);
roll -= diff.y() * 0.5;
yaw += diff.x() * 0.5;
m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
}
// YZ
else if (!m_rotDirections.x && m_rotDirections.y && m_rotDirections.z)
{
float pitch, yaw, roll;
m_rotation.getEulerAngles(&pitch, &yaw, &roll);
pitch += diff.y() * 0.5;
roll += diff.x() * 0.5;
if (pitch > 89)
pitch = 89;
else if (pitch < -89)
pitch = -89;
m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll);
}
// request an update
if (m_light.headlight)
updateLightPosition();
@ -277,14 +234,11 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
else if (m_mouse.right)
{
// get the difference between last press and now
QVector2D diff = QVector2D(e->localPos()) - m_mouse.position;
m_camera->moveAction(QVector2D(e->localPos()) - m_mouse.position);
// update the new position
m_mouse.position = QVector2D(e->localPos());
// calculate the translation
m_translation += {(float)(diff.x() * 0.01), (float)(diff.y() * -0.01), 0.0};
// request an update
if (m_light.headlight)
updateLightPosition();
@ -294,7 +248,7 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
void OglViewerWidget::wheelEvent(QWheelEvent *e)
{
m_translation += {0.0, 0.0, (float)m_zSpeed * e->angleDelta().y() / 240};
m_camera->wheelAction(e->angleDelta().y());
if (m_light.headlight)
updateLightPosition();
@ -307,6 +261,38 @@ void OglViewerWidget::keyPressEvent(QKeyEvent *e)
{
resetView();
}
else if (e->key() == Qt::Key_W)
{
emit m_camera->wheelAction(1);
if (m_light.headlight)
updateLightPosition();
update();
}
else if (e->key() == Qt::Key_S)
{
emit m_camera->wheelAction(-1);
if (m_light.headlight)
updateLightPosition();
update();
}
else if (e->key() == Qt::Key_A)
{
emit m_camera->moveAction(QVector2D(0, -1));
if (m_light.headlight)
updateLightPosition();
update();
}
else if (e->key() == Qt::Key_D)
{
emit m_camera->moveAction(QVector2D(0, 1));
if (m_light.headlight)
updateLightPosition();
update();
}
else if (e->key() == Qt::Key_Escape)
{
parentWidget()->close();
@ -318,6 +304,26 @@ void OglViewerWidget::keyPressEvent(QKeyEvent *e)
}
}
void OglViewerWidget::keyReleaseEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_W || e->key() == Qt::Key_S)
{
emit m_camera->wheelAction(0);
if (m_light.headlight)
updateLightPosition();
update();
}
else if (e->key() == Qt::Key_A || e->key() == Qt::Key_D)
{
emit m_camera->moveAction(QVector2D(0, 0));
if (m_light.headlight)
updateLightPosition();
update();
}
}
void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e)
{
if (e->mimeData()->hasUrls())
@ -341,20 +347,34 @@ void OglViewerWidget::loadFile(QString name)
m_dataEngine->loadFile(name);
}
void OglViewerWidget::toggleAxis(int axis)
void OglViewerWidget::useFreeCamera()
{
switch (axis)
{
case 1:
m_rotDirections.x = !m_rotDirections.x;
break;
case 2:
m_rotDirections.y = !m_rotDirections.y;
break;
case 3:
m_rotDirections.z = !m_rotDirections.z;
break;
}
delete m_camera;
m_camera = new FreeCamera;
if (m_lightOn)
updateLightPosition();
update();
}
void OglViewerWidget::useOrbitCamera()
{
delete m_camera;
m_camera = new OrbitCamera;
if (m_lightOn)
updateLightPosition();
update();
}
void OglViewerWidget::useMoveCamera()
{
delete m_camera;
m_camera = new MoveCamera;
if (m_lightOn)
updateLightPosition();
update();
}
void OglViewerWidget::toggleWireframe()
@ -377,6 +397,8 @@ void OglViewerWidget::toggleLight()
m_backgroundColorOff[3] = 1.0;
}
emit lightChanged(m_lightOn);
update();
}
@ -441,8 +463,3 @@ void OglViewerWidget::setBackfaceCulling(bool value)
m_backfaceCulling = value;
update();
}
void OglViewerWidget::setZoomSpeed(int percent)
{
m_zSpeed = (double) percent / 100;
}

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\SettingsManager.h"
/////////////////////////////////////////////////////////////////////////
// constructor/destructor
SettingsWindow::SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVector3D lightColor, bool autoColor, double ambCoef, double attFac, int lightType, QWidget * parent)
SettingsWindow::SettingsWindow(QWidget * parent)
: QWidget(parent)
, ui(new Ui::SettingsWindow)
{
@ -15,24 +16,41 @@ SettingsWindow::SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVecto
setupConnections();
// set default values
ui->lightOff_R_SB->setValue((int)bgOffColor[0]);
ui->lightOff_G_SB->setValue((int)bgOffColor[1]);
ui->lightOff_B_SB->setValue((int)bgOffColor[2]);
SettingsManager* sm = SettingsManager::getInstance(this);
ui->lightOn_R_SB->setValue((int)bgOnColor[0]);
ui->lightOn_G_SB->setValue((int)bgOnColor[1]);
ui->lightOn_B_SB->setValue((int)bgOnColor[2]);
ui->lightOff_R_SB->setValue((int)(sm->getBgColorOff()[0]));
ui->lightOff_G_SB->setValue((int)(sm->getBgColorOff()[1]));
ui->lightOff_B_SB->setValue((int)(sm->getBgColorOff()[2]));
ui->light_R_SB->setValue((int)lightColor[0]);
ui->light_G_SB->setValue((int)lightColor[1]);
ui->light_B_SB->setValue((int)lightColor[2]);
ui->lightOn_R_SB->setValue((int)(sm->getBgColorOn()[0]));
ui->lightOn_G_SB->setValue((int)(sm->getBgColorOn()[1]));
ui->lightOn_B_SB->setValue((int)(sm->getBgColorOn()[2]));
ui->ambCoef->setValue(ambCoef);
ui->attFac->setValue(attFac);
ui->light_R_SB->setValue((int)(sm->getLightColor()[0]));
ui->light_G_SB->setValue((int)(sm->getLightColor()[1]));
ui->light_B_SB->setValue((int)(sm->getLightColor()[2]));
ui->checkAutoColor->setChecked(autoColor);
if (lightType == 1)
ui->ambCoef->setValue(sm->getAmbient());
ui->attFac->setValue(sm->getAttenuation());
ui->checkBackfaceCulling->setChecked(sm->isBfCulling());
ui->checkAutoColor->setChecked(sm->isAutoColor());
ui->checkHeadlight->setChecked(sm->isHeadlight());
if (sm->getLightType() == 1)
ui->radioDirectLight->setChecked(true);
else
ui->radioPointLight->setChecked(true);
connect(this, &SettingsWindow::updateBGColorOff, sm, &SettingsManager::setBgColorOff);
connect(this, &SettingsWindow::updateBGColorOn, sm, &SettingsManager::setBgColorOn);
connect(this, &SettingsWindow::updateLightColor, sm, &SettingsManager::setLightColor);
connect(this, &SettingsWindow::updateAttFac, sm, &SettingsManager::setAttenuation);
connect(this, &SettingsWindow::updateAmbCoef, sm, &SettingsManager::setAmbient);
connect(this, &SettingsWindow::sendHeadlight, sm, &SettingsManager::setHeadlight);
connect(this, &SettingsWindow::sendBackfaceCulling, sm, &SettingsManager::setBfCulling);
connect(ui->checkAutoColor, &QCheckBox::stateChanged, sm, &SettingsManager::setAutoColor);
connect(this, &SettingsWindow::changeLightType, sm, &SettingsManager::setLightType);
}
@ -133,10 +151,12 @@ void SettingsWindow::radioToggled()
{
ui->attFac->setValue(0.0);
ui->attFac->setEnabled(false);
emit changeLightType(1);
}
else
{
ui->attFac->setEnabled(true);
emit changeLightType(2);
}
}

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
I started to learn OpenGL. Therefore i decided to implement a .msh viewer for SWBFII assets, since the old one
@ -12,10 +21,4 @@ So far it is just me. If you wanna help me, let me know :D
Feel free to use my code the way you like. But remember i used some public libraries. Make sure you read their
licence, too.
### To Do
- normal map,
- list all msh in a directory
- glow/emissive
- optional display bones, shadow, collision
- change pose
- animation

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