Compare commits

...

138 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
Anakin 2d9c103c01 new release version,
Features:
- Headlight option,
- zoom speed now adjust in settings window, not via +/-,
- cullface can be activated in the settings,
- text in FileInfoWindow can be marked and copied,
- alpha channel now always used,
- fixed compatibility problems,
- code and performance improvements,
Bugs:
- nothing known
2017-01-30 17:10:41 +01:00
Anakin 37e9b86daa fixed bug that sometimes alpha channel was not read in,
code improvement = performance,
2017-01-30 16:54:35 +01:00
Anakin 4342260e6d improved performance using my own tga load function always instead of QImage
improved Profiler
2017-01-30 16:00:14 +01:00
Anakin d1c68e8ba6 added Profiler to analyses the time used by code lines 2017-01-30 12:01:45 +01:00
Anakin 9c16aa32f1 headlight,
bug fixes,
code improvement,
2017-01-30 11:31:37 +01:00
Anakin fbb51563c9 fixed backface culling bug,
todo: connect headligh
2017-01-30 00:02:32 +01:00
Anakin 538453c1db added headlight option to settings,
added cullface option to settings,
zoom speed now adjust at settings,
bugs:
cullface does not work anymore,
todo:
connect headlight
2017-01-29 23:47:14 +01:00
Anakin 7b739ab892 use OutputDevice to set fileinfo,
use new connect function,
2017-01-29 15:19:20 +01:00
Anakin 98302664ca add OuputDevice as singleton to manage output to statusbar, 2017-01-29 11:35:43 +01:00
Anakin 96b7d6f736 text in FileInfoWindow can be marked and copied,
code cleaning
2017-01-28 16:54:36 +01:00
Anakin 121f5c47f1 fixed some warnings 2017-01-26 19:44:12 +01:00
Anakin fe374cb8f6 made fshader.glsl compatible with older versions 2017-01-26 18:25:24 +01:00
Anakin fb49d8685a switch from QLineEdit to QSpinBox,
init SettingsWindow with default values from OglViewerWidget,
removed old qt project
2017-01-26 18:17:54 +01:00
Anakin 3167f1acb8 new release version,
Features:
- screenshot function,
- transparency support,
- wireframe paint option,
- support phong model (ambient, diffuse, specular),
- 2 different kinds of light (directional and point),
- different background colors for light on/off,
- zoom speed now adjustable via +/- keys,
- new file info window,
- more information displayed at the info window,
- settings window,
- new GUI,
- now openGl 2.0 is minimum (before 4.5)
- some more code changes, bug fixes, performance improvements,
Bugs:
- nothing known
2017-01-24 19:46:48 +01:00
Anakin 308d238b2d add settings icon,
set ogl verison to 2.0 to make it compatible with more PCs
2017-01-24 19:39:34 +01:00
Anakin 30d41f7d85 connected settings window with software 2017-01-24 17:09:51 +01:00
C-Fu 15cd551f7c forgot light - background connection 2017-01-24 11:55:00 +01:00
C-Fu 16c9d35580 Removed slots, I use lambda now 2017-01-24 11:48:45 +01:00
C-Fu 11af758eee use lambda expressions instead of slots 2017-01-24 11:40:38 +01:00
Anakin 73ee8a4040 added settings window,
connected all slider, lineEdits, checkboxes,...,
need to connect everything with the OglViewerWidget now
2017-01-23 16:09:06 +01:00
Anakin 0a9103fdc5 differ vertexNormal and triangleNormal 2017-01-23 13:49:29 +01:00
Anakin 10718f2269 load tx1d texture 2017-01-23 12:29:10 +01:00
Anakin b2df84eb4c read tx1d tx2d tx3d texture names and print to info window 2017-01-23 12:17:26 +01:00
Anakin 2ed9e475ce fixed white scrollbar at the info window 2017-01-23 11:57:23 +01:00
Anakin cdd6ace701 save rendertype,
evaluate rednertype specular,
changed info window always on top
2017-01-22 15:41:08 +01:00
Anakin 91488c55b2 more information for the InfoWindow,
set correct values for cloth material,
enable specular map
2017-01-22 14:37:06 +01:00
Anakin 5f104e46f2 gui changes 2017-01-22 12:25:59 +01:00
Anakin a948590255 fixed flag reading bug 2017-01-21 17:16:44 +01:00
Anakin 6fa81a8ccc Some styling 2017-01-21 16:33:03 +01:00
Anakin c4444bcefd fixed background bug,
support directional light,
zoom speed can be adjust via +/-
2017-01-21 15:22:43 +01:00
Anakin 5ea90723b4 changed intensity of background 2017-01-20 16:54:27 +01:00
Anakin af94ecd541 change background when the light is on 2017-01-20 16:39:17 +01:00
Anakin 9808cd03c0 save more material information,
hold default material in geometry separated,
load diffuse color if texture cannot be opened,
fixed gamma correction on the texture,
2017-01-20 16:26:58 +01:00
C-Fu abd9070e90 Read the material name and save it,
Shorten transparency evaluation,
Need to:
- read in the data values,
- save the texture name somewhere else,
- use the data :D
2017-01-20 11:18:48 +01:00
C-Fu eb0592373f added attributes to materials 2017-01-20 10:49:43 +01:00
Anakin 28d17b2fdd trying to workaround gamma correction (remove from tga) 2017-01-19 20:15:00 +01:00
Anakin 9fb3ca03bd added specular, ambient light,...
need to fix the texutre gamma correction,
look at the todos
2017-01-19 17:57:50 +01:00
Anakin 4c177f2ddc adjust light functionality,
bugs:
- background cannot be changed during runtime
2017-01-18 17:01:43 +01:00
Anakin a521dfc292 calculate normal matrix once in cpp (performance),
added bool variable to turn light on/off (still needs button),
2017-01-17 20:18:04 +01:00
Anakin f5863752e2 fixed the light problem,
very basic light at the moment, needs a lot of work:
- custom position,
- custom intensities,
- calculate at better positions,
others:
- adjust zoom speed
2017-01-17 18:03:47 +01:00
Anakin 1c962a481f implemented light into cpp,
bug:
everything is dark,
need to calculate the normal matrix once in cpp and not for every pixel
2017-01-17 17:48:54 +01:00
Anakin 86c0559fdc Merge branch 'master' of git.rwth-aachen.de:carstenf/OpenGL 2017-01-17 17:36:35 +01:00
C-Fu 1bcb4d67c1 fixed wrong dimension 2017-01-17 11:37:07 +01:00
C-Fu 152d436dd7 Calculate vertex position in world space in vertex shaded not in fragment 2017-01-17 11:36:23 +01:00
C-Fu 5191a46f72 Added light calculation to fragment shader 2017-01-17 11:32:06 +01:00
C-Fu 9b3ff7f737 adjust vertex shaded to pass information to fragment shaded for light 2017-01-17 11:15:30 +01:00
Anakin 91b3f25dbb fixed wireframe bug 2017-01-16 16:41:52 +01:00
Anakin 47c73ed881 added custom info window,
set min size to mainwindow
2017-01-16 15:41:37 +01:00
Anakin 86dfe32145 add wireframe paint option,
write file information on the screen,
bug fixes
2017-01-16 14:24:30 +01:00
Anakin 454ed45fa1 support transparency now 2017-01-15 15:51:12 +01:00
Anakin b8f8a5c2ad fixed the problem 2017-01-15 12:33:57 +01:00
Anakin 6ead5d7bc6 working on changing the texture names to materials,
problems with call by value/reference
2017-01-15 12:26:15 +01:00
Anakin f469dff656 added transparency support,
need to sort the transparent things to the back
2017-01-14 17:20:50 +01:00
Anakin 930c49e9c7 add screenshot function 2017-01-11 16:28:51 +01:00
Anakin 77ffe7baf4 added icons 2017-01-09 16:34:54 +01:00
Anakin e41b831047 new release version
Features:
- WinXP support
2017-01-09 10:34:24 +01:00
Anakin 948578f506 add normal to VertexData 2017-01-08 14:41:53 +01:00
Anakin 5c2f5503fc new release version,
forgot to update the help text
2017-01-08 12:36:08 +01:00
Anakin c94a9c3462 new release version,
Features:
- status messages while import,
- fixed triangulation,
- rle and 24 bit image support (normally qt should support 24 bit, too),
- rotation can be limit to the directions,
- added fileinfo,
- performance,
Bugs:
- nothing known
2017-01-08 12:27:37 +01:00
Anakin 3be5793ffc limit pitch to [-90,90] 2017-01-08 12:21:56 +01:00
Anakin f5ee8a973d Using QString now,
fileinfo works now
2017-01-07 15:59:16 +01:00
Anakin 8c2ca44f20 added limited rotation,
2 directions do not work
2017-01-07 12:46:06 +01:00
Anakin e963b7538e fixed texture problem 2017-01-05 16:18:01 +01:00
Anakin b58b7c47e5 some buttons added 2017-01-05 16:04:51 +01:00
Anakin 44e36b8b0d trying to fix the 2xEmit bug,
write directly mirrored to the image,
2017-01-05 14:46:01 +01:00
Anakin 1d5d20cfb8 trying to fix the crash 2017-01-05 13:44:53 +01:00
Anakin 0bbc0da324 rle and 24bit support,
need to write direct into image for performance
2017-01-05 11:31:36 +01:00
Anakin 552f86bf2d fix quad poly bug 2017-01-05 09:39:18 +01:00
Anakin a2f5324a3c sendMessage via signal plot from file to window,
add severity to messages (black, yellow, red),
add about text,
removed unused texture from resource
2017-01-04 14:35:27 +01:00
Anakin a221ed4957 new release version,
Features:
-changed library,
-new interaction,
-new software icon,
-rotation bug fixed,
-cloth bug fixed,
Bugs:
-rle compressed tga not working.
-old assets are not displayed correctly,
2017-01-03 14:35:09 +01:00
Anakin c28a12cd8f finally fixed rotation bug,
some performance,
2017-01-03 14:18:46 +01:00
Anakin 0fefc6168b add drag and drop support 2017-01-03 11:47:27 +01:00
Anakin ae84c55559 changed default opened file 2017-01-02 17:10:22 +01:00
Anakin 191c0cbcea scale and move to center,
performance is not very good. Takes very long to load
2017-01-02 17:03:23 +01:00
Anakin fc7941a890 fixed rotation problem 2017-01-02 16:43:38 +01:00
Anakin 24d26cfdfa removed unused things from FileInterface 2017-01-02 15:07:39 +01:00
Anakin 876c689a1d cleanup code 2017-01-02 14:14:27 +01:00
Anakin fa8808fea8 add exe icon,
signal-slot for openFile,
resetView on openFile,
cleanup when open a new file,
triangulate quad poly now correctly, more not working, bug from previous version,
next:
fix 5,6,.. triangulation,
triClothMan, IC Helmet, still buggy,
2017-01-02 12:21:32 +01:00
Anakin 0735ef996d cosmetic to MainWindow,
drop does not work for widget,
fixed offset problem,
add esc key
2016-12-31 16:18:35 +01:00
Anakin dca6e61c4b parent matrix works,
texture works,
next fix multimodel problem
2016-12-31 14:40:05 +01:00
Anakin 3758a2601c cleanup data after file is no longer needed 2016-12-31 13:11:14 +01:00
Anakin 9a5d09b80c fixed crash 2016-12-31 13:04:03 +01:00
Anakin ee8705f9e4 draw all models from vector,
window cosmetic,
next:
texture,
calculate modelmatrix from parent
2016-12-31 12:31:38 +01:00
Anakin c96d05decb fixed the triangle problem :D
next:
add texture import,
test multiedged mesh,
add open button,
add drag n' drop
2016-12-30 15:39:31 +01:00
Anakin d63d5276a1 Merge branch 'master' of git.rwth-aachen.de:carstenf/OpenGL 2016-12-30 15:07:29 +01:00
Anakin 32b0a95afb use import data 2016-12-30 15:06:26 +01:00
Anakin e863c68a77 added movement and zoom 2016-12-30 13:28:07 +01:00
Anakin 353d932147 import msh file,
problems:
it is not correctly displayed (vertice and what happend to the texture?)
todo:
improve the import, remove unused garbage,
add move and zoom function
2016-12-30 12:36:05 +01:00
Anakin 82ce8ad72a manage data in vectors 2016-12-29 14:06:25 +01:00
Anakin 0499982150 move texture to GeometryEngine 2016-12-29 13:37:15 +01:00
Anakin faea3b0737 removed timer rotation, now the user has full control,
added keyboard support,
reset rotation with space
2016-12-27 14:05:39 +01:00
Anakin a30f1b125c added Qt Example, next change it to fit my project 2016-12-24 16:03:37 +01:00
Anakin b6ef34f988 still trying to fix the problem 2016-12-14 17:20:20 +01:00
Anakin 96379a9afb fixed texture error 2016-12-13 19:07:36 +01:00
Anakin 481256e8ea added open file ability from the old project to Qt,
texture seams not to open,
texture display does not work
2016-12-12 16:47:38 +01:00
Anakin 1cc4f1ca90 removed vertex class (i have my own data structure)
implemented the glInit and glPaint function
2016-12-12 12:38:13 +01:00
Anakin 53ac8c3e5b copied from the old Ppoject:
shaders,
object class
Modified to use better names and use Qt things
2016-12-11 17:46:22 +01:00
Anakin 5faf584d84 First triangle drawn in Qt Project 2016-12-10 14:42:00 +01:00
Anakin 8cf86a41eb Added new Project using Qt,
There is garbage left from Qt??
2016-12-09 15:56:45 +01:00
Anakin 1c5a33cfa7 different quat2eul function from the internet 2016-12-03 14:33:15 +01:00
Anakin 4078347023 fixed cloth problem 2016-12-03 13:39:57 +01:00
Anakin 46c4a166c4 code improvement 2016-12-02 14:04:01 +01:00
Anakin 1918d5c844 new release version,
Features:
- performance improvement,
- code improvement,
- move the model to the center,
- scale everything to 1,
- do not open a default file for release build
Bugs:
- cloth is not displayed correctly,
- turning in the wrong x direction when model is turned 180° in y direction,
- consular class corvette is not displayed,
- rep_weap_LJ-50 is not displayed correctly
2016-12-02 13:07:49 +01:00
Anakin 3118118953 some fixes 2016-12-02 13:00:38 +01:00
Anakin 9b3d12dfeb scale everything to 1,
cloth not displayed completely,
corvette is not displayed why?
2016-12-02 12:10:52 +01:00
Anakin a47eefe92e move the model to the center,
clean up variables,
use delete[]
2016-12-01 19:51:11 +01:00
Anakin 1c0ed61b34 adjust boundingbox (only for SINF)
use else if
2016-11-30 17:05:39 +01:00
Anakin ef2c341a1a using c++11 loops,
reading bbox for each geom,
added some TODO
use the bbox information
2016-11-28 14:04:09 +01:00
Anakin 5ab2f2eaf9 fixed the memory garbage problem 2016-11-26 15:39:59 +01:00
Anakin 5c5b9ac2f1 don't copy the model list. It can be very big - using pointer now,
garbage is not from the texture or object changes
2016-11-25 16:14:33 +01:00
Anakin e1e8e165fe removed unused information from texture,
don't copy the data, give a pointer,
there is some data left, need to find out if it's from these changes
2016-11-24 19:40:17 +01:00
97 changed files with 4828 additions and 276 deletions

