├── docs ├── .gitignore ├── README.md └── _config.yml ├── exit.png ├── icon.png ├── open.png ├── opend.png ├── opent.png ├── save.png ├── swap.png ├── icon_res.rc ├── openobj.png ├── rolling.jpg ├── algorithm.pdf ├── installer ├── packages │ ├── com.kapandaria.stereograma │ │ ├── data │ │ │ └── .gitignore │ │ └── meta │ │ │ └── package.xml │ ├── com.kapandaria.stereograma_models │ │ ├── data │ │ │ └── .gitignore │ │ └── meta │ │ │ └── package.xml │ ├── com.kapandaria.stereograma_depthmaps_textures │ │ ├── data │ │ │ └── .gitignore │ │ └── meta │ │ │ └── package.xml │ ├── com.kapandaria.stereograma_desktop │ │ └── meta │ │ │ ├── package.xml │ │ │ └── installscript.qs │ └── com.kapandaria.stereograma_menu │ │ └── meta │ │ ├── package.xml │ │ └── installscript.qs └── config │ └── config.xml ├── production ├── anaglyph_result │ └── README ├── stereograms │ └── README ├── depthmaps │ ├── Cow.png │ ├── Mur.png │ ├── Pot.png │ ├── Tor1.png │ ├── bull.png │ ├── fish.png │ ├── goat.png │ ├── afrik.png │ ├── dragon.png │ ├── guitar.png │ ├── hippo.png │ ├── luger.png │ ├── monkey.png │ ├── Chopper.png │ ├── dinopet.png │ ├── dolphins.png │ ├── elephant.png │ ├── kangaroo.png │ ├── molecule.png │ ├── spirals.png │ └── blender │ │ ├── curve.png │ │ ├── logo.blend │ │ ├── logo.png │ │ ├── mobius.png │ │ ├── star.blend │ │ ├── star.png │ │ ├── twist.png │ │ ├── curve.blend │ │ ├── mobius.blend │ │ ├── twist.blend │ │ ├── metaballs.blend │ │ ├── metaballs.png │ │ ├── strange_cube.png │ │ └── strange_cube.blend ├── eyehelpers │ ├── eye.png │ ├── sight.png │ ├── star.png │ ├── circle.png │ ├── cube_dual.png │ └── magen_david.png ├── textures │ ├── tx_000.jpg │ ├── tx_001.jpg │ ├── tx_002.jpg │ ├── tx_003.jpg │ ├── tx_004.jpg │ ├── tx_005.jpg │ ├── tx_006.jpg │ ├── tx_007.jpg │ ├── tx_008.jpg │ ├── tx_009.jpg │ ├── tx_010.jpg │ ├── tx_011.jpg │ ├── tx_012.jpg │ ├── tx_013.jpg │ ├── tx_014.jpg │ ├── tx_015.jpg │ ├── tx_016.jpg │ ├── tx_017.jpg │ ├── tx_018.jpg │ ├── tx_019.jpg │ ├── tx_020.jpg │ ├── tx_021.jpg │ ├── tx_022.jpg │ ├── tx_023.jpg │ └── tx_024.jpg ├── compose │ ├── compose00.png │ ├── compose01.png │ ├── compose02.png │ ├── compose03.png │ ├── compose04.png │ ├── compose05.png │ ├── compose06.png │ ├── compose07.png │ ├── compose08.png │ ├── compose09.png │ ├── compose10.png │ ├── compose11.png │ ├── compose12.png │ └── compose13.png ├── anaglyph │ ├── bonsai_left.jpg │ └── bonsai_right.jpg └── models │ ├── pyramid.obj │ └── cube.obj ├── stereograma.ico ├── .gitmodules ├── .gitignore ├── parse.h ├── ClickableLabel.cpp ├── trirender.h ├── rsc.qrc ├── stringtype.cpp ├── stringtype.h ├── main.cpp ├── anaglyphmaker.h ├── imagefiledialog.h ├── ClickableLabel.h ├── presetsketch.h ├── imageviewer.h ├── basicimagewidget.h ├── stereomaker.h ├── model3d.h ├── FormulaGen.h ├── imageviewer.cpp ├── preset.cpp ├── presetedit.h ├── imagecontainerwidget.h ├── modeldepthviewer.h ├── imagefiledialog.cpp ├── README.md ├── mainwindow.h ├── glmodelview.h ├── stereograma.pro ├── preset.h ├── basicimagewidget.cpp ├── stringtype.ui ├── presetedit.cpp ├── RPly ├── rplyfile.h └── rply.h ├── modeldepthviewer.cpp ├── anaglyphmaker.cpp ├── imageviewer.ui ├── presetsketch.cpp ├── stereograma.svg ├── imagecontainerwidget.cpp ├── presetedit.ui ├── FormulaGen.cpp ├── FormulaGen.ui ├── anaglyphmaker.ui ├── mainwindow.cpp ├── stereomaker.cpp ├── model3d.cpp ├── glmodelview.cpp ├── modeldepthviewer.ui ├── trirender.cpp └── parse.cpp /docs/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/exit.png -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/icon.png -------------------------------------------------------------------------------- /open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/open.png -------------------------------------------------------------------------------- /opend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/opend.png -------------------------------------------------------------------------------- /opent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/opent.png -------------------------------------------------------------------------------- /save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/save.png -------------------------------------------------------------------------------- /swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/swap.png -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-leap-day 2 | show_downloads: true 3 | -------------------------------------------------------------------------------- /icon_res.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "stereograma.ico" -------------------------------------------------------------------------------- /openobj.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/openobj.png -------------------------------------------------------------------------------- /rolling.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/rolling.jpg -------------------------------------------------------------------------------- /algorithm.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/algorithm.pdf -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /production/anaglyph_result/README: -------------------------------------------------------------------------------- 1 | this is the default output folder for anaglyphs 2 | -------------------------------------------------------------------------------- /stereograma.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/stereograma.ico -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_models/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /production/stereograms/README: -------------------------------------------------------------------------------- 1 | this is the default output folder for generated stereograms 2 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_depthmaps_textures/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "exprtk"] 2 | path = exprtk 3 | url = https://github.com/ArashPartow/exprtk.git 4 | -------------------------------------------------------------------------------- /production/depthmaps/Cow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/Cow.png -------------------------------------------------------------------------------- /production/depthmaps/Mur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/Mur.png -------------------------------------------------------------------------------- /production/depthmaps/Pot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/Pot.png -------------------------------------------------------------------------------- /production/depthmaps/Tor1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/Tor1.png -------------------------------------------------------------------------------- /production/depthmaps/bull.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/bull.png -------------------------------------------------------------------------------- /production/depthmaps/fish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/fish.png -------------------------------------------------------------------------------- /production/depthmaps/goat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/goat.png -------------------------------------------------------------------------------- /production/eyehelpers/eye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/eyehelpers/eye.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | moc_*.cpp 3 | moc_predefs.h 4 | ui_*.h 5 | qrc_*.cpp 6 | Makefile 7 | *.pro.user.* 8 | *.user 9 | -------------------------------------------------------------------------------- /production/depthmaps/afrik.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/afrik.png -------------------------------------------------------------------------------- /production/depthmaps/dragon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/dragon.png -------------------------------------------------------------------------------- /production/depthmaps/guitar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/guitar.png -------------------------------------------------------------------------------- /production/depthmaps/hippo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/hippo.png -------------------------------------------------------------------------------- /production/depthmaps/luger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/luger.png -------------------------------------------------------------------------------- /production/depthmaps/monkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/monkey.png -------------------------------------------------------------------------------- /production/eyehelpers/sight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/eyehelpers/sight.png -------------------------------------------------------------------------------- /production/eyehelpers/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/eyehelpers/star.png -------------------------------------------------------------------------------- /production/textures/tx_000.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_000.jpg -------------------------------------------------------------------------------- /production/textures/tx_001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_001.jpg -------------------------------------------------------------------------------- /production/textures/tx_002.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_002.jpg -------------------------------------------------------------------------------- /production/textures/tx_003.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_003.jpg -------------------------------------------------------------------------------- /production/textures/tx_004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_004.jpg -------------------------------------------------------------------------------- /production/textures/tx_005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_005.jpg -------------------------------------------------------------------------------- /production/textures/tx_006.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_006.jpg -------------------------------------------------------------------------------- /production/textures/tx_007.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_007.jpg -------------------------------------------------------------------------------- /production/textures/tx_008.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_008.jpg -------------------------------------------------------------------------------- /production/textures/tx_009.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_009.jpg -------------------------------------------------------------------------------- /production/textures/tx_010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_010.jpg -------------------------------------------------------------------------------- /production/textures/tx_011.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_011.jpg -------------------------------------------------------------------------------- /production/textures/tx_012.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_012.jpg -------------------------------------------------------------------------------- /production/textures/tx_013.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_013.jpg -------------------------------------------------------------------------------- /production/textures/tx_014.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_014.jpg -------------------------------------------------------------------------------- /production/textures/tx_015.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_015.jpg -------------------------------------------------------------------------------- /production/textures/tx_016.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_016.jpg -------------------------------------------------------------------------------- /production/textures/tx_017.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_017.jpg -------------------------------------------------------------------------------- /production/textures/tx_018.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_018.jpg -------------------------------------------------------------------------------- /production/textures/tx_019.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_019.jpg -------------------------------------------------------------------------------- /production/textures/tx_020.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_020.jpg -------------------------------------------------------------------------------- /production/textures/tx_021.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_021.jpg -------------------------------------------------------------------------------- /production/textures/tx_022.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_022.jpg -------------------------------------------------------------------------------- /production/textures/tx_023.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_023.jpg -------------------------------------------------------------------------------- /production/textures/tx_024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/textures/tx_024.jpg -------------------------------------------------------------------------------- /production/compose/compose00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose00.png -------------------------------------------------------------------------------- /production/compose/compose01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose01.png -------------------------------------------------------------------------------- /production/compose/compose02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose02.png -------------------------------------------------------------------------------- /production/compose/compose03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose03.png -------------------------------------------------------------------------------- /production/compose/compose04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose04.png -------------------------------------------------------------------------------- /production/compose/compose05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose05.png -------------------------------------------------------------------------------- /production/compose/compose06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose06.png -------------------------------------------------------------------------------- /production/compose/compose07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose07.png -------------------------------------------------------------------------------- /production/compose/compose08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose08.png -------------------------------------------------------------------------------- /production/compose/compose09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose09.png -------------------------------------------------------------------------------- /production/compose/compose10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose10.png -------------------------------------------------------------------------------- /production/compose/compose11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose11.png -------------------------------------------------------------------------------- /production/compose/compose12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose12.png -------------------------------------------------------------------------------- /production/compose/compose13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/compose/compose13.png -------------------------------------------------------------------------------- /production/depthmaps/Chopper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/Chopper.png -------------------------------------------------------------------------------- /production/depthmaps/dinopet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/dinopet.png -------------------------------------------------------------------------------- /production/depthmaps/dolphins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/dolphins.png -------------------------------------------------------------------------------- /production/depthmaps/elephant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/elephant.png -------------------------------------------------------------------------------- /production/depthmaps/kangaroo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/kangaroo.png -------------------------------------------------------------------------------- /production/depthmaps/molecule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/molecule.png -------------------------------------------------------------------------------- /production/depthmaps/spirals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/spirals.png -------------------------------------------------------------------------------- /production/eyehelpers/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/eyehelpers/circle.png -------------------------------------------------------------------------------- /production/anaglyph/bonsai_left.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/anaglyph/bonsai_left.jpg -------------------------------------------------------------------------------- /production/anaglyph/bonsai_right.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/anaglyph/bonsai_right.jpg -------------------------------------------------------------------------------- /production/eyehelpers/cube_dual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/eyehelpers/cube_dual.png -------------------------------------------------------------------------------- /production/depthmaps/blender/curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/curve.png -------------------------------------------------------------------------------- /production/depthmaps/blender/logo.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/logo.blend -------------------------------------------------------------------------------- /production/depthmaps/blender/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/logo.png -------------------------------------------------------------------------------- /production/depthmaps/blender/mobius.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/mobius.png -------------------------------------------------------------------------------- /production/depthmaps/blender/star.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/star.blend -------------------------------------------------------------------------------- /production/depthmaps/blender/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/star.png -------------------------------------------------------------------------------- /production/depthmaps/blender/twist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/twist.png -------------------------------------------------------------------------------- /production/eyehelpers/magen_david.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/eyehelpers/magen_david.png -------------------------------------------------------------------------------- /production/depthmaps/blender/curve.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/curve.blend -------------------------------------------------------------------------------- /production/depthmaps/blender/mobius.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/mobius.blend -------------------------------------------------------------------------------- /production/depthmaps/blender/twist.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/twist.blend -------------------------------------------------------------------------------- /production/depthmaps/blender/metaballs.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/metaballs.blend -------------------------------------------------------------------------------- /production/depthmaps/blender/metaballs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/metaballs.png -------------------------------------------------------------------------------- /parse.h: -------------------------------------------------------------------------------- 1 | 2 | void parse(const char* buffer); 3 | #ifdef USE_FLOAT 4 | float parseXY(const char* buffer,float x,float y,bool *ok); 5 | #endif 6 | -------------------------------------------------------------------------------- /production/depthmaps/blender/strange_cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/strange_cube.png -------------------------------------------------------------------------------- /production/depthmaps/blender/strange_cube.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gnudles/stereograma/HEAD/production/depthmaps/blender/strange_cube.blend -------------------------------------------------------------------------------- /production/models/pyramid.obj: -------------------------------------------------------------------------------- 1 | # OBJ file created by ply_to_obj.c 2 | # 3 | g Object001 4 | 5 | v 0 0 0 6 | v 1 0 0 7 | v 1 1 0 8 | v 0 1 0 9 | v 0.5 0.5 1.6 10 | 11 | f 5 2 3 12 | f 4 5 3 13 | f 6 3 2 14 | f 5 6 2 15 | f 4 6 5 16 | f 6 4 3 17 | -------------------------------------------------------------------------------- /ClickableLabel.cpp: -------------------------------------------------------------------------------- 1 | #include "ClickableLabel.h" 2 | 3 | ClickableLabel::ClickableLabel(QWidget* parent, Qt::WindowFlags f) 4 | : QLabel(parent) { 5 | 6 | } 7 | 8 | ClickableLabel::~ClickableLabel() {} 9 | 10 | void ClickableLabel::mousePressEvent(QMouseEvent* event) { 11 | emit clicked(); 12 | } 13 | -------------------------------------------------------------------------------- /trirender.h: -------------------------------------------------------------------------------- 1 | #ifndef TRIRENDER_H 2 | #define TRIRENDER_H 3 | 4 | void trirender(unsigned char *buffer, int w, int h, const float *points, int np, const unsigned int *triangles, int nt, float xrot, float yrot, float zrot, float zoom, float contrast, float xoff, float yoff, float scale); 5 | 6 | #endif // TRIRENDER_H 7 | -------------------------------------------------------------------------------- /installer/config/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Stereograma 4 | 2.6.0 5 | Stereograma Installer 6 | Kapandaria 7 | Stereograma 8 | @HomeDir@/Stereograma 9 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_models/meta/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 3D Models 4 | Install Sample 3D Models 5 | 2.6.0 6 | 2020-11-12 7 | true 8 | 9 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_depthmaps_textures/meta/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Depth maps and textures 4 | Install Additional resources 5 | 2.6.0 6 | 2020-11-12 7 | true 8 | 9 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_desktop/meta/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Desktop shortcut 4 | Install Desktop shortcut 5 | 2.6.0 6 | 2020-11-12 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_menu/meta/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Start Menu shortcut 4 | Install Start Menu shortcut 5 | 2.6.0 6 | 2020-11-12 7 | true 8 | 9 | 10 | -------------------------------------------------------------------------------- /rsc.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | stereograma.svg 4 | open.png 5 | opend.png 6 | openobj.png 7 | opent.png 8 | save.png 9 | exit.png 10 | swap.png 11 | rolling.jpg 12 | 13 | 14 | -------------------------------------------------------------------------------- /stringtype.cpp: -------------------------------------------------------------------------------- 1 | #include "stringtype.h" 2 | #include "ui_stringtype.h" 3 | 4 | StringType::StringType(const QString & title,QWidget *parent) : 5 | QDialog(parent), 6 | ui(new Ui::StringType) 7 | { 8 | ui->setupUi(this); 9 | setWindowTitle(title); 10 | } 11 | 12 | StringType::~StringType() 13 | { 14 | delete ui; 15 | } 16 | 17 | QString StringType::getString() 18 | { 19 | return ui->lineEdit->text(); 20 | } 21 | -------------------------------------------------------------------------------- /stringtype.h: -------------------------------------------------------------------------------- 1 | #ifndef STRINGTYPE_H 2 | #define STRINGTYPE_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class StringType; 8 | } 9 | 10 | class StringType : public QDialog 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit StringType(const QString &title, QWidget *parent = 0); 16 | ~StringType(); 17 | QString getString(); 18 | 19 | private: 20 | Ui::StringType *ui; 21 | }; 22 | 23 | #endif // STRINGTYPE_H 24 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "mainwindow.h" 3 | #include 4 | 5 | #include "parse.h" 6 | int main(int argc, char *argv[]) 7 | { 8 | QApplication a(argc, argv); 9 | a.setWindowIcon(QIcon(":/images/stereograma.svg")); 10 | QCoreApplication::setOrganizationName("Kapandaria"); 11 | QCoreApplication::setApplicationName("Stereograma"); 12 | MainWindow w; 13 | w.show(); 14 | 15 | return a.exec(); 16 | } 17 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma/meta/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Stereograma Binaries 4 | Install Stereograma binaries (Software) 5 | 2.6.0 6 | 2020-11-12 7 | 8 | 9 | 10 | true 11 | 12 | -------------------------------------------------------------------------------- /anaglyphmaker.h: -------------------------------------------------------------------------------- 1 | #ifndef ANAGLYPHMAKER_H 2 | #define ANAGLYPHMAKER_H 3 | 4 | #include 5 | 6 | namespace Ui { 7 | class AnaglyphMaker; 8 | } 9 | 10 | class AnaglyphMaker : public QMainWindow 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit AnaglyphMaker(QWidget *parent = 0); 16 | ~AnaglyphMaker(); 17 | 18 | private slots: 19 | void on_mergeButton_clicked(); 20 | 21 | private: 22 | Ui::AnaglyphMaker *ui; 23 | }; 24 | 25 | #endif // ANAGLYPHMAKER_H 26 | -------------------------------------------------------------------------------- /imagefiledialog.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEFILEDIALOG_H 2 | #define IMAGEFILEDIALOG_H 3 | #include 4 | #include 5 | 6 | class ImageFileDialog : public QFileDialog 7 | { 8 | Q_OBJECT 9 | public: 10 | ImageFileDialog(QWidget *parent):QFileDialog(parent){setOption(QFileDialog::DontUseNativeDialog);} 11 | void init(); 12 | void deinit(); 13 | private: 14 | QLabel *_preview; 15 | private slots: 16 | void fileChanged(const QString &file); 17 | }; 18 | 19 | #endif // IMAGEFILEDIALOG_H 20 | -------------------------------------------------------------------------------- /production/models/cube.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.69 (sub 0) OBJ File: '' 2 | # www.blender.org 3 | mtllib cube.mtl 4 | o Cube 5 | v 1.000000 -1.000000 -1.000000 6 | v 1.000000 -1.000000 1.000000 7 | v -1.000000 -1.000000 1.000000 8 | v -1.000000 -1.000000 -1.000000 9 | v 1.000000 1.000000 -0.999999 10 | v 0.999999 1.000000 1.000001 11 | v -1.000000 1.000000 1.000000 12 | v -1.000000 1.000000 -1.000000 13 | usemtl Material 14 | s off 15 | f 1 2 3 4 16 | f 5 8 7 6 17 | f 1 5 6 2 18 | f 2 6 7 3 19 | f 3 7 8 4 20 | f 5 1 4 8 21 | -------------------------------------------------------------------------------- /ClickableLabel.h: -------------------------------------------------------------------------------- 1 | #ifndef CLICKABLELABEL_H 2 | #define CLICKABLELABEL_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class ClickableLabel : public QLabel { 9 | Q_OBJECT 10 | 11 | public: 12 | explicit ClickableLabel(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); 13 | ~ClickableLabel(); 14 | 15 | signals: 16 | void clicked(); 17 | 18 | protected: 19 | void mousePressEvent(QMouseEvent* event); 20 | 21 | }; 22 | 23 | #endif // CLICKABLELABEL_H 24 | -------------------------------------------------------------------------------- /presetsketch.h: -------------------------------------------------------------------------------- 1 | #ifndef PRESETSKETCH_H 2 | #define PRESETSKETCH_H 3 | 4 | #include 5 | #include 6 | #include "preset.h" 7 | 8 | class PresetSketch : public QWidget 9 | { 10 | Q_OBJECT 11 | public: 12 | explicit PresetSketch(QWidget *parent = 0); 13 | void setPreset(Preset * preset); 14 | signals: 15 | 16 | public slots: 17 | void presetUpdated(); 18 | protected: 19 | void paintEvent(QPaintEvent *); 20 | 21 | private: 22 | float def_width; 23 | float def_height; 24 | float eye_size; 25 | Preset *m_preset; 26 | QVector m_heights; 27 | 28 | }; 29 | 30 | #endif // PRESETSKETCH_H 31 | -------------------------------------------------------------------------------- /imageviewer.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEVIEWER_H 2 | #define IMAGEVIEWER_H 3 | 4 | #include 5 | #include 6 | #include "basicimagewidget.h" 7 | 8 | namespace Ui { 9 | class ImageViewer; 10 | } 11 | 12 | class ImageViewer : public QMainWindow, public BasicImageWidget 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit ImageViewer(QWidget *parent = 0); 18 | ~ImageViewer(); 19 | void setImage(const QImage & image); 20 | 21 | private slots: 22 | void on_actionSave_As_triggered(); 23 | 24 | void on_actionInvert_triggered(); 25 | 26 | private: 27 | void mouseDoubleClickEvent(QMouseEvent * event); 28 | Ui::ImageViewer *ui; 29 | }; 30 | 31 | #endif // IMAGEVIEWER_H 32 | -------------------------------------------------------------------------------- /basicimagewidget.h: -------------------------------------------------------------------------------- 1 | #ifndef BASICIMAGEWIDGET_H 2 | #define BASICIMAGEWIDGET_H 3 | #include 4 | #include 5 | 6 | class BasicImageWidget 7 | { 8 | public: 9 | BasicImageWidget(); 10 | void saveAsImage(); 11 | void setFolderSettings(const QString &fsetting); 12 | void setFolderSettings(const char *fsetting); 13 | void setSaveTitle(const QString &stitle); 14 | void setSaveTitle(const char *stitle); 15 | void setBasicImageParent(QWidget *p); 16 | const QImage & getImage() {return imdata;} 17 | const QImage * getImagePtr() {return &imdata;} 18 | protected: 19 | QImage imdata; 20 | QString folderSettings; 21 | QString saveTitle; 22 | QWidget *m_parent; 23 | }; 24 | 25 | #endif // BASICIMAGEWIDGET_H 26 | -------------------------------------------------------------------------------- /stereomaker.h: -------------------------------------------------------------------------------- 1 | #ifndef STEREOMAKER_H 2 | #define STEREOMAKER_H 3 | 4 | #include 5 | #include 6 | #include "preset.h" 7 | 8 | void scaleLine(uchar* big,const uchar *original,int sizeoriginal); 9 | class StereoMaker 10 | { 11 | public: 12 | StereoMaker(); 13 | ~StereoMaker(); 14 | QImage render(const QImage & dmap,const QImage & ptrn,Preset *psettings,QProgressBar * qpbar,const QImage * eye_helper_right,const QImage * eye_helper_left,bool show_helper, bool helpers_margin); 15 | void composeDepth(QImage & depth,QImage & compose, float composeHeight); 16 | static const QVector & getGrayScale(); 17 | private: 18 | static QVector grayscale; 19 | int *depthsep; 20 | }; 21 | 22 | #endif // STEREOMAKER_H 23 | -------------------------------------------------------------------------------- /model3d.h: -------------------------------------------------------------------------------- 1 | #ifndef MODEL3D_H 2 | #define MODEL3D_H 3 | 4 | #include 5 | #include 6 | 7 | 8 | class Model3D 9 | { 10 | public: 11 | Model3D(); 12 | ~Model3D(); 13 | void LoadObj(const QString & filename); 14 | void LoadPly(const QString & filename); 15 | void DrawGL(bool color); 16 | unsigned int numPoints(){return m_nPoints;} 17 | const float * pointsData(){return m_points;} 18 | unsigned int numTriangles(){return m_nTriangles;} 19 | const unsigned int * trianglesData(){return m_triangles;} 20 | private: 21 | void normalize(); 22 | float *m_points; 23 | unsigned char *m_colors; 24 | unsigned int *m_triangles; 25 | unsigned int m_nPoints,m_nTriangles; 26 | }; 27 | 28 | #endif // MODEL3D_H 29 | -------------------------------------------------------------------------------- /FormulaGen.h: -------------------------------------------------------------------------------- 1 | #ifndef FORMULAGEN_H 2 | #define FORMULAGEN_H 3 | 4 | #include 5 | #include "basicimagewidget.h" 6 | namespace Ui { 7 | class FormulaGen; 8 | } 9 | class QListWidgetItem; 10 | class FormulaGen : public QMainWindow, public BasicImageWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit FormulaGen(QWidget *parent = 0); 16 | ~FormulaGen(); 17 | int getOutputImageWidth(); 18 | int getOutputImageHeight(); 19 | 20 | private slots: 21 | void on_generatePb_clicked(); 22 | 23 | void on_actionSave_Image_triggered(); 24 | 25 | void on_actionPush_Image_triggered(); 26 | 27 | void on_actionPush_Image_as_Compose_Pattern_triggered(); 28 | 29 | void on_listWidget_itemActivated(QListWidgetItem *item); 30 | 31 | private: 32 | Ui::FormulaGen *ui; 33 | QStringList formulaList; 34 | }; 35 | 36 | #endif // FORMULAGEN_H 37 | -------------------------------------------------------------------------------- /imageviewer.cpp: -------------------------------------------------------------------------------- 1 | #include "imageviewer.h" 2 | #include "ui_imageviewer.h" 3 | #include 4 | #include 5 | 6 | ImageViewer::ImageViewer(QWidget *parent) : 7 | QMainWindow(parent), 8 | ui(new Ui::ImageViewer) 9 | { 10 | ui->setupUi(this); 11 | setBasicImageParent(this); 12 | } 13 | 14 | ImageViewer::~ImageViewer() 15 | { 16 | delete ui; 17 | } 18 | 19 | void ImageViewer::setImage(const QImage & image) 20 | { 21 | imdata= image; 22 | ui->imageViewArea->setPixmap(QPixmap::fromImage(imdata)); 23 | } 24 | 25 | void ImageViewer::on_actionSave_As_triggered() 26 | { 27 | saveAsImage(); 28 | } 29 | void ImageViewer::mouseDoubleClickEvent(QMouseEvent * ) 30 | { 31 | on_actionSave_As_triggered(); 32 | } 33 | 34 | void ImageViewer::on_actionInvert_triggered() 35 | { 36 | imdata.invertPixels(); 37 | ui->imageViewArea->setPixmap(QPixmap::fromImage(imdata)); 38 | } 39 | -------------------------------------------------------------------------------- /preset.cpp: -------------------------------------------------------------------------------- 1 | #include "preset.h" 2 | 3 | Preset::Preset(const QString & name) 4 | { 5 | m_preset_name=name; 6 | m_eye_seperation=2.5; 7 | m_observer_distance=20; 8 | m_minimum_depth=5; 9 | m_maximum_depth=9; 10 | m_dpi = 150; 11 | m_isParallel=true; 12 | m_result_width=2048; 13 | m_result_height=1536; 14 | } 15 | 16 | Preset::Preset(QDataStream &qdata) 17 | { 18 | qdata>>m_preset_name; 19 | qdata>>m_eye_seperation; 20 | qdata>>m_observer_distance; 21 | qdata>>m_minimum_depth; 22 | qdata>>m_maximum_depth; 23 | qdata>>m_dpi; 24 | qdata>>m_result_width; 25 | qdata>>m_result_height; 26 | qdata>>m_isParallel; 27 | } 28 | 29 | void Preset::toStream(QDataStream &qdata) 30 | { 31 | qdata< 5 | #include "preset.h" 6 | namespace Ui { 7 | class PresetEdit; 8 | } 9 | 10 | class PresetEdit : public QWidget 11 | { 12 | Q_OBJECT 13 | 14 | public: 15 | explicit PresetEdit(QWidget *parent = 0); 16 | ~PresetEdit(); 17 | void setPreset(Preset* preset); 18 | signals: 19 | void onEdited(); 20 | private slots: 21 | void on_crossEyedCheckBox_stateChanged(int state); 22 | 23 | void on_dpiSpinBox_valueChanged(int dpi); 24 | 25 | void on_minimumDepthDoubleSpinBox_valueChanged(double mindepth); 26 | 27 | void on_maximumDepthDoubleSpinBox_valueChanged(double maxdepth); 28 | 29 | void on_eyeSeperationDoubleSpinBox_valueChanged(double eyesep); 30 | 31 | void on_observerDistanceInDoubleSpinBox_valueChanged(double obsdist); 32 | 33 | void on_imageHeightSpinBox_valueChanged(int height); 34 | 35 | void on_imageWidthSpinBox_valueChanged(int width); 36 | 37 | private: 38 | Ui::PresetEdit *ui; 39 | Preset *m_preset; 40 | }; 41 | 42 | #endif // PRESETEDIT_H 43 | -------------------------------------------------------------------------------- /imagecontainerwidget.h: -------------------------------------------------------------------------------- 1 | #ifndef IMAGEWIDGET_H 2 | #define IMAGEWIDGET_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "imageviewer.h" 9 | #include "basicimagewidget.h" 10 | 11 | class ImageContainerWidget : public QLabel, public BasicImageWidget 12 | { 13 | Q_OBJECT 14 | public: 15 | ImageContainerWidget(QWidget *parent = 0); 16 | void openDialog(); 17 | void setImage(const QImage &image); 18 | private slots: 19 | void downloadFinished(QNetworkReply* reply); 20 | void showContextMenu(const QPoint&); 21 | private: 22 | 23 | void setImage(const QString &fileName); 24 | 25 | const QString & getText(); 26 | void mySetPixmap(); 27 | void saveDialog(); 28 | void dragEnterEvent(QDragEnterEvent *event); 29 | void dropEvent(QDropEvent *event); 30 | void mouseDoubleClickEvent(QMouseEvent * event); 31 | 32 | QAction *_saveAsAction; 33 | QAction *_unloadAction; 34 | QAction *_loadAction; 35 | QAction *_viewAction; 36 | ImageViewer *m_viewer; 37 | QMenu myMenu; 38 | QString replaceText; 39 | QNetworkAccessManager netManager; 40 | }; 41 | 42 | 43 | 44 | #endif // IMAGEWIDGET_H 45 | -------------------------------------------------------------------------------- /modeldepthviewer.h: -------------------------------------------------------------------------------- 1 | #ifndef MODELDEPTHVIEWER_H 2 | #define MODELDEPTHVIEWER_H 3 | 4 | #include 5 | #include "model3d.h" 6 | 7 | namespace Ui { 8 | class ModelDepthViewer; 9 | } 10 | 11 | class ModelDepthViewer : public QMainWindow 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit ModelDepthViewer(QWidget *parent = 0); 17 | int getOutputImageWidth(); 18 | int getOutputImageHeight(); 19 | ~ModelDepthViewer(); 20 | void setModel(Model3D * model); 21 | 22 | private slots: 23 | 24 | void on_hSliderRotZ_valueChanged(int value); 25 | 26 | void on_hSliderRotY_valueChanged(int value); 27 | 28 | void on_hSliderRotX_valueChanged(int value); 29 | 30 | void on_actionSave_Image_triggered(); 31 | 32 | void on_zoomSlider_valueChanged(int value); 33 | 34 | void on_scaleSlider_valueChanged(int value); 35 | 36 | void on_contrastSlider_valueChanged(int value); 37 | 38 | void on_actionPush_Image_triggered(); 39 | 40 | void on_moveXSlider_valueChanged(int value); 41 | 42 | void on_moveYSlider_valueChanged(int value); 43 | 44 | void on_widthSpin_editingFinished(); 45 | 46 | void on_heightSpin_editingFinished(); 47 | 48 | private: 49 | Ui::ModelDepthViewer *ui; 50 | }; 51 | 52 | #endif // MODELDEPTHVIEWER_H 53 | -------------------------------------------------------------------------------- /imagefiledialog.cpp: -------------------------------------------------------------------------------- 1 | #include "imagefiledialog.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | void ImageFileDialog::init() 9 | { 10 | _preview = 0; 11 | QSplitter *splitter; 12 | splitter = ((QFileDialog*)this)->findChild("splitter"); 13 | if (splitter == 0) 14 | { 15 | return; 16 | } 17 | 18 | _preview = new QLabel(); 19 | QRect geomerty = _preview->geometry(); 20 | geomerty.setWidth(160); 21 | 22 | _preview->setGeometry(geomerty); 23 | splitter->addWidget(_preview); 24 | connect(this, SIGNAL(currentChanged(QString)), 25 | this, SLOT(fileChanged(QString))); 26 | 27 | } 28 | void ImageFileDialog::deinit() 29 | { 30 | if (_preview != 0) 31 | { 32 | delete _preview; 33 | _preview=0; 34 | } 35 | } 36 | void ImageFileDialog::fileChanged(const QString &file) 37 | { 38 | if (_preview == 0) 39 | { 40 | return; 41 | } 42 | QImage img=QImage(file); 43 | if (img.isNull()) 44 | { 45 | _preview->setPixmap(QPixmap()); 46 | } 47 | else 48 | { 49 | QSize size = _preview->size(); 50 | QImage smallimage=img.convertToFormat(QImage::Format_ARGB32).scaled(size, Qt::KeepAspectRatio); 51 | QPixmap pix=QPixmap::fromImage(smallimage); 52 | _preview->setPixmap(pix); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stereograma 2 | This is a **FREE** open source cross-platform [**stereogram maker**/**stereogram creator**/**stereogram generator**/**stereogram renderer**] written in C++ using Qt. It aims to be fast, accurate, easy to use and multifunctional piece of software, as it uses the **best** algorithm (by W.A. Steer PhD) for generating auto-stereograms (see [algorithm.pdf](algorithm.pdf)). It can even load 3D models in the .obj and .ply file formats. It also comes with some depth maps and textures so you can start to play from the first moment. One cool feature which is very unique is that it includes an interactive diagram that shows the depths of the resulted image, according to the rendering parameters. 3 | 4 | There is also an interface for combining two pictures taken from different angles into anaglyph. 5 | 6 | ### Where to download? 7 | 8 | visit that link: https://kapandaria.wordpress.com/stereograma/ 9 | 10 | ### How to build: 11 | 12 | Since it was developed with QtCreator, you can generate a makefile from the .pro file with qmake, or just compile it from within the IDE. 13 | 14 | ## Support me! 15 | 16 | I make many open source projects, and also contribute to the open source community. This project is a great example for that. 17 | If you liked this piece of software, and you want to give back, you don't have to open your wallet, just give a try to my mobile puzzle games: 18 | 19 | https://play.google.com/store/apps/details?id=com.github.gnudles.rollingmarbles 20 | 21 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include "preset.h" 6 | 7 | #define SETTINGS_FILE "settings.bin" 8 | 9 | namespace Ui { 10 | class MainWindow; 11 | } 12 | 13 | class MainWindow : public QMainWindow 14 | { 15 | Q_OBJECT 16 | 17 | public: 18 | explicit MainWindow(QWidget *parent = 0); 19 | ~MainWindow(); 20 | void setDepthImage(const QImage & image); 21 | void setComposePattern(const QImage & image); 22 | 23 | 24 | private slots: 25 | void on_renderButton_clicked(); 26 | void on_action_obj_triggered(); 27 | 28 | void on_action_ply_triggered(); 29 | 30 | void on_actionLoad_Texture_triggered(); 31 | 32 | void on_actionLoad_Depth_Map_triggered(); 33 | 34 | void on_actionCreate_Anaglyph_triggered(); 35 | 36 | void on_actionAdd_preset_triggered(); 37 | 38 | void on_presetSelect_currentIndexChanged(int index); 39 | 40 | void on_actionSave_Presets_triggered(); 41 | 42 | void on_actionReset_triggered(); 43 | 44 | void on_actionRename_Preset_triggered(); 45 | 46 | void on_actionRemove_preset_triggered(); 47 | 48 | void on_actionGenerate_Depth_Map_triggered(); 49 | 50 | void on_rolling_clicked(); 51 | 52 | void on_show_helpers_toggled(bool checked); 53 | 54 | private: 55 | void loadPresets(); 56 | void savePresets(); 57 | Ui::MainWindow *ui; 58 | Preset *cur_preset; 59 | QList m_presets; 60 | }; 61 | 62 | #endif // MAINWINDOW_H 63 | -------------------------------------------------------------------------------- /glmodelview.h: -------------------------------------------------------------------------------- 1 | #ifndef GLMODELVIEW_H 2 | #define GLMODELVIEW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "basicimagewidget.h" 8 | 9 | class GlModelView : public QOpenGLWidget,public BasicImageWidget 10 | { 11 | Q_OBJECT 12 | public: 13 | explicit GlModelView(QWidget *parent = 0); 14 | ~GlModelView(); 15 | void setViewport(int width,int height); 16 | void setModel(Model3D * model); 17 | void setRotationX(float rot){m_rotx=rot;} 18 | void setRotationY(float rot){m_roty=rot;} 19 | void setRotationZ(float rot){m_rotz=rot;} 20 | void setXOffset(float offset){m_xoffset=offset;} 21 | void setYOffset(float offset){m_yoffset=offset;} 22 | void setZoom(float zoom); 23 | void setScale(float scale); 24 | void setContrast(float contrast); 25 | void setParams(float xoff,float yoff,float zoom,float contrast,float m_rotx,float m_roty,float m_rotz,float scale); 26 | const QImage *snapShot(); 27 | protected: 28 | void setPerspective(); 29 | void initializeGL(); 30 | 31 | void paintGL(); 32 | void resizeGL( int w, int h ); 33 | /*void mousePressEvent(QMouseEvent* event); 34 | void mouseMoveEvent(QMouseEvent* event); 35 | void mouseReleaseEvent(QMouseEvent* event);*/ 36 | 37 | protected slots: 38 | 39 | signals: 40 | 41 | public slots: 42 | private: 43 | Model3D *m_model; 44 | float m_rotx,m_roty,m_rotz; 45 | float m_xoffset,m_yoffset; 46 | float m_zoom; 47 | float m_contrast; 48 | float m_scale; 49 | bool m_noShaders; 50 | bool m_antialias; 51 | int m_new_width; 52 | int m_new_height; 53 | }; 54 | 55 | #endif // GLMODELVIEW_H 56 | -------------------------------------------------------------------------------- /stereograma.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2011-07-24T20:40:23 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui network openglwidgets 8 | 9 | TARGET = stereograma 10 | TEMPLATE = app 11 | 12 | linux:LIBS += -lGLU 13 | win32:LIBS += -lGLU32 -lOpengl32 14 | win32:RC_FILE = icon_res.rc 15 | win32:QMAKE_CXXFLAGS += -Wa,-mbig-obj 16 | DEFINES+= USE_FLOAT 17 | #QMAKE_CXXFLAGS += -fsanitize=address 18 | #QMAKE_LFLAGS += -fsanitize=address 19 | 20 | SOURCES += main.cpp\ 21 | ClickableLabel.cpp \ 22 | mainwindow.cpp \ 23 | imagecontainerwidget.cpp \ 24 | imageviewer.cpp \ 25 | model3d.cpp \ 26 | imagefiledialog.cpp \ 27 | stereomaker.cpp \ 28 | glmodelview.cpp \ 29 | presetsketch.cpp \ 30 | preset.cpp \ 31 | modeldepthviewer.cpp \ 32 | basicimagewidget.cpp \ 33 | presetedit.cpp \ 34 | anaglyphmaker.cpp \ 35 | stringtype.cpp \ 36 | trirender.cpp \ 37 | RPly/rply.c \ 38 | parse.cpp \ 39 | FormulaGen.cpp 40 | 41 | HEADERS += mainwindow.h \ 42 | ClickableLabel.h \ 43 | exprtk/exprtk.hpp \ 44 | imagecontainerwidget.h \ 45 | imageviewer.h \ 46 | model3d.h \ 47 | imagefiledialog.h \ 48 | stereomaker.h \ 49 | glmodelview.h \ 50 | presetsketch.h \ 51 | preset.h \ 52 | modeldepthviewer.h \ 53 | basicimagewidget.h \ 54 | presetedit.h \ 55 | anaglyphmaker.h \ 56 | stringtype.h \ 57 | trirender.h \ 58 | RPly/rply.h \ 59 | RPly/rplyfile.h \ 60 | parse.h \ 61 | FormulaGen.h 62 | 63 | FORMS += mainwindow.ui \ 64 | imageviewer.ui \ 65 | modeldepthviewer.ui \ 66 | presetedit.ui \ 67 | anaglyphmaker.ui \ 68 | stringtype.ui \ 69 | FormulaGen.ui 70 | 71 | RESOURCES += \ 72 | rsc.qrc 73 | 74 | OTHER_FILES += \ 75 | old_render.txt 76 | -------------------------------------------------------------------------------- /preset.h: -------------------------------------------------------------------------------- 1 | #ifndef PRESET_H 2 | #define PRESET_H 3 | 4 | #include 5 | #include 6 | class Preset 7 | { 8 | public: 9 | Preset(const QString &name); 10 | Preset(QDataStream & qdata); 11 | void toStream(QDataStream & qdata); 12 | inline QString getName() { return m_preset_name;} 13 | inline void setName(const QString & str) { m_preset_name=str;} 14 | inline float getEyeSeperation() {return m_eye_seperation;} 15 | inline float getObserverDistance() {return m_observer_distance;} 16 | inline float getMinimumDepth() {return m_minimum_depth;} 17 | inline float getMaximumDepth() {return m_maximum_depth;} 18 | inline int getDotsPerInch() {return m_dpi;} 19 | inline int getResultWidth() {return m_result_width;} 20 | inline int getResultHeight() {return m_result_height;} 21 | inline bool getIsParallel() {return m_isParallel;} 22 | inline void setEyeSeperation(float eye_seperation) { m_eye_seperation=eye_seperation;} 23 | inline void setObserverDistance(float observer_distance) { m_observer_distance=observer_distance;} 24 | inline void setMinimumDepth(float minimum_depth) { m_minimum_depth=minimum_depth;} 25 | inline void setMaximumDepth(float maximum_depth) { m_maximum_depth=maximum_depth;} 26 | inline void setDotsPerInch(int dpi) { m_dpi=dpi;} 27 | inline void setIsParallel(bool isParallel) { m_isParallel=isParallel;} 28 | inline void setResultWidth(int width) {m_result_width=width;} 29 | inline void setResultHeight(int height) {m_result_height=height;} 30 | private: 31 | QString m_preset_name; 32 | float m_eye_seperation; 33 | float m_observer_distance; 34 | float m_minimum_depth; 35 | float m_maximum_depth; 36 | int m_dpi; 37 | bool m_isParallel; 38 | bool m_show_helpers; 39 | bool m_use_image_resolution; 40 | int m_result_width; 41 | int m_result_height; 42 | 43 | }; 44 | 45 | #endif // PRESET_H 46 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_desktop/meta/installscript.qs: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2017 The Qt Company Ltd. 4 | ** Contact: https://www.qt.io/licensing/ 5 | ** 6 | ** This file is part of the FOO module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and The Qt Company. For licensing terms 14 | ** and conditions see https://www.qt.io/terms-conditions. For further 15 | ** information use the contact form at https://www.qt.io/contact-us. 16 | ** 17 | ** GNU General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU 19 | ** General Public License version 3 as published by the Free Software 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 21 | ** included in the packaging of this file. Please review the following 22 | ** information to ensure the GNU General Public License requirements will 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 24 | ** 25 | ** $QT_END_LICENSE$ 26 | ** 27 | ****************************************************************************/ 28 | 29 | function Component() 30 | { 31 | // default constructor 32 | } 33 | 34 | Component.prototype.createOperations = function() 35 | { 36 | component.createOperations(); 37 | 38 | if (systemInfo.productType === "windows") { 39 | component.addOperation("CreateShortcut", 40 | "@TargetDir@/Stereograma.exe",// target 41 | "@DesktopDir@/Stereograma.lnk",// link-path 42 | "workingDirectory=@TargetDir@",// working-dir 43 | "iconPath=@TargetDir@/Stereograma.exe", "iconId=0",// icon 44 | "description=Start Stereograma");// description 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /basicimagewidget.cpp: -------------------------------------------------------------------------------- 1 | #include "basicimagewidget.h" 2 | #include "imagefiledialog.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #if QT_VERSION >= QT_VERSION_CHECK(5,15,1) 8 | #define WEBP_FILTER " *.webp *.WEBP" 9 | #else 10 | #define WEBP_FILTER "" 11 | #endif 12 | 13 | 14 | 15 | 16 | BasicImageWidget::BasicImageWidget() 17 | { 18 | m_parent=0; 19 | } 20 | 21 | void BasicImageWidget::saveAsImage() 22 | { 23 | if (!imdata.isNull()) 24 | { 25 | QSettings settings; 26 | QString cdir=settings.value(folderSettings,folderSettings).toString(); 27 | ImageFileDialog dlg(m_parent); 28 | 29 | dlg.init(); 30 | dlg.setFileMode( QFileDialog::AnyFile); 31 | dlg.setAcceptMode(QFileDialog::AcceptSave); 32 | dlg.setDirectory(cdir); 33 | dlg.setNameFilter("Images (*.png *.xpm *.jpg *.jpeg *.bmp *.tiff *.tif *.PNG *.XPM *.JPG *.JPEG *.BMP *.TIF *.TIFF" WEBP_FILTER ")"); 34 | dlg.setWindowTitle("Save "+saveTitle); 35 | QString fileName; 36 | imdata=imdata.convertToFormat(QImage::Format_ARGB32); 37 | if (dlg.exec()) 38 | { 39 | fileName = dlg.selectedFiles().first(); 40 | settings.setValue(folderSettings, QFileInfo(fileName).absoluteDir().absolutePath()); 41 | if (!imdata.save(fileName)) 42 | {//probably no file type was supplied... 43 | fileName.append(".png"); 44 | imdata.save(fileName); 45 | } 46 | } 47 | dlg.deinit(); 48 | } 49 | } 50 | 51 | void BasicImageWidget::setFolderSettings(const QString & fsetting) 52 | { 53 | folderSettings=fsetting; 54 | } 55 | void BasicImageWidget::setFolderSettings(const char * fsetting) 56 | { 57 | folderSettings=fsetting; 58 | } 59 | 60 | void BasicImageWidget::setSaveTitle(const QString& stitle) 61 | { 62 | saveTitle=stitle; 63 | } 64 | 65 | void BasicImageWidget::setSaveTitle(const char * stitle) 66 | { 67 | saveTitle=stitle; 68 | } 69 | 70 | void BasicImageWidget::setBasicImageParent(QWidget *p) 71 | { 72 | m_parent=p; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /installer/packages/com.kapandaria.stereograma_menu/meta/installscript.qs: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2017 The Qt Company Ltd. 4 | ** Contact: https://www.qt.io/licensing/ 5 | ** 6 | ** This file is part of the FOO module of the Qt Toolkit. 7 | ** 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ 9 | ** Commercial License Usage 10 | ** Licensees holding valid commercial Qt licenses may use this file in 11 | ** accordance with the commercial license agreement provided with the 12 | ** Software or, alternatively, in accordance with the terms contained in 13 | ** a written agreement between you and The Qt Company. For licensing terms 14 | ** and conditions see https://www.qt.io/terms-conditions. For further 15 | ** information use the contact form at https://www.qt.io/contact-us. 16 | ** 17 | ** GNU General Public License Usage 18 | ** Alternatively, this file may be used under the terms of the GNU 19 | ** General Public License version 3 as published by the Free Software 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT 21 | ** included in the packaging of this file. Please review the following 22 | ** information to ensure the GNU General Public License requirements will 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. 24 | ** 25 | ** $QT_END_LICENSE$ 26 | ** 27 | ****************************************************************************/ 28 | 29 | function Component() 30 | { 31 | // default constructor 32 | } 33 | 34 | Component.prototype.createOperations = function() 35 | { 36 | component.createOperations(); 37 | 38 | if (systemInfo.productType === "windows") { 39 | component.addOperation("CreateShortcut", "@TargetDir@/Stereograma.exe", "@StartMenuDir@/Stereograma.lnk", 40 | "workingDirectory=@TargetDir@", "iconPath=@TargetDir@/Stereograma.exe", 41 | "iconId=0", "description=Open Stereograma"); 42 | component.addOperation("CreateShortcut", "@TargetDir@/maintenancetool.exe", "@StartMenuDir@/Uninstall_Stereograma.lnk", 43 | "workingDirectory=@TargetDir@", "iconPath=@TargetDir@/maintenancetool.exe", 44 | "iconId=0", "description=Uninstall Stereograma"); 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /stringtype.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | StringType 4 | 5 | 6 | 7 | 0 8 | 0 9 | 322 10 | 81 11 | 12 | 13 | 14 | 15 | 400 16 | 100 17 | 18 | 19 | 20 | Dialog 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | Qt::Vertical 30 | 31 | 32 | 33 | 20 34 | 40 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Qt::Horizontal 43 | 44 | 45 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | buttonBox 55 | accepted() 56 | StringType 57 | accept() 58 | 59 | 60 | 248 61 | 254 62 | 63 | 64 | 157 65 | 274 66 | 67 | 68 | 69 | 70 | buttonBox 71 | rejected() 72 | StringType 73 | reject() 74 | 75 | 76 | 316 77 | 260 78 | 79 | 80 | 286 81 | 274 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /presetedit.cpp: -------------------------------------------------------------------------------- 1 | #include "presetedit.h" 2 | #include "ui_presetedit.h" 3 | 4 | PresetEdit::PresetEdit(QWidget *parent) : 5 | QWidget(parent), 6 | ui(new Ui::PresetEdit) 7 | { 8 | ui->setupUi(this); 9 | m_preset=0; 10 | } 11 | 12 | PresetEdit::~PresetEdit() 13 | { 14 | delete ui; 15 | } 16 | 17 | void PresetEdit::setPreset(Preset *preset) 18 | { 19 | m_preset=preset; 20 | ui->crossEyedCheckBox->setChecked(!preset->getIsParallel()); 21 | ui->dpiSpinBox->setValue(preset->getDotsPerInch()); 22 | ui->maximumDepthDoubleSpinBox->setValue(preset->getMaximumDepth()); 23 | ui->minimumDepthDoubleSpinBox->setValue(preset->getMinimumDepth()); 24 | ui->eyeSeperationDoubleSpinBox->setValue(preset->getEyeSeperation()); 25 | ui->imageHeightSpinBox->setValue(preset->getResultHeight()); 26 | ui->imageWidthSpinBox->setValue(preset->getResultWidth()); 27 | ui->observerDistanceInDoubleSpinBox->setValue(preset->getObserverDistance()); 28 | } 29 | 30 | void PresetEdit::on_crossEyedCheckBox_stateChanged(int state) 31 | { 32 | m_preset->setIsParallel(!state); 33 | emit(onEdited()); 34 | } 35 | 36 | void PresetEdit::on_dpiSpinBox_valueChanged(int dpi) 37 | { 38 | m_preset->setDotsPerInch(dpi); 39 | emit(onEdited()); 40 | } 41 | 42 | void PresetEdit::on_minimumDepthDoubleSpinBox_valueChanged(double mindepth) 43 | { 44 | m_preset->setMinimumDepth(mindepth); 45 | emit(onEdited()); 46 | } 47 | 48 | void PresetEdit::on_maximumDepthDoubleSpinBox_valueChanged(double maxdepth) 49 | { 50 | ui->minimumDepthDoubleSpinBox->setMaximum(maxdepth-1); 51 | m_preset->setMaximumDepth(maxdepth); 52 | emit(onEdited()); 53 | } 54 | 55 | void PresetEdit::on_eyeSeperationDoubleSpinBox_valueChanged(double eyesep) 56 | { 57 | m_preset->setEyeSeperation(eyesep); 58 | emit(onEdited()); 59 | } 60 | 61 | void PresetEdit::on_observerDistanceInDoubleSpinBox_valueChanged(double obsdist) 62 | { 63 | m_preset->setObserverDistance(obsdist); 64 | emit(onEdited()); 65 | } 66 | 67 | void PresetEdit::on_imageHeightSpinBox_valueChanged(int height) 68 | { 69 | m_preset->setResultHeight(height); 70 | emit(onEdited()); 71 | } 72 | 73 | void PresetEdit::on_imageWidthSpinBox_valueChanged(int width) 74 | { 75 | m_preset->setResultWidth(width); 76 | emit(onEdited()); 77 | } 78 | -------------------------------------------------------------------------------- /RPly/rplyfile.h: -------------------------------------------------------------------------------- 1 | #ifndef RPLY_FILE_H 2 | #define RPLY_FILE_H 3 | /* ---------------------------------------------------------------------- 4 | * RPly library, read/write PLY files 5 | * Diego Nehab, IMPA 6 | * http://www.impa.br/~diego/software/rply 7 | * 8 | * This library is distributed under the MIT License. See notice 9 | * at the end of this file. 10 | * ---------------------------------------------------------------------- */ 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /* ---------------------------------------------------------------------- 17 | * Opens a PLY file for reading (fails if file is not a PLY file) 18 | * 19 | * file_pointer: FILE * to file open for reading 20 | * error_cb: error callback function 21 | * idata,pdata: contextual information available to users 22 | * 23 | * Returns 1 if successful, 0 otherwise 24 | * ---------------------------------------------------------------------- */ 25 | p_ply ply_open_from_file(FILE *file_pointer, p_ply_error_cb error_cb, 26 | long idata, void *pdata); 27 | 28 | /* ---------------------------------------------------------------------- 29 | * Creates new PLY file 30 | * 31 | * file_pointer: FILE * to a file open for writing 32 | * storage_mode: file format mode 33 | * error_cb: error callback function 34 | * idata,pdata: contextual information available to users 35 | * 36 | * Returns handle to PLY file if successfull, NULL otherwise 37 | * ---------------------------------------------------------------------- */ 38 | p_ply ply_create_to_file(FILE *file_pointer, e_ply_storage_mode storage_mode, 39 | p_ply_error_cb error_cb, long idata, void *pdata); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif /* RPLY_FILE_H */ 46 | 47 | /* ---------------------------------------------------------------------- 48 | * Copyright (C) 2003-2015 Diego Nehab. All rights reserved. 49 | * 50 | * Permission is hereby granted, free of charge, to any person obtaining 51 | * a copy of this software and associated documentation files (the 52 | * "Software"), to deal in the Software without restriction, including 53 | * without limitation the rights to use, copy, modify, merge, publish, 54 | * distribute, sublicense, and/or sell copies of the Software, and to 55 | * permit persons to whom the Software is furnished to do so, subject to 56 | * the following conditions: 57 | * 58 | * The above copyright notice and this permission notice shall be 59 | * included in all copies or substantial portions of the Software. 60 | * 61 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 62 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 63 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 64 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 65 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 66 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 67 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 68 | * ---------------------------------------------------------------------- */ 69 | -------------------------------------------------------------------------------- /modeldepthviewer.cpp: -------------------------------------------------------------------------------- 1 | #include "modeldepthviewer.h" 2 | #include "ui_modeldepthviewer.h" 3 | #include 4 | #include 5 | #include "stereomaker.h" 6 | #include "mainwindow.h" 7 | 8 | ModelDepthViewer::ModelDepthViewer(QWidget *parent) : 9 | QMainWindow(parent), 10 | ui(new Ui::ModelDepthViewer) 11 | { 12 | ui->setupUi(this); 13 | ui->modelview->setSaveTitle("Rendered Depth Image"); 14 | ui->modelview->setFolderSettings("depthmaps"); 15 | ui->modelview->setBasicImageParent(this); 16 | } 17 | 18 | int ModelDepthViewer::getOutputImageWidth() 19 | { 20 | return ui->widthSpin->value(); 21 | } 22 | 23 | int ModelDepthViewer::getOutputImageHeight() 24 | { 25 | return ui->heightSpin->value(); 26 | } 27 | void ModelDepthViewer::setModel(Model3D *model) 28 | { 29 | ui->modelview->setModel(model); 30 | ui->modelview->setParams(ui->moveXSlider->value()/8.0,ui->moveYSlider->value()/8.0, 31 | ui->zoomSlider->value(),ui->contrastSlider->value(), 32 | ui->hSliderRotX->value(),ui->hSliderRotY->value(),ui->hSliderRotZ->value(),ui->scaleSlider->value()); 33 | ui->modelview->repaint(); 34 | } 35 | 36 | ModelDepthViewer::~ModelDepthViewer() 37 | { 38 | delete ui; 39 | } 40 | 41 | 42 | void ModelDepthViewer::on_hSliderRotZ_valueChanged(int value) 43 | { 44 | ui->modelview->setRotationZ(value); 45 | ui->modelview->repaint(); 46 | } 47 | 48 | void ModelDepthViewer::on_hSliderRotX_valueChanged(int value) 49 | { 50 | ui->modelview->setRotationX(value); 51 | ui->modelview->repaint(); 52 | } 53 | 54 | void ModelDepthViewer::on_hSliderRotY_valueChanged(int value) 55 | { 56 | ui->modelview->setRotationY(value); 57 | ui->modelview->repaint(); 58 | } 59 | 60 | void ModelDepthViewer::on_actionSave_Image_triggered() 61 | { 62 | ui->modelview->snapShot(); 63 | ui->modelview->saveAsImage(); 64 | } 65 | 66 | void ModelDepthViewer::on_zoomSlider_valueChanged(int value) 67 | { 68 | ui->modelview->setZoom(value); 69 | ui->modelview->repaint(); 70 | } 71 | void ModelDepthViewer::on_scaleSlider_valueChanged(int value) 72 | { 73 | ui->modelview->setScale(value); 74 | ui->modelview->repaint(); 75 | } 76 | 77 | void ModelDepthViewer::on_contrastSlider_valueChanged(int value) 78 | { 79 | ui->modelview->setContrast(value); 80 | ui->modelview->repaint(); 81 | } 82 | 83 | void ModelDepthViewer::on_actionPush_Image_triggered() 84 | { 85 | const QImage * im=ui->modelview->snapShot(); 86 | if (im!=0) 87 | ((MainWindow*)parentWidget())->setDepthImage(*im); 88 | 89 | } 90 | 91 | void ModelDepthViewer::on_moveXSlider_valueChanged(int value) 92 | { 93 | ui->modelview->setXOffset(value/8.0); 94 | ui->modelview->repaint(); 95 | } 96 | 97 | void ModelDepthViewer::on_moveYSlider_valueChanged(int value) 98 | { 99 | ui->modelview->setYOffset(value/8.0); 100 | ui->modelview->repaint(); 101 | } 102 | 103 | void ModelDepthViewer::on_widthSpin_editingFinished() 104 | { 105 | ui->modelview->setViewport(getOutputImageWidth(),getOutputImageHeight()); 106 | ui->modelview->repaint(); 107 | } 108 | 109 | void ModelDepthViewer::on_heightSpin_editingFinished() 110 | { 111 | ui->modelview->setViewport(getOutputImageWidth(),getOutputImageHeight()); 112 | ui->modelview->repaint(); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /anaglyphmaker.cpp: -------------------------------------------------------------------------------- 1 | #include "anaglyphmaker.h" 2 | #include "imageviewer.h" 3 | #include "ui_anaglyphmaker.h" 4 | #include 5 | 6 | AnaglyphMaker::AnaglyphMaker(QWidget *parent) : 7 | QMainWindow(parent), 8 | ui(new Ui::AnaglyphMaker) 9 | { 10 | ui->setupUi(this); 11 | ui->rightView->setBasicImageParent(this); 12 | ui->rightView->setFolderSettings("anaglyph"); 13 | ui->rightView->setSaveTitle("Right Image"); 14 | ui->leftView->setBasicImageParent(this); 15 | ui->leftView->setFolderSettings("anaglyph"); 16 | ui->leftView->setSaveTitle("Left Image"); 17 | } 18 | 19 | AnaglyphMaker::~AnaglyphMaker() 20 | { 21 | delete ui; 22 | } 23 | 24 | void AnaglyphMaker::on_mergeButton_clicked() 25 | { 26 | if (ui->leftView->getImage().isNull() || ui->rightView->getImage().isNull()) 27 | { 28 | QMessageBox::warning(this,"Error","Please load images"); 29 | return; 30 | } 31 | if ((ui->leftView->getImage().width() != ui->rightView->getImage().width()) 32 | || (ui->leftView->getImage().height() != ui->rightView->getImage().height())) 33 | { 34 | QMessageBox::warning(this,"Error","Images are not at the same size."); 35 | return; 36 | } 37 | int width = ui->leftView->getImage().width(); 38 | int height = ui->leftView->getImage().height(); 39 | 40 | const QImage * refLeft=ui->leftView->getImagePtr(); 41 | const QImage * refRight=ui->rightView->getImagePtr(); 42 | if (ui->swapButton->isChecked()) 43 | { 44 | const QImage *temp=refLeft; 45 | refLeft=refRight; 46 | refRight=temp; 47 | } 48 | QImage imLeft,imRight; 49 | if (ui->leftView->getImage().depth()!=32) 50 | imLeft=refLeft->convertToFormat(QImage::Format_ARGB32); 51 | else 52 | imLeft=*refLeft; 53 | 54 | if (ui->rightView->getImage().depth()!=32) 55 | imRight=refRight->convertToFormat(QImage::Format_ARGB32); 56 | else 57 | imRight=*refRight; 58 | 59 | QImage result(width,height,QImage::Format_ARGB32); 60 | unsigned int *resptr; 61 | unsigned int *endptr; 62 | const unsigned int *leftptr; 63 | const unsigned int *rightptr; 64 | unsigned int rightalpha,leftalpha; 65 | unsigned int alpha; 66 | unsigned int r,g,b; 67 | for (int i=0;i>24; 76 | leftalpha=((*leftptr)&0xff000000)>>24; 77 | r=((*leftptr)&0x00ff0000)>>16; 78 | g=((*rightptr)&0x0000ff00)>>8; 79 | b=((*rightptr)&0x000000ff); 80 | alpha = leftalpha+rightalpha-rightalpha*leftalpha/255; 81 | if (alpha==0) 82 | { 83 | *resptr=0; 84 | resptr++; 85 | rightptr++; 86 | leftptr++; 87 | } 88 | else 89 | { 90 | r=(unsigned char)((leftalpha*r)/(alpha)); 91 | 92 | g=(unsigned char)((rightalpha*g)/(alpha)); 93 | 94 | b=(unsigned char)((rightalpha*b)/(alpha)); 95 | *resptr=(alpha<<24)|(r<<16)|(g<<8)|b; 96 | resptr++; 97 | rightptr++; 98 | leftptr++; 99 | } 100 | } 101 | } 102 | ImageViewer * imview=new ImageViewer(this); 103 | imview->setWindowTitle("Result"); 104 | imview->setFolderSettings("anaglyph_result"); 105 | imview->setSaveTitle("Anaglyph"); 106 | imview->setImage(result); 107 | imview->show(); 108 | } 109 | -------------------------------------------------------------------------------- /imageviewer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ImageViewer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 800 10 | 600 11 | 12 | 13 | 14 | Image Viewer 15 | 16 | 17 | 18 | 19 | 20 | 21 | true 22 | 23 | 24 | 25 | 26 | 0 27 | 0 28 | 780 29 | 527 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 0 38 | 0 39 | 40 | 41 | 42 | 43 | 44 | 45 | Qt::AlignCenter 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 0 59 | 0 60 | 800 61 | 27 62 | 63 | 64 | 65 | 66 | File 67 | 68 | 69 | 70 | 71 | 72 | 73 | Effects 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | :/images/save.png:/images/save.png 85 | 86 | 87 | Save As... 88 | 89 | 90 | true 91 | 92 | 93 | 94 | 95 | 96 | :/images/exit.png:/images/exit.png 97 | 98 | 99 | Close 100 | 101 | 102 | true 103 | 104 | 105 | 106 | 107 | Invert 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | actionExit 117 | triggered() 118 | ImageViewer 119 | close() 120 | 121 | 122 | -1 123 | -1 124 | 125 | 126 | 399 127 | 299 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /presetsketch.cpp: -------------------------------------------------------------------------------- 1 | #include "presetsketch.h" 2 | 3 | PresetSketch::PresetSketch(QWidget *parent) : 4 | QWidget(parent) 5 | { 6 | def_width=16; 7 | def_height=50; 8 | eye_size=1; 9 | m_preset=0; 10 | m_heights.append(QPointF(-1,0)); 11 | m_heights.append(QPointF(-0.8,0.2)); 12 | m_heights.append(QPointF(-0.8,0.2)); 13 | m_heights.append(QPointF(-0.5,0.6)); 14 | m_heights.append(QPointF(-0.5,0.6)); 15 | m_heights.append(QPointF(-0.3,0.4)); 16 | m_heights.append(QPointF(-0.3,0.4)); 17 | m_heights.append(QPointF(-0.0,0.8)); 18 | m_heights.append(QPointF(-0.0,0.8)); 19 | m_heights.append(QPointF(0.1,0.64)); 20 | m_heights.append(QPointF(0.1,0.64)); 21 | m_heights.append(QPointF(0.2,0.5)); 22 | m_heights.append(QPointF(0.2,0.5)); 23 | m_heights.append(QPointF(0.5,0.7)); 24 | m_heights.append(QPointF(0.5,0.7)); 25 | m_heights.append(QPointF(0.8,0.3)); 26 | m_heights.append(QPointF(0.8,0.3)); 27 | m_heights.append(QPointF(1.0,0.1)); 28 | } 29 | 30 | void PresetSketch::setPreset(Preset *preset) 31 | { 32 | m_preset=preset; 33 | repaint(); 34 | } 35 | 36 | float min(float x,float y) 37 | { 38 | if(x>y) 39 | return y; 40 | return x; 41 | } 42 | float max(float x,float y) 43 | { 44 | if(x>y) 45 | return x; 46 | return y; 47 | } 48 | 49 | 50 | void PresetSketch::paintEvent(QPaintEvent *) 51 | { 52 | 53 | if (!m_preset) 54 | { 55 | return; 56 | } 57 | QPainter painter(this); 58 | painter.setRenderHint(QPainter::Antialiasing); 59 | float scale_factor=min(this->width()/def_width,this->height()/def_height); 60 | float shiftx=0,shifty=0; 61 | if (this->width()/def_width > this->height()/def_height) 62 | { 63 | shiftx=(this->width()-scale_factor*def_width)/2; 64 | } 65 | else 66 | { 67 | shifty=(this->height()-scale_factor*def_height)/2; 68 | } 69 | 70 | float eyesep=m_preset->getEyeSeperation(); 71 | float lefteyex=def_width/2-eyesep/2; 72 | float obs_dist=m_preset->getObserverDistance(); 73 | //two eyes 74 | painter.drawEllipse(shiftx+scale_factor*(lefteyex-eye_size/2),shifty+scale_factor*1,scale_factor*eye_size,scale_factor*eye_size); 75 | painter.drawEllipse(shiftx+scale_factor*(lefteyex-eye_size/2+eyesep),shifty+scale_factor*1,scale_factor*eye_size,scale_factor*eye_size); 76 | //screen 77 | float screen_width= m_preset->getResultWidth()/(float)m_preset->getDotsPerInch(); 78 | painter.drawLine(shiftx+scale_factor*(def_width/2-screen_width/2),shifty+scale_factor*(1+eye_size/2+obs_dist),shiftx+scale_factor*(def_width/2+screen_width/2),shifty+scale_factor*(1+eye_size/2+obs_dist)); 79 | float max_depth=m_preset->getMaximumDepth(); 80 | float min_depth=m_preset->getMinimumDepth(); 81 | bool cross=!m_preset->getIsParallel(); 82 | QVector h_proccessed; 83 | QPointF i; 84 | QPoint spoint; 85 | if(!cross) 86 | { 87 | float pxscale=(screen_width-eyesep)*(obs_dist+min_depth)/(2*obs_dist)+(eyesep/2); 88 | foreach (i, m_heights) 89 | { 90 | h_proccessed.append(QPoint (shiftx+scale_factor*(i.x()*pxscale+def_width/2),shifty+scale_factor*(-i.y()*(max_depth-min_depth)+1+eye_size/2+obs_dist+max_depth))); 91 | } 92 | 93 | } 94 | else 95 | { 96 | float in_far=obs_dist+max_depth; 97 | float in_near=obs_dist+min_depth; 98 | float screen_sep_near=(eyesep*min_depth)/in_near; 99 | float screen_sep_far=(eyesep*max_depth)/in_far; 100 | float out_far=(obs_dist*eyesep)/(eyesep+screen_sep_near); 101 | float out_near=(obs_dist*eyesep)/(eyesep+screen_sep_far); 102 | float pxscale=(screen_width+eyesep)*(out_near)/(2*obs_dist)-(eyesep/2); 103 | foreach (i, m_heights) 104 | { 105 | h_proccessed.append(QPoint (shiftx+scale_factor*(i.x()*pxscale+def_width/2),shifty+scale_factor*(-i.y()*(out_far-out_near)+1+eye_size/2+out_far))); 106 | } 107 | } 108 | painter.drawLines(h_proccessed); 109 | 110 | spoint=h_proccessed.at(3); 111 | if(!cross) 112 | { 113 | painter.drawLine(shiftx+scale_factor*(def_width/2-eyesep/2),shifty+scale_factor*(1+eye_size/2),spoint.x(),spoint.y()); 114 | painter.drawLine(shiftx+scale_factor*(def_width/2+eyesep/2),shifty+scale_factor*(1+eye_size/2),spoint.x(),spoint.y()); 115 | } 116 | else 117 | { 118 | float eyeleftx=shiftx+scale_factor*(def_width/2-eyesep/2); 119 | float eyerightx=shiftx+scale_factor*(def_width/2+eyesep/2); 120 | float eyey=shifty+scale_factor*(1+eye_size/2); 121 | float screeny=shifty+scale_factor*(1+eye_size/2+obs_dist); 122 | float leyes=(-eyeleftx+spoint.x())*(screeny-spoint.y())/(spoint.y()-eyey)+spoint.x(); 123 | float reyes=(-eyerightx+spoint.x())*(screeny-spoint.y())/(spoint.y()-eyey)+spoint.x(); 124 | painter.drawLine(eyeleftx,eyey,leyes,screeny); 125 | painter.drawLine(eyerightx,eyey,reyes,screeny); 126 | } 127 | } 128 | 129 | void PresetSketch::presetUpdated() 130 | { 131 | repaint(); 132 | } 133 | -------------------------------------------------------------------------------- /stereograma.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 33 | 37 | 41 | 42 | 52 | 53 | 73 | 78 | 79 | -------------------------------------------------------------------------------- /imagecontainerwidget.cpp: -------------------------------------------------------------------------------- 1 | #include "imagecontainerwidget.h" 2 | #include 3 | #include 4 | #include 5 | #include "imagefiledialog.h" 6 | #include 7 | #include 8 | 9 | #include 10 | #if QT_VERSION >= QT_VERSION_CHECK(5,15,1) 11 | #define WEBP_FILTER " *.webp *.WEBP" 12 | #else 13 | #define WEBP_FILTER "" 14 | #endif 15 | 16 | 17 | ImageContainerWidget::ImageContainerWidget(QWidget *parent) : 18 | QLabel(parent) 19 | { 20 | 21 | connect(&netManager, SIGNAL(finished(QNetworkReply*)), 22 | SLOT(downloadFinished(QNetworkReply*))); 23 | connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), 24 | SLOT(showContextMenu(const QPoint&))); 25 | _loadAction=myMenu.addAction("Load"); 26 | _saveAsAction=myMenu.addAction("Save As..."); 27 | _viewAction=myMenu.addAction("View"); 28 | _unloadAction=myMenu.addAction("Unload"); 29 | m_viewer=new ImageViewer(this); 30 | setAcceptDrops(true); 31 | } 32 | const QString & ImageContainerWidget::getText() 33 | { 34 | if (replaceText.isNull()) 35 | { 36 | replaceText=text(); 37 | } 38 | return replaceText; 39 | } 40 | 41 | 42 | void ImageContainerWidget::mySetPixmap() 43 | { 44 | if (replaceText.isNull()) 45 | { 46 | replaceText=text(); 47 | } 48 | if (imdata.isNull()) 49 | { 50 | setAlignment(Qt::AlignLeft | Qt::AlignTop); 51 | setText(replaceText); 52 | } 53 | else 54 | { 55 | setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 56 | setScaledContents(false); 57 | QSize size = QSize(width(),height()); 58 | QImage smallimage=imdata.convertToFormat(QImage::Format_ARGB32).scaled(size, Qt::KeepAspectRatio); 59 | setPixmap(QPixmap::fromImage(smallimage)); 60 | 61 | } 62 | } 63 | void ImageContainerWidget::setImage(const QString &fileName) 64 | { 65 | if(!imdata.load(fileName)) 66 | QMessageBox::warning(this,"Error","Unrecognized image format"); 67 | mySetPixmap(); 68 | } 69 | 70 | void ImageContainerWidget::setImage(const QImage &image) 71 | { 72 | imdata=image; 73 | mySetPixmap(); 74 | } 75 | 76 | void ImageContainerWidget::downloadFinished(QNetworkReply* reply) 77 | { 78 | if (!reply->error()) 79 | { 80 | if(!imdata.load((QIODevice*)reply,0)) 81 | QMessageBox::warning(this,"Error","Unrecognized image format"); 82 | mySetPixmap(); 83 | } 84 | else 85 | { 86 | QMessageBox::warning(this,"Error","Could not download the file"); 87 | } 88 | reply->deleteLater(); 89 | } 90 | void ImageContainerWidget::showContextMenu(const QPoint& pos) 91 | { 92 | QPoint globalPos = mapToGlobal(pos); 93 | QAction* selectedItem = myMenu.exec(globalPos); 94 | if (selectedItem == _saveAsAction) 95 | { 96 | saveDialog(); 97 | } 98 | else if (selectedItem == _unloadAction) 99 | { 100 | imdata= QImage(); 101 | mySetPixmap(); 102 | } 103 | else if(selectedItem== _loadAction) 104 | { 105 | openDialog(); 106 | } 107 | else if(selectedItem== _viewAction) 108 | { 109 | m_viewer->setFolderSettings(folderSettings); 110 | m_viewer->setSaveTitle(saveTitle); 111 | m_viewer->setImage(imdata); 112 | m_viewer->show(); 113 | } 114 | } 115 | 116 | 117 | 118 | void ImageContainerWidget::saveDialog() 119 | { 120 | saveAsImage(); 121 | } 122 | 123 | void ImageContainerWidget::openDialog() 124 | { 125 | QSettings settings; 126 | QString cdir=settings.value(folderSettings,folderSettings).toString(); 127 | 128 | ImageFileDialog dlg(this); 129 | 130 | dlg.init(); 131 | dlg.setFileMode( QFileDialog::ExistingFile); 132 | dlg.setAcceptMode(QFileDialog::AcceptOpen); 133 | dlg.setDirectory(cdir); 134 | dlg.setNameFilter(tr("Images (*.png *.xpm *.jpg *.jpeg *.bmp *.gif *.tiff *.tif *.PNG *.XPM *.JPG *.JPEG *.BMP *.GIF *.TIF *.TIFF" WEBP_FILTER ")")); 135 | dlg.setWindowTitle("Open "+getText()); 136 | QString fileName; 137 | 138 | if (dlg.exec()) 139 | { 140 | fileName = dlg.selectedFiles().first(); 141 | settings.setValue(folderSettings, QFileInfo(fileName).absoluteDir().absolutePath()); 142 | setImage(fileName); 143 | } 144 | dlg.deinit(); 145 | 146 | } 147 | 148 | void ImageContainerWidget::mouseDoubleClickEvent(QMouseEvent * ) 149 | { 150 | openDialog(); 151 | } 152 | void ImageContainerWidget::dragEnterEvent(QDragEnterEvent *event) 153 | { 154 | if (event->mimeData()->hasFormat("text/uri-list")) 155 | event->acceptProposedAction(); 156 | } 157 | void ImageContainerWidget::dropEvent(QDropEvent *event) 158 | { 159 | QList urls = event->mimeData()->urls(); 160 | if (urls.isEmpty()) 161 | return; 162 | QString fileName = urls.first().toLocalFile(); 163 | if (fileName.isEmpty()) 164 | { 165 | QNetworkRequest request(urls.first()); 166 | netManager.get(request); 167 | } 168 | else 169 | { 170 | setImage(fileName); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /presetedit.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PresetEdit 4 | 5 | 6 | 7 | 0 8 | 0 9 | 244 10 | 298 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 20 | Cross eyed 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Eye seperation (in) 35 | 36 | 37 | 38 | 39 | 40 | 41 | 1.500000000000000 42 | 43 | 44 | 3.000000000000000 45 | 46 | 47 | 0.100000000000000 48 | 49 | 50 | 2.500000000000000 51 | 52 | 53 | 54 | 55 | 56 | 57 | Observer distance (in) 58 | 59 | 60 | 61 | 62 | 63 | 64 | 16.000000000000000 65 | 66 | 67 | 26.000000000000000 68 | 69 | 70 | 0.500000000000000 71 | 72 | 73 | 22.000000000000000 74 | 75 | 76 | 77 | 78 | 79 | 80 | Maximum depth (in) 81 | 82 | 83 | 84 | 85 | 86 | 87 | 6.000000000000000 88 | 89 | 90 | 22.000000000000000 91 | 92 | 93 | 0.250000000000000 94 | 95 | 96 | 8.000000000000000 97 | 98 | 99 | 100 | 101 | 102 | 103 | Minimum depth (in) 104 | 105 | 106 | 107 | 108 | 109 | 110 | 3.000000000000000 111 | 112 | 113 | 8.000000000000000 114 | 115 | 116 | 0.250000000000000 117 | 118 | 119 | 120 | 121 | 122 | 123 | Image width (pixels) 124 | 125 | 126 | 127 | 128 | 129 | 130 | 320 131 | 132 | 133 | 4096 134 | 135 | 136 | 4 137 | 138 | 139 | 2048 140 | 141 | 142 | 143 | 144 | 145 | 146 | Image height (pixels) 147 | 148 | 149 | 150 | 151 | 152 | 153 | 240 154 | 155 | 156 | 4096 157 | 158 | 159 | 4 160 | 161 | 162 | 1536 163 | 164 | 165 | 166 | 167 | 168 | 169 | dots per inch 170 | 171 | 172 | 173 | 174 | 175 | 176 | 50 177 | 178 | 179 | 600 180 | 181 | 182 | 150 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /FormulaGen.cpp: -------------------------------------------------------------------------------- 1 | #include "FormulaGen.h" 2 | #include "ui_FormulaGen.h" 3 | #include "exprtk/exprtk.hpp" 4 | #include "stereomaker.h" 5 | #include "mainwindow.h" 6 | #include 7 | #include 8 | #include 9 | 10 | typedef exprtk::symbol_table symbol_table_t; 11 | typedef exprtk::expression expression_t; 12 | typedef exprtk::parser parser_t; 13 | 14 | FormulaGen::FormulaGen(QWidget *parent) : 15 | QMainWindow(parent), 16 | ui(new Ui::FormulaGen) 17 | { 18 | ui->setupUi(this); 19 | setBasicImageParent(this); 20 | setSaveTitle("Formula Depth Image"); 21 | setFolderSettings("depthmaps"); 22 | QSettings settings; 23 | //settings.remove("formula"); 24 | formulaList=settings.value("formula",QStringList()<<"0.5+0.5*sin( 100*(((x-0.5)*w/h)^2+(y-0.5)^2)^0.5)"<< 25 | "var f :=sin(x*2*pi)*0.3;\n" 26 | "var multip := 3.333;\n" 27 | "(f>abs((y-0.5)))*(0.5+0.5*multip*sqrt(f*f-(y-0.5)*(y-0.5)))+(-f>abs((y-0.5)))*(0.5-0.5*multip*sqrt(f*f-(y-0.5)*(y-0.5)))"<< 28 | "var x0 := (x*w/h-0.8)*4;\n" 29 | "var y0 := (y-0.5)*4;\n" 30 | "var tx := x0;\n" 31 | "var ty := y0;\n" 32 | "var temp := 0;\n" 33 | "for(var i :=0; i <=8;i+=1)\n" 34 | "{\n" 35 | "temp := tx*tx-ty*ty+x0;\n" 36 | "ty := 2*tx*ty+y0;\n" 37 | "tx := temp;\n" 38 | "}\n" 39 | "(tx*tx+ty*ty)*0.1").toStringList(); 40 | ui->listWidget->addItems(formulaList); 41 | ui->formulaPText->setPlainText(formulaList.last()); 42 | } 43 | 44 | FormulaGen::~FormulaGen() 45 | { 46 | delete ui; 47 | } 48 | 49 | int FormulaGen::getOutputImageWidth() 50 | { 51 | return ui->widthSpin->value(); 52 | } 53 | 54 | int FormulaGen::getOutputImageHeight() 55 | { 56 | return ui->heightSpin->value(); 57 | } 58 | 59 | void FormulaGen::on_generatePb_clicked() 60 | { 61 | ui->errorTable->clearContents(); 62 | ui->errorTable->setRowCount(0); 63 | int w=getOutputImageWidth(); 64 | int h=getOutputImageHeight(); 65 | QString formule_str=ui->formulaPText->toPlainText(); 66 | QByteArray formula_ba=formule_str.toLatin1(); 67 | const char* formula_buf=formula_ba.constData(); 68 | imdata=QImage(w,h,QImage::Format_RGB32); 69 | 70 | float x_s, y_s; 71 | float f_w=w, f_h=h; 72 | 73 | symbol_table_t symbol_table; 74 | symbol_table.add_pi(); 75 | symbol_table.add_constant("e", M_E); 76 | symbol_table.add_variable("x", x_s); 77 | symbol_table.add_variable("y", y_s); 78 | symbol_table.add_variable("w", f_w); 79 | symbol_table.add_variable("h", f_h); 80 | expression_t expression; 81 | 82 | expression.register_symbol_table(symbol_table); 83 | parser_t::settings_store sstore; 84 | sstore.disable_all_logic_ops(); 85 | //sstore.disable_all_assignment_ops(); 86 | sstore.disable_all_control_structures(); 87 | sstore.enable_control_structure(parser_t::settings_store::e_ctrl_for_loop); 88 | parser_t parser(sstore); 89 | 90 | bool compile_valid=parser.compile(formula_buf, expression); 91 | if (compile_valid) 92 | { 93 | int val; 94 | for (int x=0;x255) 105 | val=255; 106 | imdata.setPixel(x,y,0xff000000|(val<<16)|(val<<8)|val); 107 | } 108 | } 109 | //imdata=imdata.convertToFormat(QImage::Format_Indexed8,StereoMaker::getGrayScale()); 110 | ui->imageViewArea->setPixmap(QPixmap::fromImage(imdata)); 111 | if (!formulaList.contains(formule_str)) 112 | { 113 | formulaList<listWidget->addItem(formule_str); 117 | } 118 | 119 | 120 | } 121 | else { 122 | ui->errorTable->setRowCount(parser.error_count()); 123 | ui->errorTable->setColumnCount(3); 124 | QTextCursor cursor = ui->formulaPText->textCursor(); 125 | 126 | 127 | 128 | for (std::size_t i = 0; i < parser.error_count(); ++i) 129 | { 130 | typedef exprtk::parser_error::type error_t; 131 | 132 | error_t error = parser.get_error(i); 133 | 134 | /*printf("Error[%02d] Position: %02d Type: [%14s] Msg: %s\n", 135 | (int)i, 136 | (int)error.token.position, 137 | exprtk::parser_error::to_str(error.mode).c_str(), 138 | error.diagnostic.c_str());*/ 139 | cursor.setPosition(error.token.position); 140 | ui->errorTable->setItem(i,0,new QTableWidgetItem(QString::number(error.token.position)+QString(" [%1,%2]").arg(cursor.blockNumber()+1).arg(cursor.positionInBlock()))); 141 | ui->errorTable->setItem(i,1,new QTableWidgetItem(tr(exprtk::parser_error::to_str(error.mode).c_str()))); 142 | ui->errorTable->setItem(i,2,new QTableWidgetItem(tr(error.diagnostic.c_str()))); 143 | 144 | } 145 | cursor.setPosition(parser.get_error(0).token.position); 146 | cursor.movePosition(QTextCursor::Right,QTextCursor::KeepAnchor); 147 | ui->formulaPText->setTextCursor(cursor); 148 | 149 | 150 | 151 | } 152 | } 153 | 154 | void FormulaGen::on_actionSave_Image_triggered() 155 | { 156 | saveAsImage(); 157 | } 158 | 159 | void FormulaGen::on_actionPush_Image_triggered() 160 | { 161 | ((MainWindow*)parentWidget())->setDepthImage(imdata); 162 | } 163 | 164 | void FormulaGen::on_actionPush_Image_as_Compose_Pattern_triggered() 165 | { 166 | ((MainWindow*)parentWidget())->setComposePattern(imdata); 167 | } 168 | 169 | void FormulaGen::on_listWidget_itemActivated(QListWidgetItem *item) 170 | { 171 | ui->formulaPText->setPlainText(item->text()); 172 | } 173 | -------------------------------------------------------------------------------- /FormulaGen.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | FormulaGen 4 | 5 | 6 | 7 | 0 8 | 0 9 | 596 10 | 701 11 | 12 | 13 | 14 | Formula 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 0 27 | 0 28 | 29 | 30 | 31 | <html><head/><body><p>x=[0..1]</p><p>y=[0..1]</p><p>w=Width</p><p>h=Height</p><p><span style=" font-weight:600;">output</span> =&gt; [0..1]</p><p>see <a href="https://github.com/ArashPartow/exprtk"><span style=" text-decoration: underline; color:#0000ff;">ExprTk manual</span></a></p><p>for function list.</p></body></html> 32 | 33 | 34 | Qt::RichText 35 | 36 | 37 | true 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | Width 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 90 55 | 16777215 56 | 57 | 58 | 59 | 64 60 | 61 | 62 | 4096 63 | 64 | 65 | 2048 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | Height 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 90 85 | 16777215 86 | 87 | 88 | 89 | 64 90 | 91 | 92 | 4096 93 | 94 | 95 | 1536 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | Generate 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 0 115 | 0 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | History 129 | 130 | 131 | 132 | 133 | 134 | 135 | true 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | errors: 147 | 148 | 149 | 150 | 151 | 152 | 153 | QAbstractItemView::NoEditTriggers 154 | 155 | 156 | QAbstractItemView::SingleSelection 157 | 158 | 159 | QAbstractItemView::SelectRows 160 | 161 | 162 | false 163 | 164 | 165 | true 166 | 167 | 168 | 169 | Position 170 | 171 | 172 | 173 | 174 | Type 175 | 176 | 177 | 178 | 179 | Msg 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 0 189 | 0 190 | 191 | 192 | 193 | 194 | 360 195 | 240 196 | 197 | 198 | 199 | QFrame::Panel 200 | 201 | 202 | QFrame::Raised 203 | 204 | 205 | 206 | 207 | 208 | true 209 | 210 | 211 | Qt::AlignCenter 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 0 221 | 0 222 | 596 223 | 22 224 | 225 | 226 | 227 | 228 | File 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | :/images/save.png:/images/save.png 241 | 242 | 243 | Save Image... 244 | 245 | 246 | true 247 | 248 | 249 | 250 | 251 | Push Image as Depth Map 252 | 253 | 254 | 255 | 256 | Push Image as Compose Pattern 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | -------------------------------------------------------------------------------- /anaglyphmaker.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | AnaglyphMaker 4 | 5 | 6 | 7 | 0 8 | 0 9 | 558 10 | 407 11 | 12 | 13 | 14 | Make an Anaglyph 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 0 29 | 153 30 | 255 31 | 32 | 33 | 34 | 35 | 36 | 37 | 0 38 | 153 39 | 255 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 0 49 | 153 50 | 255 51 | 52 | 53 | 54 | 55 | 56 | 57 | 0 58 | 153 59 | 255 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 159 69 | 158 70 | 158 71 | 72 | 73 | 74 | 75 | 76 | 77 | 0 78 | 153 79 | 255 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Qt::CustomContextMenu 88 | 89 | 90 | QFrame::Box 91 | 92 | 93 | QFrame::Sunken 94 | 95 | 96 | Left 97 | 98 | 99 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 0 108 | 0 109 | 110 | 111 | 112 | swap between left and right 113 | 114 | 115 | swap left and right 116 | 117 | 118 | 119 | 120 | 121 | 122 | :/images/swap.png:/images/swap.png 123 | 124 | 125 | 126 | 24 127 | 24 128 | 129 | 130 | 131 | true 132 | 133 | 134 | false 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 0 143 | 0 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 255 153 | 255 154 | 255 155 | 156 | 157 | 158 | 159 | 160 | 161 | 255 162 | 255 163 | 255 164 | 165 | 166 | 167 | 168 | 169 | 170 | 255 171 | 255 172 | 255 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 255 182 | 255 183 | 255 184 | 185 | 186 | 187 | 188 | 189 | 190 | 255 191 | 255 192 | 255 193 | 194 | 195 | 196 | 197 | 198 | 199 | 255 200 | 255 201 | 255 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 159 211 | 158 212 | 158 213 | 214 | 215 | 216 | 217 | 218 | 219 | 159 220 | 158 221 | 158 222 | 223 | 224 | 225 | 226 | 227 | 228 | 255 229 | 255 230 | 255 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | Qt::CustomContextMenu 239 | 240 | 241 | QFrame::Box 242 | 243 | 244 | QFrame::Sunken 245 | 246 | 247 | Right 248 | 249 | 250 | Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | Merge 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 0 269 | 0 270 | 558 271 | 22 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | ImageContainerWidget 280 | QLabel 281 |
imagecontainerwidget.h
282 |
283 |
284 | 285 | 286 | 287 | 288 |
289 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include "stereomaker.h" 4 | 5 | #include "imageviewer.h" 6 | #include "modeldepthviewer.h" 7 | #include "anaglyphmaker.h" 8 | #include "FormulaGen.h" 9 | #include "stringtype.h" 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | MainWindow::MainWindow(QWidget *parent) : 19 | QMainWindow(parent), 20 | ui(new Ui::MainWindow) 21 | { 22 | ui->setupUi(this); 23 | ui->presetSelect->addItem(QString("Default")); 24 | loadPresets(); 25 | ui->depthImage->setBasicImageParent(this); 26 | ui->depthImage->setFolderSettings("depthmaps"); 27 | ui->depthImage->setSaveTitle("Depth Map"); 28 | ui->composeImage->setBasicImageParent(this); 29 | ui->composeImage->setFolderSettings("compose"); 30 | ui->composeImage->setSaveTitle("Depth Compose"); 31 | ui->textureImage->setBasicImageParent(this); 32 | ui->textureImage->setFolderSettings("textures"); 33 | ui->textureImage->setSaveTitle("Texture"); 34 | QObject::connect(ui->presetEdit,SIGNAL(onEdited()),ui->presetSketcher,SLOT(presetUpdated())); 35 | } 36 | 37 | MainWindow::~MainWindow() 38 | { 39 | delete ui; 40 | Preset *temp; 41 | foreach (temp,m_presets) 42 | delete temp; 43 | } 44 | 45 | void MainWindow::setDepthImage(const QImage &image) 46 | { 47 | ui->depthImage->setImage(image); 48 | } 49 | void MainWindow::setComposePattern(const QImage &image) 50 | { 51 | ui->composeImage->setImage(image); 52 | } 53 | 54 | 55 | void MainWindow::on_renderButton_clicked() 56 | { 57 | 58 | StereoMaker smaker; 59 | if (ui->depthImage->getImage().isNull() || ui->textureImage->getImage().isNull()) 60 | { 61 | QMessageBox::warning(this,"Error","Please first load both texture and depth images"); 62 | } 63 | else 64 | { 65 | QImage depth_image=ui->depthImage->getImage().convertToFormat(QImage::Format_Indexed8,smaker.getGrayScale()); 66 | depth_image=depth_image.scaled(cur_preset->getResultWidth(),cur_preset->getResultHeight()); 67 | if (!ui->composeImage->getImage().isNull()) 68 | { 69 | float compose_height = ui->composeLevel->value()/100.0; 70 | float compose_scale = ui->composeScale->value()/128.0; 71 | QImage compose_image=ui->composeImage->getImage(); 72 | if (compose_scale!=1) 73 | { 74 | //compose_image = compose_image.scaledToWidth((int)(compose_image.width()*compose_scale),Qt::FastTransformation); 75 | compose_image = compose_image.scaled((int)(compose_image.width()*compose_scale),(int)(compose_image.height()*compose_scale),Qt::KeepAspectRatio,Qt::SmoothTransformation); 76 | } 77 | compose_image=compose_image.convertToFormat(QImage::Format_Indexed8,smaker.getGrayScale()); 78 | smaker.composeDepth(depth_image,compose_image,compose_height); 79 | } 80 | ImageViewer * imview=new ImageViewer(this); 81 | imview->setWindowTitle("Result"); 82 | imview->setFolderSettings("stereograms"); 83 | imview->setSaveTitle("Stereogram"); 84 | if (!cur_preset->getIsParallel()) 85 | depth_image.invertPixels(); 86 | const QImage *eye_helper_left=0; 87 | const QImage *eye_helper_right=0; 88 | bool show_helpers = ui->show_helpers->isChecked(); 89 | bool margin_helpers = show_helpers && ui->margin_helpers->isChecked(); 90 | QImage eye_helper_image_left=ui->helpers_image->getImage(); 91 | QImage eye_helper_image_right; 92 | if (show_helpers) 93 | { 94 | if(!eye_helper_image_left.isNull()) 95 | { 96 | if (ui->dual_helpers->isChecked()) 97 | { 98 | int half_width=eye_helper_image_left.width()/2; 99 | int height=eye_helper_image_left.height(); 100 | eye_helper_image_right=eye_helper_image_left.copy(half_width,0,half_width,height); 101 | eye_helper_image_left=eye_helper_image_left.copy(0,0,half_width,height); 102 | 103 | if (cur_preset->getIsParallel()) 104 | { 105 | eye_helper_left=&eye_helper_image_left; 106 | eye_helper_right=&eye_helper_image_right; 107 | } 108 | else 109 | { 110 | eye_helper_right=&eye_helper_image_left; 111 | eye_helper_left=&eye_helper_image_right; 112 | } 113 | } 114 | else 115 | { 116 | eye_helper_left=&eye_helper_image_left; 117 | eye_helper_right=&eye_helper_image_left; 118 | } 119 | } 120 | 121 | } 122 | QImage result =smaker.render(depth_image, ui->textureImage->getImage(),cur_preset,ui->parallelProgress,eye_helper_right,eye_helper_left,show_helpers,margin_helpers); 123 | imview->setImage(result); 124 | imview->show(); 125 | } 126 | } 127 | 128 | 129 | void MainWindow::on_action_obj_triggered() 130 | { 131 | QSettings settings; 132 | QString setting_name="objdir"; 133 | QString cdir=settings.value(setting_name,"models/").toString(); 134 | 135 | QString fileName = QFileDialog::getOpenFileName(parentWidget(), "Load Obj file", cdir, tr("OBJ File (*.obj *.OBJ)")); 136 | Model3D *m3d; 137 | if(fileName!="") 138 | { 139 | settings.setValue(setting_name, QFileInfo(fileName).absoluteDir().absolutePath()); 140 | m3d = new Model3D(); 141 | m3d->LoadObj(fileName); 142 | ModelDepthViewer * modelviewer=new ModelDepthViewer(this); 143 | modelviewer->setModel(m3d); 144 | modelviewer->show(); 145 | } 146 | 147 | } 148 | 149 | 150 | void MainWindow::on_action_ply_triggered() 151 | { 152 | QSettings settings; 153 | QString setting_name="objdir"; 154 | QString cdir=settings.value(setting_name,"models/").toString(); 155 | QString fileName = QFileDialog::getOpenFileName(parentWidget(), "Load Ply file", cdir, tr("PLY File (*.ply *.PLY)")); 156 | Model3D *m3d; 157 | if(fileName!="") 158 | { 159 | settings.setValue(setting_name, QFileInfo(fileName).absoluteDir().absolutePath()); 160 | m3d = new Model3D(); 161 | m3d->LoadPly(fileName); 162 | ModelDepthViewer * modelviewer=new ModelDepthViewer(this); 163 | modelviewer->setModel(m3d); 164 | modelviewer->show(); 165 | } 166 | } 167 | 168 | void MainWindow::on_actionLoad_Texture_triggered() 169 | { 170 | ui->textureImage->openDialog(); 171 | } 172 | 173 | void MainWindow::on_actionLoad_Depth_Map_triggered() 174 | { 175 | ui->depthImage->openDialog(); 176 | } 177 | 178 | void MainWindow::on_actionCreate_Anaglyph_triggered() 179 | { 180 | AnaglyphMaker * anaglyphWindow=new AnaglyphMaker(); 181 | anaglyphWindow->show(); 182 | } 183 | 184 | void MainWindow::loadPresets() 185 | { 186 | cur_preset=new Preset(QString("Default")); 187 | m_presets.append(cur_preset); 188 | ui->presetEdit->setPreset(cur_preset); 189 | ui->presetSketcher->setPreset(cur_preset); 190 | QFile file(SETTINGS_FILE); 191 | if (!file.open(QIODevice::ReadOnly)) 192 | return; 193 | QDataStream in(&file); 194 | int size; 195 | in>>size; 196 | Preset * temp_preset; 197 | for(;size>0;size--) 198 | { 199 | temp_preset=new Preset(in); 200 | m_presets.append(temp_preset); 201 | ui->presetSelect->addItem(temp_preset->getName()); 202 | } 203 | file.close(); 204 | } 205 | 206 | void MainWindow::savePresets() 207 | { 208 | QFile file(SETTINGS_FILE); 209 | if (!file.open(QIODevice::WriteOnly)) 210 | return; 211 | QDataStream out(&file); 212 | int size=m_presets.size()-1; 213 | out<toStream(out); 218 | } 219 | file.close(); 220 | } 221 | void MainWindow::on_actionAdd_preset_triggered() 222 | { 223 | StringType stdialog("Select Preset Name",this); 224 | if (stdialog.exec()==QDialog::Accepted) 225 | { 226 | Preset * temp_preset=new Preset(stdialog.getString()); 227 | m_presets.append(temp_preset); 228 | ui->presetSelect->addItem(temp_preset->getName()); 229 | } 230 | } 231 | 232 | void MainWindow::on_presetSelect_currentIndexChanged(int index) 233 | { 234 | if(indexpresetEdit->setPreset(cur_preset); 238 | ui->presetSketcher->setPreset(cur_preset); 239 | } 240 | } 241 | 242 | 243 | void MainWindow::on_actionSave_Presets_triggered() 244 | { 245 | savePresets(); 246 | } 247 | 248 | void MainWindow::on_actionReset_triggered() 249 | { 250 | ui->presetSketcher->setPreset(0); 251 | Preset *temp; 252 | foreach (temp,m_presets) 253 | delete temp; 254 | m_presets.clear(); 255 | int size=ui->presetSelect->count()-1; 256 | for(;size>0;size--) 257 | { 258 | ui->presetSelect->removeItem(size); 259 | } 260 | 261 | loadPresets(); 262 | } 263 | 264 | void MainWindow::on_actionRename_Preset_triggered() 265 | { 266 | int index=ui->presetSelect->currentIndex(); 267 | if(index>0) 268 | { 269 | StringType stdialog("Rename Preset",this); 270 | if (stdialog.exec()==QDialog::Accepted) 271 | { 272 | QString input_string=stdialog.getString(); 273 | ui->presetSelect->setItemText(index,input_string); 274 | m_presets.at(index)->setName(input_string); 275 | } 276 | } 277 | } 278 | 279 | void MainWindow::on_actionRemove_preset_triggered() 280 | { 281 | int index=ui->presetSelect->currentIndex(); 282 | if(index>0) 283 | { 284 | m_presets.removeAt(index); 285 | ui->presetSelect->removeItem(index); 286 | } 287 | } 288 | 289 | void MainWindow::on_actionGenerate_Depth_Map_triggered() 290 | { 291 | FormulaGen * formulaWindow=new FormulaGen(this); 292 | formulaWindow->show(); 293 | } 294 | 295 | void MainWindow::on_rolling_clicked() 296 | { 297 | QDesktopServices::openUrl(QUrl("https://play.google.com/store/apps/details?id=com.github.gnudles.rollingmarbles")); 298 | } 299 | 300 | void MainWindow::on_show_helpers_toggled(bool checked) 301 | { 302 | 303 | ui->helpers_image->setDisabled(!checked); 304 | ui->dual_helpers->setDisabled(!checked); 305 | ui->margin_helpers->setDisabled(!checked); 306 | } 307 | -------------------------------------------------------------------------------- /stereomaker.cpp: -------------------------------------------------------------------------------- 1 | //algorithm was taken from http://www.techmind.org/stereo/stech.html 2 | #include "stereomaker.h" 3 | #include 4 | #include 5 | 6 | 7 | QVector StereoMaker::grayscale; 8 | 9 | StereoMaker::StereoMaker() 10 | { 11 | depthsep= new int [256]; 12 | } 13 | 14 | StereoMaker::~StereoMaker() 15 | { 16 | delete [] depthsep; 17 | } 18 | 19 | void StereoMaker::composeDepth(QImage & depth,QImage & compose,float compose_height) 20 | { 21 | int dw=depth.width(),dh=depth.height(),cw=compose.width(),ch=compose.height(); 22 | int x,y,cy=0; 23 | uchar * cptr; 24 | uchar * dptr; 25 | uchar * dchunk; 26 | uchar * dchunkend; 27 | uchar * ccptr; 28 | for(y=0;y *dchunk) 42 | *dchunk=value; 43 | dchunk++; 44 | ccptr++; 45 | } 46 | } 47 | if (x *dchunk) 56 | *dchunk=value; 57 | dchunk++; 58 | ccptr++; 59 | } 60 | } 61 | cy++; 62 | if (cy==ch) 63 | cy=0; 64 | } 65 | 66 | } 67 | 68 | const QVector & StereoMaker::getGrayScale() 69 | { 70 | if (StereoMaker::grayscale.isEmpty()) 71 | { 72 | int colorsetter; 73 | for (colorsetter = 0 ; colorsetter < 256 ; colorsetter++) 74 | StereoMaker::grayscale.append(qRgb(colorsetter,colorsetter,colorsetter)); 75 | } 76 | return StereoMaker::grayscale; 77 | } 78 | void scaleLine(uchar* big,const uchar* original,int sizeoriginal) 79 | { 80 | *big=*original; 81 | big++; 82 | sizeoriginal--; 83 | while(sizeoriginal>0) 84 | { 85 | sizeoriginal--; 86 | *big=((*original)*3+(*(original+1)))/4; 87 | big++; 88 | *big=((*original)+3*(*(original+1)))/4; 89 | original++; 90 | big++; 91 | } 92 | *big=*original; 93 | } 94 | 95 | QImage StereoMaker::render(const QImage & map, const QImage & ptrn, Preset *psettings, QProgressBar * qpbar, const QImage * eye_helper_right, const QImage * eye_helper_left, bool show_helper, bool helpers_margin) 96 | { 97 | qpbar->setMinimum(0); 98 | qpbar->setMaximum(10); 99 | qpbar->setValue(0); 100 | int width = map.width(); 101 | int height = map.height(); 102 | 103 | int oversam = 6; 104 | int vwidth = oversam*width*2; 105 | 106 | int x, left; 107 | int y, right; 108 | int *lookL = new int [vwidth]; 109 | int *lookR = new int [vwidth]; 110 | 111 | int dpi = psettings->getDotsPerInch(); 112 | int yShift=dpi/16; 113 | int obsDist; 114 | obsDist=dpi*psettings->getObserverDistance(); 115 | int eyeSep; 116 | eyeSep=dpi*psettings->getEyeSeperation(); 117 | int veyeSep=eyeSep*oversam*2; 118 | 119 | int maxdepth=dpi*psettings->getMaximumDepth(); 120 | int vmaxsep=(int)(((long)oversam*eyeSep*maxdepth*2)/(maxdepth+obsDist)); 121 | int maxsep=vmaxsep/(oversam*2); // pattern must be at 122 | // least this wide 123 | 124 | 125 | QImage pattern=ptrn.scaled(vmaxsep/oversam+1,(ptrn.height()*(maxsep+1))/ptrn.width(),Qt::IgnoreAspectRatio,Qt::SmoothTransformation); 126 | if (pattern.depth()!=32) 127 | pattern=pattern.convertToFormat(QImage::Format_ARGB32); 128 | int rh=0; 129 | QImage::Format out_format = pattern.format(); 130 | if (show_helper && helpers_margin) 131 | { 132 | if (eye_helper_left==0) 133 | rh=15*psettings->getDotsPerInch()/72; 134 | else 135 | { 136 | rh=eye_helper_left->height(); 137 | } 138 | rh=rh*3/2; 139 | out_format=QImage::Format_ARGB32; 140 | } 141 | 142 | QImage result(width,height+rh,out_format); 143 | QImage CurResultLine(vwidth,1,pattern.format()); 144 | QImage CurResultScaledLine;//scaled down 145 | 146 | int s=vwidth/2-vmaxsep/2; 147 | int poffset=vmaxsep-(s % vmaxsep); 148 | int pattern_height=pattern.height(); 149 | 150 | 151 | int featureZ,sep=0; 152 | bool visual; 153 | int lastlinked; 154 | int progbarval=0; 155 | int maxheight=dpi*(psettings->getMaximumDepth()-psettings->getMinimumDepth()); 156 | //benchmark 157 | QElapsedTimer t_time; 158 | t_time.start(); 159 | unsigned int **patternptr= new unsigned int *[pattern_height]; 160 | for (int i=pattern_height-1;i>=0;i--) 161 | { 162 | patternptr[i]=(unsigned int*)pattern.scanLine(i); 163 | } 164 | 165 | for(int depth_index=0;depth_index<256;depth_index++) 166 | { 167 | featureZ=maxdepth-depth_index*maxheight/256; 168 | depthsep[depth_index]=(int)((veyeSep*featureZ)/(featureZ+obsDist)); 169 | } 170 | 171 | uint *dataptr,*lineptr; 172 | uchar * mapptr=(uchar *)malloc(map.width()*2); 173 | for (y=0;y=0) && (rightright) // deeper than current 204 | { 205 | lookL[lookR[left]]=lookR[left]; // break old links 206 | lookR[left]=left; 207 | } 208 | else visual=false; 209 | } 210 | if (visual) 211 | { 212 | lookL[right]=left; 213 | lookR[left]=right; 214 | } // make link 215 | } 216 | } 217 | 218 | 219 | 220 | lastlinked=-10; // dummy initial value 221 | 222 | lineptr=(uint*)CurResultLine.scanLine(0); 223 | dataptr=lineptr+s; 224 | for (x=s; x=0; x--,dataptr--) 245 | { 246 | if (lookR[x]==x) 247 | { 248 | if (lastlinked==(x+1)) 249 | *dataptr=*(dataptr+1); 250 | else 251 | { 252 | *dataptr=patternptr[(y+((s-x)/vmaxsep+1)*yShift+pattern_height) % pattern_height][((x+poffset) % vmaxsep)/oversam]; 253 | } 254 | } 255 | else 256 | { 257 | *dataptr=*(lineptr+lookR[x]); 258 | lastlinked=x; // keep track of the last pixel to be constrained 259 | } 260 | } 261 | 262 | 263 | CurResultScaledLine = CurResultLine.scaled(width, 1, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); 264 | memcpy(result.scanLine(y+rh),CurResultScaledLine.scanLine(0),result.bytesPerLine()); 265 | if (progbarval!=10*y/(height-1)) 266 | { 267 | progbarval=10*y/(height-1); 268 | qpbar->setValue(progbarval); 269 | } 270 | } 271 | qDebug("Time elapsed: %lld ms", t_time.elapsed()); 272 | delete [] lookL; 273 | delete [] lookR; 274 | free(mapptr); 275 | delete [] patternptr; 276 | if (show_helper) 277 | { 278 | QPainter painter(&result); 279 | int rw; 280 | if (eye_helper_left==0) 281 | rw=15*psettings->getDotsPerInch()/72; 282 | else 283 | rw=eye_helper_left->width(); 284 | int rect_sep; 285 | if(!psettings->getIsParallel()) 286 | { 287 | int mindepth=dpi*psettings->getMinimumDepth(); 288 | 289 | rect_sep=(int)(((long)eyeSep*mindepth)/(mindepth+obsDist)); 290 | } 291 | else 292 | rect_sep=maxsep; 293 | if (rh == 0) 294 | { 295 | rh = 30; 296 | } 297 | if (eye_helper_left != 0 && eye_helper_right != 0) 298 | { 299 | painter.drawImage(QPoint(result.width()/2-rect_sep/2-rw/2,rh/6),*eye_helper_left); 300 | painter.drawImage(QPoint(result.width()/2+rect_sep/2-rw/2,rh/6),*eye_helper_right); 301 | } 302 | else 303 | { 304 | painter.setPen(QPen(QColor(255,255,255,128))); 305 | painter.drawRect( result.width()/2-rect_sep/2-rw/2, rh/6, rw, rw ); 306 | painter.drawRect( result.width()/2+rect_sep/2-rw/2, rh/6, rw, rw ); 307 | painter.setPen(QPen(QColor(0,0,0,128))); 308 | painter.drawRect( result.width()/2-rect_sep/2-rw/2+1, rh/6+1, rw-2, rw-2 ); 309 | painter.drawRect( result.width()/2+rect_sep/2-rw/2+1, rh/6+1, rw-2, rw-2 ); 310 | 311 | painter.fillRect( result.width()/2-rect_sep/2-rw/2+2, rh/6+2, rw-3, rw-3 ,QColor(255,255,255,60)); 312 | painter.fillRect( result.width()/2+rect_sep/2-rw/2+2, rh/6+2, rw-3, rw-3 ,QColor(255,255,255,60)); 313 | } 314 | } 315 | return result; 316 | } 317 | -------------------------------------------------------------------------------- /model3d.cpp: -------------------------------------------------------------------------------- 1 | #include "model3d.h" 2 | #if defined(__APPLE__) 3 | #define GL_SILENCE_DEPRECATION 4 | #include 5 | #include 6 | #else 7 | #include 8 | #endif 9 | #include 10 | #include 11 | #include 12 | #include "RPly/rply.h" 13 | 14 | Model3D::Model3D() 15 | { 16 | m_triangles=0; 17 | m_points=0; 18 | m_colors=0; 19 | m_nPoints=0; 20 | m_nTriangles=0; 21 | } 22 | 23 | Model3D::~Model3D() 24 | { 25 | if (m_triangles) 26 | delete [] m_triangles; 27 | if (m_points) 28 | delete [] m_points; 29 | if (m_colors) 30 | delete [] m_colors; 31 | } 32 | 33 | typedef struct 34 | { 35 | unsigned int a; 36 | unsigned int b; 37 | unsigned int c; 38 | } triple; 39 | 40 | void Model3D::LoadObj(const QString & filename) 41 | { 42 | QByteArray _filename=filename.toUtf8(); 43 | FILE *fp=fopen(_filename.data(),"r"); 44 | if (fp==0) 45 | return; 46 | QVector points; 47 | QVector triangles; 48 | float minX=INT_MAX,maxX=INT_MIN,minY=INT_MAX,maxY=INT_MIN,minZ=INT_MAX,maxZ=INT_MIN; 49 | //if (fp) 50 | { 51 | char buffer[100]; 52 | float vtx[3]; 53 | unsigned int extraface1,extraface2,extraface3; 54 | int nf; 55 | triple tf, tf_orig; 56 | unsigned int dummy; 57 | while(fgets(buffer,100,fp)) 58 | { 59 | if(buffer[0]=='v' && buffer[1]!='n' && buffer[1]!='t') 60 | { 61 | sscanf(buffer+1,"%f %f %f",vtx,vtx+1,vtx+2); 62 | points.append(QVector3D(vtx[0],vtx[1],vtx[2])); 63 | if (vtx[0]maxX) 66 | maxX=vtx[0]; 67 | if (vtx[1]maxY) 70 | maxY=vtx[1]; 71 | if (vtx[2]maxZ) 74 | maxZ=vtx[2]; 75 | } 76 | else if (buffer[0]=='f') 77 | { 78 | 79 | nf=sscanf(buffer+1,"%u %u %u %u %u %u",&tf.a,&tf.b,&tf.c,&extraface1,&extraface2,&extraface3); 80 | if (nf<3) 81 | { 82 | nf=sscanf(buffer+1,"%u/%u %u/%u %u/%u %u/%u %u/%u %u/%u",&tf.a,&dummy,&tf.b,&dummy,&tf.c,&dummy,&extraface1,&dummy,&extraface2,&dummy,&extraface3,&dummy); 83 | nf/=2; 84 | if (nf<3) 85 | { 86 | nf=sscanf(buffer+1,"%u//%u %u//%u %u//%u %u//%u %u//%u %u//%u",&tf.a,&dummy,&tf.b,&dummy,&tf.c,&dummy,&extraface1,&dummy,&extraface2,&dummy,&extraface3,&dummy); 87 | nf/=2; 88 | if (nf<3) 89 | { 90 | nf=sscanf(buffer+1,"%u/%u/%u %u/%u/%u %u/%u/%u %u/%u/%u %u/%u/%u %u/%u/%u",&tf.a,&dummy,&dummy,&tf.b,&dummy,&dummy,&tf.c,&dummy,&dummy,&extraface1,&dummy,&dummy,&extraface2,&dummy,&dummy,&extraface3,&dummy,&dummy); 91 | nf/=3; 92 | } 93 | } 94 | } 95 | if (nf>=3) 96 | { 97 | triangles.append(tf); 98 | if (nf>=4) 99 | { 100 | tf_orig = tf; 101 | if (nf == 4) //TODO: this is a dummy polygon to triangles conversion. If somebody cares... 102 | { 103 | tf.b=extraface1; 104 | triangles.append(tf); 105 | } 106 | if (nf == 5) 107 | { 108 | tf.a=tf_orig.c; 109 | tf.b=extraface1; 110 | tf.c=extraface2; 111 | triangles.append(tf); 112 | tf.a=extraface2; 113 | tf.b=tf_orig.a; 114 | tf.c=tf_orig.c; 115 | triangles.append(tf); 116 | } 117 | if (nf == 6) 118 | { 119 | tf.a=tf_orig.c; 120 | tf.b=extraface1; 121 | tf.c=extraface2; 122 | triangles.append(tf); 123 | tf.a=extraface2; 124 | tf.b=tf_orig.a; 125 | tf.c=tf_orig.c; 126 | triangles.append(tf); 127 | tf.a=extraface2; 128 | tf.b=tf_orig.a; 129 | tf.c=extraface3; 130 | triangles.append(tf); 131 | } 132 | } 133 | } 134 | } 135 | } 136 | fclose(fp); 137 | } 138 | float xh=(maxX-minX)/2; 139 | float yh=(maxY-minY)/2; 140 | float zh=(maxZ-minZ)/2; 141 | float xshift = maxX-xh; 142 | float yshift = maxY-yh; 143 | float zshift = maxZ-zh; 144 | float scale = 120.0/sqrt(xh*xh+yh*yh+zh*zh+1); 145 | 146 | m_nPoints=points.size(); 147 | m_nTriangles=triangles.size(); 148 | if (m_triangles) 149 | delete [] m_triangles; 150 | if (m_points) 151 | delete [] m_points; 152 | m_points=new float[m_nPoints*3]; 153 | m_colors=new unsigned char[m_nPoints*3]; 154 | unsigned char *colorsptr=m_colors; 155 | float *pointsptr=m_points; 156 | m_triangles=new unsigned int [m_nTriangles*3]; 157 | unsigned int *trianglesptr=m_triangles; 158 | 159 | 160 | for (unsigned int i=0;i=0) 208 | { 209 | **trianglesptr=(unsigned int)ply_get_argument_value(argument); 210 | ++*trianglesptr; 211 | } 212 | 213 | return 1; 214 | } 215 | void Model3D::LoadPly(const QString &filename) 216 | { 217 | 218 | QByteArray _filename=filename.toUtf8(); 219 | p_ply ply = ply_open(_filename.constData(), NULL, 0, NULL); 220 | if (!ply) return; 221 | if (!ply_read_header(ply)) return; 222 | m_nPoints = ply_set_read_cb(ply, "vertex", "x", 0, NULL, 0); 223 | m_nTriangles = ply_set_read_cb(ply, "face", "vertex_indices", 0, NULL, 0); 224 | if (m_triangles) 225 | delete [] m_triangles; 226 | if (m_points) 227 | delete [] m_points; 228 | m_points=new float[m_nPoints*3]; 229 | m_colors=new unsigned char[m_nPoints*3]; 230 | float* pointsptr=m_points; 231 | m_triangles=new unsigned int [m_nTriangles*3]; 232 | unsigned int* trianglesptr=m_triangles; 233 | ply_set_read_cb(ply, "face", "vertex_indices", face_cb, (void*)&trianglesptr, 0); 234 | ply_set_read_cb(ply, "vertex", "x", vertex_cb, (void*)&pointsptr, 0); 235 | ply_set_read_cb(ply, "vertex", "y", vertex_cb, (void*)&pointsptr, 0); 236 | ply_set_read_cb(ply, "vertex", "z", vertex_cb, (void*)&pointsptr, 0); 237 | //printf("%ld\n%ld\n", nvertices, ntriangles); 238 | if (!ply_read(ply)) return; 239 | ply_close(ply); 240 | normalize(); 241 | return; 242 | 243 | } 244 | 245 | void Model3D::normalize() 246 | { 247 | float minX=INT_MAX,maxX=INT_MIN,minY=INT_MAX,maxY=INT_MIN,minZ=INT_MAX,maxZ=INT_MIN; 248 | float* pointsptr=m_points; 249 | for (int i=m_nPoints;i>0;--i) 250 | { 251 | if (*pointsptrmaxX) 254 | maxX=*pointsptr; 255 | ++pointsptr; 256 | if (*pointsptrmaxY) 259 | maxY=*pointsptr; 260 | ++pointsptr; 261 | if (*pointsptrmaxZ) 264 | maxZ=*pointsptr; 265 | ++pointsptr; 266 | } 267 | float xh=(maxX-minX)/2; 268 | float yh=(maxY-minY)/2; 269 | float zh=(maxZ-minZ)/2; 270 | float xshift = maxX-xh; 271 | float yshift = maxY-yh; 272 | float zshift = maxZ-zh; 273 | float scale = 120.0/sqrt(xh*xh+yh*yh+zh*zh+1); 274 | pointsptr=m_points; 275 | unsigned char *colorsptr=m_colors; 276 | for (int i=m_nPoints;i>0;--i) 277 | { 278 | *pointsptr = (float)(*pointsptr-xshift)*scale; 279 | *colorsptr=(-*pointsptr+135.0); 280 | pointsptr++; 281 | colorsptr++; 282 | *pointsptr = (float)(*pointsptr-yshift)*scale; 283 | *colorsptr=(*pointsptr+135.0-*(pointsptr-1)/8); 284 | pointsptr++; 285 | colorsptr++; 286 | *pointsptr = (float)(*pointsptr-zshift)*scale; 287 | *colorsptr=(-*pointsptr+135.0-*(pointsptr-2)/8); 288 | pointsptr++; 289 | colorsptr++; 290 | } 291 | } 292 | 293 | void Model3D::DrawGL(bool color) 294 | { 295 | if (color) glEnableClientState(GL_COLOR_ARRAY); 296 | glEnableClientState(GL_VERTEX_ARRAY); 297 | glVertexPointer(3, GL_FLOAT, 0, m_points); 298 | if (color) glColorPointer(3, GL_UNSIGNED_BYTE, 0, m_colors); 299 | glDrawElements(GL_TRIANGLES, m_nTriangles*3, GL_UNSIGNED_INT, m_triangles); 300 | glDisableClientState(GL_VERTEX_ARRAY); 301 | if (color) glDisableClientState(GL_COLOR_ARRAY); 302 | } 303 | -------------------------------------------------------------------------------- /glmodelview.cpp: -------------------------------------------------------------------------------- 1 | #include "glmodelview.h" 2 | #include "stereomaker.h" 3 | #if defined(__APPLE__) 4 | #define GL_SILENCE_DEPRECATION 5 | #include 6 | #include 7 | #else 8 | #include 9 | #include 10 | #endif 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "modeldepthviewer.h" 20 | #include "trirender.h" 21 | 22 | GlModelView::GlModelView(QWidget *parent) : 23 | QOpenGLWidget(parent),m_zoom(500),m_contrast(100) 24 | { 25 | m_antialias=true; 26 | m_noShaders=false; 27 | m_new_width=1024; 28 | m_new_height=768; 29 | BasicImageWidget::setBasicImageParent(parent); 30 | QSurfaceFormat glf = QSurfaceFormat::defaultFormat(); 31 | glf.setSamples(4); 32 | setFormat(glf); 33 | } 34 | 35 | void GlModelView::initializeGL() 36 | { 37 | if (!(context()) || !context()->isValid()) 38 | { 39 | QMessageBox::warning(this,"No OpenGL Driver","Depth Map generation is still available"); 40 | } 41 | 42 | if (QOpenGLShader::hasOpenGLShaders(QOpenGLShader::Vertex,context()) ) 43 | { 44 | QString declarations= "//uniform mat4 gl_ModelViewMatrix; uniform mat4 gl_ProjectionMatrix; attribute vec4 gl_Vertex;\n"; 45 | QString codev= "void main() {gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;"\ 46 | "float zmax=-1.0;"\ 47 | "float zmin=1.0;"\ 48 | "float scale=(zmax-zmin);float offs=-zmin;float z=(gl_Position.z/gl_Position.w); gl_FrontColor = vec4((z+offs)/scale,(z+offs)/scale,(z+offs)/scale,1.0); } "; 49 | QOpenGLShader shaderv(QOpenGLShader::Vertex); 50 | bool compile_success=shaderv.compileSourceCode(declarations+codev); 51 | if (!compile_success) 52 | { 53 | compile_success=shaderv.compileSourceCode(codev); 54 | } 55 | if (compile_success) 56 | { 57 | QOpenGLShaderProgram program(context()); 58 | program.addShader(&shaderv); 59 | program.link(); 60 | program.bind(); 61 | } 62 | else 63 | m_noShaders=true; 64 | } 65 | else 66 | m_noShaders=true; 67 | 68 | glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // This Will Clear The Background Color To Black 69 | glEnable(GL_DEPTH_TEST); 70 | glClearDepth(1.0); // Enables Clearing Of The Depth Buffer 71 | glDepthFunc(GL_LESS); // The Type Of Depth Test To Do 72 | // Enables Depth Testing 73 | glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading 74 | 75 | m_rotx=0; 76 | m_roty=0; 77 | m_rotz=0; 78 | } 79 | void GlModelView::setModel(Model3D * model) 80 | { 81 | m_model = model; 82 | } 83 | 84 | void GlModelView::setParams(float xoff,float yoff,float zoom,float contrast,float xrot,float yrot,float zrot,float scale) 85 | { 86 | m_zoom=zoom; 87 | m_contrast=contrast; 88 | m_scale=scale; 89 | m_rotx=xrot; 90 | m_roty=yrot; 91 | m_rotz=zrot; 92 | m_xoffset=xoff; 93 | m_yoffset=yoff; 94 | setPerspective(); 95 | } 96 | 97 | void GlModelView::setZoom(float zoom) 98 | { 99 | m_zoom=zoom; 100 | setPerspective(); 101 | } 102 | void GlModelView::setScale(float scale) 103 | { 104 | m_scale=scale; 105 | setPerspective(); 106 | } 107 | 108 | void GlModelView::setContrast(float contrast) 109 | { 110 | m_contrast=contrast; 111 | setPerspective(); 112 | } 113 | typedef struct 114 | { 115 | unsigned int numPoints; 116 | unsigned int numTriangles; 117 | unsigned int raster_width; 118 | unsigned int raster_height; 119 | float rotate_x; 120 | float rotate_y; 121 | float rotate_z; 122 | float x_offset; 123 | float y_offset; 124 | float zoom; 125 | float contrast; 126 | } raster_prefs_t; 127 | 128 | const QImage* GlModelView::snapShot() 129 | { 130 | unsigned int out_width=((ModelDepthViewer*)m_parent)->getOutputImageWidth(); 131 | unsigned int out_height=((ModelDepthViewer*)m_parent)->getOutputImageHeight(); 132 | out_width=out_width&0xfffffffc; 133 | unsigned int numPoints=m_model->numPoints(); 134 | unsigned int numTriangles=m_model->numTriangles(); 135 | const float *points=m_model->pointsData(); 136 | const unsigned int *triangles=m_model->trianglesData(); 137 | unsigned char * buffer=new unsigned char[out_height*out_width]; 138 | float real_scale= pow(2,m_scale/1000); 139 | trirender(buffer, out_width, out_height, points, numPoints,triangles, numTriangles, m_rotx, m_roty, m_rotz,m_zoom,m_contrast,m_xoffset,m_yoffset,real_scale); 140 | QByteArray result = QByteArray((const char*)buffer,out_width * out_height); 141 | 142 | 143 | imdata=QImage(out_width,out_height,QImage::Format_Indexed8); 144 | imdata=imdata.convertToFormat(QImage::Format_Indexed8,StereoMaker::getGrayScale()); 145 | memcpy(imdata.bits(),result.data(),result.size()); 146 | imdata=imdata.mirrored(); 147 | delete [] buffer; 148 | return &imdata; 149 | /*raster_prefs_t rprefs; 150 | int outputSize=out_width * out_height * sizeof(GLubyte); 151 | const float *points=m_model->pointsData(); 152 | const unsigned int *triangles=m_model->trianglesData(); 153 | rprefs.numPoints=m_model->numPoints(); 154 | rprefs.numTriangles=m_model->numTriangles(); 155 | unsigned int out_width=((ModelDepthViewer*)m_parent)->getOutputImageWidth(); 156 | unsigned int out_height=((ModelDepthViewer*)m_parent)->getOutputImageHeight(); 157 | out_width=out_width&0xfffffffc; 158 | rprefs.raster_width=out_width; 159 | rprefs.raster_height=out_height; 160 | rprefs.rotate_x=m_rotx; 161 | rprefs.rotate_y=m_roty; 162 | rprefs.rotate_z=m_rotz; 163 | rprefs.x_offset=m_xoffset; 164 | rprefs.y_offset=m_yoffset; 165 | rprefs.zoom=m_zoom; 166 | rprefs.contrast=m_contrast; 167 | 168 | QProcess renderer; 169 | QString rasterizer_path=QCoreApplication::applicationDirPath ()+"/m3draster"; 170 | renderer.start(rasterizer_path); 171 | if (!renderer.waitForStarted()) 172 | { 173 | QMessageBox::warning(this,"Error","can't open "+rasterizer_path); 174 | return 0; 175 | } 176 | renderer.write((char*)&rprefs,sizeof(raster_prefs_t)); 177 | renderer.waitForBytesWritten(); 178 | int remaining=rprefs.numPoints*3*sizeof(float); 179 | int bytes_per_write=256*3*sizeof(float); 180 | int written=0; 181 | while (remaining>=bytes_per_write) 182 | { 183 | renderer.write(((char*)points)+written,bytes_per_write); 184 | remaining-=bytes_per_write; 185 | written+=bytes_per_write; 186 | renderer.waitForBytesWritten(); 187 | } 188 | if (remaining>0) 189 | { 190 | renderer.write(((char*)points)+written,remaining); 191 | renderer.waitForBytesWritten(); 192 | } 193 | 194 | remaining=rprefs.numTriangles*3*sizeof(unsigned int); 195 | bytes_per_write=256*3*sizeof(unsigned int); 196 | written=0; 197 | while (remaining>=bytes_per_write) 198 | { 199 | renderer.write(((char*)triangles)+written,bytes_per_write); 200 | remaining-=bytes_per_write; 201 | written+=bytes_per_write; 202 | renderer.waitForBytesWritten(); 203 | } 204 | if (remaining>0) 205 | { 206 | renderer.write(((char*)triangles)+written,remaining); 207 | renderer.waitForBytesWritten(); 208 | } 209 | 210 | imdata=QImage(); 211 | if (!renderer.waitForFinished()) 212 | return 0; 213 | QByteArray result = renderer.readAll(); 214 | int outputSize=out_width * out_height * sizeof(GLubyte); 215 | 216 | if ((unsigned int)result.size()==outputSize) 217 | { 218 | imdata=QImage(out_width,out_height,QImage::Format_Indexed8); 219 | imdata=imdata.convertToFormat(QImage::Format_Indexed8,StereoMaker::getGrayScale()); 220 | memcpy(imdata.bits(),result.data(),result.size()); 221 | imdata.invertPixels(); 222 | imdata=imdata.mirrored(); 223 | } 224 | 225 | return &imdata;*/ 226 | 227 | } 228 | void print_matrix(int mattype) 229 | { 230 | //usage: print_matrix(GL_MODELVIEW_MATRIX); 231 | //or: print_matrix(GL_PROJECTION_MATRIX); 232 | GLfloat matrix[16]; 233 | glGetFloatv (mattype, matrix); 234 | for (int i=0; i<16; ++i) 235 | { 236 | printf("%f ",matrix[(i%4)*4+(i/4)]); 237 | if (i%4==3) 238 | printf("\n"); 239 | } 240 | printf("\n"); 241 | fflush(0); 242 | } 243 | 244 | void GlModelView::setPerspective() 245 | { 246 | glMatrixMode(GL_PROJECTION); 247 | glLoadIdentity(); 248 | 249 | gluPerspective(20.0f,(GLfloat)m_new_width/(GLfloat)m_new_height,m_zoom-m_contrast,m_zoom+m_contrast); // Calculate The Aspect Ratio Of The Window 250 | 251 | 252 | glMatrixMode(GL_MODELVIEW); 253 | } 254 | 255 | void GlModelView::resizeGL( int width, int height ) 256 | { 257 | unsigned int out_width=((ModelDepthViewer*)m_parent)->getOutputImageWidth(); 258 | unsigned int out_height=((ModelDepthViewer*)m_parent)->getOutputImageHeight(); 259 | setViewport(out_width,out_height); 260 | } 261 | 262 | GlModelView::~GlModelView() 263 | { 264 | if (m_model) 265 | delete m_model; 266 | } 267 | 268 | void GlModelView::setViewport(int width_, int height_) 269 | { 270 | if (height_==0) // Prevent A Divide By Zero By 271 | { 272 | height_=1; // Making Height Equal One 273 | } 274 | float hratio=(float)height_/height(); 275 | float wratio=(float)width_/width(); 276 | float ratio=qMax(hratio,wratio); 277 | m_new_width=width_/ratio; 278 | if (m_new_width>width()) 279 | m_new_width=width(); 280 | m_new_height=height_/ratio; 281 | if (m_new_height>height()) 282 | m_new_height=height(); 283 | 284 | glViewport((width()-m_new_width)/2,(height()-m_new_height)/2,m_new_width,m_new_height); // Reset The Current Viewport 285 | setPerspective(); 286 | } 287 | 288 | void GlModelView::paintGL() 289 | { 290 | glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);//clear with white... 291 | if (m_antialias) 292 | glEnable(GL_MULTISAMPLE); 293 | //make black bacground... 294 | 295 | glPushMatrix(); 296 | double large_val=10000; 297 | glTranslatef(0,0,-m_zoom-m_contrast+0.01); 298 | glColor3b(255,0,0); 299 | glBegin(GL_QUADS); 300 | glVertex2d(large_val,large_val); 301 | glVertex2d(-large_val,large_val); 302 | glVertex2d(-large_val,-large_val); 303 | glVertex2d(large_val,-large_val); 304 | glEnd(); 305 | glPopMatrix(); 306 | 307 | //till here 308 | if (m_model) 309 | { 310 | glPushMatrix(); 311 | glTranslatef(m_xoffset,m_yoffset,-m_zoom); 312 | float real_scale= pow(2,m_scale/1000); 313 | glScalef(real_scale,real_scale,1.0); 314 | glRotatef(m_rotx,1,0,0); 315 | glRotatef(m_roty,0,1,0); 316 | glRotatef(m_rotz,0,0,1); 317 | m_model->DrawGL(m_noShaders); 318 | glPopMatrix(); 319 | } 320 | glDisable(GL_MULTISAMPLE); 321 | } 322 | -------------------------------------------------------------------------------- /modeldepthviewer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | ModelDepthViewer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 976 10 | 671 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | 1200 22 | 830 23 | 24 | 25 | 26 | Model Viewer 27 | 28 | 29 | 1.000000000000000 30 | 31 | 32 | 33 | 34 | 0 35 | 0 36 | 37 | 38 | 39 | 40 | 41 | 42 | true 43 | 44 | 45 | 46 | 0 47 | 0 48 | 49 | 50 | 51 | 52 | 800 53 | 600 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | Rotate X 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 150 72 | 0 73 | 74 | 75 | 76 | -180 77 | 78 | 79 | 180 80 | 81 | 82 | Qt::Horizontal 83 | 84 | 85 | 86 | 87 | 88 | 89 | Rotate Y 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 150 98 | 0 99 | 100 | 101 | 102 | -180 103 | 104 | 105 | 180 106 | 107 | 108 | Qt::Horizontal 109 | 110 | 111 | 0 112 | 113 | 114 | 115 | 116 | 117 | 118 | Rotate Z 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 150 127 | 0 128 | 129 | 130 | 131 | -180 132 | 133 | 134 | 180 135 | 136 | 137 | Qt::Horizontal 138 | 139 | 140 | QSlider::NoTicks 141 | 142 | 143 | 0 144 | 145 | 146 | 147 | 148 | 149 | 150 | Move X 151 | 152 | 153 | 154 | 155 | 156 | 157 | -800 158 | 159 | 160 | 800 161 | 162 | 163 | 0 164 | 165 | 166 | Qt::Horizontal 167 | 168 | 169 | QSlider::TicksBelow 170 | 171 | 172 | 800 173 | 174 | 175 | 176 | 177 | 178 | 179 | Move Y 180 | 181 | 182 | 183 | 184 | 185 | 186 | -800 187 | 188 | 189 | 800 190 | 191 | 192 | 10 193 | 194 | 195 | Qt::Horizontal 196 | 197 | 198 | QSlider::TicksBelow 199 | 200 | 201 | 800 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | Width 211 | 212 | 213 | 214 | 215 | 216 | 217 | 320 218 | 219 | 220 | 4096 221 | 222 | 223 | 2048 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | Height 235 | 236 | 237 | 238 | 239 | 240 | 241 | 320 242 | 243 | 244 | 4096 245 | 246 | 247 | 1536 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | Qt::Vertical 257 | 258 | 259 | 260 | 20 261 | 40 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | Scale 270 | 271 | 272 | 273 | 274 | 275 | 276 | -1000 277 | 278 | 279 | 1000 280 | 281 | 282 | 2 283 | 284 | 285 | 25 286 | 287 | 288 | 0 289 | 290 | 291 | Qt::Horizontal 292 | 293 | 294 | 295 | 296 | 297 | 298 | Distance 299 | 300 | 301 | 302 | 303 | 304 | 305 | 200 306 | 307 | 308 | 800 309 | 310 | 311 | 10 312 | 313 | 314 | 25 315 | 316 | 317 | 500 318 | 319 | 320 | Qt::Horizontal 321 | 322 | 323 | 324 | 325 | 326 | 327 | Contrast 328 | 329 | 330 | 331 | 332 | 333 | 334 | 30 335 | 336 | 337 | 150 338 | 339 | 340 | 100 341 | 342 | 343 | Qt::Horizontal 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 0 355 | 0 356 | 976 357 | 22 358 | 359 | 360 | 361 | 362 | File 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | :/images/save.png:/images/save.png 374 | 375 | 376 | Save Image... 377 | 378 | 379 | true 380 | 381 | 382 | 383 | 384 | Push Image 385 | 386 | 387 | 388 | 389 | 390 | GlModelView 391 | QWidget 392 |
glmodelview.h
393 | 1 394 |
395 |
396 | 397 | 398 | 399 | 400 |
401 | -------------------------------------------------------------------------------- /trirender.cpp: -------------------------------------------------------------------------------- 1 | #include "trirender.h" 2 | #include 3 | #include //for memset 4 | #include 5 | using namespace std; 6 | 7 | typedef struct 8 | { 9 | long long x; 10 | long long y; 11 | long long z; 12 | }Vertice; 13 | const int int_scale=1024; 14 | static unsigned char * image_buffer; 15 | static int image_width; 16 | static int image_height; 17 | int sabs(int a) 18 | { 19 | if (a<0) 20 | return -a; 21 | return a; 22 | } 23 | 24 | static void putPixel(long long x,long long y, long long value) 25 | { 26 | 27 | if (x=0 && y=0) 28 | { 29 | if (value>(256*int_scale-1)) return; 30 | //value=(256*int_scale-1); 31 | else if (value<0) 32 | value=0; 33 | if (image_buffer[(x/int_scale)+(y/int_scale)*image_width]<(unsigned char)(value/int_scale)) 34 | image_buffer[(x/int_scale)+(y/int_scale)*image_width]=(unsigned char)(value/int_scale); 35 | } 36 | 37 | } 38 | 39 | static void drawScanLine(long long fromx, long long tox,long long fromc,long long toc, long long y) 40 | { 41 | long long x,c=fromc; 42 | x=(fromx+int_scale-1); 43 | x=x-(x%int_scale); 44 | for (;x=v3.x)//rounding is toward zero... 63 | { 64 | for (; scanlineY < v2.y; scanlineY+=int_scale) 65 | { 66 | curx1 = v1.x-((-v2.x + v1.x)*(scanlineY-v1.y) / (v2.y - v1.y)); 67 | curx2 = v1.x-((-v3.x + v1.x)*(scanlineY-v1.y) / (v3.y - v1.y)); 68 | curc1 = v1.z+(v2.z - v1.z)*(scanlineY-v1.y) / (v2.y - v1.y); 69 | curc2 = v1.z+(v3.z - v1.z)*(scanlineY-v1.y) / (v3.y - v1.y); 70 | drawScanLine(curx1-1, curx2,curc1, curc2, scanlineY); 71 | } 72 | } 73 | else if (v1.x<=v2.x) 74 | { 75 | for (; scanlineY < v2.y; scanlineY+=int_scale) 76 | { 77 | curx1 = v1.x+((v2.x - v1.x)*(scanlineY-v1.y) / (v2.y - v1.y)); 78 | curx2 = v1.x+((v3.x - v1.x)*(scanlineY-v1.y) / (v3.y - v1.y)); 79 | curc1 = v1.z+(v2.z - v1.z)*(scanlineY-v1.y) / (v2.y - v1.y); 80 | curc2 = v1.z+(v3.z - v1.z)*(scanlineY-v1.y) / (v3.y - v1.y); 81 | drawScanLine(curx1, curx2+1,curc1, curc2, scanlineY); 82 | } 83 | } 84 | else 85 | for (; scanlineY < v2.y; scanlineY+=int_scale) 86 | { 87 | curx1 = v1.x-((-v2.x + v1.x)*(scanlineY-v1.y) / (v2.y - v1.y)); 88 | curx2 = v1.x+((v3.x - v1.x)*(scanlineY-v1.y) / (v3.y - v1.y)); 89 | curc1 = v1.z+(v2.z - v1.z)*(scanlineY-v1.y) / (v2.y - v1.y); 90 | curc2 = v1.z+(v3.z - v1.z)*(scanlineY-v1.y) / (v3.y - v1.y); 91 | drawScanLine(curx1-1, curx2+1,curc1, curc2, scanlineY); 92 | } 93 | } 94 | 95 | static void fillTopFlatTriangle(const Vertice& v1, const Vertice& v2, const Vertice& v3) 96 | { 97 | 98 | long long curx1; 99 | long long curx2; 100 | long long curc1; 101 | long long curc2; 102 | long long scanlineY = v3.y-1; 103 | scanlineY=scanlineY-(scanlineY%int_scale); 104 | if (v3.x>=v2.x) 105 | { 106 | for (; scanlineY >= v1.y; scanlineY-=int_scale) 107 | { 108 | curx1 = v3.x-((v3.x - v1.x)*(v3.y-scanlineY) / (v3.y - v1.y)); 109 | curx2 = v3.x-((v3.x - v2.x)*(v3.y-scanlineY) / (v3.y - v2.y)); 110 | curc1 = v3.z-(v3.z - v1.z)*(v3.y-scanlineY) / (v3.y - v1.y); 111 | curc2 = v3.z-(v3.z - v2.z)*(v3.y-scanlineY) / (v3.y - v2.y); 112 | drawScanLine(curx1-1, curx2,curc1, curc2, scanlineY); 113 | } 114 | } 115 | else if (v3.x<=v1.x) 116 | { 117 | for (; scanlineY >= v1.y; scanlineY-=int_scale) 118 | { 119 | curx1 = v3.x+((-v3.x + v1.x)*(v3.y-scanlineY) / (v3.y - v1.y)); 120 | curx2 = v3.x+((-v3.x + v2.x)*(v3.y-scanlineY) / (v3.y - v2.y)); 121 | curc1 = v3.z-(v3.z - v1.z)*(v3.y-scanlineY) / (v3.y - v1.y); 122 | curc2 = v3.z-(v3.z - v2.z)*(v3.y-scanlineY) / (v3.y - v2.y); 123 | drawScanLine(curx1, curx2+1,curc1, curc2, scanlineY); 124 | } 125 | } 126 | else 127 | for (; scanlineY >= v1.y; scanlineY-=int_scale) 128 | { 129 | curx1 = v3.x-((v3.x - v1.x)*(v3.y-scanlineY) / (v3.y - v1.y)); 130 | curx2 = v3.x+((-v3.x + v2.x)*(v3.y-scanlineY) / (v3.y - v2.y)); 131 | curc1 = v3.z-(v3.z - v1.z)*(v3.y-scanlineY) / (v3.y - v1.y); 132 | curc2 = v3.z-(v3.z - v2.z)*(v3.y-scanlineY) / (v3.y - v2.y); 133 | drawScanLine(curx1-1, curx2+1,curc1, curc2, scanlineY); 134 | } 135 | } 136 | 137 | #define SWAPON(V1,V2,C) do{if(V1->C > V2->C) {temp=V1;V1=V2;V2=temp;}}while(0); 138 | 139 | static void drawTriangle(const Vertice* v1,const Vertice* v2,const Vertice* v3) 140 | { 141 | const Vertice* temp; 142 | SWAPON(v1,v2,y); 143 | SWAPON(v1,v3,y); 144 | SWAPON(v2,v3,y); 145 | 146 | 147 | /* here we know that v1->y <= v2->y <= v3->y */ 148 | /* check for trivial case of bottom-flat triangle */ 149 | 150 | if (v1->y != v3->y) 151 | { 152 | if ( v2->y == v3->y) 153 | { 154 | SWAPON(v2,v3,x); 155 | fillBottomFlatTriangle(*v1, *v2, *v3); 156 | } 157 | // check for trivial case of top-flat triangle 158 | else if (v1->y == v2->y) 159 | { 160 | SWAPON(v1,v2,x); 161 | fillTopFlatTriangle(*v1, *v2, *v3); 162 | } 163 | else 164 | { 165 | // general case - split the triangle in a topflat and bottom-flat one 166 | Vertice v4; 167 | v4.x=(v1->x + ((v3->x - v1->x)*(v2->y - v1->y))/ (v3->y - v1->y)); 168 | v4.y=v2->y; 169 | v4.z=(v1->z + ((v3->z - v1->z)*(v2->y - v1->y))/ (v3->y - v1->y)); 170 | drawTriangle(v1, v2, &v4); 171 | drawTriangle(v2, &v4, v3); 172 | 173 | } 174 | } 175 | else// all y are equal 176 | { 177 | /*SWAPON(v1,v2,x); 178 | SWAPON(v1,v3,x); 179 | SWAPON(v2,v3,x); 180 | drawScanLine(v2->x, v3->x,v2->z, v3->z, v2->y); 181 | drawScanLine(v1->x, v3->x,v1->z, v3->z, v1->y); 182 | drawScanLine(v1->x, v2->x,v1->z, v2->z, v1->y);*/ 183 | 184 | } 185 | } 186 | static void drawTri(/*unsigned char *buffer, int w, int h,*/const long long *points,const unsigned int *triangles, int tri_ind) 187 | { 188 | unsigned int t[3]; 189 | for (int i=0;i<3;++i) 190 | t[i]=triangles[tri_ind*3+i]; 191 | const Vertice *v[3]; 192 | for (int i=0;i<3;++i) 193 | { 194 | v[i]=(const Vertice*)&points[t[i]*3]; 195 | } 196 | drawTriangle(v[0],v[1],v[2]); 197 | } 198 | #define DEG2RAD (M_PI/180.0) 199 | #define MAP_MATRIX(I,J) (J*4+I) 200 | static void my_PerspectiveFOV(float fov, float aspect, float near, float far, float* mret) { 201 | 202 | float yScale = 1.0 / tan(DEG2RAD * fov / 2); 203 | float xScale = yScale / aspect; 204 | float nearmfar = near - far; 205 | float m[16] = { 206 | xScale, 0, 0, 0, 207 | 0, yScale, 0, 0, 208 | 0, 0, (far + near) / nearmfar, -1, 209 | 0, 0, 2*far*near / nearmfar, 0 210 | }; 211 | memcpy(mret, m, sizeof(float)*16); 212 | } 213 | static void mult_mat(float* m1,float* m2,float* res) 214 | { 215 | float m[16] = { 216 | m1[ 0 ]*m2[ 0 ]+m1[ 4 ]*m2[ 1 ]+m1[ 8 ]*m2[ 2 ]+m1[ 12 ]*m2[ 3 ], 217 | m1[ 1 ]*m2[ 0 ]+m1[ 5 ]*m2[ 1 ]+m1[ 9 ]*m2[ 2 ]+m1[ 13 ]*m2[ 3 ], 218 | m1[ 2 ]*m2[ 0 ]+m1[ 6 ]*m2[ 1 ]+m1[ 10 ]*m2[ 2 ]+m1[ 14 ]*m2[ 3 ], 219 | m1[ 3 ]*m2[ 0 ]+m1[ 7 ]*m2[ 1 ]+m1[ 11 ]*m2[ 2 ]+m1[ 15 ]*m2[ 3 ], 220 | m1[ 0 ]*m2[ 4 ]+m1[ 4 ]*m2[ 5 ]+m1[ 8 ]*m2[ 6 ]+m1[ 12 ]*m2[ 7 ], 221 | m1[ 1 ]*m2[ 4 ]+m1[ 5 ]*m2[ 5 ]+m1[ 9 ]*m2[ 6 ]+m1[ 13 ]*m2[ 7 ], 222 | m1[ 2 ]*m2[ 4 ]+m1[ 6 ]*m2[ 5 ]+m1[ 10 ]*m2[ 6 ]+m1[ 14 ]*m2[ 7 ], 223 | m1[ 3 ]*m2[ 4 ]+m1[ 7 ]*m2[ 5 ]+m1[ 11 ]*m2[ 6 ]+m1[ 15 ]*m2[ 7 ], 224 | m1[ 0 ]*m2[ 8 ]+m1[ 4 ]*m2[ 9 ]+m1[ 8 ]*m2[ 10 ]+m1[ 12 ]*m2[ 11 ], 225 | m1[ 1 ]*m2[ 8 ]+m1[ 5 ]*m2[ 9 ]+m1[ 9 ]*m2[ 10 ]+m1[ 13 ]*m2[ 11 ], 226 | m1[ 2 ]*m2[ 8 ]+m1[ 6 ]*m2[ 9 ]+m1[ 10 ]*m2[ 10 ]+m1[ 14 ]*m2[ 11 ], 227 | m1[ 3 ]*m2[ 8 ]+m1[ 7 ]*m2[ 9 ]+m1[ 11 ]*m2[ 10 ]+m1[ 15 ]*m2[ 11 ], 228 | m1[ 0 ]*m2[ 12 ]+m1[ 4 ]*m2[ 13 ]+m1[ 8 ]*m2[ 14 ]+m1[ 12 ]*m2[ 15 ], 229 | m1[ 1 ]*m2[ 12 ]+m1[ 5 ]*m2[ 13 ]+m1[ 9 ]*m2[ 14 ]+m1[ 13 ]*m2[ 15 ], 230 | m1[ 2 ]*m2[ 12 ]+m1[ 6 ]*m2[ 13 ]+m1[ 10 ]*m2[ 14 ]+m1[ 14 ]*m2[ 15 ], 231 | m1[ 3 ]*m2[ 12 ]+m1[ 7 ]*m2[ 13 ]+m1[ 11 ]*m2[ 14 ]+m1[ 15 ]*m2[ 15 ] 232 | }; 233 | memcpy(res, m, sizeof(float)*16); 234 | } 235 | 236 | static void xrotation_mat(float xrot, float* mret) { 237 | 238 | float cxrot=cosf(xrot*DEG2RAD); 239 | float sxrot=sinf(xrot*DEG2RAD); 240 | float m[16] = { 241 | 1, 0, 0, 0, 242 | 0, cxrot, sxrot, 0, 243 | 0, -sxrot, cxrot, 0, 244 | 0, 0, 0, 1 245 | }; 246 | memcpy(mret, m, sizeof(float)*16); 247 | } 248 | static void yrotation_mat(float yrot, float* mret) { 249 | 250 | float cyrot=cosf(yrot*DEG2RAD); 251 | float syrot=sinf(yrot*DEG2RAD); 252 | float m[16] = { 253 | cyrot, 0, -syrot, 0, 254 | 0 , 1, 0 , 0, 255 | syrot, 0, cyrot , 0, 256 | 0, 0, 0, 1 257 | }; 258 | memcpy(mret, m, sizeof(float)*16); 259 | } 260 | static void zrotation_mat(float zrot, float* mret) { 261 | 262 | float czrot=cosf(zrot*DEG2RAD); 263 | float szrot=sinf(zrot*DEG2RAD); 264 | float m[16] = { 265 | czrot, szrot, 0, 0, 266 | -szrot , czrot, 0 , 0, 267 | 0, 0, 1, 0, 268 | 0, 0, 0, 1 269 | }; 270 | memcpy(mret, m, sizeof(float)*16); 271 | } 272 | static void translation_mat(float x,float y,float z, float* mret) { 273 | 274 | float m[16] = { 275 | 1, 0, 0, 0, 276 | 0 , 1, 0 , 0, 277 | 0, 0, 1, 0, 278 | x, y, z, 1 279 | }; 280 | memcpy(mret, m, sizeof(float)*16); 281 | } 282 | static void scale_mat(float sx,float sy,float sz, float* mret) { 283 | 284 | float m[16] = { 285 | sx, 0, 0, 0, 286 | 0 , sy, 0 , 0, 287 | 0, 0, sz, 0, 288 | 0, 0, 0, 1 289 | }; 290 | memcpy(mret, m, sizeof(float)*16); 291 | } 292 | 293 | static void mult_mat_vec(float* m , float *v,float *out_v) 294 | { 295 | float res[4] = { 296 | m[ 0 ]*v[ 0 ]+m[ 4 ]*v[ 1 ]+m[ 8 ]*v[ 2 ]+m[ 12 ]*v[ 3 ], 297 | m[ 1 ]*v[ 0 ]+m[ 5 ]*v[ 1 ]+m[ 9 ]*v[ 2 ]+m[ 13 ]*v[ 3 ], 298 | m[ 2 ]*v[ 0 ]+m[ 6 ]*v[ 1 ]+m[ 10 ]*v[ 2 ]+m[ 14 ]*v[ 3 ], 299 | m[ 3 ]*v[ 0 ]+m[ 7 ]*v[ 1 ]+m[ 11 ]*v[ 2 ]+m[ 15 ]*v[ 3 ]}; 300 | memcpy(out_v, res, sizeof(float)*4); 301 | } 302 | 303 | extern float projMatrix[16]; 304 | extern float modelMatrix[16]; 305 | 306 | void trirender(unsigned char *buffer, int width, int height, const float *points, int np,const unsigned int *triangles, int nt, float xrot, float yrot, float zrot, 307 | float zoom,float contrast,float xoff,float yoff,float scale) 308 | { 309 | image_buffer=buffer; 310 | image_width=width; 311 | image_height=height; 312 | memset(buffer,0,width*height); 313 | 314 | long long *i_points=new long long[np*3]; 315 | /*float cxrot=cosf(xrot*DEG2RAD); 316 | float sxrot=sinf(xrot*DEG2RAD); 317 | float cyrot=cosf(yrot*DEG2RAD); 318 | float syrot=sinf(yrot*DEG2RAD); 319 | float czrot=cosf(zrot*DEG2RAD); 320 | float szrot=sinf(zrot*DEG2RAD);*/ 321 | float prjmat[16]; 322 | float temp_mat[16]; 323 | float model_mat[16]={1,0,0,0, 324 | 0,1,0,0, 325 | 0,0,1,0, 326 | 0,0,0,1}; 327 | 328 | my_PerspectiveFOV(20,(float)width/height,(zoom-contrast),(zoom+contrast),prjmat); 329 | 330 | //float _w,old_val_x; 331 | 332 | 333 | //float x,y,z; 334 | translation_mat(xoff,yoff,-zoom,temp_mat); 335 | mult_mat(model_mat,temp_mat,model_mat); 336 | scale_mat(scale,scale,1,temp_mat); 337 | mult_mat(model_mat,temp_mat,model_mat); 338 | xrotation_mat(xrot,temp_mat); 339 | mult_mat(model_mat,temp_mat,model_mat); 340 | yrotation_mat(yrot,temp_mat); 341 | mult_mat(model_mat,temp_mat,model_mat); 342 | zrotation_mat(zrot,temp_mat); 343 | mult_mat(model_mat,temp_mat,model_mat); 344 | 345 | for (int i=0;i 3 | #define MY_PRECISION 512 4 | #else 5 | #include 6 | #endif 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define INVALID_OFFSET (-1) 14 | #define MYDEBUG 0 15 | 16 | #ifndef USE_MPFR 17 | #ifndef USE_FLOAT 18 | #ifndef USE_LDBL 19 | typedef double DBL_T; 20 | #define STR_FUNC strtod 21 | #define EXP_FUNC exp 22 | #define POW_FUNC pow 23 | #define SIN_FUNC sin 24 | #define TYPE_MOD "%lf" 25 | #ifndef NAN 26 | #define NAN nan(""); 27 | #endif 28 | #else 29 | typedef long double DBL_T; 30 | #define STR_FUNC strtold 31 | #define EXP_FUNC expl 32 | #define POW_FUNC powl 33 | #define SIN_FUNC sinl 34 | #define TYPE_MOD "%Lf" 35 | #ifndef NAN 36 | #define NAN nanl(""); 37 | #endif 38 | #endif 39 | #else 40 | typedef float DBL_T; 41 | #define STR_FUNC strtof 42 | #define EXP_FUNC expf 43 | #define POW_FUNC powf 44 | #define SIN_FUNC sinf 45 | #define TYPE_MOD "%f" 46 | #ifndef NAN 47 | #define NAN nanf(""); 48 | #endif 49 | #endif 50 | #endif 51 | #ifdef USE_MPFR 52 | #define TYPE_MOD "%.128Rf" 53 | void parse_level1(const char* buffer, int *offset, mpfr_t res, mpfr_t* values); 54 | void parse_level2(const char* buffer, int *offset, mpfr_t res, mpfr_t* values); 55 | void parse_level3(const char* buffer, int *offset, mpfr_t res, mpfr_t* values); 56 | void parse_level4(const char* buffer, int *offset, mpfr_t res, mpfr_t* values); 57 | #else 58 | #define MPFR_DECL_INIT(X,PERC) DBL_T X=NAN; 59 | #define mpfr_init2(X,Y) {do{} while(0);} 60 | #define mpfr_set(X,Y,METHOD) {do{X=Y;} while(0);} 61 | #define mpfr_set_si(X,Y, METHOD) {do{X=Y;} while(0);} 62 | #define mpfr_clear(X) do{} while(0); 63 | #define mpfr_add(RES,A,B,METHOD) {do{RES=A+B;} while(0);} 64 | #define mpfr_mul(RES,A,B,METHOD) {do{RES=A*B;} while(0);} 65 | #define mpfr_div(RES,A,B,METHOD) {do{RES=A/B;} while(0);} 66 | #define mpfr_pow(RES,A,B,METHOD) {do{RES=POW_FUNC(A,B);} while(0);} 67 | #define mpfr_sin(RES,X,METHOD) {do{RES=SIN_FUNC(X);} while(0);} 68 | #define mpfr_exp(RES,POWER,METHOD) {do{RES=EXP_FUNC(POWER);} while(0);} 69 | #define mpfr_set_nan(X) {do{X=NAN;} while(0);} 70 | #define mpfr_strtofr(X, STR, TAIL, BASE, METHOD) X=STR_FUNC(STR, TAIL); 71 | #define mpfr_const_pi(X,METHOD) {do{X=M_PI;} while(0);} 72 | #define mpfr_printf(...) {do{printf(__VA_ARGS__);} while(0);} 73 | 74 | #define MPFR_RNDN 0 75 | typedef DBL_T mpfr_t; 76 | void parse_level1(const char* buffer, int *offset, DBL_T& res, mpfr_t* values); 77 | void parse_level2(const char* buffer, int *offset, DBL_T& res, mpfr_t* values); 78 | void parse_level3(const char* buffer, int *offset, DBL_T& res, mpfr_t* values); 79 | void parse_level4(const char* buffer, int *offset, DBL_T& res, mpfr_t* values); 80 | #endif 81 | #define STRLEN(X) (sizeof(X)/sizeof(X[0])-1) //minus one to remove the null termination 82 | #define CHECK_INITIALS(STR,NEEDLE) (strncmp(STR,NEEDLE,STRLEN(NEEDLE))==0 && isalnum(*(STR+STRLEN(NEEDLE)))==0) 83 | 84 | bool is_whitespace(char c) 85 | { 86 | return (' ' == c) || ('\n' == c) || 87 | ('\r' == c) || ('\t' == c) || 88 | ('\b' == c) || ('\v' == c) || 89 | ('\f' == c) ; 90 | } 91 | bool is_functional(char c) 92 | { 93 | return ('(' == c) || (')' == c) || 94 | ('+' == c) || ('-' == c) || 95 | ('*' == c) || ('/' == c)|| ('.' == c); 96 | } 97 | bool is_Digit(char c) 98 | { 99 | return (c>='0' && c<='9'); 100 | } 101 | bool is_Alpha(char c) 102 | { 103 | return (c>='a' && c<='z')||(c>='A' && c<='Z'); 104 | } 105 | void skip_spaces(const char* buffer, int *offset) 106 | { 107 | while (is_whitespace(buffer[*offset])) 108 | { 109 | (*offset)++; 110 | } 111 | } 112 | 113 | 114 | #ifdef USE_MPFR 115 | void parse_level1(const char* buffer, int *offset, mpfr_t res, mpfr_t* values) //addition and subtraction 116 | #else 117 | void parse_level1(const char* buffer, int *offset, DBL_T& res, mpfr_t* values) //addition and subtraction 118 | #endif 119 | { 120 | #if MYDEBUG 121 | printf("parse_level1 %d\n",*offset); 122 | #endif 123 | 124 | mpfr_t left; 125 | int my_offset; 126 | skip_spaces(buffer, offset); 127 | my_offset=*offset; 128 | 129 | parse_level2(buffer,&my_offset,left,values); 130 | #if MYDEBUG 131 | printf("parse_level1 a %d\n",*offset); 132 | #ifdef USE_MPFR 133 | mpfr_printf ("parse_level1 n = " TYPE_MOD "\n",left); 134 | #endif 135 | #endif 136 | if (*offset==my_offset || *offset==INVALID_OFFSET) 137 | { 138 | *offset=INVALID_OFFSET; 139 | return; 140 | } 141 | 142 | #if MYDEBUG 143 | printf("parse_level1 b %d\n",*offset); 144 | #endif 145 | skip_spaces(buffer, &my_offset); 146 | *offset=my_offset; 147 | while (buffer[my_offset]=='+' || buffer[my_offset]=='-') 148 | { 149 | #if MYDEBUG 150 | printf("parse_level1 loop %d\n",*offset); 151 | #endif 152 | char op=buffer[my_offset]; 153 | if (op=='-') 154 | { 155 | op='+'; 156 | } 157 | else 158 | ++my_offset; 159 | mpfr_t right; 160 | skip_spaces(buffer, &my_offset); 161 | *offset=my_offset; 162 | parse_level2(buffer,&my_offset,right,values); 163 | #if MYDEBUG 164 | printf("parse_level1 c %d %d\n",*offset,my_offset); 165 | #endif 166 | if (*offset==my_offset || *offset==INVALID_OFFSET) 167 | { 168 | *offset=INVALID_OFFSET; 169 | return; 170 | } 171 | #if MYDEBUG 172 | printf("parse_level1 d %d\n",*offset); 173 | #endif 174 | skip_spaces(buffer, &my_offset); 175 | 176 | *offset=my_offset; 177 | mpfr_add(left,left,right,MPFR_RNDN); 178 | mpfr_clear (right); 179 | 180 | 181 | } 182 | if (buffer[my_offset]!='\n' && buffer[my_offset]!=')' && buffer[my_offset]!='\0' && buffer[my_offset]!=',') 183 | { 184 | *offset=INVALID_OFFSET; 185 | return; 186 | } 187 | #if MYDEBUG 188 | else 189 | { 190 | printf("parse_level1 character %c\n",buffer[my_offset]); 191 | } 192 | #endif 193 | 194 | mpfr_init2(res,MY_PRECISION); 195 | mpfr_set(res,left,MPFR_RNDN); 196 | mpfr_clear (left); 197 | 198 | return; 199 | } 200 | #ifdef USE_MPFR 201 | void parse_level2(const char* buffer, int *offset, mpfr_t res, mpfr_t* values) //multiplication and division 202 | #else 203 | void parse_level2(const char* buffer, int *offset, DBL_T& res, mpfr_t* values) 204 | #endif 205 | { 206 | mpfr_t left; 207 | 208 | 209 | int my_offset; 210 | 211 | my_offset=*offset; 212 | parse_level3(buffer,&my_offset,left,values); 213 | 214 | 215 | if (*offset==my_offset || *offset==INVALID_OFFSET) 216 | { 217 | *offset=INVALID_OFFSET; 218 | return; 219 | } 220 | *offset=my_offset; 221 | while (buffer[my_offset]=='*' || buffer[my_offset]=='/') 222 | { 223 | 224 | char op=buffer[my_offset]; 225 | ++my_offset; 226 | mpfr_t right; 227 | skip_spaces(buffer, &my_offset); 228 | *offset=my_offset; 229 | parse_level3(buffer,&my_offset,right,values); 230 | if (*offset==my_offset || *offset==INVALID_OFFSET) 231 | { 232 | *offset=INVALID_OFFSET; 233 | return; 234 | } 235 | skip_spaces(buffer, &my_offset); 236 | *offset=my_offset; 237 | if (op=='*') 238 | { 239 | mpfr_mul(left,left,right,MPFR_RNDN); 240 | } 241 | else 242 | { 243 | mpfr_div(left,left,right,MPFR_RNDN); 244 | } 245 | mpfr_clear (right); 246 | } 247 | 248 | mpfr_init2(res,MY_PRECISION); 249 | mpfr_set(res,left,MPFR_RNDN); 250 | mpfr_clear (left); 251 | 252 | return; 253 | } 254 | #ifdef USE_MPFR 255 | void parse_level3(const char* buffer, int *offset, mpfr_t res, mpfr_t* values) //minus sign 256 | #else 257 | void parse_level3(const char* buffer, int *offset, DBL_T& res, mpfr_t* values) 258 | #endif 259 | { 260 | 261 | char op=0; 262 | 263 | int my_offset; 264 | 265 | my_offset=*offset; 266 | if (buffer[my_offset]=='-') 267 | { 268 | op='-'; 269 | ++my_offset; 270 | } 271 | parse_level4(buffer,&my_offset,res,values); 272 | 273 | if (*offset==my_offset || *offset==INVALID_OFFSET) 274 | { 275 | 276 | *offset=INVALID_OFFSET; 277 | return; 278 | } 279 | skip_spaces(buffer, &my_offset); 280 | *offset=my_offset; 281 | 282 | if (op) 283 | { 284 | mpfr_t minus_one; 285 | mpfr_init2(minus_one,MPFR_PREC_MIN+2); 286 | mpfr_set_si (minus_one, -1, MPFR_RNDN); 287 | mpfr_mul(res,res,minus_one,MPFR_RNDN); 288 | mpfr_clear(minus_one); 289 | } 290 | 291 | } 292 | #ifdef USE_MPFR 293 | void parse_level4(const char* buffer, int *offset, mpfr_t res, mpfr_t* values) //object itself 294 | #else 295 | void parse_level4(const char* buffer, int *offset, DBL_T& res, mpfr_t* values) 296 | #endif 297 | { 298 | 299 | int my_offset; 300 | my_offset=*offset; 301 | if (buffer[*offset]==0 || buffer[*offset]==')')//unbalanced? 302 | { 303 | *offset=INVALID_OFFSET; 304 | return; 305 | } 306 | if (buffer[my_offset]=='(') 307 | { 308 | ++my_offset; 309 | parse_level1(buffer,&my_offset,res,values); 310 | 311 | if (buffer[my_offset]!=')') 312 | { 313 | *offset=INVALID_OFFSET; 314 | return; 315 | } 316 | ++my_offset; 317 | *offset=my_offset; 318 | return; 319 | } 320 | 321 | if (values!=0) 322 | { 323 | if (CHECK_INITIALS(&buffer[my_offset],"x")) 324 | { 325 | mpfr_init2(res,MY_PRECISION); 326 | mpfr_set(res,values[0],MPFR_RNDN); 327 | my_offset+=STRLEN("x"); 328 | *offset=my_offset; 329 | return; 330 | } 331 | if (CHECK_INITIALS(&buffer[my_offset],"y")) 332 | { 333 | mpfr_init2(res,MY_PRECISION); 334 | mpfr_set(res,values[1],MPFR_RNDN); 335 | my_offset+=STRLEN("y"); 336 | *offset=my_offset; 337 | return; 338 | } 339 | } 340 | if (CHECK_INITIALS(&buffer[my_offset],"pi")) 341 | { 342 | mpfr_init2(res,MY_PRECISION); 343 | mpfr_const_pi (res,MPFR_RNDN); 344 | my_offset+=STRLEN("pi"); 345 | *offset=my_offset; 346 | return; 347 | } 348 | if (CHECK_INITIALS(&buffer[my_offset],"e")) 349 | { 350 | mpfr_init2(res,MY_PRECISION); 351 | mpfr_set_si(res,1,MPFR_RNDN); 352 | mpfr_exp (res, res, MPFR_RNDN); 353 | my_offset+=STRLEN("e"); 354 | *offset=my_offset; 355 | return; 356 | } 357 | if (CHECK_INITIALS(&buffer[my_offset],"pow")) 358 | { 359 | my_offset+=STRLEN("pow"); 360 | *offset=my_offset; 361 | skip_spaces(buffer, &my_offset); 362 | if (buffer[my_offset]=='(') 363 | { 364 | ++my_offset; 365 | mpfr_t left; 366 | parse_level1(buffer,&my_offset,left,values); 367 | 368 | if (buffer[my_offset]!=',') 369 | { 370 | *offset=INVALID_OFFSET; 371 | return; 372 | } 373 | ++my_offset; 374 | mpfr_t right; 375 | parse_level1(buffer,&my_offset,right,values); 376 | if (buffer[my_offset]!=')') 377 | { 378 | *offset=INVALID_OFFSET; 379 | return; 380 | } 381 | ++my_offset; 382 | *offset=my_offset; 383 | mpfr_init2(res,MY_PRECISION); 384 | mpfr_pow(res,left,right,MPFR_RNDN); 385 | mpfr_clear (right); 386 | mpfr_clear (left); 387 | return; 388 | } 389 | else 390 | { 391 | *offset=INVALID_OFFSET; 392 | return; 393 | } 394 | return; 395 | } 396 | if (CHECK_INITIALS(&buffer[my_offset],"sin")) 397 | { 398 | my_offset+=STRLEN("sin"); 399 | *offset=my_offset; 400 | skip_spaces(buffer, &my_offset); 401 | if (buffer[my_offset]=='(') 402 | { 403 | ++my_offset; 404 | mpfr_t left; 405 | parse_level1(buffer,&my_offset,left,values); 406 | if (my_offset==INVALID_OFFSET) 407 | { 408 | *offset=INVALID_OFFSET; 409 | return; 410 | } 411 | if (buffer[my_offset]!=')') 412 | { 413 | *offset=INVALID_OFFSET; 414 | return; 415 | } 416 | ++my_offset; 417 | *offset=my_offset; 418 | mpfr_init2(res,MY_PRECISION); 419 | mpfr_sin(res,left,MPFR_RNDN); 420 | mpfr_clear (left); 421 | return; 422 | } 423 | else 424 | { 425 | *offset=INVALID_OFFSET; 426 | return; 427 | } 428 | } 429 | if (is_Digit(buffer[my_offset])||buffer[my_offset]=='.'||buffer[my_offset]=='+') 430 | { 431 | mpfr_init2(res,MY_PRECISION); 432 | char* endptr; 433 | mpfr_strtofr (res, buffer+my_offset, &endptr, 10, MPFR_RNDN); 434 | *offset=my_offset=(int)((ptrdiff_t)endptr-(ptrdiff_t)buffer); 435 | } 436 | else 437 | { 438 | *offset=INVALID_OFFSET; 439 | return; 440 | } 441 | } 442 | 443 | 444 | void parse(const char* buffer) 445 | { 446 | mpfr_t res; 447 | int offset=0; 448 | do{ 449 | parse_level1(buffer, &offset,res,0); 450 | if (offset!=INVALID_OFFSET && (buffer[offset]==0||buffer[offset]==',')) 451 | { 452 | mpfr_printf ("!! res = " TYPE_MOD "\n",res); 453 | } 454 | else 455 | { 456 | mpfr_init2(res,MY_PRECISION); 457 | mpfr_set_nan(res); 458 | break; 459 | } 460 | } 461 | while(buffer[offset++]==','); 462 | #ifdef USE_MPFR 463 | mpfr_free_cache(); 464 | #endif 465 | } 466 | #ifdef USE_FLOAT 467 | float parseXY(const char* buffer,float x,float y,bool* ok) 468 | { 469 | float values[2]; 470 | values[0]=x; 471 | values[1]=y; 472 | int offset=0; 473 | float res; 474 | parse_level1(buffer, &offset,res,values); 475 | //mpfr_printf ("!! res = " TYPE_MOD "\n",res); 476 | if (offset!=INVALID_OFFSET && buffer[offset]==0) 477 | { 478 | *ok=true; 479 | } 480 | else 481 | { 482 | *ok=false; 483 | } 484 | return res; 485 | 486 | } 487 | #endif 488 | -------------------------------------------------------------------------------- /RPly/rply.h: -------------------------------------------------------------------------------- 1 | #ifndef RPLY_H 2 | #define RPLY_H 3 | /* ---------------------------------------------------------------------- 4 | * RPly library, read/write PLY files 5 | * Diego Nehab, IMPA 6 | * http://www.impa.br/~diego/software/rply 7 | * 8 | * This library is distributed under the MIT License. See notice 9 | * at the end of this file. 10 | * ---------------------------------------------------------------------- */ 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | #define RPLY_VERSION "RPly 1.1.4" 17 | #define RPLY_COPYRIGHT "Copyright (C) 2003-2015 Diego Nehab" 18 | #define RPLY_AUTHORS "Diego Nehab" 19 | 20 | /* ---------------------------------------------------------------------- 21 | * Types 22 | * ---------------------------------------------------------------------- */ 23 | /* structures are opaque */ 24 | typedef struct t_ply_ *p_ply; 25 | typedef struct t_ply_element_ *p_ply_element; 26 | typedef struct t_ply_property_ *p_ply_property; 27 | typedef struct t_ply_argument_ *p_ply_argument; 28 | 29 | /* ply format mode type */ 30 | typedef enum e_ply_storage_mode_ { 31 | PLY_BIG_ENDIAN, 32 | PLY_LITTLE_ENDIAN, 33 | PLY_ASCII, 34 | PLY_DEFAULT /* has to be the last in enum */ 35 | } e_ply_storage_mode; /* order matches ply_storage_mode_list */ 36 | 37 | /* ply data type */ 38 | typedef enum e_ply_type { 39 | PLY_INT8, PLY_UINT8, PLY_INT16, PLY_UINT16, 40 | PLY_INT32, PLY_UIN32, PLY_FLOAT32, PLY_FLOAT64, 41 | PLY_CHAR, PLY_UCHAR, PLY_SHORT, PLY_USHORT, 42 | PLY_INT, PLY_UINT, PLY_FLOAT, PLY_DOUBLE, 43 | PLY_LIST /* has to be the last in enum */ 44 | } e_ply_type; /* order matches ply_type_list */ 45 | 46 | /* ---------------------------------------------------------------------- 47 | * Error callback prototype 48 | * 49 | * message: error message 50 | * ply: handle returned by ply_open or ply_create 51 | * ---------------------------------------------------------------------- */ 52 | typedef void (*p_ply_error_cb)(p_ply ply, const char *message); 53 | 54 | /* ---------------------------------------------------------------------- 55 | * Gets user data from within an error callback 56 | * 57 | * ply: handle returned by ply_open or ply_create 58 | * idata,pdata: contextual information set in ply_open or ply_create 59 | * ---------------------------------------------------------------------- */ 60 | int ply_get_ply_user_data(p_ply ply, void **pdata, long *idata); 61 | 62 | /* ---------------------------------------------------------------------- 63 | * Opens a PLY file for reading (fails if file is not a PLY file) 64 | * 65 | * name: file name 66 | * error_cb: error callback function 67 | * idata,pdata: contextual information available to users 68 | * 69 | * Returns 1 if successful, 0 otherwise 70 | * ---------------------------------------------------------------------- */ 71 | p_ply ply_open(const char *name, p_ply_error_cb error_cb, long idata, 72 | void *pdata); 73 | 74 | /* ---------------------------------------------------------------------- 75 | * Reads and parses the header of a PLY file returned by ply_open 76 | * 77 | * ply: handle returned by ply_open 78 | * 79 | * Returns 1 if successfull, 0 otherwise 80 | * ---------------------------------------------------------------------- */ 81 | int ply_read_header(p_ply ply); 82 | 83 | /* ---------------------------------------------------------------------- 84 | * Property reading callback prototype 85 | * 86 | * argument: parameters for property being processed when callback is called 87 | * 88 | * Returns 1 if should continue processing file, 0 if should abort. 89 | * ---------------------------------------------------------------------- */ 90 | typedef int (*p_ply_read_cb)(p_ply_argument argument); 91 | 92 | /* ---------------------------------------------------------------------- 93 | * Sets up callbacks for property reading after header was parsed 94 | * 95 | * ply: handle returned by ply_open 96 | * element_name: element where property is 97 | * property_name: property to associate element with 98 | * read_cb: function to be called for each property value 99 | * pdata/idata: user data that will be passed to callback 100 | * 101 | * Returns 0 if no element or no property in element, returns the 102 | * number of element instances otherwise. 103 | * ---------------------------------------------------------------------- */ 104 | long ply_set_read_cb(p_ply ply, const char *element_name, 105 | const char *property_name, p_ply_read_cb read_cb, 106 | void *pdata, long idata); 107 | 108 | /* ---------------------------------------------------------------------- 109 | * Returns information about the element originating a callback 110 | * 111 | * argument: handle to argument 112 | * element: receives a the element handle (if non-null) 113 | * instance_index: receives the index of the current element instance 114 | * (if non-null) 115 | * 116 | * Returns 1 if successfull, 0 otherwise 117 | * ---------------------------------------------------------------------- */ 118 | int ply_get_argument_element(p_ply_argument argument, 119 | p_ply_element *element, long *instance_index); 120 | 121 | /* ---------------------------------------------------------------------- 122 | * Returns information about the property originating a callback 123 | * 124 | * argument: handle to argument 125 | * property: receives the property handle (if non-null) 126 | * length: receives the number of values in this property (if non-null) 127 | * value_index: receives the index of current property value (if non-null) 128 | * 129 | * Returns 1 if successfull, 0 otherwise 130 | * ---------------------------------------------------------------------- */ 131 | int ply_get_argument_property(p_ply_argument argument, 132 | p_ply_property *property, long *length, long *value_index); 133 | 134 | /* ---------------------------------------------------------------------- 135 | * Returns user data associated with callback 136 | * 137 | * pdata: receives a copy of user custom data pointer (if non-null) 138 | * idata: receives a copy of user custom data integer (if non-null) 139 | * 140 | * Returns 1 if successfull, 0 otherwise 141 | * ---------------------------------------------------------------------- */ 142 | int ply_get_argument_user_data(p_ply_argument argument, void **pdata, 143 | long *idata); 144 | 145 | /* ---------------------------------------------------------------------- 146 | * Returns the value associated with a callback 147 | * 148 | * argument: handle to argument 149 | * 150 | * Returns the current data item 151 | * ---------------------------------------------------------------------- */ 152 | double ply_get_argument_value(p_ply_argument argument); 153 | 154 | /* ---------------------------------------------------------------------- 155 | * Reads all elements and properties calling the callbacks defined with 156 | * calls to ply_set_read_cb 157 | * 158 | * ply: handle returned by ply_open 159 | * 160 | * Returns 1 if successfull, 0 otherwise 161 | * ---------------------------------------------------------------------- */ 162 | int ply_read(p_ply ply); 163 | 164 | /* ---------------------------------------------------------------------- 165 | * Iterates over all elements by returning the next element. 166 | * Call with NULL to return handle to first element. 167 | * 168 | * ply: handle returned by ply_open 169 | * last: handle of last element returned (NULL for first element) 170 | * 171 | * Returns element if successfull or NULL if no more elements 172 | * ---------------------------------------------------------------------- */ 173 | p_ply_element ply_get_next_element(p_ply ply, p_ply_element last); 174 | 175 | /* ---------------------------------------------------------------------- 176 | * Iterates over all comments by returning the next comment. 177 | * Call with NULL to return pointer to first comment. 178 | * 179 | * ply: handle returned by ply_open 180 | * last: pointer to last comment returned (NULL for first comment) 181 | * 182 | * Returns comment if successfull or NULL if no more comments 183 | * ---------------------------------------------------------------------- */ 184 | const char *ply_get_next_comment(p_ply ply, const char *last); 185 | 186 | /* ---------------------------------------------------------------------- 187 | * Iterates over all obj_infos by returning the next obj_info. 188 | * Call with NULL to return pointer to first obj_info. 189 | * 190 | * ply: handle returned by ply_open 191 | * last: pointer to last obj_info returned (NULL for first obj_info) 192 | * 193 | * Returns obj_info if successfull or NULL if no more obj_infos 194 | * ---------------------------------------------------------------------- */ 195 | const char *ply_get_next_obj_info(p_ply ply, const char *last); 196 | 197 | /* ---------------------------------------------------------------------- 198 | * Returns information about an element 199 | * 200 | * element: element of interest 201 | * name: receives a pointer to internal copy of element name (if non-null) 202 | * ninstances: receives the number of instances of this element (if non-null) 203 | * 204 | * Returns 1 if successfull or 0 otherwise 205 | * ---------------------------------------------------------------------- */ 206 | int ply_get_element_info(p_ply_element element, const char** name, 207 | long *ninstances); 208 | 209 | /* ---------------------------------------------------------------------- 210 | * Iterates over all properties by returning the next property. 211 | * Call with NULL to return handle to first property. 212 | * 213 | * element: handle of element with the properties of interest 214 | * last: handle of last property returned (NULL for first property) 215 | * 216 | * Returns element if successfull or NULL if no more properties 217 | * ---------------------------------------------------------------------- */ 218 | p_ply_property ply_get_next_property(p_ply_element element, 219 | p_ply_property last); 220 | 221 | /* ---------------------------------------------------------------------- 222 | * Returns information about a property 223 | * 224 | * property: handle to property of interest 225 | * name: receives a pointer to internal copy of property name (if non-null) 226 | * type: receives the property type (if non-null) 227 | * length_type: for list properties, receives the scalar type of 228 | * the length field (if non-null) 229 | * value_type: for list properties, receives the scalar type of the value 230 | * fields (if non-null) 231 | * 232 | * Returns 1 if successfull or 0 otherwise 233 | * ---------------------------------------------------------------------- */ 234 | int ply_get_property_info(p_ply_property property, const char** name, 235 | e_ply_type *type, e_ply_type *length_type, e_ply_type *value_type); 236 | 237 | /* ---------------------------------------------------------------------- 238 | * Creates new PLY file 239 | * 240 | * name: file name 241 | * storage_mode: file format mode 242 | * error_cb: error callback function 243 | * idata,pdata: contextual information available to users 244 | * 245 | * Returns handle to PLY file if successfull, NULL otherwise 246 | * ---------------------------------------------------------------------- */ 247 | p_ply ply_create(const char *name, e_ply_storage_mode storage_mode, 248 | p_ply_error_cb error_cb, long idata, void *pdata); 249 | 250 | /* ---------------------------------------------------------------------- 251 | * Adds a new element to the PLY file created by ply_create 252 | * 253 | * ply: handle returned by ply_create 254 | * name: name of new element 255 | * ninstances: number of element of this time in file 256 | * 257 | * Returns 1 if successfull, 0 otherwise 258 | * ---------------------------------------------------------------------- */ 259 | int ply_add_element(p_ply ply, const char *name, long ninstances); 260 | 261 | /* ---------------------------------------------------------------------- 262 | * Adds a new property to the last element added by ply_add_element 263 | * 264 | * ply: handle returned by ply_create 265 | * name: name of new property 266 | * type: property type 267 | * length_type: scalar type of length field of a list property 268 | * value_type: scalar type of value fields of a list property 269 | * 270 | * Returns 1 if successfull, 0 otherwise 271 | * ---------------------------------------------------------------------- */ 272 | int ply_add_property(p_ply ply, const char *name, e_ply_type type, 273 | e_ply_type length_type, e_ply_type value_type); 274 | 275 | /* ---------------------------------------------------------------------- 276 | * Adds a new list property to the last element added by ply_add_element 277 | * 278 | * ply: handle returned by ply_create 279 | * name: name of new property 280 | * length_type: scalar type of length field of a list property 281 | * value_type: scalar type of value fields of a list property 282 | * 283 | * Returns 1 if successfull, 0 otherwise 284 | * ---------------------------------------------------------------------- */ 285 | int ply_add_list_property(p_ply ply, const char *name, 286 | e_ply_type length_type, e_ply_type value_type); 287 | 288 | /* ---------------------------------------------------------------------- 289 | * Adds a new property to the last element added by ply_add_element 290 | * 291 | * ply: handle returned by ply_create 292 | * name: name of new property 293 | * type: property type 294 | * 295 | * Returns 1 if successfull, 0 otherwise 296 | * ---------------------------------------------------------------------- */ 297 | int ply_add_scalar_property(p_ply ply, const char *name, e_ply_type type); 298 | 299 | /* ---------------------------------------------------------------------- 300 | * Adds a new comment item 301 | * 302 | * ply: handle returned by ply_create 303 | * comment: pointer to string with comment text 304 | * 305 | * Returns 1 if successfull, 0 otherwise 306 | * ---------------------------------------------------------------------- */ 307 | int ply_add_comment(p_ply ply, const char *comment); 308 | 309 | /* ---------------------------------------------------------------------- 310 | * Adds a new obj_info item 311 | * 312 | * ply: handle returned by ply_create 313 | * comment: pointer to string with obj_info data 314 | * 315 | * Returns 1 if successfull, 0 otherwise 316 | * ---------------------------------------------------------------------- */ 317 | int ply_add_obj_info(p_ply ply, const char *obj_info); 318 | 319 | /* ---------------------------------------------------------------------- 320 | * Writes the PLY file header after all element and properties have been 321 | * defined by calls to ply_add_element and ply_add_property 322 | * 323 | * ply: handle returned by ply_create 324 | * 325 | * Returns 1 if successfull, 0 otherwise 326 | * ---------------------------------------------------------------------- */ 327 | int ply_write_header(p_ply ply); 328 | 329 | /* ---------------------------------------------------------------------- 330 | * Writes one property value, in the order they should be written to the 331 | * file. For each element type, write all elements of that type in order. 332 | * For each element, write all its properties in order. For scalar 333 | * properties, just write the value. For list properties, write the length 334 | * and then each of the values. 335 | * 336 | * ply: handle returned by ply_create 337 | * 338 | * Returns 1 if successfull, 0 otherwise 339 | * ---------------------------------------------------------------------- */ 340 | int ply_write(p_ply ply, double value); 341 | 342 | /* ---------------------------------------------------------------------- 343 | * Closes a PLY file handle. Releases all memory used by handle 344 | * 345 | * ply: handle to be closed. 346 | * 347 | * Returns 1 if successfull, 0 otherwise 348 | * ---------------------------------------------------------------------- */ 349 | int ply_close(p_ply ply); 350 | 351 | #ifdef __cplusplus 352 | } 353 | #endif 354 | 355 | #endif /* RPLY_H */ 356 | 357 | /* ---------------------------------------------------------------------- 358 | * Copyright (C) 2003-2015 Diego Nehab. All rights reserved. 359 | * 360 | * Permission is hereby granted, free of charge, to any person obtaining 361 | * a copy of this software and associated documentation files (the 362 | * "Software"), to deal in the Software without restriction, including 363 | * without limitation the rights to use, copy, modify, merge, publish, 364 | * distribute, sublicense, and/or sell copies of the Software, and to 365 | * permit persons to whom the Software is furnished to do so, subject to 366 | * the following conditions: 367 | * 368 | * The above copyright notice and this permission notice shall be 369 | * included in all copies or substantial portions of the Software. 370 | * 371 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 372 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 373 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 374 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 375 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 376 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 377 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 378 | * ---------------------------------------------------------------------- */ 379 | --------------------------------------------------------------------------------