View File

@ -14,6 +14,12 @@ enum Mtyp {
shadowMesh = 6
};
struct Bbox {
float quaternion[4];
float center[3];
float extents[3];
};
struct ChunkHeader {
char name[5];
std::uint32_t size;
@ -24,7 +30,7 @@ struct Segment {
std::uint32_t textureIndex = 0;
float* vertex = nullptr;
float* uv = nullptr;
std::vector<std::vector<std::uint32_t>*> meshIndices; // indices into vertex array
std::vector<std::vector<std::uint32_t>> meshIndices; // indices into vertex array
};
struct Modl {
@ -45,10 +51,10 @@ public:
private:
std::vector<Modl*> vModls;
std::vector<Modl*>* vModls;
std::fstream fsMesh;
std::vector<std::string> vTextures;
Bbox boundingBox;
private:
void loadChunks(std::list<ChunkHeader*> &destination, std::streampos start, const std::uint32_t end);
@ -60,10 +66,11 @@ private:
void analyseClthChunks(Modl* dataDestination, std::list<ChunkHeader*> &chunkList);
void readVertex(Segment* dataDestination, std::streampos position);
void readUV(Segment* dataDestination, std::streampos position);
void quat2eul(float &quat0, float &quat1, float &quat2, float &quat3);
public:
std::vector<Modl*> getModels() const;
std::vector<Modl*>* getModels() const;
std::vector<std::string> getTextureList() const;
Bbox getBoundgBox() const;
};

View File

@ -70,8 +70,9 @@ private:
// ========================================
// data
std::vector<Modl*> vModels;
std::vector<Modl*>* vModels = NULL;
std::vector<textureData*> vTextures;
Bbox sceneBoundingBox;
// transformation =========================
//values
@ -80,7 +81,7 @@ private:
float fRotationZ = 0;
double dTranslationX = 0;
double dTranslationY = 0;
double dTranslationZ = 5;
double dTranslationZ = 3;
// ========================================

View File

@ -9,22 +9,13 @@ public:
~TextureTGA();
private:
std::vector<std::uint8_t> vui8Pixels;
bool bCompressed;
std::uint32_t ui32IDLength;
bool bColorTabel;
std::uint32_t ui32PicType;
std::uint32_t ui32PaletteBegin;
std::uint32_t ui32PaletteLength;
std::uint32_t ui32PaletteBpP;
std::vector<std::uint8_t>* vui8Pixels;
std::uint32_t ui32BpP;
std::uint32_t ui32Width;
std::uint32_t ui32Height;
std::uint32_t ui32Size;
std::uint32_t ui32BpP;
std::uint32_t ui32Attribut;
public:
std::vector<std::uint8_t> getData() const;
std::vector<std::uint8_t>* getData() const;
bool hasAlpha() const;
std::uint32_t getWidth() const;
std::uint32_t getHeight() const;

View File

@ -10,6 +10,8 @@
Object::Object(const char* path)
{
vModls = new std::vector<Modl*>;
// open file
fsMesh.open(path, std::ios::in | std::ios::binary);
@ -65,9 +67,6 @@ Object::~Object()
{
// clear texture list
vTextures.clear();
// clear Model list (don't delete the elements)
vModls.clear();
}
@ -108,28 +107,57 @@ void Object::loadChunks(std::list<ChunkHeader*>& destination, std::streampos sta
void Object::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
{
for (std::list<ChunkHeader*>::iterator it = chunkList.begin(); it != chunkList.end(); it++)
for (auto& it : chunkList)
{
if (!strcmp("MATL", (*it)->name))
if (!strcmp("SINF", it->name))
{
std::list<ChunkHeader*> tempSinfChunks;
loadChunks(tempSinfChunks, it->position, it->size);
// evaluate MATL subchunks
for (auto& it : tempSinfChunks)
{
if (!strcmp("BBOX", it->name))
{
fsMesh.seekg(it->position);
// read in the quaternion
for (int i = 0; i < 4; i++)
fsMesh.read(reinterpret_cast<char*>(&boundingBox.quaternion[i]), sizeof(float));
//read in the center
for (int i = 0; i < 3; i++)
fsMesh.read(reinterpret_cast<char*>(&boundingBox.center[i]), sizeof(float));
//read in the extents
for (int i = 0; i < 3; i++)
fsMesh.read(reinterpret_cast<char*>(&boundingBox.extents[i]), sizeof(float));
}
}
for (ChunkHeader* it : tempSinfChunks)
delete it;
}
else if (!strcmp("MATL", it->name))
{
// "useless" information how many MATD follow
fsMesh.seekg((*it)->position);
std::uint32_t tempMatdCount;
fsMesh.read(reinterpret_cast<char*>(&tempMatdCount), sizeof(std::uint32_t));
fsMesh.seekg(it->position);
fsMesh.seekg(sizeof(std::uint32_t), std::ios_base::cur);
// get all MATD from MATL list
std::list<ChunkHeader*> tempMatlChunks;
loadChunks(tempMatlChunks, fsMesh.tellg(), (*it)->size - 4);
loadChunks(tempMatlChunks, fsMesh.tellg(), it->size - 4);
// evaluate MATL subchunks
for (std::list<ChunkHeader*>::iterator it = tempMatlChunks.begin(); it != tempMatlChunks.end(); it++)
for (auto& it : tempMatlChunks)
{
// This shouldn't be anything else than MATD
if (!strcmp("MATD", (*it)->name))
if (!strcmp("MATD", it->name))
{
// get all subchunks from MATD
std::list<ChunkHeader*> tempMatdChunks;
loadChunks(tempMatdChunks, (*it)->position, (*it)->size);
loadChunks(tempMatdChunks, it->position, it->size);
vTextures.push_back("");
@ -153,17 +181,15 @@ void Object::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
tempMatlChunks.pop_front();
delete tempCursor;
}
continue;
}
if (!strcmp("MODL", (*it)->name))
else if (!strcmp("MODL", it->name))
{
Modl* tempModl = new Modl;
// get all subchunks
std::list<ChunkHeader*> tempChunks;
loadChunks(tempChunks, (*it)->position, (*it)->size);
loadChunks(tempChunks, it->position, it->size);
// evaluate MODL subchunks
analyseModlChunks(tempModl, tempChunks);
@ -177,100 +203,84 @@ void Object::analyseMsh2Chunks(std::list<ChunkHeader*>& chunkList)
}
// save Model data
vModls.push_back(tempModl);
continue;
vModls->push_back(tempModl);
}
}
}
void Object::analyseMatdChunks(std::list<ChunkHeader*>& chunkList)
{
for (std::list<ChunkHeader*>::iterator it = chunkList.begin(); it != chunkList.end(); it++)
for (auto& it : chunkList)
{
//TX1D, TX2D, TX3D
if (!strcmp("TX0D", (*it)->name))
if (!strcmp("TX0D", it->name))
{
fsMesh.seekg((*it)->position);
char* buffer = new char[(*it)->size + 1];
fsMesh.seekg(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
fsMesh.read(buffer, (*it)->size);
fsMesh.read(buffer, it->size);
vTextures.back() = buffer;
delete buffer;
continue;
delete[] buffer;
}
}
}
void Object::analyseModlChunks(Modl* dataDestination, std::list<ChunkHeader*>& chunkList)
{
for (std::list<ChunkHeader*>::iterator it = chunkList.begin(); it != chunkList.end(); it++)
for (auto& it : chunkList)
{
if (!strcmp("MTYP", (*it)->name))
if (!strcmp("MTYP", it->name))
{
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
std::uint32_t tempType;
fsMesh.read(reinterpret_cast<char*>(&tempType), sizeof(tempType));
dataDestination->type = (Mtyp)tempType;
continue;
}
if (!strcmp("PRNT", (*it)->name))
else if (!strcmp("PRNT", it->name))
{
fsMesh.seekg((*it)->position);
char* buffer = new char[(*it)->size];
fsMesh.seekg(it->position);
char* buffer = new char[it->size];
*buffer = { 0 };
fsMesh.read(buffer, (*it)->size);
fsMesh.read(buffer, it->size);
dataDestination->parent = buffer;
delete buffer;
continue;
delete[] buffer;
}
if (!strcmp("NAME", (*it)->name))
else if (!strcmp("NAME", it->name))
{
fsMesh.seekg((*it)->position);
char* buffer = new char[(*it)->size];
fsMesh.seekg(it->position);
char* buffer = new char[it->size];
*buffer = { 0 };
fsMesh.read(buffer, (*it)->size);
fsMesh.read(buffer, it->size);
dataDestination->name = buffer;
delete buffer;
continue;
delete[] buffer;
}
if (!strcmp("FLGS", (*it)->name))
else if (!strcmp("FLGS", it->name))
{
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
fsMesh.read(reinterpret_cast<char*>(&dataDestination->renderFlags), sizeof(dataDestination->renderFlags));
continue;
}
if (!strcmp("TRAN", (*it)->name))
else if (!strcmp("TRAN", it->name))
{
float tempScale[3];
float tempRotation[4];
float tempTrans[3];
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
fsMesh.read(reinterpret_cast<char*>(&tempScale[0]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempScale[1]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempScale[2]), sizeof(float));
for(int i = 0; i < 3; i++)
fsMesh.read(reinterpret_cast<char*>(&tempScale[i]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempRotation[0]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempRotation[1]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempRotation[2]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempRotation[3]), sizeof(float));
for (int i = 0; i < 4; i++)
fsMesh.read(reinterpret_cast<char*>(&tempRotation[i]), sizeof(float));
//calculate x,y,z rotation
tempRotation[0] = atan2(2 * (tempRotation[0] * tempRotation[1] + tempRotation[2] * tempRotation[3]),
1 - 2 * (pow(tempRotation[1], 2) + pow(tempRotation[2], 2)));
tempRotation[1] = asin(2 * (tempRotation[0] * tempRotation[2] - tempRotation[3] * tempRotation[1]));
tempRotation[2] = atan2(2 * (tempRotation[0] * tempRotation[3] + tempRotation[1] * tempRotation[2]),
1 - 2 * (pow(tempRotation[2], 2) + pow(tempRotation[3], 2))) - PI;
quat2eul(tempRotation[0], tempRotation[1], tempRotation[2], tempRotation[3]);
fsMesh.read(reinterpret_cast<char*>(&tempTrans[0]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempTrans[1]), sizeof(float));
fsMesh.read(reinterpret_cast<char*>(&tempTrans[2]), sizeof(float));
for (int i = 0; i < 3; i++)
fsMesh.read(reinterpret_cast<char*>(&tempTrans[i]), sizeof(float));
dataDestination->m4x4Translation = glm::scale(
dataDestination->m4x4Translation,
@ -300,14 +310,13 @@ void Object::analyseModlChunks(Modl* dataDestination, std::list<ChunkHeader*>& c
glm::vec3(0, 0, 1)
);
continue;
}
if (!strcmp("GEOM", (*it)->name))
else if (!strcmp("GEOM", it->name))
{
// get all subchunks
std::list<ChunkHeader*> tempGeomChunks;
loadChunks(tempGeomChunks, (*it)->position, (*it)->size);
loadChunks(tempGeomChunks, it->position, it->size);
// evaluate GEOM subchunks
analyseGeomChunks(dataDestination, tempGeomChunks);
@ -319,21 +328,19 @@ void Object::analyseModlChunks(Modl* dataDestination, std::list<ChunkHeader*>& c
tempGeomChunks.pop_front();
delete tempCursor;
}
continue;
}
}
}
void Object::analyseGeomChunks(Modl * dataDestination, std::list<ChunkHeader*>& chunkList)
{
for (std::list<ChunkHeader*>::iterator it = chunkList.begin(); it != chunkList.end(); it++)
for (auto& it : chunkList)
{
if (!strcmp("SEGM", (*it)->name))
if (!strcmp("SEGM", it->name))
{
// get all subchunks
std::list<ChunkHeader*> tempSegmChunks;
loadChunks(tempSegmChunks, (*it)->position, (*it)->size);
loadChunks(tempSegmChunks, it->position, it->size);
// evaluate SEGM subchunks
analyseSegmChunks(dataDestination, tempSegmChunks);
@ -348,11 +355,11 @@ void Object::analyseGeomChunks(Modl * dataDestination, std::list<ChunkHeader*>&
continue;
}
if (!strcmp("CLTH", (*it)->name))
if (!strcmp("CLTH", it->name))
{
// get all subchunks
std::list<ChunkHeader*> tempClthChunks;
loadChunks(tempClthChunks, (*it)->position, (*it)->size);
loadChunks(tempClthChunks, it->position, it->size);
// evaluate CLTH subchunks
analyseClthChunks(dataDestination, tempClthChunks);
@ -373,39 +380,35 @@ void Object::analyseSegmChunks(Modl * dataDestination, std::list<ChunkHeader*>&
{
Segment* tempData = new Segment;
for (std::list<ChunkHeader*>::iterator it = chunkList.begin(); it != chunkList.end(); it++)
for (auto& it : chunkList)
{
if (!strcmp("MATI", (*it)->name))
if (!strcmp("MATI", it->name))
{
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
fsMesh.read(reinterpret_cast<char*>(&tempData->textureIndex), sizeof(tempData->textureIndex));
continue;
}
if (!strcmp("POSL", (*it)->name))
else if (!strcmp("POSL", it->name))
{
readVertex(tempData, (*it)->position);
continue;
readVertex(tempData, it->position);
}
/*if (!strcmp("NRML", (*it)->name))
/*else if (!strcmp("NRML", it->name))
{
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
std::uint32_t tempSize;
fsMesh.read(reinterpret_cast<char*>(&tempSize), sizeof(tempSize));
// List of normals
// long int - 4 - number of normal vectores stored in this list
// float[3][] - 12 each - UVW vector for each vertex
continue;
}*/
if (!strcmp("UV0L", (*it)->name))
else if (!strcmp("UV0L", it->name))
{
readUV(tempData, (*it)->position);
continue;
readUV(tempData, it->position);
}
if (!strcmp("STRP", (*it)->name))
else if (!strcmp("STRP", it->name))
{
// don't get null, bone, shadowMesh and hidden mesh indices
if (dataDestination->type == null ||
@ -416,11 +419,11 @@ void Object::analyseSegmChunks(Modl * dataDestination, std::list<ChunkHeader*>&
// jump to the data section and read the size;
std::uint32_t tempSize;
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
fsMesh.read(reinterpret_cast<char*>(&tempSize), sizeof(tempSize));
int highBitCount(0);
std::vector<uint32_t>* tempPoly = new std::vector<uint32_t>;
std::vector<uint32_t> tempPoly; // = new std::vector<uint32_t>;
for (unsigned int i = 0; i < tempSize; i++)
{
@ -435,7 +438,7 @@ void Object::analyseSegmChunks(Modl * dataDestination, std::list<ChunkHeader*>&
tempValue = (std::uint16_t(tempValue << 1) >> 1);
}
tempPoly->push_back((std::uint32_t)tempValue);
tempPoly.push_back((std::uint32_t)tempValue);
// new Polygon found
if (highBitCount == 2)
@ -447,18 +450,17 @@ void Object::analyseSegmChunks(Modl * dataDestination, std::list<ChunkHeader*>&
std::uint32_t saveData[2];
for (int i = 0; i < 2; i++)
{
saveData[i] = tempPoly->back();
tempPoly->pop_back();
saveData[i] = tempPoly.back();
tempPoly.pop_back();
}
// ..and save them in the new vector
std::vector<uint32_t>* newPointer = new std::vector<uint32_t>;
for (int i = 1; i >= 0; i--)
newPointer->push_back(saveData[i]);
// save the old vector and set the pointer to the new one
tempData->meshIndices.push_back(tempPoly);
tempPoly = newPointer;
tempPoly.clear();
for (int i = 1; i >= 0; i--)
tempPoly.push_back(saveData[i]);
} // if high bit set
} // for all values
@ -468,9 +470,9 @@ void Object::analyseSegmChunks(Modl * dataDestination, std::list<ChunkHeader*>&
// kick the first element, it's empty as a reason of the algo above;
tempData->meshIndices.erase(tempData->meshIndices.begin());
continue;
}
}
dataDestination->segmLst.push_back(tempData);
}
@ -478,14 +480,14 @@ void Object::analyseClthChunks(Modl * dataDestination, std::list<ChunkHeader*>&
{
Segment* tempData = new Segment;
for (std::list<ChunkHeader*>::iterator it = chunkList.begin(); it != chunkList.end(); it++)
for (auto& it : chunkList)
{
if (!strcmp("CTEX", (*it)->name))
if (!strcmp("CTEX", it->name))
{
fsMesh.seekg((*it)->position);
char* buffer = new char[(*it)->size];
fsMesh.seekg(it->position);
char* buffer = new char[it->size];
*buffer = { 0 };
fsMesh.read(buffer, (*it)->size);
fsMesh.read(buffer, it->size);
bool tempFound(false);
@ -505,46 +507,42 @@ void Object::analyseClthChunks(Modl * dataDestination, std::list<ChunkHeader*>&
tempData->textureIndex = vTextures.size() - 1;
}
delete buffer;
continue;
delete[] buffer;
}
if (!strcmp("CPOS", (*it)->name))
else if (!strcmp("CPOS", it->name))
{
readVertex(tempData, (*it)->position);
continue;
readVertex(tempData, it->position);
}
if (!strcmp("CUV0", (*it)->name))
else if (!strcmp("CUV0", it->name))
{
readUV(tempData, (*it)->position);
continue;
readUV(tempData, it->position);
}
if (!strcmp("CMSH", (*it)->name))
else if (!strcmp("CMSH", it->name))
{
// jump to the data section and read the size;
std::uint32_t tempSize;
fsMesh.seekg((*it)->position);
fsMesh.seekg(it->position);
fsMesh.read(reinterpret_cast<char*>(&tempSize), sizeof(tempSize));
std::vector<uint32_t>* tempPoly;
std::vector<uint32_t> tempPoly;
// for every triangle..
for (unsigned int i = 0; i < tempSize; i += 3)
for (unsigned int i = 0; i < tempSize * 3; i += 3)
{
tempPoly = new std::vector<uint32_t>;
tempPoly.clear();
// ..get the 3 indices and save them
for (int j = 0; j < 3; j++)
{
std::uint32_t tempValue;
fsMesh.read(reinterpret_cast<char*>(&tempValue), sizeof(std::uint32_t));
tempPoly->push_back(tempValue);
tempPoly.push_back(tempValue);
}
tempData->meshIndices.push_back(tempPoly);
}
continue;
}
}
dataDestination->segmLst.push_back(tempData);
@ -574,11 +572,29 @@ void Object::readUV(Segment* dataDestination, std::streampos position)
fsMesh.read(reinterpret_cast<char*>(&dataDestination->uv[i]), sizeof(float));
}
void Object::quat2eul(float &quat0, float &quat1, float & quat2, float &quat3)
{
float ysqr = quat1 * quat1;
float t0 = -2.0f * (ysqr + quat2 * quat2) + 1.0f;
float t1 = +2.0f * (quat0 * quat1 - quat3 * quat2);
float t2 = -2.0f * (quat0 * quat2 + quat3 * quat1);
float t3 = +2.0f * (quat1 * quat2 - quat3 * quat0);
float t4 = -2.0f * (quat0 * quat0 + ysqr) + 1.0f;
t2 = t2 > 1.0f ? 1.0f : t2;
t2 = t2 < -1.0f ? -1.0f : t2;
quat1 = std::asin(t2);
quat0 = std::atan2(t3, t4);
quat2 = std::atan2(t1, t0);
}
/////////////////////////////////////////////////////////////////////////
// public getter
std::vector<Modl*> Object::getModels() const
std::vector<Modl*>* Object::getModels() const
{
return vModls;
}
@ -588,6 +604,11 @@ std::vector<std::string> Object::getTextureList() const
return vTextures;
}
Bbox Object::getBoundgBox() const
{
return boundingBox;
}
/////////////////////////////////////////////////////////////////////////
// public functions

View File

@ -109,37 +109,40 @@ void OpenGLController::processInit()
void OpenGLController::deleteVectors()
{
while (!vModels.empty())
if (vModels != NULL)
{
Modl* cursor = vModels.back();
vModels.pop_back();
while (!cursor->segmLst.empty())
while (!vModels->empty())
{
Segment* segmCuror = cursor->segmLst.back();
cursor->segmLst.pop_back();
Modl* modelVectorElement = vModels->back();
vModels->pop_back();
delete segmCuror->uv;
delete segmCuror->vertex;
while (!segmCuror->meshIndices.empty())
while (!modelVectorElement->segmLst.empty())
{
std::vector<std::uint32_t>* meshCursor = segmCuror->meshIndices.back();
meshCursor->clear();
segmCuror->meshIndices.pop_back();
delete meshCursor;
Segment* segmentVectorElement = modelVectorElement->segmLst.back();
modelVectorElement->segmLst.pop_back();
delete[] segmentVectorElement->uv;
delete[] segmentVectorElement->vertex;
while (!segmentVectorElement->meshIndices.empty())
{
segmentVectorElement->meshIndices.back().clear();
segmentVectorElement->meshIndices.pop_back();
}
delete segmentVectorElement;
}
delete segmCuror;
delete modelVectorElement;
}
delete cursor;
delete vModels;
}
while (!vTextures.empty())
{
textureData* cursor = vTextures.back();
vTextures.pop_back();
cursor->data->clear();
delete cursor->data;
delete cursor;
}
@ -207,16 +210,16 @@ glm::mat4 OpenGLController::getModelMatrix(unsigned int index)
{
glm::mat4 tempParentMatrix = glm::mat4(1.0f);
for (unsigned int loop = 0; loop < vModels.size(); loop++)
for (unsigned int loop = 0; loop < vModels->size(); loop++)
{
if (!strcmp(vModels[index]->parent.c_str(), vModels[loop]->name.c_str()))
if (!strcmp(vModels->at(index)->parent.c_str(), vModels->at(loop)->name.c_str()))
{
tempParentMatrix = getModelMatrix(loop);
break;
}
}
return tempParentMatrix * vModels[index]->m4x4Translation;
return tempParentMatrix * vModels->at(index)->m4x4Translation;
}
glm::mat4 OpenGLController::getMVPMatrix(unsigned int index)
@ -237,8 +240,19 @@ glm::mat4 OpenGLController::getMVPMatrix(unsigned int index)
m4x4ModelRot = glm::rotate(m4x4ModelRot, fRotationY, glm::vec3(0, 1, 0));
m4x4ModelRot = glm::rotate(m4x4ModelRot, fRotationZ, glm::vec3(0, 0, 1));
// move to center
glm::mat4 m4x4ModelCenter = glm::translate(
glm::mat4(1.0f),
glm::vec3(-sceneBoundingBox.center[0], -sceneBoundingBox.center[1], -sceneBoundingBox.center[2])
);
//scale to 1
float maxExtent = max(max(sceneBoundingBox.extents[0], sceneBoundingBox.extents[1]), sceneBoundingBox.extents[2]);
glm::mat4 m4x4Normalize = glm::mat4(1.0f);
m4x4Normalize = glm::scale(m4x4Normalize, glm::vec3(1/maxExtent, 1 / maxExtent, 1 / maxExtent));
// Return MVP
return m4x4Projection * m4x4View * m4x4ModelRot * getModelMatrix(index);
return m4x4Projection * m4x4View * m4x4ModelRot * m4x4Normalize * m4x4ModelCenter * getModelMatrix(index);
}
@ -309,52 +323,54 @@ void OpenGLController::updateScene()
// tell sampler to use texture unit 0
glUniform1i(gluiSamplerID, 0);
int instanceOffset(0);
for (unsigned int modelIndex = 0; modelIndex < vModels.size(); modelIndex++)
if (vModels != NULL)
{
// skip null, bones, shadowMesh, hidden things (don't increase textrue index!!)
if (vModels[modelIndex]->type == null ||
vModels[modelIndex]->type == bone ||
vModels[modelIndex]->type == shadowMesh ||
vModels[modelIndex]->renderFlags == 1)
continue;
int instanceOffset(0);
for (auto& segIt : vModels[modelIndex]->segmLst)
for (unsigned int modelIndex = 0; modelIndex < vModels->size(); modelIndex++)
{
// give texture to the shader
std::uint32_t tempTexIndex = segIt->textureIndex >= vTextures.size() ? vTextures.size() - 1 : segIt->textureIndex;
// skip null, bones, shadowMesh, hidden things (don't increase textrue index!!)
if (vModels->at(modelIndex)->type == null ||
vModels->at(modelIndex)->type == bone ||
vModels->at(modelIndex)->type == shadowMesh ||
vModels->at(modelIndex)->renderFlags == 1)
continue;
glTexImage2D(
GL_TEXTURE_2D,
0,
vTextures[tempTexIndex]->alpha ? GL_RGBA : GL_RGB,
vTextures[tempTexIndex]->width,
vTextures[tempTexIndex]->height,
0,
vTextures[tempTexIndex]->alpha ? GL_BGRA : GL_BGR,
GL_UNSIGNED_BYTE,
vTextures[tempTexIndex]->data->data()
);
for (auto& segIt : vModels->at(modelIndex)->segmLst)
{
// give texture to the shader
std::uint32_t tempTexIndex = segIt->textureIndex >= vTextures.size() ? vTextures.size() - 1 : segIt->textureIndex;
glGenerateMipmap(GL_TEXTURE_2D);
glTexImage2D(
GL_TEXTURE_2D,
0,
vTextures[tempTexIndex]->alpha ? GL_RGBA : GL_RGB,
vTextures[tempTexIndex]->width,
vTextures[tempTexIndex]->height,
0,
vTextures[tempTexIndex]->alpha ? GL_BGRA : GL_BGR,
GL_UNSIGNED_BYTE,
vTextures[tempTexIndex]->data->data()
);
// give the MVP to the shader
glUniformMatrix4fv(gluiMatrixID, 1, GL_FALSE, &getMVPMatrix(modelIndex)[0][0]);
glGenerateMipmap(GL_TEXTURE_2D);
// calculate the number of vertex
unsigned int vertexCount(0);
for (auto& it : segIt->meshIndices)
vertexCount += (it->size() - 2) * 3;
// give the MVP to the shader
glUniformMatrix4fv(gluiMatrixID, 1, GL_FALSE, &getMVPMatrix(modelIndex)[0][0]);
// calculate the number of vertex
unsigned int vertexCount(0);
for (auto& it : segIt->meshIndices)
vertexCount += (it.size() - 2) * 3;
glDrawArrays(GL_TRIANGLES, instanceOffset, vertexCount);
glDrawArrays(GL_TRIANGLES, instanceOffset, vertexCount);
// increase the offset
instanceOffset += vertexCount;
// increase the offset
instanceOffset += vertexCount;
}
}
}
glfwSwapBuffers(pWindow);
glfwPollEvents();
}
@ -372,26 +388,27 @@ void OpenGLController::loadMsh(const char * path)
Object obj(path);
vModels = obj.getModels();
tempTexList = obj.getTextureList();
sceneBoundingBox = obj.getBoundgBox();
}
catch (std::invalid_argument e)
{
MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
return; exit(1);
return;
}
// collect vertex data of all models
std::vector<Vertex> tempBufferData;
for (auto& modIt : vModels) // for every model chunk
for (auto& modIt : *vModels) // for every model chunk
{
for (auto& segIt : modIt->segmLst) // for every cluster
{
for (auto& mshIt : segIt->meshIndices) // for every polygon
{
if (mshIt->size() >= 3) // multipoly
if (mshIt.size() >= 3) // multipoly
{
// for every triangle of the multi polygon
for (unsigned int tri = 0; tri < mshIt->size() - 2; tri++)
for (unsigned int tri = 0; tri < mshIt.size() - 2; tri++)
{
// for every edge of the triangle
for (int triEdge = 0; triEdge < 3; triEdge++)
@ -399,7 +416,7 @@ void OpenGLController::loadMsh(const char * path)
Vertex tempVertex;
// every edge has 3 coordinates
for (int j = 0; j < 3; j++)
tempVertex.position[j] = (GLfloat)segIt->vertex[(*mshIt)[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 3 + j];
tempVertex.position[j] = (GLfloat)segIt->vertex[mshIt[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 3 + j];
// and 2 UV
if (segIt->uv == NULL)
@ -410,7 +427,7 @@ void OpenGLController::loadMsh(const char * path)
else
{
for (int j = 0; j < 2; j++)
tempVertex.uv[j] = (GLfloat)segIt->uv[(*mshIt)[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 2 + j];
tempVertex.uv[j] = (GLfloat)segIt->uv[mshIt[tri + triEdge - ((tri % 2) * (triEdge - 1) * 2)] * 2 + j];
}
tempBufferData.push_back(tempVertex);
}
@ -436,6 +453,8 @@ void OpenGLController::loadMsh(const char * path)
);
glBindBuffer(GL_ARRAY_BUFFER, 0);
tempBufferData.clear();
// get textures path
std::string tempPath = path;
@ -455,7 +474,7 @@ void OpenGLController::loadMsh(const char * path)
tempData->alpha = tempTex.hasAlpha();
tempData->width = tempTex.getWidth();
tempData->height = tempTex.getHeight();
tempData->data = new std::vector<std::uint8_t>(tempTex.getData());
tempData->data = tempTex.getData();
}
catch (std::invalid_argument e)
{

View File

@ -13,35 +13,26 @@ TextureTGA::TextureTGA(const char * filePath)
std::uint8_t ui8x18Header[19] = { 0 };
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header)-1);
//get variables
vui8Pixels = new std::vector<std::uint8_t>;
bool bCompressed;
std::uint32_t ui32IDLength;
std::uint32_t ui32PicType;
std::uint32_t ui32PaletteLength;
std::uint32_t ui32Size;
// extract all information from header
ui32IDLength = ui8x18Header[0];
bColorTabel = ui8x18Header[1] == 1;
ui32PicType = ui8x18Header[2];
ui32PaletteBegin = ui8x18Header[4] * 0x100 + ui8x18Header[3];
ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5];
ui32PaletteBpP = ui8x18Header[7];
ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12];
ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14];
ui32BpP = ui8x18Header[16];
ui32Attribut = ui8x18Header[17];
// calculate some more information
ui32Size = ui32Width * ui32Height * ui32BpP/8;
bCompressed = ui32PicType == 9 || ui32PicType == 10;
vui8Pixels.resize(ui32Size);
/* consol output of the header
std::cout << "Header\n"
<< "ID länge: " << ui32IDLength << std::endl
<< "Farbtabelle: " << (int)bColorTabel << std::endl
<< "Bildtype: " << ui32PicType << std::endl
<< "Palletenbegin: " << ui32PaletteBegin << std::endl
<< "Palletenlängen: " << ui32PaletteLength << std::endl
<< "Bits pro Palleteneintrag: " << ui32PaletteBpP << std::endl
<< "Breite: " << ui32Width << std::endl
<< "Höhe: " << ui32Height << std::endl
<< "Bit pro Pixel: " << ui32BpP << std::endl
<< "Bild Attribute: " << ui32Attribut << std::endl;*/
vui8Pixels->resize(ui32Size);
// jump to the data block
fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);
@ -49,7 +40,7 @@ TextureTGA::TextureTGA(const char * filePath)
// If not compressed 24 or 32 bit
if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32))
{
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
fsPicture.read(reinterpret_cast<char*>(vui8Pixels->data()), ui32Size);
}
// else if compressed 24 or 32 bit
else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed
@ -70,10 +61,10 @@ TextureTGA::TextureTGA(const char * filePath)
for (int i = 0; i <= tempChunkHeader; i++)
{
vui8Pixels[tempByteIndex++] = tempData[0];
vui8Pixels[tempByteIndex++] = tempData[1];
vui8Pixels[tempByteIndex++] = tempData[2];
if(ui32BpP == 32) vui8Pixels[tempByteIndex++] = tempData[3];
vui8Pixels->at(tempByteIndex++) = tempData[0];
vui8Pixels->at(tempByteIndex++) = tempData[1];
vui8Pixels->at(tempByteIndex++) = tempData[2];
if(ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3];
}
}
else // data count
@ -85,10 +76,10 @@ TextureTGA::TextureTGA(const char * filePath)
{
fsPicture.read(reinterpret_cast<char*>(&tempData), ui32BpP/8);
vui8Pixels[tempByteIndex++] = tempData[0];
vui8Pixels[tempByteIndex++] = tempData[1];
vui8Pixels[tempByteIndex++] = tempData[2];
if (ui32BpP == 32) vui8Pixels[tempByteIndex++] = tempData[3];
vui8Pixels->at(tempByteIndex++) = tempData[0];
vui8Pixels->at(tempByteIndex++) = tempData[1];
vui8Pixels->at(tempByteIndex++) = tempData[2];
if (ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3];
}
}
} while (tempByteIndex < ui32Size);
@ -105,10 +96,9 @@ TextureTGA::TextureTGA(const char * filePath)
TextureTGA::~TextureTGA()
{
vui8Pixels.clear();
}
std::vector<std::uint8_t> TextureTGA::getData() const
std::vector<std::uint8_t>* TextureTGA::getData() const
{
return vui8Pixels;
}

View File

@ -17,7 +17,9 @@ int main(int argc, char** argv)
else
scene = OpenGLController::getInstance();
scene->loadMsh("..\\Release\\Msh\\quadPoly.msh");
#ifdef _DEBUG
scene->loadMsh("..\\Release\\Msh\\triClothMan.msh");
#endif // DEBUG
do {
scene->updateScene();

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>FileInfoWindow</class>
<widget class="QWidget" name="FileInfoWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>320</width>
<height>400</height>
</rect>
</property>
<property name="windowTitle">
<string>File information</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="basic">
<property name="text">
<string>Name: -
Materials: -
Vertices: -
Triangles: -</string>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>322</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="detail">
<property name="text">
<string>No file is open</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindowClass</class>
<widget class="QMainWindow" name="MainWindowClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>400</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>600</width>
<height>400</height>
</size>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<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>
</property>
<attribute name="toolBarArea">
<enum>LeftToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</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>
<include location="../Resources/Resources.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -0,0 +1,555 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsWindow</class>
<widget class="QWidget" name="SettingsWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>358</height>
</rect>
</property>
<property name="windowTitle">
<string>Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBackground">
<property name="title">
<string>Background</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="5">
<widget class="QSpinBox" name="lightOn_G_SB">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="4" column="7">
<widget class="QLabel" name="label_5">
<property name="text">
<string>B:</string>
</property>
</widget>
</item>
<item row="4" column="6">
<widget class="QSlider" name="lightOn_G_S">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="9">
<widget class="QSlider" name="lightOn_B_S">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="3" colspan="3">
<widget class="QCheckBox" name="checkAutoColor">
<property name="text">
<string>auto color</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="8">
<widget class="QSpinBox" name="lightOn_B_SB">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QLabel" name="label_0">
<property name="text">
<string>R:</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QLabel" name="label_1">
<property name="text">
<string>G:</string>
</property>
</widget>
</item>
<item row="2" column="7">
<widget class="QLabel" name="label_2">
<property name="text">
<string>B:</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QSpinBox" name="lightOff_G_SB">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="2" column="8">
<widget class="QSpinBox" name="lightOff_B_SB">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="2" column="9">
<widget class="QSlider" name="lightOff_B_S">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="lightOff_R_SB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QSlider" name="lightOff_G_S">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>204</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QSlider" name="lightOff_R_S">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>127</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="labelLightOn">
<property name="text">
<string>Light on:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="10">
<widget class="QLabel" name="labelLightOff">
<property name="text">
<string>Light off:</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>R:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QSpinBox" name="lightOn_R_SB">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QSlider" name="lightOn_R_S">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="4" column="4">
<widget class="QLabel" name="label_4">
<property name="text">
<string>G:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="groupLight">
<property name="title">
<string>Light</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="1">
<widget class="QSpinBox" name="light_R_SB">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_7">
<property name="text">
<string>G:</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="4">
<widget class="QLabel" name="labelAttFac">
<property name="text">
<string>Attenuationfactor:</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QSpinBox" name="light_G_SB">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QLabel" name="label_8">
<property name="text">
<string>B:</string>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QSpinBox" name="light_B_SB">
<property name="maximumSize">
<size>
<width>30</width>
<height>16777215</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::NoButtons</enum>
</property>
<property name="maximum">
<number>255</number>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSlider" name="light_R_S">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="8">
<widget class="QSlider" name="light_B_S">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>R:</string>
</property>
</widget>
</item>
<item row="0" column="0" colspan="4">
<widget class="QRadioButton" name="radioDirectLight">
<property name="text">
<string>Directional light</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="4" colspan="2">
<widget class="QDoubleSpinBox" name="attFac">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>1</number>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
</widget>
</item>
<item row="2" column="4" colspan="2">
<widget class="QDoubleSpinBox" name="ambCoef">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>55</width>
<height>16777215</height>
</size>
</property>
<property name="decimals">
<number>3</number>
</property>
<property name="maximum">
<double>1.000000000000000</double>
</property>
<property name="singleStep">
<double>0.001000000000000</double>
</property>
<property name="value">
<double>0.005000000000000</double>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QSlider" name="light_G_S">
<property name="maximum">
<number>255</number>
</property>
<property name="value">
<number>255</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QLabel" name="labelAmbCoeff">
<property name="text">
<string>Ambientcoefficient:</string>
</property>
</widget>
</item>
<item row="0" column="7" colspan="2">
<widget class="QCheckBox" name="checkHeadlight">
<property name="text">
<string>Headlight</string>
</property>
</widget>
</item>
<item row="0" column="4" colspan="3">
<widget class="QRadioButton" name="radioPointLight">
<property name="text">
<string>Point light</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupGeneral">
<property name="title">
<string>General</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="1" column="3">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labelZoomSpeed">
<property name="text">
<string>Zoom speed:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSpinBox" name="spinZSpeed">
<property name="suffix">
<string>%</string>
</property>
<property name="maximum">
<number>200</number>
</property>
<property name="singleStep">
<number>10</number>
</property>
<property name="value">
<number>100</number>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QCheckBox" name="checkBackfaceCulling">
<property name="text">
<string>Backface Culling</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

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

@ -0,0 +1,27 @@
#pragma once
#include <QWidget>
#include "ui_FileInfoWindow.h"
class FileInfoWindow : public QWidget
{
Q_OBJECT
public:
FileInfoWindow(QWidget *parent = Q_NULLPTR)
: QWidget(parent)
, ui(new Ui::FileInfoWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint);
ui->scrollArea->widget()->setStyleSheet("background-color: #ffffff");
};
~FileInfoWindow() { delete ui; };
private:
Ui::FileInfoWindow* ui;
public:
void setBasicText(QString text) { ui->basic->setText(text); };
void setDetailText(QString text) { ui->detail->setText(text); };
};

View File

@ -0,0 +1,136 @@
#pragma once
#include <QOpenGlTexture>
#include <QFile>
#include <QVector>
#include <QVector2D>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QRegExp>
struct BoundingBox {
QQuaternion rotation;
QVector3D center;
QVector3D extents;
};
struct VertexData
{
QVector3D position;
QVector2D texCoord;
QVector3D vertexNormal;
QVector3D polygonNormal;
QVector3D tangent;
QVector3D bitangent;
};
struct Segment {
quint32 textureIndex = 0;
QVector<VertexData> vertices;
QVector<GLuint> indices;
};
struct Model {
QString name = "";
QString parent = "";
QMatrix4x4 m4x4Translation;
QQuaternion quadRotation;
QVector<Segment*> segmList;
};
struct Material {
QString name;
QString tx0d;
QString tx1d;
QString tx2d;
QString tx3d;
QOpenGLTexture* texture0 = Q_NULLPTR;
QOpenGLTexture* texture1 = Q_NULLPTR;
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 = 1;
bool flags[8] = { false };
bool transparent = false;
quint8 rendertype = 0;
quint8 dataValues[2] = { 0 };
};
class FileInterface
{
public:
explicit FileInterface(QString path)
: m_models(new QVector<Model*>)
, m_materials(new QVector<Material>)
{
//open file
m_file.setFileName(path);
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("/|\\\\")));
};
virtual ~FileInterface()
{
// close file
m_file.close();
//clean up
for (Model* modelIt : *m_models)
{
for (Segment* segIt : modelIt->segmList)
{
segIt->indices.clear();
segIt->vertices.clear();
delete segIt;
}
modelIt->segmList.clear();
delete modelIt;
}
m_models->clear();
delete m_models;
};
protected:
QVector<Model*>* m_models;
QFile m_file;
QVector<Material>* m_materials;
BoundingBox m_sceneBbox;
QString m_filepath;
virtual void import() = 0;
public:
virtual QVector<Model*>* getModels() const { return m_models; };
virtual QVector<Material>* getMaterials() const { return m_materials; };
virtual BoundingBox getBoundingBox() const { return m_sceneBbox; };
static Material* getDefaultMaterial() {
Material* defMaterial = new Material;
QImage img(1, 1, QImage::Format_RGB32);
img.fill(Qt::red);
QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored());
// Set nearest filtering mode for texture minification
new_texture->setMinificationFilter(QOpenGLTexture::Nearest);
// Set bilinear filtering mode for texture magnification
new_texture->setMagnificationFilter(QOpenGLTexture::Linear);
// Wrap texture coordinates by repeating
// f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
new_texture->setWrapMode(QOpenGLTexture::Repeat);
defMaterial->texture0 = new_texture;
defMaterial->name = "Default Material";
return defMaterial;
};
};

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

@ -0,0 +1,48 @@
#pragma once
#include <QObject>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QVector>
#include "FileInterface.h"
struct DrawInformation {
unsigned int offset;
unsigned int size;
unsigned int textureIndex;
QMatrix4x4 modelMatrix;
};
class GeometryEngine : public QObject, protected QOpenGLFunctions
{
Q_OBJECT
public:
GeometryEngine(QObject *parent = Q_NULLPTR);
virtual ~GeometryEngine();
// attributes
private:
QOpenGLBuffer m_arrayBuf;
QOpenGLBuffer m_indexBuf;
QVector<Material>* m_materials = Q_NULLPTR;
Material* m_defaultMaterial;
BoundingBox m_boundings;
QVector<DrawInformation> m_drawList;
// functions
private:
void clearData();
void setupPipeline(QOpenGLShaderProgram * program);
public:
void drawGeometry(QOpenGLShaderProgram *program);
void loadFile(QString filePath);
// signals
signals:
void requestResetView();
void requestUpdate();
};

View File

@ -0,0 +1,50 @@
#pragma once
#include <QtWidgets/QMainWindow>
#include <QWidget>
#include "ui_MainWindow.h"
#include "FileInfoWindow.h"
#include <QByteArray>
#include <QLabel>
struct Material;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = Q_NULLPTR);
~MainWindow();
// attributes
private:
Ui::MainWindowClass* ui;
QByteArray m_fileInfo;
QLabel* m_output;
int m_curSeverity;
FileInfoWindow* m_infoWindow;
// functions
private:
void setupWidgets();
void getAssetLibrary();
void searchMeshFiles(QString path);
void openFile();
void takeScreenShot();
void aboutTool();
protected:
virtual void resizeEvent(QResizeEvent * e) Q_DECL_OVERRIDE;
// slots
public slots:
void printMessage(QString message, int severity);
void setFileInfo(QString name, QVector<Material>* materials, int vertices, int triangle);
// signals
signals:
void loadFile(QString);
};

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

@ -0,0 +1,50 @@
#pragma once
#include "..\Header\FileInterface.h"
#include <QList>
struct ChunkHeader {
QString name;
quint32 size;
qint64 position;
};
enum ModelTyp {
null,
dynamicMesh,
cloth,
bone,
staticMesh,
shadowMesh = 6
};
class MshFile : public FileInterface
{
public:
explicit MshFile(QString path);
virtual ~MshFile();
private:
ModelTyp m_currentType = ModelTyp::null;
std::int32_t m_currentRenderFlag = -1;
virtual void import() Q_DECL_OVERRIDE Q_DECL_FINAL;
void loadChunks(QList<ChunkHeader*> &destination, qint64 start, const quint32 length);
void analyseMsh2Chunks(QList<ChunkHeader*> &chunkList);
void analyseMatdChunks(QList<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, qint64 position);
void readUV(Segment* dataDestination, qint64 position);
void loadTexture(QOpenGLTexture*& destination, QString filepath, QString& filename);
QMatrix4x4 getParentMatrix(QString parent) const;
QQuaternion getParentRotation(QString parent) const;
};

View File

@ -0,0 +1,99 @@
#pragma once
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QMatrix4x4>
#include "GeometryEngine.h"
#include "SettingsWindow.h"
#include "CameraInterface.h"
class GeometryEngine;
class OglViewerWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit OglViewerWidget(QWidget *parent = 0);
~OglViewerWidget();
// attributes
private:
QOpenGLShaderProgram m_program;
GeometryEngine *m_dataEngine;
QVector4D m_backgroundColorOn;
QVector4D m_backgroundColorOff;
bool m_wireframe;
bool m_lightOn;
bool m_backfaceCulling;
struct {
QVector4D position;
QVector3D intensities;
float attenuationFactor;
float ambientCoefficient;
bool headlight;
} m_light;
struct {
bool left = false;
bool right = false;
QVector2D position;
} m_mouse;
QMatrix4x4 m_projection;
CameraInterface* m_camera;
SettingsWindow* m_settings;
// functions
private:
void setDefaultValues();
void initShaders();
void resetView();
void updateLightPosition();
protected:
void initializeGL() Q_DECL_OVERRIDE;
void resizeGL(int w, int h) Q_DECL_OVERRIDE;
void paintGL() Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
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;
// slots
public slots:
void loadFile(QString name);
void useFreeCamera();
void useOrbitCamera();
void useMoveCamera();
void toggleWireframe();
void toggleLight();
void showSettings();
void setBGColorOff(QVector3D value);
void setBGColorOn(QVector3D value);
void setLightColor(QVector3D value);
void setAttFac(double value);
void setAmbCoef(double value);
void setHeadlight(bool value);
void setBackfaceCulling(bool value);
// 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,32 @@
#pragma once
#include <QObject>
struct Material;
class OutputDevice : public QObject
{
Q_OBJECT
private:
OutputDevice(QObject *parent = Q_NULLPTR) : QObject(parent) {};
public:
OutputDevice(OutputDevice const&) = delete;
void operator=(OutputDevice const&) = delete;
~OutputDevice() {};
static OutputDevice* getInstance(QObject *parent = Q_NULLPTR) {
static OutputDevice* instance = new OutputDevice(parent);
return instance;
};
void print(QString message, int severity) { emit sendMessage(message, severity); };
void setFileInfo(QString name, QVector<Material>* materials, int vertices, int triangle) {
emit sendFileInfo(name, materials, vertices, triangle);
};
signals:
void sendMessage(QString message, int severity);
void sendFileInfo(QString name, QVector<Material>* materials, int vertices, int triangle);
};

View File

@ -0,0 +1,38 @@
#pragma once
#ifdef _DEBUG
#include <QElapsedTimer.h>
#include <QString>
#include <iostream>
#define TIC(val) Profiler::getInstance().startTimer(val);
#define TOC(val) Profiler::getInstance().takeTime(val);
class Profiler
{
private:
Profiler() { timer.start(); };
QElapsedTimer timer;
public:
~Profiler() {};
static Profiler& getInstance() {
static Profiler instance;
return instance;
}
void startTimer(QString position = "") {
std::cout << "from: " << position.toStdString() << std::endl;
timer.restart();
};
void takeTime(QString position = "") {
std::cout << "to: "<< position.toStdString() << " time elapsed: " << timer.elapsed() << std::endl;
};
};
#else
#define TIC(val)
#define TOC(val)
#endif

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

@ -0,0 +1,38 @@
#pragma once
#include <QWidget>
#include "ui_SettingsWindow.h"
#include <QVector3D>
class SettingsWindow : public QWidget
{
Q_OBJECT
public:
SettingsWindow(QWidget * parent = Q_NULLPTR);
~SettingsWindow();
private:
Ui::SettingsWindow* ui;
void setupConnections();
private slots:
void autoColorToggled();
void radioToggled();
void backgroundColorOffChanged();
void backgroundColorOnChanged();
void lightColorChanged();
signals:
void updateBGColorOff(QVector3D value);
void updateBGColorOn(QVector3D value);
void updateLightColor(QVector3D value);
void updateAttFac(double value);
void updateAmbCoef(double value);
void sendHeadlight(bool value);
void sendBackfaceCulling(bool value);
void sendZommSpeed(int percent);
void changeLightType(int value);
};

128
QtMeshViewer/Header/tga.h Normal file
View File

@ -0,0 +1,128 @@
#pragma once
#include "OutputDevice.h"
#include <QImage>
#include <QColor>
#include <QVector>
#include <QFile>
QImage loadTga(QString filePath, bool &success)
{
QImage img;
success = true;
// open the file
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
{
success = false;
}
else
{
// 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;
}
}
if (file.isOpen())
file.close();
return qMove(img).rgbSwapped();
}

View File

@ -0,0 +1,28 @@
<RCC>
<qresource prefix="/shaders">
<file>fshader.glsl</file>
<file>vshader.glsl</file>
</qresource>
<qresource prefix="/images">
<file>icon.ico</file>
</qresource>
<qresource prefix="/files">
<file>about.txt</file>
<file>StyleSheet.txt</file>
</qresource>
<qresource prefix="/images/toolbar">
<file>placeholder.png</file>
<file>info.png</file>
<file>about.png</file>
<file>open.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>settings.png</file>
<file>freeCamera.png</file>
<file>orbitalCamera.png</file>
<file>walkCamera.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,79 @@
QLabel#output {
color : white;
min-width: 400px;
min-height: 50px;
}
QToolButton {
image: url(:/images/toolbar/placeholder.png);
border-style: none;
padding: 2px;
width: 22px;
height: 22px;
}
QToolButton:checked {
image: url(:/images/toolbar/placeholder.png);
border-style: none;
padding: 2px;
width: 22px;
height: 22px;
}
QToolButton:hover {
border-style: solid;
padding: 1px;
border-width: 1px;
border-radius: 5px;
border-color: #a4daff;
min-height: 25px
}
QToolButton#openFile {
image: url(:/images/toolbar/open.png);
}
QToolButton#screenshot {
image: url(:/images/toolbar/screenshot.png);
}
QToolButton#freeCamera {
image: url(:/images/toolbar/freeCamera.png);
}
QToolButton#orbitalCamera {
image: url(:/images/toolbar/orbitalCamera.png);
}
QToolButton#walkCamera {
image: url(:/images/toolbar/walkCamera.png);
}
QToolButton#wireframe {
image: url(:/images/toolbar/solid.png);
}
QToolButton#wireframe:checked {
image: url(:/images/toolbar/wireframe.png);
}
QToolButton#light {
image: url(:/images/toolbar/light_off.png);
}
QToolButton#light:checked {
image: url(:/images/toolbar/light_on.png);
}
QToolButton#settings {
image: url(:/images/toolbar/settings.png);
}
QToolButton#fileInfo {
image: url(:/images/toolbar/info.png);
}
QToolButton#help {
image: url(:/images/toolbar/about.png);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 932 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

View File

@ -0,0 +1,37 @@
This is a viewer for .msh files made by Anakin.
questions, bug reports, requests: http://www.gametoast.com/viewtopic.php?f=29&t=32624
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
using the X, Y, Z buttons you can activate/deactivate the rotating directions.
tipp: do round movement to rotate the object in z-direction, when all directions are acitvated
textures marked with a '*' couldn't be open.
===============================================================
Credits:
ANDEWEGET
opengl.org
forum.qt.io

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

View File

@ -0,0 +1,127 @@
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif
uniform mat3 normalMatrix;
uniform vec3 cameraPosition;
uniform sampler2D tx0;
uniform sampler2D tx1;
uniform struct Material {
float shininess;
vec3 specularColor;
bool isTransparent;
bool hasSpecularmap;
bool hasNormalmap;
bool isGlow;
} material;
uniform bool useLight;
uniform struct Light {
vec4 position;
vec3 intensities;
float attenuationFactor;
float ambientCoefficient;
} 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(useLight && !material.isGlow)
{
// get the color and undo gamma correction
vec4 surfaceColor = vec4(texture2D(tx0, v_surfaceUV));
surfaceColor.rgb = pow(surfaceColor.rgb, vec3(2.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);
// 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 component
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
/////////////////////////////////////////////////////////////////////////////////////
// specular component
float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0)
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
vec3 linearColor = ambient + attenuation * (diffuse + specular);
/////////////////////////////////////////////////////////////////////////////////////
// gama correction
vec3 gamma = vec3(1.0/2.2);
if(!material.isTransparent)
surfaceColor.a = 1.0;
gl_FragColor = vec4(pow(linearColor, gamma), surfaceColor.a);
}
// don't use light
else
{
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: 264 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

View File

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "icon.ico"

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

View File

@ -0,0 +1,38 @@
#ifdef GL_ES
// Set default precision to medium
precision mediump int;
precision mediump float;
#endif
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 = 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(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

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 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

@ -0,0 +1,265 @@
#include "..\Header\GeometryEngine.h"
#include "..\Header\MshFile.h"
#include "..\Header\OglViewerWidget.h"
#include "..\Header\MainWindow.h"
#include "..\Header\OutputDevice.h"
#include <QRegExp>
/////////////////////////////////////////////////////////////////////////
// constructor/destructor
GeometryEngine::GeometryEngine(QObject *parent)
: QObject(parent)
, m_indexBuf(QOpenGLBuffer::IndexBuffer)
, m_defaultMaterial(FileInterface::getDefaultMaterial())
{
initializeOpenGLFunctions();
}
GeometryEngine::~GeometryEngine()
{
clearData();
delete m_defaultMaterial->texture0;
delete m_defaultMaterial;
}
/////////////////////////////////////////////////////////////////////////
// functions
void GeometryEngine::clearData()
{
if (m_arrayBuf.isCreated())
m_arrayBuf.destroy();
if (m_indexBuf.isCreated())
m_indexBuf.destroy();
if (m_materials != Q_NULLPTR)
{
for (auto it : *m_materials)
{
if (it.texture0 != Q_NULLPTR)
delete it.texture0;
if (it.texture1 != Q_NULLPTR)
delete it.texture1;
}
m_materials->clear();
delete m_materials;
}
m_drawList.clear();
}
void GeometryEngine::setupPipeline(QOpenGLShaderProgram *program)
{
// Offset for position
quintptr offset = 0;
// Tell OpenGL programmable pipeline how to locate vertex position data
int vertexLocation = program->attributeLocation("a_position");
program->enableAttributeArray(vertexLocation);
program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData));
// Offset for texture coordinate
offset += sizeof(QVector3D);
// Tell OpenGL programmable pipeline how to locate vertex texture coordinate data
int texcoordLocation = program->attributeLocation("a_texcoord");
program->enableAttributeArray(texcoordLocation);
program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData));
//Offset for vertexNormal
offset += sizeof(QVector2D);
// Tell OpenGL programmable pipeline how to locate vertex normal data
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(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(0);
tmp_transparent = m_defaultMaterial->transparent;
}
// Set model matrix
program->setUniformValue("modelMatrix", it.modelMatrix);
// Set normal matrix
program->setUniformValue("normalMatrix", (normMatrix * it.modelMatrix).normalMatrix());
// set some material attributes
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)));
}
}
void GeometryEngine::loadFile(QString filePath)
{
// cleanup old stuff and recreate buffers
clearData();
m_arrayBuf.create();
m_indexBuf.create();
//reset view
emit requestResetView();
OutputDevice::getInstance()->print("loading file..", 0);
try
{
QVector<Model*>* models;
QVector<VertexData> vertexData;
QVector<GLuint> indexData;
// open file and get the information
MshFile file(filePath);
models = file.getModels();
m_materials = file.getMaterials();
m_boundings = file.getBoundingBox();
// collect data
unsigned int indexOffset(0);
unsigned int vertexOffset(0);
for (auto& modelIterator : *models)
{
for (auto& segmentIterator : modelIterator->segmList)
{
// get draw information
DrawInformation new_info;
new_info.offset = indexOffset;
new_info.size = segmentIterator->indices.size();
new_info.textureIndex = segmentIterator->textureIndex;
new_info.modelMatrix = modelIterator->m4x4Translation;
new_info.modelMatrix.rotate(modelIterator->quadRotation);
// add offset to indices, no need to do it for the first one (maybe it's very big)
if (vertexOffset != 0)
for (auto& it : segmentIterator->indices)
it += vertexOffset;
// save data
vertexData += segmentIterator->vertices;
indexData += segmentIterator->indices;
if (segmentIterator->textureIndex < (unsigned) m_materials->size() && m_materials->at(segmentIterator->textureIndex).transparent)
m_drawList.push_back(new_info);
else
m_drawList.push_front(new_info);
// update offset
indexOffset += new_info.size;
vertexOffset += segmentIterator->vertices.size();
}
}
// Transfer vertex data to VBO 0
m_arrayBuf.bind();
m_arrayBuf.allocate(vertexData.data(), vertexData.size() * sizeof(VertexData));
// Transfer index data to VBO 1
m_indexBuf.bind();
m_indexBuf.allocate(indexData.data(), indexData.size() * sizeof(GLuint));
emit requestUpdate();
OutputDevice::getInstance()->print("done..", 0);
OutputDevice::getInstance()->setFileInfo(filePath.right(filePath.size() - filePath.lastIndexOf(QRegExp("/|\\\\")) - 1), m_materials, vertexData.size(), indexData.size() / 3);
}
catch (std::invalid_argument e)
{
clearData();
OutputDevice::getInstance()->print(QString(e.what()), 2);
}
}

View File

@ -0,0 +1,376 @@
#include "..\Header\MainWindow.h"
#include "..\Header\OglViewerWidget.h"
#include "..\Header\FileInterface.h"
#include "..\Header\OutputDevice.h"
#include <QSurfaceFormat>
#include <QSignalMapper>
#include <QToolButton>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QPalette>
#include <QResizeEvent>
#define WINDOW_NAME "Mesh Viewer"
/////////////////////////////////////////////////////////////////////////
// constructor/destructor
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindowClass)
, m_output(new QLabel(this))
, m_curSeverity(0)
, m_infoWindow(new FileInfoWindow(this))
{
// setup window
ui->setupUi(this);
setWindowTitle(WINDOW_NAME);
setWindowIcon(QIcon(":/images/icon.ico"));
connect(OutputDevice::getInstance(this), &OutputDevice::sendMessage, this, &MainWindow::printMessage);
connect(OutputDevice::getInstance(this), &OutputDevice::sendFileInfo, this, &MainWindow::setFileInfo);
// setup opengl things
QSurfaceFormat format;
format.setDepthBufferSize(24);
QSurfaceFormat::setDefaultFormat(format);
// set default text to file info
m_fileInfo = "Filename: -\nMaterials: -\nVertices: -\nTriangle: -<detail>No file is open";
// add widgets to the window
setupWidgets();
// load stylesheet
QFile styleSheet(":/files/StyleSheet.txt");
styleSheet.open(QIODevice::ReadOnly);
this->setStyleSheet(styleSheet.readAll());
getAssetLibrary();
printMessage("MeshViewer by Anakin", 0);
}
MainWindow::~MainWindow()
{
delete ui;
delete m_output;
delete m_infoWindow;
}
/////////////////////////////////////////////////////////////////////////
// functions
void MainWindow::setupWidgets()
{
// Ogl Viewer
OglViewerWidget* viewer = new OglViewerWidget(this);
setCentralWidget(viewer);
connect(this, &MainWindow::loadFile, viewer, &OglViewerWidget::loadFile);
// open file
QToolButton *openFile = new QToolButton(this);
openFile->setObjectName("openFile");
openFile->setToolTip("open file");
connect(openFile, &QToolButton::pressed, this, &MainWindow::openFile);
ui->mainToolBar->addWidget(openFile);
// screenshot
QToolButton *screenshot = new QToolButton(this);
screenshot->setObjectName("screenshot");
screenshot->setToolTip("take screenshot");
connect(screenshot, &QToolButton::pressed, this, &MainWindow::takeScreenShot);
ui->mainToolBar->addWidget(screenshot);
//////////////////////////////////////////////////
ui->mainToolBar->addSeparator();
// 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);
// 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);
// 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();
// wireframe
QToolButton *wireframe = new QToolButton(this);
wireframe->setObjectName("wireframe");
wireframe->setToolTip("wireframe");
wireframe->setCheckable(true);
wireframe->setChecked(false);
connect(wireframe, &QToolButton::pressed, viewer, &OglViewerWidget::toggleWireframe);
ui->mainToolBar->addWidget(wireframe);
// light
QToolButton *light = new QToolButton(this);
light->setObjectName("light");
light->setToolTip("toggle light");
light->setCheckable(true);
light->setChecked(false);
connect(light, &QToolButton::pressed, viewer, &OglViewerWidget::toggleLight);
ui->mainToolBar->addWidget(light);
// settings
QToolButton *settings = new QToolButton(this);
settings->setObjectName("settings");
settings->setToolTip("settings");
connect(settings, &QToolButton::pressed, viewer, &OglViewerWidget::showSettings);
ui->mainToolBar->addWidget(settings);
//////////////////////////////////////////////////
ui->mainToolBar->addSeparator();
// fileinfo
QToolButton *fileInfo = new QToolButton(this);
fileInfo->setObjectName("fileInfo");
fileInfo->setToolTip("file info");
connect(fileInfo, &QToolButton::pressed, m_infoWindow, &FileInfoWindow::show);
ui->mainToolBar->addWidget(fileInfo);
// help
QToolButton *help = new QToolButton(this);
help->setObjectName("help");
help->setToolTip("help");
connect(help, &QToolButton::pressed, this, &MainWindow::aboutTool);
ui->mainToolBar->addWidget(help);
// output on screen
m_output->setObjectName("output");
m_output->setAlignment(Qt::AlignTop);
m_output->setText(m_fileInfo.left(m_fileInfo.indexOf("<detail>")));
m_output->raise();
}
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)");
if(!fileName.isEmpty())
emit loadFile(fileName);
}
void MainWindow::takeScreenShot()
{
QString destination = QFileDialog::getSaveFileName(this, "Save as...", "", "PNG (*.png);; BMP (*.bmp);;TIFF (*.tiff, *.tif);;JPEG (*.jpg *jpeg)");
OglViewerWidget* viewer = dynamic_cast<OglViewerWidget*>(centralWidget());
if (!destination.isEmpty() && viewer != NULL)
viewer->grab().save(destination);
}
void MainWindow::aboutTool()
{
QFile file(":/files/about.txt");
file.open(QIODevice::ReadOnly);
QMessageBox* dialog = new QMessageBox(
QMessageBox::Question,
WINDOW_NAME,
QString(file.readAll()),
QMessageBox::StandardButton::Close,
this,
Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
file.close();
dialog->exec();
delete dialog;
}
void MainWindow::resizeEvent(QResizeEvent * e)
{
m_output->move(40, e->size().height() - 80);
}
/////////////////////////////////////////////////////////////////////////
// slots
void MainWindow::printMessage(QString message, int severity)
{
if (!ui->statusBar->currentMessage().isEmpty() && severity < m_curSeverity)
return;
m_curSeverity = severity;
int time(0);
QPalette palette;
switch (severity)
{
case 1:
time = 3000;
palette.setColor(QPalette::WindowText, Qt::darkYellow);
break;
case 2:
time = 3000;
palette.setColor(QPalette::WindowText, Qt::red);
break;
case 0:
default:
time = 2000;
palette.setColor(QPalette::WindowText, Qt::black);
break;
}
ui->statusBar->setPalette(palette);
ui->statusBar->showMessage(message, time);
}
void MainWindow::setFileInfo(QString name, QVector<Material>* materials, int vertices, int triangle)
{
// save basic file information
m_fileInfo = QByteArray("Filename: ");
m_fileInfo += name;
m_fileInfo += "\nMaterials: ";
m_fileInfo += QByteArray::number(materials->size());
m_fileInfo += "\nVertices: ";
m_fileInfo += QByteArray::number(vertices);
m_fileInfo += "\nTriangle: ";
m_fileInfo += QByteArray::number(triangle);
m_fileInfo += "<detail>";
// add detailed information
for (auto& it : *materials)
{
m_fileInfo += it.name;
m_fileInfo += "\n";
m_fileInfo += "TX0D:\t\t";
if (it.tx0d.isEmpty())
m_fileInfo += "-";
else
m_fileInfo += it.tx0d;
m_fileInfo += "\n";
m_fileInfo += "TX1D:\t\t";
if (it.tx1d.isEmpty())
m_fileInfo += "-";
else
m_fileInfo += it.tx1d;
m_fileInfo += "\n";
m_fileInfo += "TX2D:\t\t";
if (it.tx2d.isEmpty())
m_fileInfo += "-";
else
m_fileInfo += it.tx2d;
m_fileInfo += "\n";
m_fileInfo += "TX3D:\t\t";
if (it.tx3d.isEmpty())
m_fileInfo += "-";
else
m_fileInfo += it.tx3d;
m_fileInfo += "\n";
m_fileInfo += "Flags:\t\t";
for (int i = 0; i < 8; i++)
{
if (it.flags[i])
m_fileInfo += "1";
else
m_fileInfo += "0";
}
m_fileInfo += "\n";
m_fileInfo += "Rendertype:\t";
m_fileInfo += QByteArray::number(it.rendertype);
m_fileInfo += "\n";
m_fileInfo += "Gloss:\t";
m_fileInfo += QByteArray::number(it.shininess);
m_fileInfo += "\tData0:\t";
m_fileInfo += QByteArray::number(it.dataValues[0]);
m_fileInfo += "\tData1:\t";
m_fileInfo += QByteArray::number(it.dataValues[1]);
m_fileInfo += "\n";
m_fileInfo += "Diffusecolor:\tR: ";
m_fileInfo += QByteArray::number(it.diffuseColor.x());
m_fileInfo += "\tG: ";
m_fileInfo += QByteArray::number(it.diffuseColor.y());
m_fileInfo += "\tB: ";
m_fileInfo += QByteArray::number(it.diffuseColor.z());
m_fileInfo += "\tA: ";
m_fileInfo += QByteArray::number(it.diffuseColor.w());
m_fileInfo += "\n";
m_fileInfo += "Ambientcolor:\tR: ";
m_fileInfo += QByteArray::number(it.ambientColor.x());
m_fileInfo += "\tG: ";
m_fileInfo += QByteArray::number(it.ambientColor.y());
m_fileInfo += "\tB: ";
m_fileInfo += QByteArray::number(it.ambientColor.z());
m_fileInfo += "\tA: ";
m_fileInfo += QByteArray::number(it.ambientColor.w());
m_fileInfo += "\n";
m_fileInfo += "Specularcolor:\tR: ";
m_fileInfo += QByteArray::number(it.specularColor.x());
m_fileInfo += "\tG: ";
m_fileInfo += QByteArray::number(it.specularColor.y());
m_fileInfo += " \tB: ";
m_fileInfo += QByteArray::number(it.specularColor.z());
m_fileInfo += " \tA: ";
m_fileInfo += QByteArray::number(it.specularColor.w());
m_fileInfo += "\n";
m_fileInfo += "-----------------------------------------------------------------\n";
}
// print basic information on screen
m_output->setText(m_fileInfo.left(m_fileInfo.indexOf("<detail>")));
// print basic and detailed information on info window
m_infoWindow->setBasicText(QString(m_fileInfo.left(m_fileInfo.indexOf("<detail>"))));
m_infoWindow->setDetailText(QString(m_fileInfo.right(m_fileInfo.size() - m_fileInfo.indexOf("<detail>") - 8)));
}

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

@ -0,0 +1,975 @@
#include "..\Header\MshFile.h"
#include "..\Header\tga.h"
#include "..\Header\OutputDevice.h"
#include <QVector3D>
// helper function to save data from file to any variable type
#define F2V(variableName) reinterpret_cast<char*>(&variableName)
/////////////////////////////////////////////////////////////////////////
// public constructor/destructor
MshFile::MshFile(QString path)
: FileInterface(path)
{
import();
}
MshFile::~MshFile()
{
}
/////////////////////////////////////////////////////////////////////////
// private functions
void MshFile::import()
{
// go to file size information
m_file.seek(4);
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.pos(), tmp_fileSize);
// evaulate HEDR subchunks (= find MSH2)
for (ChunkHeader* it : tmp_mainChunks)
{
if ("MSH2" == it->name)
{
// get all subchunks
QList<ChunkHeader*> tmp_msh2Chunks;
loadChunks(tmp_msh2Chunks, it->position, it->size);
// evaluate MSH2 subchunks
analyseMsh2Chunks(tmp_msh2Chunks);
// clean up
while (!tmp_msh2Chunks.empty())
{
ChunkHeader* curs = tmp_msh2Chunks.front();
tmp_msh2Chunks.pop_front();
delete curs;
}
}
}
// clean up
while (!tmp_mainChunks.empty())
{
ChunkHeader* cur = tmp_mainChunks.front();
tmp_mainChunks.pop_front();
delete cur;
}
}
void MshFile::loadChunks(QList<ChunkHeader*>& destination, qint64 start, const quint32 length)
{
// jump to first chunk
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
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.pos();
// store information
destination.push_back(tmp_header);
// jump to next header
m_file.seek(tmp_header->size + m_file.pos());
} while (m_file.pos() - start != length);
}
void MshFile::analyseMsh2Chunks(QList<ChunkHeader*>& chunkList)
{
for (auto& it : chunkList)
{
// scene information
if ("SINF" == it->name)
{
// get SINF subchunks
QList<ChunkHeader*> tmp_sinfChunks;
loadChunks(tmp_sinfChunks, it->position, it->size);
// evaluate SINF subchunks
for (auto& it : tmp_sinfChunks)
{
if ("BBOX" == it->name)
{
m_file.seek(it->position);
// read in the quaternion
float tmp_quat[4];
for (int i = 0; i < 4; i++)
m_file.read(F2V(tmp_quat[i]), sizeof(float));
m_sceneBbox.rotation.setX(tmp_quat[0]);
m_sceneBbox.rotation.setY(tmp_quat[1]);
m_sceneBbox.rotation.setZ(tmp_quat[2]);
m_sceneBbox.rotation.setScalar(tmp_quat[3]);
//read in the center
for (int i = 0; i < 3; i++)
m_file.read(F2V(m_sceneBbox.center[i]), sizeof(float));
//read in the extents
for (int i = 0; i < 3; i++)
m_file.read(F2V(m_sceneBbox.extents[i]), sizeof(float));
}
}
// clean up SINF subchunks
for (ChunkHeader* it : tmp_sinfChunks)
delete it;
}
// material list
else if ("MATL" == it->name)
{
OutputDevice::getInstance()->print("loading materials..", 0);
// "useless" information how many MATD follow, jump over it
m_file.seek(it->position);
m_file.seek(sizeof(quint32) + m_file.pos());
// get all MATL subchunk
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 ("MATD" == it->name)
{
// get all subchunks from MATD
QList<ChunkHeader*> tmp_matdChunks;
loadChunks(tmp_matdChunks, it->position, it->size);
m_materials->push_back(Material());
// analyse MATD subchunks
analyseMatdChunks(tmp_matdChunks);
// clean up MATD subchunks
while (!tmp_matdChunks.empty())
{
ChunkHeader* cur = tmp_matdChunks.front();
tmp_matdChunks.pop_front();
delete cur;
}
}
}
// clean up MATL subchunks
while (!tmp_matlChunks.empty())
{
ChunkHeader* cur = tmp_matlChunks.front();
tmp_matlChunks.pop_front();
delete cur;
}
}
// model
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
QList<ChunkHeader*> tmp_chunks;
loadChunks(tmp_chunks, it->position, it->size);
// evaluate MODL subchunks
analyseModlChunks(new_model, tmp_chunks);
//clean up MODL subchunks
while (!tmp_chunks.empty())
{
ChunkHeader* cur = tmp_chunks.front();
tmp_chunks.pop_front();
delete cur;
}
// save Model data
m_models->push_back(new_model);
}
}
}
void MshFile::analyseMatdChunks(QList<ChunkHeader*>& chunkList)
{
for (auto& it : chunkList)
{
// name
if ("NAME" == it->name)
{
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
m_materials->back().name = buffer;
delete[] buffer;
}
// data
else if("DATA" == it->name)
{
m_file.seek(it->position);
// diffuse
for (unsigned int i = 0; i < 4; i++)
m_file.read(F2V(m_materials->back().diffuseColor[i]), sizeof(float));
// specular
for (unsigned int i = 0; i < 4; i++)
m_file.read(F2V(m_materials->back().specularColor[i]), sizeof(float));
// ambient
for (unsigned int i = 0; i < 4; i++)
m_file.read(F2V(m_materials->back().ambientColor[i]), sizeof(float));
// shininess
m_file.read(F2V(m_materials->back().shininess), sizeof(float));
}
// attributes
else if ("ATRB" == it->name)
{
// get pointer to current material
Material* curMat = &m_materials->back();
// read the attributes
m_file.seek(it->position);
quint8 flag;
m_file.read(F2V(flag), sizeof(flag));
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
// 1: glow
// 2: single-sided transparency
// 3: double-sided transparency
// 4: hard-edged transparency
// 5: per-pixel lighting
// 6: additive transparency
// 7: specular
for (unsigned int i = 0; i < 8; i++)
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 ("TX0D" == it->name)
{
// get the texture name
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
m_materials->back().tx0d = buffer;
delete[] buffer;
// load the texture if the name is not empty
if (!m_materials->back().tx0d.isEmpty())
loadTexture(m_materials->back().texture0, m_filepath, m_materials->back().tx0d);
}
// texture 1
else if ("TX1D" == it->name)
{
// get the texture name
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
m_materials->back().tx1d = buffer;
delete[] buffer;
if (!m_materials->back().tx1d.isEmpty())
loadTexture(m_materials->back().texture1, m_filepath, m_materials->back().tx1d);
}
// texture 2
else if ("TX2D" == it->name)
{
// get the texture name
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
m_materials->back().tx2d = buffer;
delete[] buffer;
}
// texture 3
else if ("TX3D" == it->name)
{
// get the texture name
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
m_materials->back().tx3d = buffer;
delete[] buffer;
}
}
}
void MshFile::analyseModlChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
{
for (auto& it : chunkList)
{
// model type
if ("MTYP" == it->name)
{
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 ("PRNT" == it->name)
{
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
dataDestination->parent = buffer;
delete[] buffer;
}
// model name
else if ("NAME" == it->name)
{
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
dataDestination->name = buffer;
delete[] buffer;
}
// render flags
else if ("FLGS" == it->name)
{
m_file.seek(it->position);
m_file.read(F2V(m_currentRenderFlag), sizeof(m_currentRenderFlag));
}
// translation
else if ("TRAN" == it->name)
{
float tmp_scale[3];
float tmp_rotation[4];
float tmp_trans[3];
m_file.seek(it->position);
// read in the data
for (int i = 0; i < 3; i++)
m_file.read(F2V(tmp_scale[i]), sizeof(float));
for (int i = 0; i < 4; i++)
m_file.read(F2V(tmp_rotation[i]), sizeof(float));
for (int i = 0; i < 3; i++)
m_file.read(F2V(tmp_trans[i]), sizeof(float));
// modify the matrix and quaternion
dataDestination->m4x4Translation.scale(tmp_scale[0], tmp_scale[1], tmp_scale[2]);
dataDestination->m4x4Translation.translate(tmp_trans[0], tmp_trans[1], tmp_trans[2]);
dataDestination->quadRotation.setVector(QVector3D(tmp_rotation[0], tmp_rotation[1], tmp_rotation[2]));
dataDestination->quadRotation.setScalar(tmp_rotation[3]);
dataDestination->m4x4Translation = getParentMatrix(dataDestination->parent) * dataDestination->m4x4Translation;
dataDestination->quadRotation = getParentRotation(dataDestination->parent) * dataDestination->quadRotation;
}
// geometry data
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
QList<ChunkHeader*> tmp_geomChunks;
loadChunks(tmp_geomChunks, it->position, it->size);
// evaluate GEOM subchunks
analyseGeomChunks(dataDestination, tmp_geomChunks);
// clean up GEOM subchunks
while (!tmp_geomChunks.empty())
{
ChunkHeader* cur = tmp_geomChunks.front();
tmp_geomChunks.pop_front();
delete cur;
}
}
}
}
void MshFile::analyseGeomChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
{
for (auto& it : chunkList)
{
// segment
if ("SEGM" == it->name)
{
// get all SEGM subchunks
QList<ChunkHeader*> tmp_segmChunks;
loadChunks(tmp_segmChunks, it->position, it->size);
// evaluate SEGM subchunks
analyseSegmChunks(dataDestination, tmp_segmChunks);
// clean up SEGM subchunk
while (!tmp_segmChunks.empty())
{
ChunkHeader* cur = tmp_segmChunks.front();
tmp_segmChunks.pop_front();
delete cur;
}
}
// cloth
else if ("CLTH" == it->name)
{
// get all CLTH subchunks
QList<ChunkHeader*> tmp_clthChunks;
loadChunks(tmp_clthChunks, it->position, it->size);
// evaluate CLTH subchunks
analyseClthChunks(dataDestination, tmp_clthChunks);
// clean up CLTH subchunks
while (!tmp_clthChunks.empty())
{
ChunkHeader* cur = tmp_clthChunks.front();
tmp_clthChunks.pop_front();
delete cur;
}
}
}
}
void MshFile::analyseSegmChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
{
Segment* new_segment = new Segment;
for (auto& it : chunkList)
{
// material index
if ("MATI" == it->name)
{
m_file.seek(it->position);
m_file.read(F2V(new_segment->textureIndex), sizeof(new_segment->textureIndex));
}
// position list (vertex)
else if ("POSL" == it->name)
{
readVertex(new_segment, it->position);
}
// normals
else if ("NRML" == it->name)
{
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())
{
OutputDevice::getInstance()->print("WARNING: too less normals " + QString::number(tmp_size) + " < " + QString::number(new_segment->vertices.size()), 1);
for (unsigned int i = new_segment->vertices.size(); i != tmp_size; i--)
for (unsigned int j = 0; j < 3; j++)
new_segment->vertices[i - 1].vertexNormal[j] = 0;
}
else if (tmp_size > (unsigned) new_segment->vertices.size())
{
OutputDevice::getInstance()->print("WARNING: too many normals " + QString::number(tmp_size) + " > " + QString::number(new_segment->vertices.size()), 1);
tmp_size = new_segment->vertices.size();
}
for (unsigned int i = 0; i < tmp_size; i++)
for (unsigned int j = 0; j < 3; j++)
m_file.read(F2V(new_segment->vertices[i].vertexNormal[j]), sizeof(float));
}
// uv
else if ("UV0L" == it->name)
{
readUV(new_segment, it->position);
}
// polygons (indices into vertex/uv list)
else if ("STRP" == it->name)
{
// jump to the data section and read the size;
quint32 tmp_size;
m_file.seek(it->position);
m_file.read(F2V(tmp_size), sizeof(tmp_size));
int highBitCount(0);
QVector<GLuint> tmp_buffer;
for (unsigned int i = 0; i < tmp_size; i++)
{
// ReadData
quint16 tmp_value;
m_file.read(F2V(tmp_value), sizeof(tmp_value));
// Check if highbit is set
if (tmp_value >> 15)
{
highBitCount++;
// remove the high bit, to get the actually value
tmp_value = (quint16(tmp_value << 1) >> 1);
}
// save data
tmp_buffer.push_back((GLuint)tmp_value);
// if the last 2 highBits are set, it was a new poly
if (highBitCount == 2)
{
// reset highBitCount
highBitCount = 0;
if (tmp_buffer.size() == 5)
{
// 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++)
{
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);
}
} // if 2 high bits are set
} // for all values
// save the last polygon (no 2 high bit followed)
if (tmp_buffer.size() == 3)
{
// 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++)
{
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);
}
}
}
}
}
}
dataDestination->segmList.push_back(new_segment);
}
void MshFile::analyseClthChunks(Model * dataDestination, QList<ChunkHeader*>& chunkList)
{
Segment* new_segment = new Segment;
for (auto& it : chunkList)
{
// texture name
if ("CTEX" == it->name)
{
// read the texture name
m_file.seek(it->position);
char* buffer = new char[it->size + 1];
*buffer = { 0 };
m_file.read(buffer, it->size);
m_materials->push_back(Material());
m_materials->back().name = "Cloth Material";
m_materials->back().tx0d = QString(buffer);
m_materials->back().shininess = 10;
if (!m_materials->back().tx0d.isEmpty())
loadTexture(m_materials->back().texture0, m_filepath, m_materials->back().tx0d);
new_segment->textureIndex = m_materials->size() - 1;
delete[] buffer;
}
// position list (vertex)
else if ("CPOS" == it->name)
{
readVertex(new_segment, it->position);
}
// uv
else if ("CUV0" == it->name)
{
readUV(new_segment, it->position);
}
// triangles (indices into vertex/uv list)
else if ("CMSH" == it->name)
{
// jump to the data section and read the size;
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; i++)
{
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]);
}
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();
}
}
}
}
dataDestination->segmList.push_back(new_segment);
}
void MshFile::readVertex(Segment * dataDestination, qint64 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++)
{
float tmp[3];
for (unsigned int j = 0; j < 3; j++)
m_file.read(F2V(tmp[j]), sizeof(float));
VertexData new_data;
new_data.position = QVector3D(tmp[0], tmp[1], tmp[2]);
dataDestination->vertices.push_back(new_data);
}
}
void MshFile::readUV(Segment * dataDestination, qint64 position)
{
quint32 tmp_size;
m_file.seek(position);
m_file.read(F2V(tmp_size), sizeof(tmp_size));
if (tmp_size < (unsigned) dataDestination->vertices.size())
{
OutputDevice::getInstance()->print("WARNING: too less UVs " + QString::number(tmp_size) + " < " + QString::number(dataDestination->vertices.size()),1);
for (unsigned int i = dataDestination->vertices.size(); i != tmp_size; i--)
for (unsigned int j = 0; j < 2; j++)
dataDestination->vertices[i - 1].texCoord[j] = 0;
}
else if (tmp_size > (unsigned) dataDestination->vertices.size())
{
OutputDevice::getInstance()->print("WARNING: too many UVs " + QString::number(tmp_size) + " > " + QString::number(dataDestination->vertices.size()), 1);
tmp_size = dataDestination->vertices.size();
}
for (unsigned int i = 0; i < tmp_size; i++)
for (unsigned int j = 0; j < 2; j++)
m_file.read(F2V(dataDestination->vertices[i].texCoord[j]), sizeof(float));
}
void MshFile::loadTexture(QOpenGLTexture *& destination, QString filepath, QString& filename)
{
bool loadSuccess(false);
QImage img = loadTga(filepath + "/" + filename, loadSuccess);
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 += " *";
}
// Load image to OglTexture
QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored());
// Set nearest filtering mode for texture minification
new_texture->setMinificationFilter(QOpenGLTexture::Nearest);
// Set bilinear filtering mode for texture magnification
new_texture->setMagnificationFilter(QOpenGLTexture::Linear);
// Wrap texture coordinates by repeating
// f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
new_texture->setWrapMode(QOpenGLTexture::Repeat);
destination = new_texture;
}
QMatrix4x4 MshFile::getParentMatrix(QString parent) const
{
QMatrix4x4 matrix;
for (auto& it : *m_models)
{
if (parent == it->name)
{
matrix = getParentMatrix(it->parent) * it->m4x4Translation;
break;
}
}
return matrix;
}
QQuaternion MshFile::getParentRotation(QString parent) const
{
QQuaternion rotation;
for (auto& it : *m_models)
{
if (parent == it->name)
{
rotation = getParentRotation(it->parent) * it->quadRotation;
break;
}
}
return rotation;
}

View File

@ -0,0 +1,465 @@
#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>
#include "..\Header\Profiler.h"
#define DEFAULT_Z_DISTANCE -4.0
/////////////////////////////////////////////////////////////////////////
// constructor/destructor
OglViewerWidget::OglViewerWidget(QWidget *parent)
: QOpenGLWidget(parent)
, m_dataEngine(Q_NULLPTR)
, m_camera(new FreeCamera)
{
setFocus();
setAcceptDrops(true);
// settings window
setDefaultValues();
m_settings = new SettingsWindow(this);
connect(m_settings, &SettingsWindow::updateBGColorOff, this, &OglViewerWidget::setBGColorOff);
connect(m_settings, &SettingsWindow::updateBGColorOn, this, &OglViewerWidget::setBGColorOn);
connect(m_settings, &SettingsWindow::updateLightColor, this, &OglViewerWidget::setLightColor);
connect(m_settings, &SettingsWindow::updateAttFac, this, &OglViewerWidget::setAttFac);
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](int value) {m_camera->setZoomSpeed(value); });
}
OglViewerWidget::~OglViewerWidget()
{
// Make sure the context is current when deleting the texture
// and the buffers.
makeCurrent();
delete m_dataEngine;
doneCurrent();
delete m_camera;
delete m_settings;
}
/////////////////////////////////////////////////////////////////////////
// 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
if (!m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl"))
close();
// Compile fragment shader
if (!m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl"))
close();
// Link shader pipeline
if (!m_program.link())
close();
// Bind shader pipeline for use
if (!m_program.bind())
close();
}
void OglViewerWidget::resetView()
{
m_camera->resetView();
if (m_light.headlight)
updateLightPosition();
update();
}
void OglViewerWidget::updateLightPosition()
{
QVector4D lightPosition = { 0,0,0,1 };
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 ///////////////////////////////////////////////////////////////
void OglViewerWidget::initializeGL()
{
initializeOpenGLFunctions();
initShaders();
// Enable depth buffer
glEnable(GL_DEPTH_TEST);
// Enable transparency
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_dataEngine = new GeometryEngine(this);
connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView);
connect(m_dataEngine, &GeometryEngine::requestUpdate, this, static_cast<void(OglViewerWidget::*)(void)>(&OglViewerWidget::update));
}
void OglViewerWidget::resizeGL(int w, int h)
{
// Calculate aspect ratio
qreal aspect = qreal(w) / qreal(h ? h : 1);
// Set near plane to 3.0, far plane to 7.0, field of view 45 degrees
const qreal zNear = 0.1, zFar = 100.0, fov = 45.0;
// Reset projection
m_projection.setToIdentity();
// Set perspective projection
m_projection.perspective(fov, aspect, zNear, zFar);
}
void OglViewerWidget::paintGL()
{
// set background color, last value is dirtybit
if (m_lightOn && m_backgroundColorOn[3] == 1.0)
{
glClearColor(m_backgroundColorOn[0], m_backgroundColorOn[1], m_backgroundColorOn[2], 0.0000f);
m_backgroundColorOn[3] = 0.0;
}
else if (!m_lightOn && m_backgroundColorOff[3] == 1.0)
{
glClearColor(m_backgroundColorOff[0], m_backgroundColorOff[1], m_backgroundColorOff[2], 0.0000f);
m_backgroundColorOff[3] = 0.0;
}
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Set view-projection matrix
m_program.setUniformValue("viewProjection", m_projection * m_camera->getMatrix());
// Set Light values
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
m_program.setUniformValue("cameraPosition", (m_camera->getMatrix().inverted() * QVector4D(0,0,0,1)).toVector3D());
// Draw cube geometry
if (m_backfaceCulling)
glEnable(GL_CULL_FACE);
if (m_wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
m_dataEngine->drawGeometry(&m_program);
glDisable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
// Inputs ///////////////////////////////////////////////////////////////
void OglViewerWidget::mousePressEvent(QMouseEvent *e)
{
// Save mouse press position
m_mouse.position = QVector2D(e->localPos());
// Which button has been pressed?
if (e->button() == Qt::LeftButton)
m_mouse.left = true;
else if (e->button() == Qt::RightButton)
m_mouse.right = true;
}
void OglViewerWidget::mouseReleaseEvent(QMouseEvent *e)
{
if (e->button() == Qt::LeftButton)
m_mouse.left = false;
else if (e->button() == Qt::RightButton)
m_mouse.right = false;
}
void OglViewerWidget::mouseMoveEvent(QMouseEvent *e)
{
if (m_mouse.left)
{
// get the difference between last press and now
m_camera->rotateAction(QVector2D(e->localPos()) - m_mouse.position);
// update the new position
m_mouse.position = QVector2D(e->localPos());
// request an update
if (m_light.headlight)
updateLightPosition();
update();
}
else if (m_mouse.right)
{
// get the difference between last press and now
m_camera->moveAction(QVector2D(e->localPos()) - m_mouse.position);
// update the new position
m_mouse.position = QVector2D(e->localPos());
// request an update
if (m_light.headlight)
updateLightPosition();
update();
}
}
void OglViewerWidget::wheelEvent(QWheelEvent *e)
{
m_camera->wheelAction(e->angleDelta().y());
if (m_light.headlight)
updateLightPosition();
update();
}
void OglViewerWidget::keyPressEvent(QKeyEvent *e)
{
if (e->key() == Qt::Key_Space)
{
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();
}
else if (e->key() == Qt::Key_L)
{
updateLightPosition();
update();
}
}
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())
if(e->mimeData()->urls().size() == 1)
if(e->mimeData()->urls().first().toLocalFile().endsWith(".msh"))
e->acceptProposedAction();
}
void OglViewerWidget::dropEvent(QDropEvent * e)
{
m_dataEngine->loadFile(e->mimeData()->urls().first().toLocalFile());
}
/////////////////////////////////////////////////////////////////////////
// public slots
void OglViewerWidget::loadFile(QString name)
{
m_dataEngine->loadFile(name);
}
void OglViewerWidget::useFreeCamera()
{
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()
{
m_wireframe = !m_wireframe;
update();
}
void OglViewerWidget::toggleLight()
{
m_lightOn = !m_lightOn;
if (m_lightOn)
{
m_backgroundColorOn[3] = 1.0;
updateLightPosition();
}
else
{
m_backgroundColorOff[3] = 1.0;
}
emit lightChanged(m_lightOn);
update();
}
void OglViewerWidget::showSettings()
{
m_settings->show();
}
void OglViewerWidget::setBGColorOff(QVector3D value)
{
m_backgroundColorOff = QVector4D(value / 255, 1.0f);
if (!m_lightOn)
update();
}
void OglViewerWidget::setBGColorOn(QVector3D value)
{
m_backgroundColorOn = QVector4D(value / 255, 1.0f);
if (m_lightOn)
update();
}
void OglViewerWidget::setLightColor(QVector3D value)
{
m_light.intensities = value / 255;
if (m_lightOn)
update();
}
void OglViewerWidget::setAttFac(double value)
{
m_light.attenuationFactor = (float)value;
if (m_lightOn)
update();
}
void OglViewerWidget::setAmbCoef(double value)
{
m_light.ambientCoefficient = (float)value;
if (m_lightOn)
update();
}
void OglViewerWidget::setHeadlight(bool value)
{
m_light.headlight = value;
if (m_lightOn && value)
{
updateLightPosition();
update();
}
}
void OglViewerWidget::setBackfaceCulling(bool value)
{
m_backfaceCulling = value;
update();
}

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

@ -0,0 +1,183 @@
#include "..\Header\SettingsWindow.h"
#include "..\Header\SettingsManager.h"
/////////////////////////////////////////////////////////////////////////
// constructor/destructor
SettingsWindow::SettingsWindow(QWidget * parent)
: QWidget(parent)
, ui(new Ui::SettingsWindow)
{
ui->setupUi(this);
setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint);
setupConnections();
// set default values
SettingsManager* sm = SettingsManager::getInstance(this);
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->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->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->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);
}
SettingsWindow::~SettingsWindow()
{
delete ui;
}
/////////////////////////////////////////////////////////////////////////
// functions
void SettingsWindow::setupConnections()
{
// light off
connect(ui->lightOff_R_SB, SIGNAL(valueChanged(int)), ui->lightOff_R_S, SLOT(setValue(int)));
connect(ui->lightOff_R_S, SIGNAL(valueChanged(int)), ui->lightOff_R_SB, SLOT(setValue(int)));
connect(ui->lightOff_R_S, &QSlider::valueChanged, this, &SettingsWindow::backgroundColorOffChanged);
connect(ui->lightOff_G_SB, SIGNAL(valueChanged(int)), ui->lightOff_G_S, SLOT(setValue(int)));
connect(ui->lightOff_G_S, SIGNAL(valueChanged(int)), ui->lightOff_G_SB, SLOT(setValue(int)));
connect(ui->lightOff_G_S, &QSlider::valueChanged, this, &SettingsWindow::backgroundColorOffChanged);
connect(ui->lightOff_B_SB, SIGNAL(valueChanged(int)), ui->lightOff_B_S, SLOT(setValue(int)));
connect(ui->lightOff_B_S, SIGNAL(valueChanged(int)), ui->lightOff_B_SB, SLOT(setValue(int)));
connect(ui->lightOff_B_S, &QSlider::valueChanged, this, &SettingsWindow::backgroundColorOffChanged);
// light on
connect(ui->lightOn_R_SB, SIGNAL(valueChanged(int)), ui->lightOn_R_S, SLOT(setValue(int)));
connect(ui->lightOn_R_S, SIGNAL(valueChanged(int)), ui->lightOn_R_SB, SLOT(setValue(int)));
connect(ui->lightOn_R_S, &QSlider::valueChanged, this, &SettingsWindow::backgroundColorOnChanged);
connect(ui->lightOn_G_SB, SIGNAL(valueChanged(int)), ui->lightOn_G_S, SLOT(setValue(int)));
connect(ui->lightOn_G_S, SIGNAL(valueChanged(int)), ui->lightOn_G_SB, SLOT(setValue(int)));
connect(ui->lightOn_G_S, &QSlider::valueChanged, this, &SettingsWindow::backgroundColorOnChanged);
connect(ui->lightOn_B_SB, SIGNAL(valueChanged(int)), ui->lightOn_B_S, SLOT(setValue(int)));
connect(ui->lightOn_B_S, SIGNAL(valueChanged(int)), ui->lightOn_B_SB, SLOT(setValue(int)));
connect(ui->lightOn_B_S, &QSlider::valueChanged, this, &SettingsWindow::backgroundColorOnChanged);
// light
connect(ui->light_R_SB, SIGNAL(valueChanged(int)), ui->light_R_S, SLOT(setValue(int)));
connect(ui->light_R_S, SIGNAL(valueChanged(int)), ui->light_R_SB, SLOT(setValue(int)));
connect(ui->light_R_S, &QSlider::valueChanged, this, &SettingsWindow::lightColorChanged);
connect(ui->light_G_SB, SIGNAL(valueChanged(int)), ui->light_G_S, SLOT(setValue(int)));
connect(ui->light_G_S, SIGNAL(valueChanged(int)), ui->light_G_SB, SLOT(setValue(int)));
connect(ui->light_G_S, &QSlider::valueChanged, this, &SettingsWindow::lightColorChanged);
connect(ui->light_B_SB, SIGNAL(valueChanged(int)), ui->light_B_S, SLOT(setValue(int)));
connect(ui->light_B_S, SIGNAL(valueChanged(int)), ui->light_B_SB, SLOT(setValue(int)));
connect(ui->light_B_S, &QSlider::valueChanged, this, &SettingsWindow::lightColorChanged);
connect(ui->checkAutoColor, &QCheckBox::toggled, this, &SettingsWindow::autoColorToggled);
connect(ui->radioDirectLight, &QRadioButton::toggled, this, &SettingsWindow::radioToggled);
connect(ui->ambCoef, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {emit updateAmbCoef(value); });
connect(ui->attFac, static_cast<void(QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [this](double value) {emit updateAttFac(value); });
connect(ui->checkBackfaceCulling, &QCheckBox::toggled, [this]() {emit sendBackfaceCulling(ui->checkBackfaceCulling->isChecked()); });
connect(ui->spinZSpeed, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int value) {emit sendZommSpeed(value); });
connect(ui->checkHeadlight, &QCheckBox::toggled, [this]() {emit sendHeadlight(ui->checkHeadlight->isChecked()); });
}
/////////////////////////////////////////////////////////////////////////
// slots
void SettingsWindow::autoColorToggled()
{
if (!ui->checkAutoColor->isChecked())
{
ui->lightOn_R_SB->setEnabled(true);
ui->lightOn_R_S->setEnabled(true);
ui->lightOn_G_SB->setEnabled(true);
ui->lightOn_G_S->setEnabled(true);
ui->lightOn_B_SB->setEnabled(true);
ui->lightOn_B_S->setEnabled(true);
}
else
{
ui->lightOn_R_SB->setEnabled(false);
ui->lightOn_R_S->setEnabled(false);
ui->lightOn_G_SB->setEnabled(false);
ui->lightOn_G_S->setEnabled(false);
ui->lightOn_B_SB->setEnabled(false);
ui->lightOn_B_S->setEnabled(false);
ui->lightOn_R_S->setValue((int)(ui->light_R_S->value() / 50));
ui->lightOn_G_S->setValue((int)(ui->light_G_S->value() / 50));
ui->lightOn_B_S->setValue((int)(ui->light_B_S->value() / 50));
}
}
void SettingsWindow::radioToggled()
{
if (ui->radioDirectLight->isChecked())
{
ui->attFac->setValue(0.0);
ui->attFac->setEnabled(false);
emit changeLightType(1);
}
else
{
ui->attFac->setEnabled(true);
emit changeLightType(2);
}
}
void SettingsWindow::backgroundColorOffChanged()
{
emit updateBGColorOff(QVector3D(ui->lightOff_R_S->value(), ui->lightOff_G_S->value(), ui->lightOff_B_S->value()));
}
void SettingsWindow::backgroundColorOnChanged()
{
emit updateBGColorOn(QVector3D(ui->lightOn_R_S->value(), ui->lightOn_G_S->value(), ui->lightOn_B_S->value()));
}
void SettingsWindow::lightColorChanged()
{
emit updateLightColor(QVector3D(ui->light_R_S->value(), ui->light_G_S->value(), ui->light_B_S->value()));
if (ui->checkAutoColor->isChecked())
{
ui->lightOn_R_S->setValue((int)(ui->light_R_S->value() / 50));
ui->lightOn_G_S->setValue((int)(ui->light_G_S->value() / 50));
ui->lightOn_B_S->setValue((int)(ui->light_B_S->value() / 50));
}
}

12
QtMeshViewer/main.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "Header\MainWindow.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

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,14 +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
- cloth not working correctly
- optional display bones, shadow, collision,...
- integrate into a software:
-> gui open file ( + drag and drop),
-> list all msh under a directory,
-> display shadows,
-> display colisions,
-> lights,
-> handle render flags,

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: 48 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.

BIN
Release/Qt5Core.dll Normal file

Binary file not shown.

BIN
Release/Qt5Gui.dll Normal file

Binary file not shown.

BIN
Release/Qt5Widgets.dll Normal file

Binary file not shown.

BIN
Release/QtMeshViewer.exe Normal file

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
Release/msvcp140.dll Normal file

Binary file not shown.

Binary file not shown.

BIN
preview.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB