├── .gitignore ├── FSwindow ├── .gitignore ├── FSwindow.pro └── main.cpp ├── README.md ├── cvDisplacementMapFilter ├── README.md ├── cvDisplacementMapFilter.pro ├── main.cpp ├── map.jpg ├── screenshot.gif └── target.png ├── cvFruitClassification ├── README.md ├── apples │ ├── 1.png │ ├── 10.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ └── 9.png ├── cvFruitClassification.pro ├── dirent.h ├── main.cpp ├── oranges │ ├── 1.png │ ├── 10.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ └── 9.png ├── screenshot.jpg ├── test │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.png │ └── 8.jpg └── toolbox.h ├── cvQtCameraGL ├── README.md ├── cvQtCameraGL.pro ├── main.cpp ├── screenshot.gif ├── widget.cpp └── widget.h ├── cvQtImage ├── README.md ├── cvImage.cpp ├── cvImage.h ├── cvQtImage.pro ├── main.cpp └── screenshot.jpg ├── cvQtVideo ├── README.md ├── cvQtVideo.pro ├── cvWindow.cpp ├── cvWindow.h ├── main.cpp └── screenshot.gif ├── cvWatershedSegmentation ├── README.md ├── beans.png ├── cvWatershedSegmentation.pro ├── main.cpp └── screenshot.jpg ├── ipcQTgesture ├── gesture_handler.cpp ├── gesture_handler.h ├── ipcQTgesture.pro ├── ipc_window.cpp ├── ipc_window.h └── main.cpp ├── ipcQtGesture ├── gesture_handler.cpp ├── gesture_handler.h ├── ipcQtGesture.pro ├── ipc_window.cpp ├── ipc_window.h └── main.cpp ├── qml2DQuadTree ├── Point.qml ├── QuadTree.qml ├── README.md ├── Rect.qml ├── draw.js ├── main.cpp ├── main.qml ├── qml.qrc ├── qml2DQuadTree.pro └── screenshot.gif ├── qml2DRaycasting ├── Boundary.qml ├── Particle.qml ├── README.md ├── Ray.qml ├── draw.js ├── main.cpp ├── main.qml ├── qml.qrc ├── qml2DRaycasting.pro └── screenshot.gif ├── qml2DRaycastingEngine ├── Boundary.qml ├── Particle.qml ├── README.md ├── Ray.qml ├── draw.js ├── main.cpp ├── main.qml ├── qml.qrc ├── qml2DRaycastingEngine.pro └── screenshot.gif ├── qml3DTerrain ├── README.md ├── TerrainEntity.qml ├── WireframeEffect.qml ├── WireframeMaterial.qml ├── main.cpp ├── main.qml ├── qml.qrc ├── qml3DTerrain.pro ├── screenshot.gif └── shaders │ ├── robustwireframe.frag │ ├── robustwireframe.geom │ └── robustwireframe.vert ├── qml3DWater ├── CrystalEntity.qml ├── CustomTerrainEntity.qml ├── PhongShadingMaterial.qml ├── README.md ├── TerrainEntity.qml ├── TextureEntity.qml ├── TreeEntity.qml ├── WaterEntity.qml ├── WaterMaterial.qml ├── assets.qrc ├── assets │ ├── minecraft │ │ ├── Forest.png │ │ ├── ForestNoWater.mtl │ │ └── ForestNoWater.obj │ ├── tree.obj │ ├── waterDUDV.png │ └── waterNormalMap.png ├── main.cpp ├── main.qml ├── perlin.js ├── qml.qrc ├── qml3DWater.pro ├── screenshot.gif └── shaders │ ├── light.inc.frag │ ├── phong.inc.frag │ ├── terrain.frag │ ├── terrain.vert │ ├── water.frag │ └── water.vert ├── qmlBattery ├── Battery.qml ├── README.md ├── batterycontroller.cpp ├── batterycontroller.h ├── main.cpp ├── main.qml ├── qml.qrc ├── qmlBattery.pro └── screenshot.gif ├── qt3DRenderer ├── README.md ├── assets │ ├── crab.obj │ ├── crab.png │ ├── cube.obj │ ├── cube.png │ ├── drone.obj │ ├── drone.png │ ├── efa.obj │ ├── efa.png │ ├── f117.obj │ ├── f117.png │ ├── f22.obj │ ├── f22.png │ ├── runway.obj │ └── runway.png ├── camera.cpp ├── camera.h ├── clipping.cpp ├── clipping.h ├── cubemesh.cpp ├── cubemesh.h ├── display.cpp ├── display.h ├── face.cpp ├── face.h ├── light.cpp ├── light.h ├── main.cpp ├── mat4.cpp ├── mat4.h ├── mesh.cpp ├── mesh.h ├── objloader.cpp ├── objloader.h ├── qt3DRenderer.pro ├── screenshot.gif ├── tex2.cpp ├── tex2.h ├── triangle.cpp ├── triangle.h ├── vec2d.cpp ├── vec2d.h ├── vec3d.cpp ├── vec3d.h ├── vec4d.cpp ├── vec4d.h ├── window.cpp └── window.h ├── qtArduinoSerial ├── main.cpp ├── qtArduinoSerial.pro ├── serialportreader.cpp └── serialportreader.h ├── qtFPSvsTIMEAnimation ├── README.md ├── fps_anim.cpp ├── fps_anim.h ├── fps_canvas.cpp ├── fps_canvas.h ├── main.cpp ├── qtFPSvsTIMEAnimation.pro ├── screenshot.gif ├── time_anim.cpp ├── time_anim.h ├── time_anim_improved.cpp ├── time_anim_improved.h ├── time_canvas.cpp └── time_canvas.h ├── qtGLMdemo ├── README.md ├── data │ ├── porsche.mtl │ └── porsche.obj ├── glm.c ├── glm.h ├── glwidget.cpp ├── glwidget.h ├── main.cpp ├── qtGLMdemo.pro └── screenshot.gif ├── qtKinectVideo ├── main.cpp ├── qtKinectVideo.pro ├── window.cpp └── window.h ├── qtLinearRegressionGD ├── Madplotlib.h ├── README.md ├── main.cpp ├── qtLinearRegressionGD.pro └── screenshot.jpg ├── qtLogoBlurGL ├── GLwindow.cpp ├── GLwindow.h ├── README.md ├── main.cpp ├── qtLogoBlurGL.pro └── screenshot.jpg └── qtSmoothColorTransition ├── .gitignore ├── README.md ├── heightmap.jpg ├── main.cpp ├── qtSmoothColorTransition.pro └── screenshot.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | *.pro.user 2 | build-* 3 | -------------------------------------------------------------------------------- /FSwindow/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | .directory 25 | *.debug 26 | Makefile* 27 | *.prl 28 | *.app 29 | moc_*.cpp 30 | ui_*.h 31 | qrc_*.cpp 32 | Thumbs.db 33 | *.res 34 | *.rc 35 | /.qmake.cache 36 | /.qmake.stash 37 | 38 | # qtcreator generated files 39 | *.pro.user* 40 | 41 | # xemacs temporary files 42 | *.flc 43 | 44 | # Vim temporary files 45 | .*.swp 46 | 47 | # Visual Studio generated files 48 | *.ib_pdb_index 49 | *.idb 50 | *.ilk 51 | *.pdb 52 | *.sln 53 | *.suo 54 | *.vcproj 55 | *vcproj.*.*.user 56 | *.ncb 57 | *.sdf 58 | *.opensdf 59 | *.vcxproj 60 | *vcxproj.* 61 | 62 | # MinGW generated files 63 | *.Debug 64 | *.Release 65 | 66 | # Python byte code 67 | *.pyc 68 | 69 | # Binaries 70 | # -------- 71 | *.dll 72 | *.exe 73 | 74 | -------------------------------------------------------------------------------- /FSwindow/FSwindow.pro: -------------------------------------------------------------------------------- 1 | CONFIG += static 2 | 3 | SOURCES += \ 4 | main.cpp 5 | 6 | LIBS += user32.lib 7 | -------------------------------------------------------------------------------- /FSwindow/main.cpp: -------------------------------------------------------------------------------- 1 | // https://westechsolutions.net/sites/WindowedBorderlessGaming/ 2 | #include 3 | #include 4 | 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | HWND win_handle = FindWindow(0, L"Overwatch"); 9 | if (!win_handle) 10 | { 11 | std::cout << "Failed FindWindow" << std::endl; 12 | return 0; 13 | } 14 | 15 | // Resize 16 | // unsigned int flags = (SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER); 17 | // unsigned int flags = (SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); 18 | unsigned int flags = (SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); 19 | flags &= ~SWP_NOSIZE; // essential 20 | unsigned int x = 300; 21 | unsigned int y = 200; 22 | unsigned int w = 960; 23 | unsigned int h = 540; 24 | SetWindowPos(win_handle, HWND_NOTOPMOST, x, y, w, h, flags); 25 | 26 | 27 | // SendMessage(win_handle, WM_SIZE, SIZE_RESTORED, MAKELPARAM(x, y)); 28 | // PostMessage(win_handle, WM_SIZE, SIZE_RESTORED, MAKELPARAM(x, y)); 29 | 30 | // InvalidateRect(win_handle, NULL, TRUE); 31 | // SendMessage(win_handle, WM_SETREDRAW, TRUE, 0); // Re-enable repaint 32 | // RedrawWindow(win_handle, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 33 | 34 | 35 | // RedrawWindow(win_handle, &g::rcDesktop , 0 , RDW_INTERNALPAINT | RDW_UPDATENOW | RDW_ALLCHILDREN | RDW_INVALIDATE); 36 | 37 | // Borderless 38 | // SetWindowLong(win_handle, GWL_STYLE, GetWindowLong(win_handle, GWL_EXSTYLE) | WS_EX_TOPMOST); 39 | // SetWindowLong(win_handle, GWL_STYLE, WS_CAPTION | WS_BORDER | WS_SYSMENU | WS_MINIMIZEBOX | WS_OVERLAPPEDWINDOW); 40 | // SetWindowLong(win_handle, GWL_STYLE, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX); 41 | SetWindowLong(win_handle, GWL_STYLE, WS_SYSMENU | WS_OVERLAPPEDWINDOW); 42 | 43 | 44 | // UpdateWindow(win_handle); 45 | 46 | // RECT rc = { x, y, w, h}; 47 | // RedrawWindow(win_handle, &rc, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW ); 48 | 49 | ShowWindow(win_handle, SW_SHOW); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /cvDisplacementMapFilter/README.md: -------------------------------------------------------------------------------- 1 | # cvDisplacementMapFilter 2 | 3 | Screenshot 4 | -------------------------------------------------------------------------------- /cvDisplacementMapFilter/cvDisplacementMapFilter.pro: -------------------------------------------------------------------------------- 1 | SOURCES += \ 2 | main.cpp 3 | 4 | # On my system I have to specify g++ as compiler else it will use clang++ by default 5 | #QMAKE_CXX=g++ 6 | #QMAKE_CC=gcc 7 | 8 | ## OpenCV settings for Unix/Linux 9 | unix:!mac { 10 | message("* Using settings for Unix/Linux.") 11 | INCLUDEPATH += /usr/local/include/opencv 12 | 13 | LIBS += -L/usr/local/lib/ \ 14 | -lopencv_core \ 15 | -lopencv_highgui \ 16 | -lopencv_imgproc 17 | } 18 | 19 | ## OpenCV settings for Mac OS X 20 | macx { 21 | message("* Using settings for Mac OS X.") 22 | INCLUDEPATH += /usr/local/include/opencv 23 | 24 | LIBS += -L/usr/local/lib/ \ 25 | -lopencv_core \ 26 | -lopencv_highgui \ 27 | -lopencv_imgproc 28 | } 29 | 30 | ## OpenCV settings for Windows and OpenCV 4.5.0 31 | win32 { 32 | message("* Using settings for Windows.") 33 | INCLUDEPATH += "C:\\opencv\\build\\install\\include" \ 34 | "C:\\opencv\\build\\install\\include\\opencv2" \ 35 | 36 | CONFIG(debug, debug | release) { 37 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 38 | -lopencv_core450d \ 39 | -lopencv_highgui450d \ 40 | -lopencv_imgproc450d \ 41 | -lopencv_imgcodecs450d 42 | 43 | # Projects > Build & Run > Run 44 | # Check: add build library search path to PATH 45 | # This allows OpenCV DLLs to be found when running this application 46 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 47 | } 48 | 49 | CONFIG(release, debug | release) { 50 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 51 | -lopencv_core450 \ 52 | -lopencv_highgui450 \ 53 | -lopencv_imgproc450 \ 54 | -lopencv_imgcodecs450 55 | 56 | # Projects > Build & Run > Run 57 | # Check: add build library search path to PATH 58 | # This allows OpenCV DLLs to be found when running this application 59 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 60 | } 61 | } 62 | 63 | # Runs this app automatically after the building has succeeded 64 | #QMAKE_POST_LINK=./$$TARGET 65 | -------------------------------------------------------------------------------- /cvDisplacementMapFilter/map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvDisplacementMapFilter/map.jpg -------------------------------------------------------------------------------- /cvDisplacementMapFilter/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvDisplacementMapFilter/screenshot.gif -------------------------------------------------------------------------------- /cvDisplacementMapFilter/target.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvDisplacementMapFilter/target.png -------------------------------------------------------------------------------- /cvFruitClassification/README.md: -------------------------------------------------------------------------------- 1 | # cvFruitClassification 2 | 3 | Screenshot -------------------------------------------------------------------------------- /cvFruitClassification/apples/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/1.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/10.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/2.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/3.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/4.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/5.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/6.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/7.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/8.png -------------------------------------------------------------------------------- /cvFruitClassification/apples/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/apples/9.png -------------------------------------------------------------------------------- /cvFruitClassification/cvFruitClassification.pro: -------------------------------------------------------------------------------- 1 | ## OpenCV settings for Windows and OpenCV 4.5.0 2 | win32 { 3 | message("* Using settings for Windows.") 4 | INCLUDEPATH += "C:\\opencv\\build\\install\\include" \ 5 | "C:\\opencv\\build\\install\\include\\opencv2" \ 6 | 7 | CONFIG(debug, debug | release) { 8 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 9 | -lopencv_core450d \ 10 | -lopencv_highgui450d \ 11 | -lopencv_imgproc450d \ 12 | -lopencv_imgcodecs450d 13 | 14 | # Projects > Build & Run > Run 15 | # Check: add build library search path to PATH 16 | # This allows OpenCV DLLs to be found when running this application 17 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 18 | } 19 | 20 | CONFIG(release, debug | release) { 21 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 22 | -lopencv_core450 \ 23 | -lopencv_highgui450 \ 24 | -lopencv_imgproc450 \ 25 | -lopencv_imgcodecs450 26 | 27 | # Projects > Build & Run > Run 28 | # Check: add build library search path to PATH 29 | # This allows OpenCV DLLs to be found when running this application 30 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 31 | } 32 | } 33 | 34 | ## OpenCV settings for Unix/Linux 35 | unix:!mac { 36 | message("* Using settings for Unix/Linux.") 37 | INCLUDEPATH += /usr/local/include/opencv 38 | 39 | LIBS += -L/usr/local/lib/ \ 40 | -lopencv_core \ 41 | -lopencv_highgui \ 42 | -lopencv_imgproc 43 | } 44 | 45 | ## OpenCV settings for Mac OS X 46 | macx { 47 | message("* Using settings for Mac OS X.") 48 | INCLUDEPATH += /usr/local/include/opencv 49 | 50 | LIBS += -L/usr/local/lib/ \ 51 | -lopencv_core \ 52 | -lopencv_highgui \ 53 | -lopencv_imgproc 54 | } 55 | 56 | SOURCES += \ 57 | main.cpp 58 | 59 | HEADERS += \ 60 | toolbox.h \ 61 | dirent.h 62 | -------------------------------------------------------------------------------- /cvFruitClassification/oranges/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/1.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/10.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/2.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/3.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/4.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/5.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/6.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/7.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/8.png -------------------------------------------------------------------------------- /cvFruitClassification/oranges/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/oranges/9.png -------------------------------------------------------------------------------- /cvFruitClassification/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/screenshot.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/1.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/2.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/3.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/4.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/5.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/6.jpg -------------------------------------------------------------------------------- /cvFruitClassification/test/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/7.png -------------------------------------------------------------------------------- /cvFruitClassification/test/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvFruitClassification/test/8.jpg -------------------------------------------------------------------------------- /cvQtCameraGL/README.md: -------------------------------------------------------------------------------- 1 | # cvQtCameraGL 2 | 3 | Screenshot -------------------------------------------------------------------------------- /cvQtCameraGL/cvQtCameraGL.pro: -------------------------------------------------------------------------------- 1 | QT += core gui opengl 2 | 3 | contains(QT_VERSION, ^5\\.[0-8]\\..*) { 4 | message("* Using Qt $${QT_VERSION}.") 5 | QT += widgets 6 | 7 | # On my system I have to specify g++ as compiler else it will use clang++ by default 8 | #QMAKE_CXX=g++ 9 | #QMAKE_CC=gcc 10 | } 11 | 12 | SOURCES += \ 13 | main.cpp \ 14 | widget.cpp 15 | 16 | HEADERS += \ 17 | widget.h 18 | 19 | ## OpenCV settings for Unix/Linux 20 | unix:!mac { 21 | message("* Using settings for Unix/Linux.") 22 | INCLUDEPATH += /usr/local/include/opencv 23 | 24 | LIBS += -L/usr/local/lib/ \ 25 | -lopencv_core \ 26 | -lopencv_highgui \ 27 | -lopencv_imgproc 28 | } 29 | 30 | ## OpenCV settings for Mac OS X with OpenCV 3.1 31 | macx { 32 | message("* Using settings for Mac OS X.") 33 | 34 | # Solve imwrite() undefined symbol 35 | QMAKE_CXXFLAGS += -stdlib=libc++ 36 | 37 | INCLUDEPATH += "/usr/local/opt/opencv3/include" 38 | 39 | LIBS += -L"/usr/local/opt/opencv3/lib" \ 40 | -lopencv_core \ 41 | -lopencv_highgui \ 42 | -lopencv_imgproc \ 43 | -lopencv_imgcodecs \ 44 | -lopencv_videoio \ 45 | -lc++ 46 | } 47 | 48 | ## OpenCV settings for Windows and OpenCV 4.5.0 49 | win32 { 50 | message("* Using settings for Windows.") 51 | INCLUDEPATH += "C:\\opencv\\build\\install\\include" \ 52 | "C:\\opencv\\build\\install\\include\\opencv2" \ 53 | 54 | LIBS += -lopengl32 55 | 56 | CONFIG(debug, debug | release) { 57 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 58 | -lopencv_core450d \ 59 | -lopencv_highgui450d \ 60 | -lopencv_imgproc450d \ 61 | -lopencv_imgcodecs450d \ 62 | -lopencv_videoio450d 63 | 64 | # Projects > Build & Run > Run 65 | # Check: add build library search path to PATH 66 | # This allows OpenCV DLLs to be found when running this application 67 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 68 | } 69 | 70 | CONFIG(release, debug | release) { 71 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 72 | -lopencv_core450 \ 73 | -lopencv_highgui450 \ 74 | -lopencv_imgproc450 \ 75 | -lopencv_imgcodecs450 \ 76 | -lopencv_videoio450 77 | 78 | # Projects > Build & Run > Run 79 | # Check: add build library search path to PATH 80 | # This allows OpenCV DLLs to be found when running this application 81 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /cvQtCameraGL/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013-2020 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include 11 | #include "widget.h" 12 | 13 | int main(int argc, char* argv[]) 14 | { 15 | QApplication app(argc, argv); 16 | 17 | // For OpenGL Graphics 18 | GLWidget gl_widget; 19 | gl_widget.show(); 20 | 21 | return app.exec(); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /cvQtCameraGL/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvQtCameraGL/screenshot.gif -------------------------------------------------------------------------------- /cvQtCameraGL/widget.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013-2020 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include 12 | #include 13 | #include 14 | 15 | class GLWidget : public QGLWidget 16 | { 17 | Q_OBJECT 18 | public: 19 | explicit GLWidget(QWidget* parent = 0); 20 | virtual ~GLWidget(); 21 | 22 | /* OpenGL initialization, viewport resizing, and painting */ 23 | 24 | void initializeGL(); 25 | void paintGL(); 26 | void resizeGL( int width, int height); 27 | 28 | private: 29 | int _width; 30 | int _height; 31 | cv::Mat cv_frame; 32 | cv::VideoCapture cv_capture; 33 | int _fps; 34 | GLuint _texture; 35 | 36 | protected slots: 37 | void _tick(); 38 | }; 39 | -------------------------------------------------------------------------------- /cvQtImage/README.md: -------------------------------------------------------------------------------- 1 | # cvQtImage 2 | 3 | Screenshot 4 | -------------------------------------------------------------------------------- /cvQtImage/cvImage.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | class cvImage : public QMainWindow 10 | { 11 | Q_OBJECT 12 | 13 | public: 14 | cvImage(); 15 | ~cvImage(); 16 | 17 | void paintEvent(QPaintEvent* e); 18 | void keyPressEvent(QKeyEvent* event); 19 | void mouseMoveEvent(QMouseEvent *event); 20 | 21 | private: 22 | QMenuBar _menu_bar; 23 | QMenu* _menu; 24 | QImage _image; 25 | 26 | private slots: 27 | void _open(); 28 | 29 | protected: 30 | void _close(); 31 | 32 | signals: 33 | void closed(); 34 | }; 35 | -------------------------------------------------------------------------------- /cvQtImage/cvQtImage.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += core gui widgets 4 | 5 | contains(QT_VERSION, ^5\\.[0-8]\\..*) { 6 | message("* Using Qt $${QT_VERSION}.") 7 | QT += widgets 8 | 9 | # On my system I have to specify g++ as compiler else it will use clang++ by default 10 | #QMAKE_CXX=g++ 11 | #QMAKE_CC=gcc 12 | } 13 | 14 | SOURCES += \ 15 | main.cpp \ 16 | cvImage.cpp 17 | 18 | HEADERS += \ 19 | cvImage.h 20 | 21 | ## OpenCV settings for Unix/Linux 22 | unix:!mac { 23 | message("* Using settings for Unix/Linux.") 24 | INCLUDEPATH += /usr/local/include/opencv 25 | 26 | LIBS += -L/usr/local/lib/ \ 27 | -lopencv_core \ 28 | -lopencv_highgui \ 29 | -lopencv_imgproc 30 | } 31 | 32 | ## OpenCV settings for Mac OS X 33 | macx { 34 | message("* Using settings for Mac OS X.") 35 | INCLUDEPATH += /usr/local/include/opencv 36 | 37 | LIBS += -L/usr/local/lib/ \ 38 | -lopencv_core \ 39 | -lopencv_highgui \ 40 | -lopencv_imgproc 41 | } 42 | 43 | ## OpenCV settings for Windows and OpenCV 4.5.0 44 | win32 { 45 | message("* Using settings for Windows.") 46 | INCLUDEPATH += "C:\\opencv\\build\\install\\include" \ 47 | "C:\\opencv\\build\\install\\include\\opencv2" \ 48 | 49 | CONFIG(debug, debug | release) { 50 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 51 | -lopencv_core450d \ 52 | -lopencv_highgui450d \ 53 | -lopencv_imgproc450d \ 54 | -lopencv_imgcodecs450d 55 | 56 | # Projects > Build & Run > Run 57 | # Check: add build library search path to PATH 58 | # This allows OpenCV DLLs to be found when running this application 59 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 60 | } 61 | 62 | CONFIG(release, debug | release) { 63 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 64 | -lopencv_core450 \ 65 | -lopencv_highgui450 \ 66 | -lopencv_imgproc450 \ 67 | -lopencv_imgcodecs450 68 | 69 | # Projects > Build & Run > Run 70 | # Check: add build library search path to PATH 71 | # This allows OpenCV DLLs to be found when running this application 72 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 73 | } 74 | } 75 | 76 | # Runs this app automatically after the building has succeeded 77 | #QMAKE_POST_LINK=./$$TARGET 78 | -------------------------------------------------------------------------------- /cvQtImage/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "cvImage.h" 11 | 12 | #include 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | QApplication app(argc, argv); 17 | 18 | cvImage win; 19 | win.show(); 20 | 21 | QObject::connect(&win, SIGNAL(closed()), 22 | &app, SLOT(quit()) ); 23 | 24 | return app.exec(); 25 | } 26 | 27 | -------------------------------------------------------------------------------- /cvQtImage/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvQtImage/screenshot.jpg -------------------------------------------------------------------------------- /cvQtVideo/README.md: -------------------------------------------------------------------------------- 1 | # cvQtVideo 2 | 3 | Screenshot -------------------------------------------------------------------------------- /cvQtVideo/cvQtVideo.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | QT += core gui widgets 4 | 5 | contains(QT_VERSION, ^5\\.[0-8]\\..*) { 6 | message("* Using Qt $${QT_VERSION}.") 7 | QT += widgets 8 | 9 | # On my system I have to specify g++ as compiler else it will use clang++ by default 10 | #QMAKE_CXX=g++ 11 | #QMAKE_CC=gcc 12 | } 13 | 14 | HEADERS += \ 15 | cvWindow.h 16 | 17 | SOURCES += \ 18 | main.cpp \ 19 | cvWindow.cpp 20 | 21 | ## OpenCV settings for Unix/Linux 22 | unix:!mac { 23 | message("* Using settings for Unix/Linux.") 24 | INCLUDEPATH += /usr/local/include/opencv 25 | 26 | LIBS += -L/usr/local/lib/ \ 27 | -lopencv_core \ 28 | -lopencv_highgui \ 29 | -lopencv_imgproc 30 | } 31 | 32 | ## OpenCV settings for Mac OS X 33 | macx { 34 | message("* Using settings for Mac OS X.") 35 | INCLUDEPATH += /usr/local/include/opencv 36 | 37 | LIBS += -L/usr/local/lib/ \ 38 | -lopencv_core \ 39 | -lopencv_highgui \ 40 | -lopencv_imgproc 41 | } 42 | 43 | ## OpenCV settings for Windows and OpenCV 4.5.0 44 | win32 { 45 | message("* Using settings for Windows.") 46 | INCLUDEPATH += "C:\\opencv\\build\\install\\include" \ 47 | "C:\\opencv\\build\\install\\include\\opencv2" \ 48 | 49 | CONFIG(debug, debug | release) { 50 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 51 | -lopencv_core450d \ 52 | -lopencv_highgui450d \ 53 | -lopencv_imgproc450d \ 54 | -lopencv_imgcodecs450d \ 55 | -lopencv_videoio450d 56 | 57 | # Projects > Build & Run > Run 58 | # Check: add build library search path to PATH 59 | # This allows OpenCV DLLs to be found when running this application 60 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 61 | } 62 | 63 | CONFIG(release, debug | release) { 64 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 65 | -lopencv_core450 \ 66 | -lopencv_highgui450 \ 67 | -lopencv_imgproc450 \ 68 | -lopencv_imgcodecs450 \ 69 | -lopencv_videoio450 70 | 71 | # Projects > Build & Run > Run 72 | # Check: add build library search path to PATH 73 | # This allows OpenCV DLLs to be found when running this application 74 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 75 | } 76 | } 77 | 78 | # Runs this app automatically after the building has succeeded 79 | #QMAKE_POST_LINK=./$$TARGET 80 | -------------------------------------------------------------------------------- /cvQtVideo/cvWindow.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | 20 | class cvWindow : public QMainWindow 21 | { 22 | Q_OBJECT 23 | 24 | public: 25 | cvWindow(); 26 | ~cvWindow(); 27 | 28 | void _draw_video_frame(QPainter& painter); 29 | void _draw_info_text(QPainter& painter); 30 | 31 | void paintEvent(QPaintEvent* e); 32 | void keyPressEvent(QKeyEvent* event); 33 | 34 | private: 35 | QMenuBar _menu_bar; 36 | QMenu* _menu; 37 | QImage* _image; 38 | cv::VideoCapture* _capture; 39 | int _tick_ms; 40 | Qt::AspectRatioMode _ar_mode; 41 | int _fps; 42 | int _video_width; 43 | int _video_height; 44 | QTimer* _timer; 45 | 46 | private slots: 47 | void _open(); 48 | void _tick(); 49 | 50 | protected: 51 | void _close(); 52 | 53 | signals: 54 | void closed(); 55 | }; 56 | -------------------------------------------------------------------------------- /cvQtVideo/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "cvWindow.h" 11 | 12 | #include 13 | 14 | int main(int argc, char* argv[]) 15 | { 16 | QApplication app(argc, argv); 17 | 18 | cvWindow win; 19 | win.show(); 20 | 21 | QObject::connect(&win, SIGNAL(closed()), 22 | &app, SLOT(quit()) ); 23 | 24 | return app.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /cvQtVideo/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvQtVideo/screenshot.gif -------------------------------------------------------------------------------- /cvWatershedSegmentation/README.md: -------------------------------------------------------------------------------- 1 | # cvWatershedSegmentation 2 | 3 | Screenshot -------------------------------------------------------------------------------- /cvWatershedSegmentation/beans.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvWatershedSegmentation/beans.png -------------------------------------------------------------------------------- /cvWatershedSegmentation/cvWatershedSegmentation.pro: -------------------------------------------------------------------------------- 1 | ## OpenCV settings for Windows and OpenCV 4.5.0 2 | win32 { 3 | message("* Using settings for Windows.") 4 | INCLUDEPATH += "C:\\opencv\\build\\install\\include" \ 5 | "C:\\opencv\\build\\install\\include\\opencv2" \ 6 | 7 | CONFIG(debug, debug | release) { 8 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 9 | -lopencv_core450d \ 10 | -lopencv_highgui450d \ 11 | -lopencv_imgproc450d \ 12 | -lopencv_imgcodecs450d \ 13 | -lopencv_videoio450d 14 | 15 | # Projects > Build & Run > Run 16 | # Check: add build library search path to PATH 17 | # This allows OpenCV DLLs to be found when running this application 18 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 19 | } 20 | 21 | CONFIG(release, debug | release) { 22 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\lib" \ 23 | -lopencv_core450 \ 24 | -lopencv_highgui450 \ 25 | -lopencv_imgproc450 \ 26 | -lopencv_imgcodecs450 \ 27 | -lopencv_videoio450 28 | 29 | # Projects > Build & Run > Run 30 | # Check: add build library search path to PATH 31 | # This allows OpenCV DLLs to be found when running this application 32 | LIBS += -L"C:\\opencv\\build\\install\\x64\\vc16\\bin" 33 | } 34 | } 35 | 36 | SOURCES += \ 37 | main.cpp 38 | 39 | -------------------------------------------------------------------------------- /cvWatershedSegmentation/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/cvWatershedSegmentation/screenshot.jpg -------------------------------------------------------------------------------- /ipcQTgesture/gesture_handler.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "util_render.h" 12 | #include "util_pipeline.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | class GestureHandler : public QObject 22 | { 23 | Q_OBJECT 24 | public: 25 | GestureHandler(); 26 | ~GestureHandler(); 27 | 28 | bool start(); 29 | void stop(); 30 | QSize image_size(); 31 | 32 | signals: 33 | void notify_gesture(PXCGesture::Gesture gesture_evt); 34 | void notify_image(QPixmap pixmap); 35 | 36 | private slots: 37 | void _stream(); 38 | 39 | private: 40 | bool _streaming; 41 | bool _init_error; 42 | QTimer _fps_timer; 43 | UtilPipeline _pipeline; 44 | QElapsedTimer _elapsed_timer; 45 | PXCGesture::Gesture::Label _last_gesture; 46 | }; 47 | -------------------------------------------------------------------------------- /ipcQTgesture/ipcQTgesture.pro: -------------------------------------------------------------------------------- 1 | QT += core gui widgets 2 | 3 | SOURCES += \ 4 | ipc_window.cpp \ 5 | main.cpp \ 6 | gesture_handler.cpp 7 | 8 | HEADERS += \ 9 | ipc_window.h \ 10 | gesture_handler.h 11 | 12 | win32 { 13 | QMAKE_CXXFLAGS_DEBUG += -Zi -MTd 14 | QMAKE_CXXFLAGS_RELEASE += -MT 15 | 16 | INCLUDEPATH += "C:\\Program Files\\Intel\\PCSDK\\include" \ 17 | "C:\\Program Files\\Intel\\PCSDK\\sample\\common\\include" \ 18 | "C:\\Program Files\\Intel\\PCSDK\\sample\\common\\res" 19 | 20 | LIBS += -L"C:\\Program Files\\Intel\\PCSDK\\lib\\Win32" \ 21 | -L"C:\\Program Files\\Intel\\PCSDK\\sample\\common\\lib\\Win32\\v100" 22 | 23 | CONFIG (debug, debug|release) { 24 | message("* Configuring project for Debug.") 25 | 26 | LIBS += -llibpxc_d \ 27 | -llibpxcutils_d 28 | 29 | LIBS += "advapi32.lib" "msvcrtd.lib" "libcmtd.lib" 30 | } 31 | else { 32 | message("* Configuring project for Release.") 33 | 34 | LIBS += -llibpxc \ 35 | -llibpxcutils 36 | 37 | LIBS += "advapi32.lib" "msvcrt.lib" "libcmt.lib" 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /ipcQTgesture/ipc_window.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "gesture_handler.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | class IPCWindow: public QMainWindow 20 | { 21 | Q_OBJECT 22 | public: 23 | IPCWindow(); 24 | ~IPCWindow(); 25 | 26 | bool start_streaming(); 27 | void stop_streaming(); 28 | 29 | void keyPressEvent(QKeyEvent* evt); 30 | 31 | private slots: 32 | void _gesture_evt(PXCGesture::Gesture gesture_evt); 33 | void _image_evt(QPixmap pixmap); 34 | 35 | private: 36 | QLabel* _label; 37 | QLabel* _status_label; 38 | GestureHandler _gesture_handler; 39 | }; 40 | -------------------------------------------------------------------------------- /ipcQTgesture/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "ipc_window.h" 11 | 12 | #include 13 | 14 | #include 15 | 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | QApplication app(argc, argv); 20 | 21 | IPCWindow* window = new IPCWindow(); 22 | window->show(); 23 | 24 | return app.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /ipcQtGesture/gesture_handler.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "util_render.h" 12 | #include "util_pipeline.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | class GestureHandler : public QObject 22 | { 23 | Q_OBJECT 24 | public: 25 | GestureHandler(); 26 | ~GestureHandler(); 27 | 28 | bool start(); 29 | void stop(); 30 | QSize image_size(); 31 | 32 | signals: 33 | void notify_gesture(PXCGesture::Gesture gesture_evt); 34 | void notify_image(QPixmap pixmap); 35 | 36 | private slots: 37 | void _stream(); 38 | 39 | private: 40 | bool _streaming; 41 | bool _init_error; 42 | QTimer _fps_timer; 43 | UtilPipeline _pipeline; 44 | QElapsedTimer _elapsed_timer; 45 | PXCGesture::Gesture::Label _last_gesture; 46 | }; 47 | -------------------------------------------------------------------------------- /ipcQtGesture/ipcQtGesture.pro: -------------------------------------------------------------------------------- 1 | QT += core gui widgets 2 | 3 | SOURCES += \ 4 | ipc_window.cpp \ 5 | main.cpp \ 6 | gesture_handler.cpp 7 | 8 | HEADERS += \ 9 | ipc_window.h \ 10 | gesture_handler.h 11 | 12 | win32 { 13 | QMAKE_CXXFLAGS_DEBUG += -Zi -MTd 14 | QMAKE_CXXFLAGS_RELEASE += -MT 15 | 16 | INCLUDEPATH += "C:\\Program Files\\Intel\\PCSDK\\include" \ 17 | "C:\\Program Files\\Intel\\PCSDK\\sample\\common\\include" \ 18 | "C:\\Program Files\\Intel\\PCSDK\\sample\\common\\res" 19 | 20 | LIBS += -L"C:\\Program Files\\Intel\\PCSDK\\lib\\Win32" \ 21 | -L"C:\\Program Files\\Intel\\PCSDK\\sample\\common\\lib\\Win32\\v100" 22 | 23 | CONFIG (debug, debug|release) { 24 | message("* Configuring project for Debug.") 25 | 26 | LIBS += -llibpxc_d \ 27 | -llibpxcutils_d 28 | 29 | LIBS += "advapi32.lib" "msvcrtd.lib" "libcmtd.lib" 30 | } 31 | else { 32 | message("* Configuring project for Release.") 33 | 34 | LIBS += -llibpxc \ 35 | -llibpxcutils 36 | 37 | LIBS += "advapi32.lib" "msvcrt.lib" "libcmt.lib" 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /ipcQtGesture/ipc_window.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "gesture_handler.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | class IPCWindow: public QMainWindow 20 | { 21 | Q_OBJECT 22 | public: 23 | IPCWindow(); 24 | ~IPCWindow(); 25 | 26 | bool start_streaming(); 27 | void stop_streaming(); 28 | 29 | void keyPressEvent(QKeyEvent* evt); 30 | 31 | private slots: 32 | void _gesture_evt(PXCGesture::Gesture gesture_evt); 33 | void _image_evt(QPixmap pixmap); 34 | 35 | private: 36 | QLabel* _label; 37 | QLabel* _status_label; 38 | GestureHandler _gesture_handler; 39 | }; 40 | -------------------------------------------------------------------------------- /ipcQtGesture/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "ipc_window.h" 11 | 12 | #include 13 | 14 | #include 15 | 16 | 17 | int main(int argc, char* argv[]) 18 | { 19 | QApplication app(argc, argv); 20 | 21 | IPCWindow* window = new IPCWindow(); 22 | window->show(); 23 | 24 | return app.exec(); 25 | } 26 | -------------------------------------------------------------------------------- /qml2DQuadTree/Point.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Point is an element that stores the x,y position of a particle on the screen. 3 | */ 4 | import QtQuick 2.0 5 | 6 | Item { 7 | id: point 8 | } 9 | -------------------------------------------------------------------------------- /qml2DQuadTree/README.md: -------------------------------------------------------------------------------- 1 | # qml2DQuadTree 2 | 3 | A QML/Javascript implementation of the data structure *Quadtree* that partitions the 2D space recursively subdividing it into 4 quadrants in order to speed up the search operation to find all the points that are within a specific rectangular area: 4 | 5 | Screenshot 6 | 7 | **Reference**: 8 | 9 | - [Wikipedia: Quadtree](https://en.wikipedia.org/wiki/Quadtree) 10 | - [The Coding Train - Coding Challenge #98.1: Quadtree](https://www.youtube.com/watch?v=OJxEcs0w_kE) 11 | -------------------------------------------------------------------------------- /qml2DQuadTree/Rect.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Rect is an element that stores the x,y,width,height position of a rectangle on the screen. 3 | */ 4 | import QtQuick 2.12 5 | 6 | Item { 7 | id: rect 8 | 9 | property var w : 0 10 | property var h : 0 11 | 12 | // contains: check if a point is within the boundary of this Rect 13 | function contains(point) { 14 | return (point.x >= this.x - this.w && 15 | point.x <= this.x + this.w && 16 | point.y >= this.y - this.h && 17 | point.y <= this.y + this.h); 18 | } 19 | 20 | // intersects: AABB collision detection 21 | function intersects(range) { 22 | return !(range.x - range.w > this.x + this.w || 23 | range.x + range.w < this.x - this.w || 24 | range.y - range.h > this.y + this.h || 25 | range.y + range.h < this.y - this.h); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /qml2DQuadTree/draw.js: -------------------------------------------------------------------------------- 1 | // helper functions for drawing inside Canvas 2 | 3 | function line(ctx, x1, y1, x2, y2, color, lineWidth=1) { 4 | ctx.save(); 5 | ctx.beginPath(); 6 | ctx.lineWidth = lineWidth; 7 | ctx.strokeStyle = color; 8 | ctx.moveTo(x1, y1); 9 | ctx.lineTo(x2, y2); 10 | ctx.closePath(); 11 | ctx.stroke(); 12 | ctx.restore(); 13 | } 14 | 15 | function circle(ctx, x, y, radius, color) { 16 | ctx.save(); 17 | ctx.beginPath() 18 | ctx.strokeStyle = color; 19 | ctx.fillStyle = color; 20 | ctx.arc(x, y, radius, 0, 360, false); 21 | ctx.fill(); 22 | ctx.closePath() 23 | ctx.restore(); 24 | } 25 | 26 | function rect(ctx, x, y, w, h, color, fill=true, lineWidth=1) { 27 | ctx.save(); 28 | ctx.beginPath() 29 | 30 | // border width and color 31 | ctx.lineWidth = lineWidth; 32 | ctx.strokeStyle = color; 33 | ctx.rect(x, y, w, h); 34 | 35 | // fill color 36 | if (fill) { 37 | ctx.fillStyle = color; 38 | ctx.fill(); 39 | } 40 | 41 | ctx.stroke(); 42 | ctx.closePath() 43 | ctx.restore(); 44 | } 45 | 46 | function rectCenter(ctx, x, y, w, h, color, borderColor, border=true) { 47 | ctx.save(); 48 | ctx.beginPath(); 49 | 50 | x -= w / 2; 51 | y -= h / 2; 52 | 53 | ctx.strokeStyle = borderColor; 54 | 55 | ctx.rect(x, y, w, h); 56 | ctx.fillStyle = color; 57 | ctx.fill(); 58 | 59 | if (!border) { 60 | ctx.lineWidth = 1; 61 | } 62 | 63 | ctx.stroke(); 64 | ctx.closePath() 65 | ctx.restore(); 66 | } 67 | 68 | function rectCenter(ctx, x, y, w, h, color, borderColor, fill=true, lineWidth=1) { 69 | // move x,y to the left/top 70 | x -= w / 2; 71 | y -= h / 2; 72 | 73 | ctx.save(); 74 | ctx.beginPath() 75 | 76 | // border width and color 77 | ctx.lineWidth = lineWidth; 78 | ctx.strokeStyle = borderColor; 79 | ctx.rect(x, y, w, h); 80 | 81 | // fill color 82 | if (fill) { 83 | ctx.fillStyle = color; 84 | ctx.fill(); 85 | } 86 | 87 | ctx.stroke(); 88 | ctx.closePath() 89 | ctx.restore(); 90 | } 91 | 92 | function text(ctx, text, x, y, color, font="20px sans-serif") { 93 | ctx.save(); 94 | ctx.font = font; 95 | ctx.fillStyle = color; 96 | ctx.fillText(qsTr(text), x, y); 97 | ctx.stroke(); 98 | ctx.restore(); 99 | } 100 | -------------------------------------------------------------------------------- /qml2DQuadTree/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 7 | 8 | QGuiApplication app(argc, argv); 9 | 10 | QQmlApplicationEngine engine; 11 | const QUrl url(QStringLiteral("qrc:/main.qml")); 12 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 13 | &app, [url](QObject *obj, const QUrl &objUrl) { 14 | if (!obj && url == objUrl) 15 | QCoreApplication::exit(-1); 16 | }, Qt::QueuedConnection); 17 | engine.load(url); 18 | 19 | return app.exec(); 20 | } 21 | -------------------------------------------------------------------------------- /qml2DQuadTree/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | draw.js 5 | Rect.qml 6 | Point.qml 7 | QuadTree.qml 8 | 9 | 10 | -------------------------------------------------------------------------------- /qml2DQuadTree/qml2DQuadTree.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | # You can make your code fail to compile if it uses deprecated APIs. 6 | # In order to do so, uncomment the following line. 7 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 8 | 9 | SOURCES += \ 10 | main.cpp 11 | 12 | RESOURCES += qml.qrc 13 | 14 | # Additional import path used to resolve QML modules in Qt Creator's code model 15 | QML_IMPORT_PATH = 16 | 17 | # Additional import path used to resolve QML modules just for Qt Quick Designer 18 | QML_DESIGNER_IMPORT_PATH = 19 | 20 | # Default rules for deployment. 21 | qnx: target.path = /tmp/$${TARGET}/bin 22 | else: unix:!android: target.path = /opt/$${TARGET}/bin 23 | !isEmpty(target.path): INSTALLS += target 24 | -------------------------------------------------------------------------------- /qml2DQuadTree/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml2DQuadTree/screenshot.gif -------------------------------------------------------------------------------- /qml2DRaycasting/Boundary.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import "draw.js" as Draw 3 | 4 | Item { 5 | property vector2d a: Qt.vector2d(0, 0) 6 | property vector2d b: Qt.vector2d(0, 0) 7 | 8 | function show(ctx) { 9 | Draw.line(ctx, a.x, a.y, b.x, b.y, Qt.rgba(255, 255, 255, 1), 1); 10 | 11 | //console.log("Boundary.show: a=" + a); 12 | //console.log("Boundary.show: b=" + b); 13 | } 14 | 15 | Component.onCompleted: { 16 | console.log("Boundary constructed: a=" + a + " b=" + b); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /qml2DRaycasting/README.md: -------------------------------------------------------------------------------- 1 | # qmlRayCasting2D 2 | 3 | A naive implementation of 2D raycasting using line segment "surfaces" and vector "rays". 4 | 5 | Screenshot 6 | 7 | **Reference**: 8 | 9 | - [The Coding Train - Coding Challenge #145: 2D Raycasting](https://www.youtube.com/watch?v=TOEi6T2mtHo) 10 | 11 | -------------------------------------------------------------------------------- /qml2DRaycasting/Ray.qml: -------------------------------------------------------------------------------- 1 | /* Ray 2 | * A component that represents a ray of light. 3 | * It calculates the point of interception with a wall if they collide. 4 | */ 5 | import QtQuick 2.0 6 | import "draw.js" as Draw 7 | 8 | Item { 9 | id: ray 10 | 11 | property var angle: 0.0 // the angle of the light in radians 12 | property vector2d pos: Qt.vector2d(0, 0) // starting position of the ray 13 | property vector2d dir: fromAngle(angle) // unit vector that guides the direction of the light 14 | 15 | property var raySize: 16 // size of the ray for debugging purposes 16 | 17 | // show: draw the light of ray on the screen (red) 18 | function show(ctx) { 19 | Draw.line(ctx, ray.pos.x, ray.pos.y, ray.pos.x+ray.dir.x*raySize, ray.pos.y+ray.dir.y*raySize, "red"); 20 | //console.log("Ray.show: pos=" + pos + " angle=" + angle + " dir=" + dir); 21 | } 22 | 23 | // fromAngle: creates a unit vector with the direction of the angle (radians) 24 | function fromAngle(rad) { 25 | return Qt.vector2d(Math.cos(rad), Math.sin(rad)); 26 | } 27 | 28 | // lookAt: sets the direction to where the ray is looking at 29 | function lookAt(x, y) { 30 | ray.dir.x = x - ray.pos.x; 31 | ray.dir.y = y - ray.pos.y; 32 | ray.dir = ray.dir.normalized(); // shortens the ray 33 | } 34 | 35 | // cast: returns the point of intersection between two lines. Otherwise, it returns NULL. 36 | function cast(wall) { 37 | /* The intersection point falls within the first line segment if 0.0 <= t <= 1.0 38 | * AND if it falls within the second line segment if: u >= 0 39 | */ 40 | // wall endpoints 41 | var x1 = wall.a.x; 42 | var y1 = wall.a.y; 43 | var x2 = wall.b.x; 44 | var y2 = wall.b.y; 45 | //console.log("Ray::cast wall pt1=" + x1 + "," + y1 + " pt2=" + x2 + "," + y2); 46 | 47 | // ray endpoints 48 | var x3 = ray.pos.x; 49 | var y3 = ray.pos.y; 50 | var x4 = ray.pos.x + ray.dir.x; 51 | var y4 = ray.pos.y + ray.dir.y; 52 | //console.log("Ray::cast ray pt1=" + x3 + "," + y3 + " pt2=" + x4 + "," + y4); 53 | 54 | // calculate the denominator 55 | var den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); 56 | //console.log("den=" + den); 57 | 58 | // if den is 0, it means that ray and wall are perfectly parallel to each other and will never TouchPoint 59 | if (den === 0) 60 | return {}; 61 | 62 | // calculate t and u 63 | var t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den; 64 | var u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den; 65 | //console.log("t=" + t); 66 | //console.log("u=" + u); 67 | 68 | // if they intersect, calculate the point of intersection 69 | if (t > 0 && t < 1 && u > 0) { 70 | var pt = Qt.vector2d(0, 0); 71 | pt.x = x1 + t * (x2 - x1); 72 | pt.y = y1 + t * (y2 - y1); 73 | return pt; 74 | } 75 | 76 | // otherwise, return undefined: no intersection found 77 | return {}; 78 | } 79 | 80 | Component.onCompleted: { 81 | console.log("Ray constructed: pos=" + pos.x + "," + pos.y + " angle=" + angle + " dir=" + dir); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /qml2DRaycasting/draw.js: -------------------------------------------------------------------------------- 1 | // helper functions for drawing inside Canvas 2 | 3 | function line(ctx, x1, y1, x2, y2, color, lineWidth=1) { 4 | ctx.save(); 5 | ctx.beginPath(); 6 | ctx.lineWidth = lineWidth; 7 | ctx.strokeStyle = color; 8 | ctx.moveTo(x1, y1); 9 | ctx.lineTo(x2, y2); 10 | ctx.closePath(); 11 | ctx.stroke(); 12 | ctx.restore(); 13 | } 14 | 15 | function circle(ctx, x, y, radius, color) { 16 | ctx.save(); 17 | ctx.beginPath() 18 | ctx.strokeStyle = color; 19 | ctx.fillStyle = color; 20 | ctx.arc(x, y, radius, 0, 360, false); 21 | ctx.fill(); 22 | ctx.closePath() 23 | ctx.restore(); 24 | } 25 | 26 | function rect(ctx, x, y, w, h, color, border=true) { 27 | ctx.save(); 28 | ctx.beginPath() 29 | 30 | ctx.rect(x, y, w, h); 31 | ctx.fillStyle = color; 32 | ctx.fill(); 33 | 34 | if (!border) { 35 | ctx.lineWidth = 1; 36 | ctx.strokeStyle = color; 37 | } 38 | 39 | ctx.stroke(); 40 | ctx.closePath() 41 | ctx.restore(); 42 | } 43 | 44 | function text(ctx, text, x, y, color, font="20px sans-serif") { 45 | ctx.save(); 46 | ctx.font = font; 47 | ctx.fillStyle = color; 48 | ctx.fillText(qsTr(text), x, y); 49 | ctx.stroke(); 50 | ctx.restore(); 51 | } 52 | -------------------------------------------------------------------------------- /qml2DRaycasting/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 7 | 8 | QGuiApplication app(argc, argv); 9 | 10 | QQmlApplicationEngine engine; 11 | const QUrl url(QStringLiteral("qrc:/main.qml")); 12 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 13 | &app, [url](QObject *obj, const QUrl &objUrl) { 14 | if (!obj && url == objUrl) 15 | QCoreApplication::exit(-1); 16 | }, Qt::QueuedConnection); 17 | engine.load(url); 18 | 19 | return app.exec(); 20 | } 21 | -------------------------------------------------------------------------------- /qml2DRaycasting/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | Boundary.qml 5 | Ray.qml 6 | Particle.qml 7 | draw.js 8 | 9 | 10 | -------------------------------------------------------------------------------- /qml2DRaycasting/qml2DRaycasting.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | # You can make your code fail to compile if it uses deprecated APIs. 6 | # In order to do so, uncomment the following line. 7 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 8 | 9 | SOURCES += \ 10 | main.cpp 11 | 12 | RESOURCES += qml.qrc 13 | 14 | # Additional import path used to resolve QML modules in Qt Creator's code model 15 | QML_IMPORT_PATH = 16 | 17 | # Additional import path used to resolve QML modules just for Qt Quick Designer 18 | QML_DESIGNER_IMPORT_PATH = 19 | 20 | # Default rules for deployment. 21 | qnx: target.path = /tmp/$${TARGET}/bin 22 | else: unix:!android: target.path = /opt/$${TARGET}/bin 23 | !isEmpty(target.path): INSTALLS += target 24 | -------------------------------------------------------------------------------- /qml2DRaycasting/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml2DRaycasting/screenshot.gif -------------------------------------------------------------------------------- /qml2DRaycastingEngine/Boundary.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import "draw.js" as Draw 3 | 4 | Item { 5 | id: wall 6 | property vector2d a: Qt.vector2d(0, 0) 7 | property vector2d b: Qt.vector2d(0, 0) 8 | property var color: "cyan" 9 | 10 | function show(ctx) { 11 | Draw.line(ctx, a.x, a.y, b.x, b.y, wall.color, 1); 12 | 13 | //console.log("Boundary.show: a=" + a); 14 | //console.log("Boundary.show: b=" + b); 15 | } 16 | 17 | Component.onCompleted: { 18 | console.log("Boundary constructed: a=" + a + " b=" + b); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/README.md: -------------------------------------------------------------------------------- 1 | # qml2DRaycastingEngine 2 | 3 | A naive implementation of 2D a raycasting engine in QML based on the [qml2DRaycasting](https://github.com/karlphillip/GraphicsProgramming/tree/master/qml2DRaycasting) demo. 4 | 5 | Screenshot 6 | 7 | **References**: 8 | 9 | - [The Coding Train - Coding Challenge #146: Rendering Raycasting](https://www.youtube.com/watch?v=vYgIKn7iDH8) 10 | - [Raycasting Basics with JavaScript](https://courses.pikuma.com/courses/take/raycasting/lessons/7503441-wall-projection) 11 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/Ray.qml: -------------------------------------------------------------------------------- 1 | /* Ray 2 | * A component that represents a ray of light. 3 | * It calculates the point of interception with a wall if they collide. 4 | */ 5 | import QtQuick 2.0 6 | import "draw.js" as Draw 7 | 8 | Item { 9 | id: ray 10 | 11 | property var angle: 0.0 // the angle of the light in radians 12 | property vector2d pos: Qt.vector2d(0, 0) // starting position of the ray 13 | property vector2d dir: fromAngle(angle) // unit vector that guides the direction of the light 14 | 15 | property double heading: Math.atan2(dir.y, dir.x) // heading of Qt.vector2d(30, 50) is 1.0303768265243125 16 | 17 | property var raySize: 25 // size of the ray for debugging purposes 18 | 19 | // show: draw the light of ray on the screen (red) 20 | function show(ctx) { 21 | Draw.line(ctx, ray.pos.x, ray.pos.y, ray.pos.x+ray.dir.x*raySize, ray.pos.y+ray.dir.y*raySize, "red"); 22 | //console.log("Ray.show: pos=" + pos + " dir=" + dir + " angle=" + angle); 23 | } 24 | 25 | function setAngle(angle) { 26 | ray.dir = fromAngle(angle); 27 | //console.log("Ray.setAngle: dir=" + ray.dir); 28 | } 29 | 30 | // fromAngle: creates a unit vector with the direction of the angle (radians) 31 | function fromAngle(rad) { 32 | return Qt.vector2d(Math.cos(rad), Math.sin(rad)); 33 | } 34 | 35 | // lookAt: sets the direction to where the ray is looking at 36 | function lookAt(x, y) { 37 | ray.dir.x = x - ray.pos.x; 38 | ray.dir.y = y - ray.pos.y; 39 | ray.dir = ray.dir.normalized(); // shortens the ray 40 | } 41 | 42 | // cast: returns the point of intersection between two lines. Otherwise, it returns NULL. 43 | function cast(wall) { 44 | /* The intersection point falls within the first line segment if 0.0 <= t <= 1.0 45 | * AND if it falls within the second line segment if: u >= 0 46 | */ 47 | // wall endpoints 48 | var x1 = wall.a.x; 49 | var y1 = wall.a.y; 50 | var x2 = wall.b.x; 51 | var y2 = wall.b.y; 52 | //console.log("Ray::cast wall pt1=" + x1 + "," + y1 + " pt2=" + x2 + "," + y2); 53 | 54 | // ray endpoints 55 | var x3 = ray.pos.x; 56 | var y3 = ray.pos.y; 57 | var x4 = ray.pos.x + ray.dir.x; 58 | var y4 = ray.pos.y + ray.dir.y; 59 | //console.log("Ray::cast ray pt1=" + x3 + "," + y3 + " pt2=" + x4 + "," + y4); 60 | 61 | // calculate the denominator 62 | var den = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); 63 | //console.log("den=" + den); 64 | 65 | // if den is 0, it means that ray and wall are perfectly parallel to each other and will never TouchPoint 66 | if (den === 0) 67 | return {}; 68 | 69 | // calculate t and u 70 | var t = ((x1 - x3) * (y3 - y4) - (y1 - y3) * (x3 - x4)) / den; 71 | var u = -((x1 - x2) * (y1 - y3) - (y1 - y2) * (x1 - x3)) / den; 72 | //console.log("t=" + t); 73 | //console.log("u=" + u); 74 | 75 | // if they intersect, calculate the point of intersection 76 | if (t > 0 && t < 1 && u > 0) { 77 | var pt = Qt.vector2d(0, 0); 78 | pt.x = x1 + t * (x2 - x1); 79 | pt.y = y1 + t * (y2 - y1); 80 | return pt; 81 | } 82 | 83 | // otherwise, return undefined: no intersection found 84 | return {}; 85 | } 86 | 87 | Component.onCompleted: { 88 | console.log("Ray constructed: pos=" + pos.x + "," + pos.y + " angle=" + angle + " dir=" + dir); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/draw.js: -------------------------------------------------------------------------------- 1 | // helper functions for drawing inside Canvas 2 | 3 | function line(ctx, x1, y1, x2, y2, color, lineWidth=1) { 4 | ctx.save(); 5 | ctx.beginPath(); 6 | ctx.lineWidth = lineWidth; 7 | ctx.strokeStyle = color; 8 | ctx.moveTo(x1, y1); 9 | ctx.lineTo(x2, y2); 10 | ctx.closePath(); 11 | ctx.stroke(); 12 | ctx.restore(); 13 | } 14 | 15 | function circle(ctx, x, y, radius, color) { 16 | ctx.save(); 17 | ctx.beginPath() 18 | ctx.strokeStyle = color; 19 | ctx.fillStyle = color; 20 | ctx.arc(x, y, radius, 0, 360, false); 21 | ctx.fill(); 22 | ctx.closePath() 23 | ctx.restore(); 24 | } 25 | 26 | function rect(ctx, x, y, w, h, color, border=true) { 27 | ctx.save(); 28 | ctx.beginPath() 29 | 30 | ctx.rect(x, y, w, h); 31 | ctx.fillStyle = color; 32 | ctx.fill(); 33 | 34 | if (!border) { 35 | ctx.lineWidth = 1; 36 | ctx.strokeStyle = color; 37 | } 38 | 39 | ctx.stroke(); 40 | ctx.closePath() 41 | ctx.restore(); 42 | } 43 | 44 | function text(ctx, text, x, y, color, font="20px sans-serif") { 45 | ctx.save(); 46 | ctx.font = font; 47 | ctx.fillStyle = color; 48 | ctx.fillText(qsTr(text), x, y); 49 | ctx.stroke(); 50 | ctx.restore(); 51 | } 52 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 7 | 8 | QGuiApplication app(argc, argv); 9 | 10 | QQmlApplicationEngine engine; 11 | const QUrl url(QStringLiteral("qrc:/main.qml")); 12 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, 13 | &app, [url](QObject *obj, const QUrl &objUrl) { 14 | if (!obj && url == objUrl) 15 | QCoreApplication::exit(-1); 16 | }, Qt::QueuedConnection); 17 | engine.load(url); 18 | 19 | return app.exec(); 20 | } 21 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | Boundary.qml 5 | Ray.qml 6 | Particle.qml 7 | draw.js 8 | 9 | 10 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/qml2DRaycastingEngine.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | # You can make your code fail to compile if it uses deprecated APIs. 6 | # In order to do so, uncomment the following line. 7 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 8 | 9 | SOURCES += \ 10 | main.cpp 11 | 12 | RESOURCES += qml.qrc 13 | 14 | # Additional import path used to resolve QML modules in Qt Creator's code model 15 | QML_IMPORT_PATH = 16 | 17 | # Additional import path used to resolve QML modules just for Qt Quick Designer 18 | QML_DESIGNER_IMPORT_PATH = 19 | 20 | # Default rules for deployment. 21 | qnx: target.path = /tmp/$${TARGET}/bin 22 | else: unix:!android: target.path = /opt/$${TARGET}/bin 23 | !isEmpty(target.path): INSTALLS += target 24 | -------------------------------------------------------------------------------- /qml2DRaycastingEngine/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml2DRaycastingEngine/screenshot.gif -------------------------------------------------------------------------------- /qml3DTerrain/README.md: -------------------------------------------------------------------------------- 1 | # qml3DTerrain 2 | 3 | Qt3D/QML implementation of dynamic terrain generation based on the Perlin noise: 4 | 5 | Screenshot 6 | 7 | Terrain generation and the wireframe looks are both transformations done by GLSL shaders on the meshes of a `PlaneMesh` entity. 8 | 9 | **References**: 10 | 11 | - [Qt 3D: Wireframe QML Example](https://doc.qt.io/qt-5/qt3d-wireframe-example.html). 12 | - [The Coding Train - Coding Challenge #11: 3D Terrain Generation with Perlin Noise in Processing](https://www.youtube.com/watch?v=IKB1hWWedMk) 13 | - [Generic Noise Algorithms in GLSL](https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83) 14 | -------------------------------------------------------------------------------- /qml3DTerrain/TerrainEntity.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.12 2 | import Qt3D.Render 2.12 3 | import Qt3D.Input 2.12 4 | import Qt3D.Logic 2.12 5 | import Qt3D.Extras 2.12 6 | 7 | Entity { 8 | id: root 9 | property var cols : 2 10 | property var rows : 2 11 | property real xoff 12 | property real yoff 13 | 14 | /* validateRange: doesn't let the total number of indices in a mesh be larger 15 | * than quint16 (65536). 16 | * 17 | * const int faces = 2 * (resolution.width() - 1) * (resolution.height() - 1); 18 | * const int indices = 3 * faces; 19 | * Q_ASSERT(indices < std::numeric_limits::max()); 20 | */ 21 | function validateRange(c, r, returnCols) { 22 | let faces = 2 * (c - 1) * (r - 1); 23 | let indices = 3 * faces; 24 | if (indices >= 65536) { 25 | return 105; 26 | } 27 | 28 | if (returnCols) 29 | return c; 30 | 31 | return r; 32 | } 33 | 34 | function evalMeshSize() { 35 | //console.log("evalMeshSize: c=", root.cols, "r=", root.rows); 36 | let cols = validateRange(root.cols, root.rows, true); 37 | let rows = validateRange(root.cols, root.rows, false); 38 | //console.log("evalMeshSize: cols=", cols, "rows=", rows); 39 | return Qt.size(cols, rows); 40 | } 41 | 42 | PlaneMesh { 43 | id: customMesh 44 | width: 10.0 45 | height: 20.0 46 | meshResolution: evalMeshSize() 47 | } 48 | 49 | Transform { 50 | id: transform 51 | translation: Qt.vector3d(0.0, 0.0, 0.0) 52 | rotationX: 10 // 90 53 | } 54 | 55 | PhongAlphaMaterial { 56 | id: material 57 | ambient: "blue" 58 | diffuse: "blue" 59 | alpha: 0.8 60 | } 61 | 62 | WireframeMaterial { 63 | id: wireframeMaterial 64 | yoff: root.yoff 65 | 66 | ambient: Qt.rgba( 0.2, 0.2, 0.2, 1.0 ) 67 | diffuse: Qt.rgba( 0.8, 0.8, 0.8, 1.0 ) 68 | effect: WireframeEffect { } 69 | } 70 | 71 | //components: [ customMesh, transform, material ] 72 | components: [ customMesh, transform, wireframeMaterial ] 73 | } 74 | -------------------------------------------------------------------------------- /qml3DTerrain/WireframeEffect.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.12 2 | import Qt3D.Render 2.12 3 | 4 | Effect { 5 | id: root 6 | 7 | parameters: [ 8 | Parameter { name: "ka"; value: Qt.vector3d( 0.1, 0.1, 0.1 ) }, 9 | Parameter { name: "kd"; value: Qt.vector3d( 0.7, 0.7, 0.7 ) }, 10 | Parameter { name: "ks"; value: Qt.vector3d( 0.95, 0.95, 0.95 ) }, 11 | Parameter { name: "shininess"; value: 0.0 } 12 | ] 13 | 14 | techniques: [ 15 | Technique { 16 | graphicsApiFilter { 17 | api: GraphicsApiFilter.OpenGL 18 | profile: GraphicsApiFilter.CoreProfile 19 | majorVersion: 3 20 | minorVersion: 1 21 | } 22 | 23 | filterKeys: [ FilterKey { name: "renderingStyle"; value: "forward" } ] 24 | 25 | parameters: [ 26 | Parameter { name: "light.intensity"; value: Qt.vector3d( 0.3, 0.3, 0.3 ) }, 27 | Parameter { name: "light.position"; value: Qt.vector4d( 0.0, 0.0, 0.0, 1.0 ) }, 28 | Parameter { name: "line.width"; value: 1.0 }, 29 | Parameter { name: "line.color"; value: Qt.vector4d( 1.0, 1.0, 1.0, 1.0 ) } 30 | ] 31 | 32 | renderPasses: [ 33 | RenderPass { 34 | shaderProgram: ShaderProgram { 35 | vertexShaderCode: loadSource("qrc:/shaders/robustwireframe.vert") 36 | geometryShaderCode: loadSource("qrc:/shaders/robustwireframe.geom") 37 | fragmentShaderCode: loadSource("qrc:/shaders/robustwireframe.frag") 38 | } 39 | } 40 | ] 41 | } 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /qml3DTerrain/WireframeMaterial.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.12 2 | import Qt3D.Render 2.12 3 | 4 | Material { 5 | id: root 6 | 7 | property color ambient: Qt.rgba( 0.05, 0.05, 0.05, 1.0 ) 8 | property color diffuse: Qt.rgba( 0.7, 0.7, 0.7, 1.0 ) 9 | property color specular: Qt.rgba( 0.95, 0.95, 0.95, 1.0 ) 10 | property real shininess: 50.0 11 | property real lineWidth: 1.0 12 | property color lineColor: Qt.rgba( 1.0, 1.0, 1.0, 1.0 ) // set wireframe color: white 13 | 14 | // variable that controls Perlin noise in the vertex shader 15 | property real xoff: 0.0 16 | property real yoff: 0.0 17 | 18 | parameters: [ 19 | Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) }, 20 | Parameter { name: "kd"; value: Qt.vector3d(root.diffuse.r, root.diffuse.g, root.diffuse.b) }, 21 | Parameter { name: "ksp"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) }, 22 | Parameter { name: "shininess"; value: root.shininess }, 23 | Parameter { name: "line.width"; value: root.lineWidth }, 24 | Parameter { name: "line.color"; value: root.lineColor }, 25 | Parameter { name: "xoff"; value: root.yoff }, 26 | Parameter { name: "yoff"; value: root.yoff } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /qml3DTerrain/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void setSurfaceFormat() 8 | { 9 | QSurfaceFormat format; 10 | #ifdef QT_OPENGL_ES_2 11 | format.setRenderableType(QSurfaceFormat::OpenGLES); 12 | #else 13 | if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) { 14 | format.setVersion(4, 3); 15 | format.setProfile(QSurfaceFormat::CoreProfile); 16 | } 17 | #endif 18 | format.setDepthBufferSize(24); 19 | format.setSamples(4); 20 | format.setStencilBufferSize(8); 21 | QSurfaceFormat::setDefaultFormat(format); 22 | } 23 | 24 | int main(int argc, char **argv) 25 | { 26 | QGuiApplication app(argc, argv); 27 | setSurfaceFormat(); 28 | 29 | QQuickView view; 30 | 31 | view.engine()->rootContext()->setContextProperty("_window", &view); 32 | view.resize(1024, 1024); 33 | view.setResizeMode(QQuickView::SizeRootObjectToView); 34 | view.setSource(QUrl("qrc:/main.qml")); 35 | view.show(); 36 | 37 | return app.exec(); 38 | } 39 | -------------------------------------------------------------------------------- /qml3DTerrain/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Scene3D 2.12 3 | import Qt3D.Render 2.12 4 | import Qt3D.Core 2.12 5 | import Qt3D.Extras 2.12 6 | 7 | Rectangle { 8 | id: window 9 | anchors.fill: parent 10 | color: "white" 11 | 12 | property var w: _window.width 13 | property var h: _window.height 14 | property var scale: 10 15 | 16 | MouseArea { 17 | id: mouseArea 18 | anchors.fill: parent 19 | } 20 | 21 | Scene3D { 22 | id: scene3d 23 | anchors.fill: parent 24 | focus: true 25 | aspects: ["input", "logic"] 26 | cameraAspectRatioMode: Scene3D.AutomaticAspectRatio 27 | multisample: false 28 | 29 | Entity { 30 | 31 | // !!! OrthographicProjection does not work this these shaders !!! 32 | Camera { 33 | id: mainCamera 34 | projectionType: CameraLens.PerspectiveProjection 35 | fieldOfView: 45 36 | aspectRatio: window.w / window.h 37 | nearPlane: 0.01 38 | farPlane: 1000.0 39 | 40 | position: Qt.vector3d( 0.0, 0.0, 5.0 ) 41 | viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) 42 | upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) 43 | } 44 | 45 | components: [ 46 | RenderSettings { 47 | activeFrameGraph: ForwardRenderer { 48 | id: renderer 49 | clearColor: "white" 50 | camera: mainCamera 51 | } 52 | } 53 | ] 54 | 55 | TerrainEntity { 56 | id: terrain 57 | cols: window.w / window.scale 58 | rows: window.h / window.scale 59 | xoff: 0 60 | yoff: 0 61 | 62 | /* animate the mesh uses robustwireframe.vert to create the elevations */ 63 | 64 | NumberAnimation { 65 | target: terrain; 66 | property: "xoff"; 67 | duration: 60*1000; // 60sec 68 | from: 0.0 69 | to: 40.0 70 | 71 | loops: Animation.Infinite 72 | running: true 73 | } 74 | 75 | NumberAnimation { 76 | target: terrain; 77 | property: "yoff"; 78 | duration: 60*1000; // 60sec 79 | from: 0.0 80 | to: 40.0 81 | 82 | loops: Animation.Infinite 83 | running: true 84 | } 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /qml3DTerrain/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | TerrainEntity.qml 5 | WireframeMaterial.qml 6 | WireframeEffect.qml 7 | shaders/robustwireframe.frag 8 | shaders/robustwireframe.geom 9 | shaders/robustwireframe.vert 10 | 11 | 12 | -------------------------------------------------------------------------------- /qml3DTerrain/qml3DTerrain.pro: -------------------------------------------------------------------------------- 1 | QT += qml quick 3dquick 3dquickextras 2 | #QT += 3dcore 3drender 3dinput 3dquick qml quick 3dquickextras 3 | 4 | CONFIG += c++11 5 | 6 | # You can make your code fail to compile if it uses deprecated APIs. 7 | # In order to do so, uncomment the following line. 8 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 9 | 10 | SOURCES += \ 11 | main.cpp 12 | 13 | RESOURCES += qml.qrc 14 | 15 | # Additional import path used to resolve QML modules in Qt Creator's code model 16 | QML_IMPORT_PATH = 17 | 18 | # Additional import path used to resolve QML modules just for Qt Quick Designer 19 | QML_DESIGNER_IMPORT_PATH = 20 | 21 | # Default rules for deployment. 22 | qnx: target.path = /tmp/$${TARGET}/bin 23 | else: unix:!android: target.path = /opt/$${TARGET}/bin 24 | !isEmpty(target.path): INSTALLS += target 25 | -------------------------------------------------------------------------------- /qml3DTerrain/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml3DTerrain/screenshot.gif -------------------------------------------------------------------------------- /qml3DTerrain/shaders/robustwireframe.frag: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | uniform struct LightInfo { 4 | vec4 position; 5 | vec3 intensity; 6 | } light; 7 | 8 | uniform struct LineInfo { 9 | float width; 10 | vec4 color; 11 | } line; 12 | 13 | uniform vec3 ka; // Ambient reflectivity 14 | uniform vec3 kd; // Diffuse reflectivity 15 | uniform vec3 ks; // Specular reflectivity 16 | uniform float shininess; // Specular shininess factor 17 | 18 | in WireframeVertex { 19 | vec3 position; 20 | vec3 normal; 21 | noperspective vec4 edgeA; 22 | noperspective vec4 edgeB; 23 | flat int configuration; 24 | } fs_in; 25 | 26 | out vec4 fragColor; 27 | 28 | vec3 adsModel( const in vec3 pos, const in vec3 n ) 29 | { 30 | // Calculate the vector from the light to the fragment 31 | vec3 s = normalize( vec3( light.position ) - pos ); 32 | 33 | // Calculate the vector from the fragment to the eye position (the 34 | // origin since this is in "eye" or "camera" space 35 | vec3 v = normalize( -pos ); 36 | 37 | // Refleft the light beam using the normal at this fragment 38 | vec3 r = reflect( -s, n ); 39 | 40 | // Calculate the diffus component 41 | vec3 diffuse = vec3( max( dot( s, n ), 0.0 ) ); 42 | 43 | // Calculate the specular component 44 | vec3 specular = vec3( pow( max( dot( r, v ), 0.0 ), shininess ) ); 45 | 46 | // Combine the ambient, diffuse and specular contributions 47 | return light.intensity * ( ka + kd * diffuse + ks * specular ); 48 | } 49 | 50 | vec4 shadeLine( const in vec4 color ) 51 | { 52 | // Find the smallest distance between the fragment and a triangle edge 53 | float d; 54 | if ( fs_in.configuration == 0 ) 55 | { 56 | // Common configuration 57 | d = min( fs_in.edgeA.x, fs_in.edgeA.y ); 58 | d = min( d, fs_in.edgeA.z ); 59 | } 60 | else 61 | { 62 | // Handle configuration where screen space projection breaks down 63 | // Compute and compare the squared distances 64 | vec2 AF = gl_FragCoord.xy - fs_in.edgeA.xy; 65 | float sqAF = dot( AF, AF ); 66 | float AFcosA = dot( AF, fs_in.edgeA.zw ); 67 | d = abs( sqAF - AFcosA * AFcosA ); 68 | 69 | vec2 BF = gl_FragCoord.xy - fs_in.edgeB.xy; 70 | float sqBF = dot( BF, BF ); 71 | float BFcosB = dot( BF, fs_in.edgeB.zw ); 72 | d = min( d, abs( sqBF - BFcosB * BFcosB ) ); 73 | 74 | // Only need to care about the 3rd edge for some configurations. 75 | if ( fs_in.configuration == 1 || fs_in.configuration == 2 || fs_in.configuration == 4 ) 76 | { 77 | float AFcosA0 = dot( AF, normalize( fs_in.edgeB.xy - fs_in.edgeA.xy ) ); 78 | d = min( d, abs( sqAF - AFcosA0 * AFcosA0 ) ); 79 | } 80 | 81 | d = sqrt( d ); 82 | } 83 | 84 | // Blend between line color and phong color 85 | float mixVal; 86 | if ( d < line.width - 1.0 ) 87 | { 88 | mixVal = 1.0; 89 | } 90 | else if ( d > line.width + 1.0 ) 91 | { 92 | mixVal = 0.0; 93 | } 94 | else 95 | { 96 | float x = d - ( line.width - 1.0 ); 97 | mixVal = exp2( -2.0 * ( x * x ) ); 98 | } 99 | 100 | return mix( color, line.color, mixVal ); 101 | } 102 | 103 | void main() 104 | { 105 | // Calculate the color from the phong model 106 | vec4 color = vec4( adsModel( fs_in.position, normalize( fs_in.normal ) ), 1.0 ); 107 | fragColor = shadeLine( color ); 108 | } 109 | -------------------------------------------------------------------------------- /qml3DTerrain/shaders/robustwireframe.vert: -------------------------------------------------------------------------------- 1 | #version 330 core 2 | 3 | in vec3 vertexPosition; 4 | in vec3 vertexNormal; 5 | 6 | out EyeSpaceVertex { 7 | vec3 position; 8 | vec3 normal; 9 | } vs_out; 10 | 11 | uniform mat4 modelView; 12 | uniform mat3 modelViewNormal; 13 | uniform mat4 mvp; 14 | 15 | // external CPU variables that control Perlin noise 16 | uniform float xoff; 17 | uniform float yoff; 18 | 19 | /* Classic Perlin 2D Noise 20 | * by Stefan Gustavson 21 | */ 22 | vec4 permute(vec4 x){ return mod(((x*34.0)+1.0)*x, 289.0); } 23 | vec2 fade(vec2 t) { return t*t*t*(t*(t*6.0-15.0)+10.0); } 24 | 25 | float cnoise(vec2 P){ 26 | vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0); 27 | vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0); 28 | Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation 29 | vec4 ix = Pi.xzxz; 30 | vec4 iy = Pi.yyww; 31 | vec4 fx = Pf.xzxz; 32 | vec4 fy = Pf.yyww; 33 | vec4 i = permute(permute(ix) + iy); 34 | vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024... 35 | vec4 gy = abs(gx) - 0.5; 36 | vec4 tx = floor(gx + 0.5); 37 | gx = gx - tx; 38 | vec2 g00 = vec2(gx.x,gy.x); 39 | vec2 g10 = vec2(gx.y,gy.y); 40 | vec2 g01 = vec2(gx.z,gy.z); 41 | vec2 g11 = vec2(gx.w,gy.w); 42 | vec4 norm = 1.79284291400159 - 0.85373472095314 * 43 | vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)); 44 | g00 *= norm.x; 45 | g01 *= norm.y; 46 | g10 *= norm.z; 47 | g11 *= norm.w; 48 | float n00 = dot(g00, vec2(fx.x, fy.x)); 49 | float n10 = dot(g10, vec2(fx.y, fy.y)); 50 | float n01 = dot(g01, vec2(fx.z, fy.z)); 51 | float n11 = dot(g11, vec2(fx.w, fy.w)); 52 | vec2 fade_xy = fade(Pf.xy); 53 | vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x); 54 | float n_xy = mix(n_x.x, n_x.y, fade_xy.y); 55 | return 2.3 * n_xy; 56 | } 57 | 58 | float map(float value, float min1, float max1, float min2, float max2) { 59 | return min2 + (value - min1) * (max2 - min2) / (max1 - min1); 60 | } 61 | 62 | /* 63 | * Entry Point: main() 64 | */ 65 | float magFactor = 0.8; 66 | float widthFactor = 0.4; 67 | 68 | void main() 69 | { 70 | vs_out.normal = normalize( modelViewNormal * vertexNormal ); 71 | vs_out.position = vec3( modelView * vec4( vertexPosition, 1.0 ) ); 72 | 73 | gl_Position = mvp * vec4( vertexPosition, 1.0 ); 74 | 75 | /* adjust y position based on Perlin noise: 76 | * - widthFactor: spread the mountains apart from each other 77 | * - magFactor: increases the magnitude of the mountains (aka. heightFactor) 78 | */ 79 | float noise = cnoise(vec2((gl_Position.x+xoff)*widthFactor, gl_Position.y+yoff)); 80 | gl_Position.y += noise * magFactor; 81 | 82 | 83 | //float terrainHeight = map(noise, 0.0, 1.0, -0.5, 0.5); 84 | //gl_Position.y += terrainHeight * heightFactor; 85 | } 86 | -------------------------------------------------------------------------------- /qml3DWater/CrystalEntity.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.0 2 | import Qt3D.Render 2.0 3 | import Qt3D.Input 2.0 4 | import Qt3D.Extras 2.0 5 | 6 | Entity { 7 | id: root 8 | 9 | property Layer layer 10 | property vector3d pos: Qt.vector3d(0, 0, 0) 11 | 12 | property alias scale: transform.scale 13 | property alias rotationX: transform.rotationX 14 | property alias rotationY: transform.rotationY 15 | property alias rotationZ: transform.rotationZ 16 | 17 | property color color: "green" 18 | //property alias alpha: material.alpha 19 | 20 | //components: [ mesh, transform, material, root.layer ] 21 | components: [ mesh, transform, materialGLSL, root.layer ] 22 | 23 | Mesh { 24 | id: mesh 25 | source: "qrc:/assets/low_poly_crystals.obj" 26 | } 27 | 28 | Transform { 29 | id: transform 30 | translation: Qt.vector3d(root.pos.x, root.pos.y, root.pos.z) 31 | } 32 | 33 | PhongMaterial { 34 | id: material 35 | ambient: Qt.rgba(0.19225, 0.19225, 0.19225, 1) // emitted by an object without any other light source. 36 | diffuse: root.color // emitted for rought surface reflections with the lights 37 | specular: Qt.rgba(0.508273, 0.508273, 0.508273, 1) // emitted for shiny surface reflections with the lights 38 | shininess: 51.2 39 | //alpha: 1.0 40 | } 41 | 42 | PhongShadingMaterial { 43 | id: materialGLSL 44 | ambient: Qt.rgba(0.19225, 0.19225, 0.19225, 1) // emitted by an object without any other light source. 45 | diffuse: root.color // emitted for rought surface reflections with the lights 46 | specular: Qt.rgba(0.508273, 0.508273, 0.508273, 1) // emitted for shiny surface reflections with the lights 47 | shininess: 51.2 48 | //alpha: 1.0 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /qml3DWater/PhongShadingMaterial.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.0 2 | import Qt3D.Render 2.0 3 | import Qt3D.Input 2.0 4 | import Qt3D.Extras 2.0 5 | 6 | Material { 7 | id: root 8 | 9 | // GLSL uniforms for phong shading model 10 | property color ambient: Qt.rgba(0.0, 0.0, 0.0) 11 | property color diffuse: Qt.rgba(0.0, 0.0, 0.0) 12 | property color specular: Qt.rgba(0.0, 0.0, 0.0) 13 | property real shininess: 0.0 14 | 15 | property vector3d lightPosition: Qt.vector3d(0.0, 0.0, 0.0) 16 | property vector3d lightIntensity: Qt.vector3d(1.0, 1.0, 1.0) 17 | 18 | property TextureLoader baseTexture 19 | property bool isBaseTextureLoaded: (baseTexture) ? true : false 20 | 21 | // define standard uniform variables (share data with the shaders) 22 | parameters: [ 23 | Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) }, 24 | Parameter { name: "kd"; value: Qt.vector3d(root.diffuse.r, root.diffuse.g, root.diffuse.b) }, 25 | Parameter { name: "ks"; value: Qt.vector3d(root.specular.r, root.specular.g, root.specular.b) }, 26 | Parameter { name: "shininess"; value: root.shininess }, 27 | Parameter { name: "lightPosition"; value: root.lightPosition }, 28 | Parameter { name: "lightIntensity"; value: root.lightIntensity }, 29 | Parameter { name: "baseTexture"; value: root.baseTexture }, 30 | Parameter { name: "isBaseTextureLoaded"; value: root.isBaseTextureLoaded } 31 | ] 32 | 33 | effect: Effect { 34 | techniques: [ 35 | 36 | // 37 | // Profile for OpenGL 3.3 - NVIDIA GeForce GTX 1660 and NVIDIA RTX 3080 38 | // 39 | 40 | Technique { 41 | graphicsApiFilter { 42 | api: GraphicsApiFilter.OpenGL 43 | profile: GraphicsApiFilter.CoreProfile 44 | majorVersion: 3 45 | minorVersion: 3 46 | } 47 | 48 | ShaderProgram { 49 | id: gl3shader 50 | vertexShaderCode: loadSource("qrc:/shaders/terrain.vert") 51 | fragmentShaderCode: loadSource("qrc:/shaders/terrain.frag") 52 | } 53 | 54 | 55 | renderPasses: [ 56 | // 57 | // RenderPass #1: filters the framegraph for key "clippingPlane" with value 1 58 | // for refraction 59 | // 60 | 61 | RenderPass { 62 | filterKeys: [ 63 | FilterKey { name: "clippingPlane"; value: 1 } 64 | ] 65 | 66 | shaderProgram: gl3shader 67 | 68 | parameters: [ 69 | // culls everything above the specified height 70 | Parameter { name: "clipPlane"; value: Qt.vector4d(0.0, -1.0, 0.0, waterEntity.pos.y) } 71 | ] 72 | }, 73 | 74 | // 75 | // RenderPass #2: filters the framegraph for key "clippingPlane" with value 2 76 | // for reflection 77 | // 78 | RenderPass { 79 | // filters the framegraph for key "clippingPlane" with value 2 80 | filterKeys: [ 81 | FilterKey { name: "clippingPlane"; value: 2 } 82 | ] 83 | 84 | shaderProgram: gl3shader 85 | 86 | parameters: [ 87 | // culls everything below the specified height 88 | Parameter { name: "clipPlane"; value: Qt.vector4d(0.0, 1.0, 0.0, -waterEntity.pos.y + 2.0) } 89 | ] 90 | } 91 | ] 92 | 93 | } // Technique 94 | ] // techniques 95 | 96 | } // effect 97 | } 98 | -------------------------------------------------------------------------------- /qml3DWater/README.md: -------------------------------------------------------------------------------- 1 | # qml3DWater 2 | 3 | Qt3D/QML implementation of water reflection/refraction using clipping planes. 4 | 5 | The water is just a simple a `PlaneMesh` entity and most of the work is done by `water.frag`: 6 | 7 | - DuDv map is used to create distortions on the water surface; 8 | - The Fresnel effect allows the water to be more transparent when looking from above; 9 | - Specular highlights are based on a Normal map; 10 | - The mesh of the water is not changed at all by the vertex shader; 11 | 12 | Screenshot 13 | 14 | **References**: 15 | 16 | - [OpenGL Water Tutorials](https://www.youtube.com/playlist?list=PLRIWtICgwaX23jiqVByUs0bqhnalNTNZh) 17 | -------------------------------------------------------------------------------- /qml3DWater/TerrainEntity.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.0 2 | import Qt3D.Render 2.0 3 | import Qt3D.Input 2.0 4 | import Qt3D.Extras 2.0 5 | 6 | Entity { 7 | id: root 8 | 9 | property Layer layer 10 | property vector3d pos: Qt.vector3d(0, 0, 0) 11 | 12 | property alias scale: transform.scale 13 | property alias rotationX: transform.rotationX 14 | property alias rotationY: transform.rotationY 15 | property alias rotationZ: transform.rotationZ 16 | 17 | property alias baseTexture: materialGLSL.baseTexture 18 | 19 | property color color: "green" 20 | //property alias alpha: material.alpha 21 | 22 | // components: [ mesh, transform, diffuseMapMaterial, root.layer ] 23 | components: [ mesh, transform, materialGLSL, root.layer ] 24 | 25 | Mesh { 26 | id: mesh 27 | // source: "qrc:/assets/minecraft/Forest.obj" 28 | source: "qrc:/assets/minecraft/ForestNoWater.obj" 29 | } 30 | 31 | Transform { 32 | id: transform 33 | translation: Qt.vector3d(root.pos.x, root.pos.y, root.pos.z) 34 | } 35 | 36 | // DiffuseMapMaterial { 37 | // id: diffuseMapMaterial 38 | // diffuse: TextureLoader { source: "qrc:/assets/minecraft/Forest.png" } 39 | // } 40 | 41 | PhongShadingMaterial { 42 | id: materialGLSL 43 | ambient: Qt.rgba(1.0, 1.0, 1.0, 1.0) // white 44 | baseTexture: TextureLoader { source: "qrc:/assets/minecraft/Forest.png" } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /qml3DWater/TextureEntity.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.0 2 | import Qt3D.Render 2.0 3 | import Qt3D.Input 2.0 4 | import Qt3D.Extras 2.9 5 | 6 | Entity { 7 | id: root 8 | 9 | property Layer layer 10 | property vector3d pos: Qt.vector3d(0, 0, 0) 11 | property int width: 0 12 | property int height: 0 13 | property size meshResolution: Qt.size(2, 2) 14 | 15 | property Texture2D offscreenTexture // offscreen surface 16 | property bool invertYaxis: true 17 | 18 | //components: [ mesh, transform, material, root.layer ] // phong material 19 | components: [ mesh, transform, material2, root.layer ] // GLSL shaders 20 | 21 | PlaneMesh { 22 | id: mesh 23 | width: root.width 24 | height: root.height 25 | meshResolution: root.meshResolution 26 | } 27 | 28 | Transform { 29 | id: transform 30 | translation: Qt.vector3d(root.pos.x, root.pos.y, root.pos.z) 31 | rotationX: 90 32 | } 33 | 34 | PhongMaterial { 35 | id: material 36 | ambient: "orange" 37 | diffuse: "orange" 38 | } 39 | 40 | Material { 41 | id: material2 42 | 43 | parameters: [ 44 | Parameter { name: "offscreenTexture"; value: root.offscreenTexture }, 45 | Parameter { name: "invertYaxis"; value: root.invertYaxis } 46 | ] 47 | 48 | effect: Effect { 49 | techniques: [ 50 | Technique { 51 | graphicsApiFilter { 52 | api: GraphicsApiFilter.OpenGL 53 | majorVersion: 3 54 | minorVersion: 2 55 | profile: GraphicsApiFilter.CoreProfile 56 | } 57 | 58 | renderPasses: RenderPass { 59 | shaderProgram: ShaderProgram { 60 | vertexShaderCode: " 61 | #version 150 62 | in vec3 vertexPosition; 63 | in vec2 vertexTexCoord; 64 | out vec2 texCoord; 65 | uniform mat4 mvp; 66 | uniform bool invertYaxis; 67 | 68 | void main() 69 | { 70 | // pass texture coordinates to the fragment shader 71 | if (invertYaxis) 72 | texCoord = vec2(vertexTexCoord.s, 1.0 - vertexTexCoord.t); 73 | else 74 | texCoord = vec2(vertexTexCoord.s, vertexTexCoord.t); 75 | 76 | // Calculate the clip-space coordinates 77 | gl_Position = mvp * vec4(vertexPosition, 1.0); 78 | } 79 | " 80 | 81 | fragmentShaderCode: " 82 | #version 150 83 | in vec2 texCoord; 84 | uniform sampler2D offscreenTexture; 85 | out vec4 fragColor; 86 | 87 | void main() 88 | { 89 | vec3 texColor = texture(offscreenTexture, texCoord).rgb; 90 | fragColor = vec4(texColor, 1.0); 91 | } 92 | " 93 | } 94 | } 95 | } 96 | ] 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /qml3DWater/TreeEntity.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 as QQ2 2 | import Qt3D.Core 2.0 3 | import Qt3D.Render 2.0 4 | import Qt3D.Input 2.0 5 | import Qt3D.Extras 2.0 6 | 7 | Entity { 8 | id: root 9 | property Layer layer 10 | 11 | // 12 | // Base platform 13 | // 14 | 15 | Entity { 16 | components: [ platformMesh, platformTransform, platformMaterial, root.layer ] 17 | 18 | TorusMesh { 19 | id: platformMesh 20 | radius: 4 21 | minorRadius: 0.3 22 | rings: 60 23 | slices: 30 24 | } 25 | 26 | Transform { 27 | id: platformTransform 28 | translation: Qt.vector3d(-10, 7, 25) 29 | scale: 10 30 | 31 | QQ2.NumberAnimation on rotationY { 32 | from: 0 33 | to: 360 34 | duration: 4000 35 | loops: QQ2.Animation.Infinite 36 | } 37 | } 38 | 39 | // gold 40 | PhongShadingMaterial { 41 | id: platformMaterial 42 | ambient: Qt.rgba(0.24725, 0.1995, 0.0745, 1.0) 43 | diffuse: Qt.rgba(0.75164, 0.60648, 0.22648, 1.0) 44 | specular: Qt.rgba(0.628281, 0.555802, 0.366065, 1.0) 45 | shininess: 51.2 46 | 47 | lightPosition: sunLightEntity.position 48 | lightIntensity: Qt.vector3d(1.0, 1.0, 1.0) 49 | 50 | // Note: not defining a proper baseTexture here triggers this warning: 51 | // Unknown uniform type or value: QVariant(std::nullptr_t, (nullptr)) Please check your QParameters 52 | } 53 | } 54 | 55 | // 56 | // Tree 57 | // 58 | 59 | Entity { 60 | components: [ treeMesh, treeTransform, treeMaterial, root.layer ] 61 | 62 | Mesh { 63 | id: treeMesh 64 | source: "qrc:/assets/tree.obj" 65 | } 66 | 67 | Transform { 68 | id: treeTransform 69 | translation: Qt.vector3d(-10, 0, 25) 70 | scale: 10 71 | } 72 | 73 | // gold 74 | PhongShadingMaterial { 75 | id: treeMaterial 76 | ambient: Qt.rgba(0.24725, 0.1995, 0.0745, 1.0) 77 | diffuse: Qt.rgba(0.75164, 0.60648, 0.22648, 1.0) 78 | specular: Qt.rgba(0.628281, 0.555802, 0.366065, 1.0) 79 | shininess: 51.2 80 | 81 | lightPosition: sunLightEntity.position 82 | lightIntensity: Qt.vector3d(1.0, 1.0, 1.0) 83 | 84 | // Note: not defining a proper baseTexture here triggers this warning: 85 | // Unknown uniform type or value: QVariant(std::nullptr_t, (nullptr)) Please check your QParameters 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /qml3DWater/WaterEntity.qml: -------------------------------------------------------------------------------- 1 | import Qt3D.Core 2.0 2 | import Qt3D.Render 2.0 3 | import Qt3D.Input 2.0 4 | import Qt3D.Extras 2.0 5 | 6 | Entity { 7 | id: root 8 | 9 | property Layer layer 10 | property vector3d pos: Qt.vector3d(0, 0, 0) 11 | property alias width: mesh.width 12 | property alias height: mesh.height 13 | property alias x: transform.x 14 | property alias y: transform.y 15 | property alias z: transform.z 16 | property alias reflectionTexture: material.reflectionTexture 17 | property alias refractionTexture: material.refractionTexture 18 | property alias refractionDepthTexture: material.refractionDepthTexture 19 | property alias waterViewProjection: material.waterViewProjection 20 | property alias dudvMap: material.dudvMap 21 | property alias cameraPosition: material.cameraPosition 22 | property alias normalMap: material.normalMap 23 | property alias lightColor: material.lightColor 24 | property alias lightPosition: material.lightPosition 25 | 26 | components: [ mesh, material, transform, root.layer ] 27 | 28 | PlaneMesh { 29 | id: mesh 30 | width: 20 31 | height: 20 32 | } 33 | 34 | WaterMaterial { 35 | id: material 36 | } 37 | 38 | Transform { 39 | id: transform 40 | property int x: 0 41 | property int y: 0 42 | property int z: 0 43 | translation: Qt.vector3d(root.pos.x, root.pos.y, root.pos.z) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /qml3DWater/WaterMaterial.qml: -------------------------------------------------------------------------------- 1 | // Enabling clipping planes on the framegraph is essential to be able to set gl_ClipDistance[0] and have 2 | // OpenGL use it for vertex culling. 3 | // 4 | // This tells us how far a vertex is from the clipping plane 0. OpenGL only cares about the signed distance 5 | // of each vertex from that plane wherever that plane may be: 6 | // https://www.youtube.com/watch?v=0NH9k4zTAqk&list=PLRIWtICgwaX23jiqVByUs0bqhnalNTNZh&index=3 7 | // 8 | // Imagine a clipping plane separating whats below water and whats above water level: 9 | // - The distance is positive when the vertex is inside of the plane (below water level); 10 | // - The distance is negative when the vertex is outside the plane (above water level, the culling side of the plane); 11 | // 12 | // Since this is done for every vertex, and OpenGL interpolates these distances to the whole Geometry 13 | // and any part of the geometry with a negative distnace is culled and therefore its not rendered, while 14 | // anything with a distance of 0.0 or bigger than 0.0 is rendered. 15 | import Qt3D.Core 2.0 16 | import Qt3D.Render 2.0 17 | import Qt3D.Input 2.0 18 | import Qt3D.Extras 2.0 19 | 20 | Material { 21 | id: root 22 | 23 | // used to render the refraction and reflection on the water surface 24 | property Texture2D reflectionTexture 25 | property Texture2D refractionTexture 26 | property matrix4x4 waterViewProjection 27 | 28 | // used to add some distortion on reflection/refraction on the water surface 29 | property TextureLoader dudvMap 30 | 31 | // used for fresnel effect 32 | property vector3d cameraPosition 33 | 34 | // used to create specular highlights 35 | property TextureLoader normalMap 36 | property vector3d lightColor 37 | property vector3d lightPosition 38 | 39 | // 40 | property Texture2D refractionDepthTexture 41 | 42 | parameters: [ 43 | Parameter { name: "reflectionTex"; value: root.reflectionTexture }, 44 | Parameter { name: "refractionTex"; value: root.refractionTexture }, 45 | Parameter { name: "refractionDepthTex"; value: root.refractionDepthTexture }, 46 | Parameter { name: "waterViewProjection"; value: root.waterViewProjection }, 47 | Parameter { name: "dudvMap"; value: root.dudvMap }, 48 | Parameter { name: "cameraPosition"; value: root.cameraPosition }, 49 | Parameter { name: "normalMap"; value: root.normalMap }, 50 | Parameter { name: "lightColor"; value: root.lightColor }, 51 | Parameter { name: "lightPosition"; value: root.lightPosition } 52 | ] 53 | 54 | effect: Effect { 55 | FilterKey { 56 | id: forward 57 | name: "renderingStyle" 58 | value: "forward" 59 | } 60 | 61 | ShaderProgram { 62 | id: gl3Shader 63 | vertexShaderCode: loadSource("qrc:/shaders/water.vert") 64 | fragmentShaderCode: loadSource("qrc:/shaders/water.frag") 65 | } 66 | 67 | techniques: [ 68 | // 69 | // OpenGL 3.2+ (Desktop) 70 | // 71 | Technique { 72 | graphicsApiFilter { 73 | api: GraphicsApiFilter.OpenGL 74 | profile: GraphicsApiFilter.CoreProfile 75 | majorVersion: 3 76 | minorVersion: 2 77 | } 78 | 79 | renderPasses: [ 80 | RenderPass { 81 | filterKeys: [ forward ] 82 | shaderProgram: gl3Shader 83 | } 84 | ] 85 | } 86 | ] 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /qml3DWater/assets.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | assets/minecraft/Forest.png 4 | assets/minecraft/ForestNoWater.mtl 5 | assets/minecraft/ForestNoWater.obj 6 | assets/tree.obj 7 | assets/waterDUDV.png 8 | assets/waterNormalMap.png 9 | 10 | 11 | -------------------------------------------------------------------------------- /qml3DWater/assets/minecraft/Forest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml3DWater/assets/minecraft/Forest.png -------------------------------------------------------------------------------- /qml3DWater/assets/minecraft/ForestNoWater.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'None' 2 | # Material Count: 1 3 | 4 | newmtl palette.001 5 | Ns 0.000000 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 1.000000 1.000000 1.000000 8 | Ks 0.000000 0.000000 0.000000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.450000 11 | d 1.000000 12 | illum 1 13 | map_Kd Forest.png 14 | -------------------------------------------------------------------------------- /qml3DWater/assets/waterDUDV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml3DWater/assets/waterDUDV.png -------------------------------------------------------------------------------- /qml3DWater/assets/waterNormalMap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml3DWater/assets/waterNormalMap.png -------------------------------------------------------------------------------- /qml3DWater/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | 10 | 11 | int main(int argc, char **argv) 12 | { 13 | QGuiApplication app(argc, argv); 14 | 15 | if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) 16 | { 17 | qDebug() << "QOpenGLContext::openGLModuleType LibGL"; 18 | } 19 | 20 | if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) 21 | { 22 | qDebug() << "QOpenGLContext::openGLModuleType LibGLES"; 23 | } 24 | 25 | //qDebug() << "OpenGL flags:" << QGLFormat::openGLVersionFlags(); 26 | 27 | QSurfaceFormat format = QSurfaceFormat::defaultFormat(); 28 | format.setProfile(QSurfaceFormat::CoreProfile); 29 | format.setVersion(4, 3); 30 | format.setDepthBufferSize(32); 31 | format.setSamples(0); 32 | format.setStencilBufferSize(8); 33 | QSurfaceFormat::setDefaultFormat(format); 34 | 35 | qDebug() << "QSurfaceFormat version=" << QSurfaceFormat::defaultFormat().version() << 36 | " profile=" << QSurfaceFormat::defaultFormat().profile() << 37 | " depthBufferSize=" << QSurfaceFormat::defaultFormat().depthBufferSize() << 38 | " samples=" << QSurfaceFormat::defaultFormat().samples() << 39 | "stencilBufferSize=" << QSurfaceFormat::defaultFormat().stencilBufferSize(); 40 | 41 | Qt3DExtras::Quick::Qt3DQuickWindow view; 42 | 43 | view.setSource(QUrl("qrc:/main.qml")); 44 | view.resize(1600, 1280); 45 | view.show(); 46 | 47 | return app.exec(); 48 | } 49 | -------------------------------------------------------------------------------- /qml3DWater/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | CustomTerrainEntity.qml 5 | WaterEntity.qml 6 | perlin.js 7 | shaders/phong.inc.frag 8 | shaders/terrain.frag 9 | shaders/terrain.vert 10 | shaders/light.inc.frag 11 | PhongShadingMaterial.qml 12 | TextureEntity.qml 13 | CrystalEntity.qml 14 | WaterMaterial.qml 15 | shaders/water.vert 16 | shaders/water.frag 17 | TerrainEntity.qml 18 | TreeEntity.qml 19 | 20 | 21 | -------------------------------------------------------------------------------- /qml3DWater/qml3DWater.pro: -------------------------------------------------------------------------------- 1 | QT += quick opengl 3dcore 3drender 3dinput 3dextras 3dquickextras 2 | 3 | # You can make your code fail to compile if it uses deprecated APIs. 4 | # In order to do so, uncomment the following line. 5 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 6 | 7 | SOURCES += \ 8 | main.cpp 9 | 10 | RESOURCES += qml.qrc \ 11 | assets.qrc 12 | 13 | # Additional import path used to resolve QML modules in Qt Creator's code model 14 | QML_IMPORT_PATH = 15 | 16 | # Additional import path used to resolve QML modules just for Qt Quick Designer 17 | QML_DESIGNER_IMPORT_PATH = 18 | 19 | # Default rules for deployment. 20 | qnx: target.path = /tmp/$${TARGET}/bin 21 | else: unix:!android: target.path = /opt/$${TARGET}/bin 22 | !isEmpty(target.path): INSTALLS += target 23 | 24 | win32 { 25 | #message("YESS PWD=" + "$$PWD") 26 | } 27 | -------------------------------------------------------------------------------- /qml3DWater/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qml3DWater/screenshot.gif -------------------------------------------------------------------------------- /qml3DWater/shaders/light.inc.frag: -------------------------------------------------------------------------------- 1 | const int MAX_LIGHTS = 8; 2 | const int TYPE_POINT = 0; 3 | const int TYPE_DIRECTIONAL = 1; 4 | const int TYPE_SPOT = 2; 5 | struct Light { 6 | int type; 7 | vec3 position; 8 | vec3 color; 9 | float intensity; 10 | vec3 direction; 11 | float constantAttenuation; 12 | float linearAttenuation; 13 | float quadraticAttenuation; 14 | float cutOffAngle; 15 | }; 16 | uniform Light lights[MAX_LIGHTS]; 17 | uniform int lightCount; 18 | 19 | // Pre-convolved environment maps 20 | struct EnvironmentLight { 21 | samplerCube irradiance; // For diffuse contribution 22 | samplerCube specular; // For specular contribution 23 | int specularMipLevels; 24 | }; 25 | uniform EnvironmentLight envLight; 26 | uniform int envLightCount = 0; 27 | -------------------------------------------------------------------------------- /qml3DWater/shaders/terrain.frag: -------------------------------------------------------------------------------- 1 | #version 150 core 2 | #ifdef GL_ES 3 | precision highp float; 4 | #endif 5 | in vec3 worldPosition; 6 | in vec3 worldNormal; 7 | in vec2 texCoord; 8 | in vec3 vertexColor; 9 | 10 | out vec4 fragColor; 11 | 12 | // Qt3D uniforms 13 | uniform vec3 eyePosition; 14 | 15 | // QML uniforms 16 | uniform sampler2D baseTexture; 17 | uniform bool isBaseTextureLoaded; 18 | uniform vec3 lightPosition; 19 | uniform vec3 lightIntensity; 20 | uniform vec3 ka; // Ambient reflectivity 21 | uniform vec3 kd; // Diffuse reflectivity 22 | uniform vec3 ks; // Specular reflectivity 23 | uniform float shininess; // Specular shininess factor 24 | 25 | 26 | vec3 adsModel(const in vec3 baseColor, const in vec3 vpos, const in vec3 vnormal) 27 | { 28 | vec3 n = normalize(vnormal); 29 | vec3 s = normalize(lightPosition - vpos); 30 | float diffuse = max(dot(s, n), 0.0); 31 | 32 | float specular = 0.0; 33 | if (diffuse > 0.0 && shininess > 0.0) { 34 | vec3 r = reflect(-s, n); 35 | vec3 v = normalize(eyePosition - vpos); 36 | float normFactor = (shininess + 2.0) / 2.0; 37 | specular = normFactor * pow(max(dot(r, v), 0.0), shininess); 38 | } 39 | 40 | return lightIntensity * (ka * baseColor 41 | + kd * diffuse * baseColor 42 | + ks * specular); 43 | } 44 | 45 | void main() 46 | { 47 | if (isBaseTextureLoaded) 48 | { 49 | // sample color from the texture and calculate Phong (ADS) 50 | vec4 baseColor = texture(baseTexture, texCoord); 51 | vec3 color = adsModel(baseColor.rgb, worldPosition, worldNormal); 52 | fragColor = vec4(color, baseColor.a); 53 | 54 | // fragColor = baseColor; 55 | return; 56 | } 57 | 58 | // otherwise, use the color calculated on the vertex shader 59 | fragColor = vec4(vertexColor, 1.0); 60 | } 61 | -------------------------------------------------------------------------------- /qml3DWater/shaders/terrain.vert: -------------------------------------------------------------------------------- 1 | #version 150 core 2 | in vec3 vertexPosition; 3 | in vec3 vertexNormal; 4 | in vec2 vertexTexCoord; 5 | 6 | out vec2 texCoord; 7 | out vec3 worldPosition; 8 | out vec3 worldNormal; 9 | out vec3 worldView; 10 | out vec3 vertexColor; 11 | 12 | uniform vec3 ka; // Ambient reflectivity 13 | uniform vec3 kd; // Diffuse reflectivity 14 | uniform vec3 ks; // Specular reflectivity 15 | uniform float shininess; // Specular shininess factor 16 | uniform vec3 eyePosition; 17 | 18 | uniform mat4 modelMatrix; 19 | uniform mat3 modelNormalMatrix; 20 | uniform mat4 modelViewProjection; 21 | 22 | // (A,B,C,D) represents the horizontal plane's normal and the Distance (height = water.position.y) 23 | uniform vec4 clipPlane; // vec4(0.0, -1.0, 0.0, 55.0); 24 | 25 | #pragma include phong.inc.frag 26 | 27 | 28 | void main() 29 | { 30 | // pass through 31 | texCoord = vertexTexCoord; 32 | worldNormal = normalize(modelNormalMatrix * vertexNormal); 33 | worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0)); 34 | 35 | // calculate Phong on the vertex shader 36 | worldView = normalize(eyePosition - worldPosition); 37 | vec3 diffuseColor, specularColor; 38 | adsModel(worldPosition, worldNormal, worldView, shininess, diffuseColor, specularColor); 39 | vertexColor = ka + kd * diffuseColor + ks * specularColor; 40 | 41 | // output vertex position 42 | gl_Position = modelViewProjection * vec4(vertexPosition, 1.0); 43 | 44 | // calculate the distance between this vertex and the horizontal clipping plane: 45 | // When gl_ClipDistance[0] = -1. the vertex is clipped and therefore its not rendered 46 | vec4 worldPos = modelMatrix * vec4(vertexPosition, 1.0); 47 | gl_ClipDistance[0] = dot(worldPos, clipPlane); 48 | } 49 | -------------------------------------------------------------------------------- /qml3DWater/shaders/water.vert: -------------------------------------------------------------------------------- 1 | #version 150 core 2 | in vec3 vertexPosition; 3 | in vec2 vertexTexCoord; 4 | 5 | out vec2 tc; 6 | out vec4 clipSpace; 7 | out vec4 positionInWaterSpace; 8 | out vec3 toCameraVector; // from water to camera 9 | out vec3 fromLightVector; // from light to water 10 | 11 | // Qt3D default uniforms 12 | uniform mat4 mvp; 13 | uniform mat4 modelMatrix; 14 | uniform mat4 viewMatrix; 15 | uniform mat4 projectionMatrix; 16 | 17 | // QML uniforms 18 | uniform mat4 waterViewProjection; 19 | uniform vec3 cameraPosition; 20 | uniform vec3 lightPosition; // sun position 21 | 22 | // global constants 23 | const float tiling = 4.0; // tile the DuDV map 24 | 25 | void main() 26 | { 27 | // calculate clip space coordinates 28 | gl_Position = mvp * vec4(vertexPosition, 1.0); 29 | 30 | // forward the Clip Space coords to the Fragment Shader for projective texture mapping 31 | clipSpace = gl_Position; 32 | 33 | // forward the vertex coordinates 34 | tc = vertexTexCoord.xy * tiling; 35 | 36 | // distance between this vertex on the water surface and the camera 37 | vec4 worldPosition = modelMatrix * vec4(vertexPosition, 1.0); 38 | toCameraVector = cameraPosition - worldPosition.xyz; 39 | 40 | // distance between this vertex on the water surface and the light 41 | fromLightVector = worldPosition.xyz - lightPosition; 42 | 43 | // forward fragment position as if it were in Water Space (reflection) 44 | // 45 | // multiplying the vertex by waterViewProjection transforms it into homogeneous coordinates [-1, 1] 46 | // however, texture sampling must happen between [0, 1]. 47 | // 48 | // this means that a fragment in the middle of the screen will be at (0,0) in homogeneous coords 49 | // but since it will have to sample the middle of the texture, the UVs will have to be (0.5, 0.5) 50 | const mat4 biasMatrix = mat4(0.5, 0.0, 0.0, 0.0, 51 | 0.0, 0.5, 0.0, 0.0, 52 | 0.0, 0.0, 0.5, 0.0, 53 | 0.5, 0.5, 0.5, 1.0); 54 | 55 | positionInWaterSpace = biasMatrix * waterViewProjection * modelMatrix * vec4(vertexPosition, 1.0); 56 | } 57 | -------------------------------------------------------------------------------- /qmlBattery/Battery.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Layouts 1.15 3 | 4 | Item { 5 | id: batteryId 6 | width: 210 7 | height: 300 8 | anchors.centerIn: parent 9 | 10 | property int charge: 100 11 | property int maxBars: 4 12 | property int bars: calcCharges() 13 | property string color: getColor() 14 | 15 | function getColor() 16 | { 17 | if (charge >= 75) return "#1FA900"; // green 18 | if (charge >= 50) return "#FF9C00"; // orange-ish 19 | if (charge >= 25) return "#D40027"; // darkred 20 | 21 | return "#AA2500"; // red 22 | } 23 | 24 | function calcCharges() 25 | { 26 | if (charge == 0) 27 | return 0; 28 | 29 | var numCharges = (charge / 100 * maxBars); 30 | //console.log("calcCharges: numCharges=", numCharges); 31 | 32 | if (numCharges > 1) 33 | return numCharges; 34 | 35 | return 1; 36 | } 37 | 38 | Rectangle { 39 | id: canvasId 40 | property int borderWidth: (0.08 * batteryId.width) 41 | property int chargeSpace: (0.07 * batteryId.width) 42 | 43 | // define the outter frame 44 | width: batteryId.width 45 | height: batteryId.height 46 | border.color: batteryId.color 47 | border.width: borderWidth 48 | radius: 20 49 | 50 | // Debug: 51 | //Component.onCompleted: print("canvasId: width=" + width + " height=" + height) 52 | 53 | // draw battery charges 54 | ColumnLayout { 55 | spacing: canvasId.chargeSpace // defines the space between the charges 56 | //Layout.alignment: Qt.AlignBottom 57 | anchors.bottom: canvasId.bottom 58 | anchors.bottomMargin: canvasId.borderWidth + canvasId.chargeSpace 59 | anchors.horizontalCenter: canvasId.horizontalCenter // ColumnLayout looses anchors upon redraw 60 | 61 | Repeater { 62 | model: batteryId.bars 63 | 64 | // each charge size is calculated dinamically 65 | Rectangle { 66 | color: batteryId.color 67 | width: canvasId.width - (canvasId.borderWidth * 4); 68 | height: (canvasId.height - ((canvasId.borderWidth + canvasId.chargeSpace)*2) - (canvasId.chargeSpace * (batteryId.maxBars-1))) / batteryId.maxBars; 69 | 70 | // Debug: 71 | //Component.onCompleted: print("Rectangle: charge=" + batteryId.charge + " bars=" + batteryId.bars + " x:" + x + " y:" + y + " height:" + height) 72 | } 73 | } // Repeater 74 | } // ColumnLayout 75 | } // Rectangle 76 | } // Item 77 | -------------------------------------------------------------------------------- /qmlBattery/README.md: -------------------------------------------------------------------------------- 1 | qmlBattery 2 | =================== 3 | A battery widget designed in QML that displays the amount energy left as stacked bars according to the battery charge. 4 | 5 | On this demo, the charge is updated dynamically from the C++ side every 2 seconds. 6 | 7 | Usage 8 | -------------- 9 | ``` 10 | Battery { 11 | id: batteryId 12 | charge: 100 13 | maxBars: 4 14 | } 15 | ``` 16 | 17 | Screenshot 18 | -------------- 19 | Screenshot 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /qmlBattery/batterycontroller.cpp: -------------------------------------------------------------------------------- 1 | #include "batterycontroller.h" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | // defines how often (milisec) the charge changes 10 | #define TIME_INTERVAL 2000 11 | 12 | BatteryController::BatteryController(QObject *parent) 13 | : QObject(parent), _charge(100) 14 | { 15 | // start generating random values for _charge 16 | QTimer::singleShot(TIME_INTERVAL, this, SLOT(_tick())); 17 | } 18 | 19 | void BatteryController::_tick() 20 | { 21 | // generate a random number between 0-100 every 5 seconds 22 | unsigned int ms = static_cast(QDateTime::currentMSecsSinceEpoch()); 23 | std::mt19937 gen(ms); 24 | std::uniform_int_distribution<> uid(0, 100); // min, max 25 | _charge = uid(gen); 26 | 27 | qDebug() << "_tick: charge=" << _charge; 28 | emit chargeValueChanged(); 29 | 30 | QTimer::singleShot(TIME_INTERVAL, this, SLOT(_tick())); 31 | } 32 | 33 | int BatteryController::chargeValue() 34 | { 35 | return _charge; 36 | } 37 | 38 | void BatteryController::setChargeValue(int value) 39 | { 40 | _charge = value; 41 | emit chargeValueChanged(); 42 | } 43 | -------------------------------------------------------------------------------- /qmlBattery/batterycontroller.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class BatteryController : public QObject 6 | { 7 | Q_OBJECT 8 | 9 | Q_PROPERTY(int chargeValue READ chargeValue WRITE setChargeValue NOTIFY chargeValueChanged) 10 | //Q_PROPERTY(int chargeValue READ chargeValue WRITE setChargeValue) 11 | 12 | public: 13 | explicit BatteryController(QObject *parent = nullptr); 14 | 15 | protected slots: 16 | void _tick(); 17 | 18 | signals: 19 | void chargeValueChanged(); 20 | 21 | private: 22 | int chargeValue(); 23 | void setChargeValue(int value); 24 | 25 | int _charge; 26 | }; 27 | -------------------------------------------------------------------------------- /qmlBattery/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "batterycontroller.h" 4 | 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 9 | QGuiApplication app(argc, argv); 10 | 11 | QQmlApplicationEngine engine; 12 | const QUrl url(QStringLiteral("qrc:/main.qml")); 13 | 14 | qmlRegisterType("com.company.batterycontroller", 1, 0, "BatteryController"); 15 | 16 | QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { 17 | if (!obj && url == objUrl) 18 | QCoreApplication::exit(-1); 19 | }, Qt::QueuedConnection); 20 | 21 | engine.load(url); 22 | 23 | return app.exec(); 24 | } 25 | -------------------------------------------------------------------------------- /qmlBattery/main.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * A demo that displays a battery widget in QML. The desired amount of charge can be set through the "charge" property. 3 | * The number of bars displayed set automatically the color of the widget. On this demo, a new charge value is randomly 4 | * set by the C++ application every 2 seconds. 5 | */ 6 | import QtQuick 2.12 7 | import QtQuick.Window 2.12 8 | import QtQuick.Controls 2.12 9 | import com.company.batterycontroller 1.0 10 | 11 | Window { 12 | visible: true 13 | width: 640 14 | height: 480 15 | title: qsTr("Battery Demo") 16 | 17 | BatteryController { 18 | id: batteryControllerId 19 | } 20 | 21 | Text { 22 | text: batteryId.charge + "%" 23 | color: batteryId.color 24 | anchors.horizontalCenter: parent.horizontalCenter 25 | font.pointSize: 20 26 | } 27 | 28 | Battery { 29 | id: batteryId 30 | 31 | // battery charge can be set to a staticvalue in QML or dinamically with BatteryController in C++ 32 | //charge: 50 33 | charge: batteryControllerId.chargeValue 34 | 35 | // additional settings: 36 | //color : "blue" 37 | maxBars: 4 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /qmlBattery/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | Battery.qml 5 | 6 | 7 | -------------------------------------------------------------------------------- /qmlBattery/qmlBattery.pro: -------------------------------------------------------------------------------- 1 | QT += quick 2 | 3 | CONFIG += c++11 4 | 5 | # The following define makes your compiler emit warnings if you use 6 | # any Qt feature that has been marked deprecated (the exact warnings 7 | # depend on your compiler). Refer to the documentation for the 8 | # deprecated API to know how to port your code away from it. 9 | DEFINES += QT_DEPRECATED_WARNINGS 10 | 11 | # You can also make your code fail to compile if it uses deprecated APIs. 12 | # In order to do so, uncomment the following line. 13 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 14 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 15 | 16 | SOURCES += \ 17 | batterycontroller.cpp \ 18 | main.cpp 19 | 20 | RESOURCES += qml.qrc 21 | 22 | # Additional import path used to resolve QML modules in Qt Creator's code model 23 | QML_IMPORT_PATH = 24 | 25 | # Additional import path used to resolve QML modules just for Qt Quick Designer 26 | QML_DESIGNER_IMPORT_PATH = 27 | 28 | # Default rules for deployment. 29 | qnx: target.path = /tmp/$${TARGET}/bin 30 | else: unix:!android: target.path = /opt/$${TARGET}/bin 31 | !isEmpty(target.path): INSTALLS += target 32 | 33 | DISTFILES += 34 | 35 | HEADERS += \ 36 | batterycontroller.h 37 | -------------------------------------------------------------------------------- /qmlBattery/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qmlBattery/screenshot.gif -------------------------------------------------------------------------------- /qt3DRenderer/README.md: -------------------------------------------------------------------------------- 1 | # qt3DRenderer 2 | 3 | A complete 3D software renderer written in C++: 4 | 5 | Screenshot 6 | 7 | It currently supports the following operations: 8 | 9 | - Several vectors and matrices operations in 2D and 3D; 10 | - Transforms for Model Space, World Space, Camera Space, Perspective Projection, Image Space and Screen Space; 11 | - Back-face Culling; 12 | - Frustum Clipping; 13 | - Flat Shading; 14 | 15 | Other supported features include: 16 | - UV Mapping; 17 | - Loading vertices, faces and texture coordinates from Wavefront files; 18 | - Loading external JPG/PNG texture images; 19 | 20 | Its dependency on Qt is just to be able to load PNG/JPG textures and create the window that displays the pixels. 21 | 22 | Minor changes are required to port this renderer to other GUI frameworks (SDL, GTK+, EFL, ...). 23 | 24 | **References** 25 | - [Pikuma: 3D Graphics Programming](https://courses.pikuma.com/courses/learn-computer-graphics-programming) 26 | -------------------------------------------------------------------------------- /qt3DRenderer/assets/crab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/crab.png -------------------------------------------------------------------------------- /qt3DRenderer/assets/cube.obj: -------------------------------------------------------------------------------- 1 | 2 | # cube.obj 3 | # 4 | 5 | mtllib cube.mtl 6 | o cube 7 | 8 | v -1.000000 -1.000000 1.000000 9 | v 1.000000 -1.000000 1.000000 10 | v -1.000000 1.000000 1.000000 11 | v 1.000000 1.000000 1.000000 12 | v -1.000000 1.000000 -1.000000 13 | v 1.000000 1.000000 -1.000000 14 | v -1.000000 -1.000000 -1.000000 15 | v 1.000000 -1.000000 -1.000000 16 | 17 | vt 1.000000 0.000000 18 | vt 0.000000 0.000000 19 | vt 1.000000 1.000000 20 | vt 0.000000 1.000000 21 | 22 | vn 0.000000 0.000000 1.000000 23 | vn 0.000000 1.000000 0.000000 24 | vn 0.000000 0.000000 -1.000000 25 | vn 0.000000 -1.000000 0.000000 26 | vn 1.000000 0.000000 0.000000 27 | vn -1.000000 0.000000 0.000000 28 | 29 | g cube 30 | usemtl cube 31 | s 1 32 | f 1/1/1 2/2/1 3/3/1 33 | f 3/3/1 2/2/1 4/4/1 34 | s 2 35 | f 3/1/2 4/2/2 5/3/2 36 | f 5/3/2 4/2/2 6/4/2 37 | s 3 38 | f 5/4/3 6/3/3 7/2/3 39 | f 7/2/3 6/3/3 8/1/3 40 | s 4 41 | f 7/1/4 8/2/4 1/3/4 42 | f 1/3/4 8/2/4 2/4/4 43 | s 5 44 | f 2/1/5 8/2/5 4/3/5 45 | f 4/3/5 8/2/5 6/4/5 46 | s 6 47 | f 7/1/6 1/2/6 5/3/6 48 | f 5/3/6 1/2/6 3/4/6 49 | -------------------------------------------------------------------------------- /qt3DRenderer/assets/cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/cube.png -------------------------------------------------------------------------------- /qt3DRenderer/assets/drone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/drone.png -------------------------------------------------------------------------------- /qt3DRenderer/assets/efa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/efa.png -------------------------------------------------------------------------------- /qt3DRenderer/assets/f117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/f117.png -------------------------------------------------------------------------------- /qt3DRenderer/assets/f22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/f22.png -------------------------------------------------------------------------------- /qt3DRenderer/assets/runway.obj: -------------------------------------------------------------------------------- 1 | 2 | # runway.obj 3 | 4 | v -3.000000 0.000000 -20.000000 5 | v -3.000000 0.000000 20.000000 6 | v 3.000000 0.000000 20.000000 7 | v 3.000000 0.000000 -20.000000 8 | 9 | vt 0.000000 0.000000 10 | vt 0.000000 1.000000 11 | vt 1.000000 1.000000 12 | vt 1.000000 0.000000 13 | 14 | f 1/1/1 2/2/1 3/3/1 15 | f 1/1/1 3/3/1 4/4/1 -------------------------------------------------------------------------------- /qt3DRenderer/assets/runway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/assets/runway.png -------------------------------------------------------------------------------- /qt3DRenderer/camera.cpp: -------------------------------------------------------------------------------- 1 | #include "camera.h" 2 | 3 | Camera::Camera() 4 | { 5 | position = Vec3d(0.f, 0.f, 0.f); 6 | direction = Vec3d(0.f, 0.f, 1.f); 7 | forwardVelocity = Vec3d(0.f, 0.f, 0.f); 8 | yaw = 0.f; 9 | pitch = 0.f; 10 | } 11 | 12 | void Camera::rotateYaw(const float& angle) 13 | { 14 | this->yaw += angle; 15 | } 16 | 17 | void Camera::rotatePitch(const float& angle) 18 | { 19 | this->pitch += angle; 20 | } 21 | 22 | Vec3d Camera::lookAtTarget() 23 | { 24 | Mat4 cameraPitchRotation = Mat4::rotateX(this->pitch); 25 | Mat4 cameraYawRotation = Mat4::rotateY(this->yaw); 26 | 27 | // create a camera rotation matrix based on Yaw and Pitch 28 | Mat4 cameraRotation = Mat4::eye(); 29 | cameraRotation = cameraPitchRotation * cameraRotation; 30 | cameraRotation = cameraYawRotation * cameraRotation; 31 | 32 | // update camera direction based on the rotation 33 | Vec3d target(0, 0, 1); // target is looking at the positive Z-axis 34 | this->direction = Vec4d::toVec3d( Vec3d::toVec4d(target) * cameraRotation ); 35 | 36 | // offset the camera position in the direction where the camera is looking at 37 | target = this->position + this->direction; 38 | return target; 39 | } 40 | -------------------------------------------------------------------------------- /qt3DRenderer/camera.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec3d.h" 3 | 4 | 5 | class Camera 6 | { 7 | public: 8 | Camera(); 9 | 10 | Vec3d lookAtTarget(); 11 | void rotateYaw(const float& angle); 12 | void rotatePitch(const float& angle); 13 | 14 | Vec3d position; // the location of the camera in World Space 15 | Vec3d direction; // points to the target 16 | Vec3d forwardVelocity; // direction and magnitude of the camera speed movement 17 | float yaw; // angle (radians) for yaw rotation (around Y-axis) 18 | float pitch; // angle (radians) for pitch rotation (around X-axis) 19 | }; 20 | -------------------------------------------------------------------------------- /qt3DRenderer/clipping.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec3d.h" 3 | #include "vec4d.h" 4 | #include "triangle.h" 5 | 6 | #include 7 | 8 | 9 | enum FRUSTUM_PLANE 10 | { 11 | LEFT = 0, 12 | RIGHT = 1, 13 | TOP = 2, 14 | BOTTOM = 3, 15 | NEAR = 4, 16 | FAR = 5 17 | }; 18 | 19 | 20 | class Plane 21 | { 22 | public: 23 | Plane(); 24 | 25 | Vec3d point; 26 | Vec3d normal; 27 | }; 28 | 29 | 30 | class Polygon 31 | { 32 | public: 33 | // Constructor: receive the vertices for a triangle and its associated texture coordinates 34 | Polygon(const Vec3d& v1, const Vec3d& v2, const Vec3d& v3, const Tex2& t1, const Tex2& t2, const Tex2& t3); 35 | 36 | // clip: performs polygon clipping based on each of the Frustum sides 37 | void clip(const Plane frustumPlanes[6]); 38 | 39 | // triangles: breaks down the vertices vector into one or more Triangle objects 40 | std::vector triangles(); 41 | 42 | std::vector vertices; 43 | std::vector texCoords; 44 | 45 | private: 46 | void _clipAgainstPlane(const Plane& frustumPlane); 47 | }; 48 | -------------------------------------------------------------------------------- /qt3DRenderer/cubemesh.cpp: -------------------------------------------------------------------------------- 1 | #include "cubemesh.h" 2 | 3 | 4 | CubeMesh::CubeMesh() 5 | { 6 | _init(); 7 | } 8 | 9 | CubeMesh::CubeMesh(const uint32_t* texData, const int& texWidth, const int& texHeight) 10 | : Mesh(texData, texWidth, texHeight) 11 | { 12 | _init(); 13 | } 14 | 15 | void CubeMesh::_init() 16 | { 17 | /* initialize cube vertices */ 18 | 19 | vertices.push_back(Vec3d(-1, -1, -1)); // 1 20 | vertices.push_back(Vec3d(-1, 1, -1)); // 2 21 | vertices.push_back(Vec3d( 1, 1, -1)); // 3 22 | vertices.push_back(Vec3d( 1, -1, -1)); // 4 23 | vertices.push_back(Vec3d( 1, 1, 1)); // 5 24 | vertices.push_back(Vec3d( 1, -1, 1)); // 6 25 | vertices.push_back(Vec3d(-1, 1, 1)); // 7 26 | vertices.push_back(Vec3d(-1, -1, 1)); // 8 27 | 28 | /* initialize cube faces: 6 cube faces, 2 triangles per face == 12 elements 29 | * Each face has an associated texture coordinate, however, they could be draw just with their predefined color. 30 | * 31 | * Texture Coordinate origin: 32 | * 33 | * (u,v) 34 | * 0,0 1,0 35 | * o --------> 36 | * | 37 | * | 38 | * | 39 | * v o 40 | * 0,1 1,1 41 | */ 42 | 43 | // front 44 | faces.push_back(Face(0, 1, 2, Tex2(0,1), Tex2(0,0), Tex2(1,0), 0xFFFFFFFF)); // 0xFFFF0000 45 | faces.push_back(Face(0, 2, 3, Tex2(0,1), Tex2(1,0), Tex2(1,1), 0xFFFFFFFF)); // 0xFFFF0000 46 | 47 | // right 48 | faces.push_back(Face(3, 2, 4, Tex2(0,1), Tex2(0,0), Tex2(1,0), 0xFFFFFFFF)); // 0xFF00FF00 49 | faces.push_back(Face(3, 4, 5, Tex2(0,1), Tex2(1,0), Tex2(1,1), 0xFFFFFFFF)); // 0xFF00FF00 50 | 51 | // back 52 | faces.push_back(Face(5, 4, 6, Tex2(0,1), Tex2(0,0), Tex2(1,0), 0xFFFFFFFF)); // 0xFF0000FF 53 | faces.push_back(Face(5, 6, 7, Tex2(0,1), Tex2(1,0), Tex2(1,1), 0xFFFFFFFF)); // 0xFF0000FF 54 | 55 | // left 56 | faces.push_back(Face(7, 6, 1, Tex2(0,1), Tex2(0,0), Tex2(1,0), 0xFFFFFFFF)); // 0xFFFFFF00 57 | faces.push_back(Face(7, 1, 0, Tex2(0,1), Tex2(1,0), Tex2(1,1), 0xFFFFFFFF)); // 0xFFFFFF00 58 | 59 | // top 60 | faces.push_back(Face(1, 6, 4, Tex2(0,1), Tex2(0,0), Tex2(1,0), 0xFFFFFFFF)); // 0xFF00FFFF 61 | faces.push_back(Face(1, 4, 2, Tex2(0,1), Tex2(1,0), Tex2(1,1), 0xFFFFFFFF)); // 0xFF00FFFF 62 | 63 | // bottom 64 | faces.push_back(Face(5, 7, 0, Tex2(0,1), Tex2(0,0), Tex2(1,0), 0xFFFFFFFF)); // 0xFFFF00FF 65 | faces.push_back(Face(5, 0, 3, Tex2(0,1), Tex2(1,0), Tex2(1,1), 0xFFFFFFFF)); // 0xFFFF00FF 66 | } 67 | -------------------------------------------------------------------------------- /qt3DRenderer/cubemesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "mesh.h" 3 | 4 | 5 | class CubeMesh : public Mesh 6 | { 7 | public: 8 | CubeMesh(); 9 | CubeMesh(const uint32_t* texData, const int& texWidth, const int& texHeight); 10 | 11 | private: 12 | void _init(); 13 | }; 14 | -------------------------------------------------------------------------------- /qt3DRenderer/display.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec3d.h" 3 | #include "vec2d.h" 4 | #include "tex2.h" 5 | 6 | #include 7 | 8 | extern bool USE_PAINTERS_ALGO; 9 | 10 | class Display 11 | { 12 | public: 13 | Display(); 14 | ~Display(); 15 | 16 | // setup: allocates new color buffer 17 | void setup(); 18 | 19 | // setSize: set a new screen size (i.e. color buffer) 20 | void setSize(const int& width, const int& height); 21 | 22 | // width: return the width of the 3D screen 23 | int width(); 24 | 25 | // height: return the height of the 3D screen 26 | int height(); 27 | 28 | // clearColorBuffer: fill color buffer with specific color 29 | void clearColorBuffer(const uint32_t& color); 30 | 31 | // 32 | void clearDepthBuffer(const float& depth); 33 | 34 | // 35 | uint32_t* colorBuffer(); 36 | 37 | // 38 | float* depthBuffer(); 39 | 40 | // 41 | void drawGrid(); 42 | 43 | // 44 | void drawPixel(const int& x, const int& y, const uint32_t& color); 45 | 46 | // 47 | void drawPixel(const int& x, const int& y, const Vec4d& a, const Vec4d& b, const Vec4d& c, const uint32_t& color); 48 | 49 | // 50 | void drawTexel(const int& x, const int& y, 51 | const Vec4d& a, const Vec4d& b, const Vec4d& c, 52 | const Tex2& a_uv, const Tex2& b_uv, const Tex2& c_uv, 53 | const uint32_t* texture, const int& textureWidth, const int& textureHeight, 54 | const bool& fixDistortion = true); 55 | 56 | // 57 | void drawLine(const int& x1, const int& y1, const int& x2, const int& y2, const uint32_t& color); 58 | 59 | // 60 | void drawRect(const int& x, const int& y, const int& w, const int& h, const uint32_t& color); 61 | 62 | // 63 | void drawTriangle(const int& x1, const int& y1, const int& x2, const int& y2, const int& x3, const int& y3, const uint32_t& color); 64 | 65 | // 66 | void fillTriangle(Vec4d p1, Vec4d p2, Vec4d p3, const uint32_t& color); 67 | 68 | // 69 | void drawTexturedTriangle(Vec4d p1, Vec4d p2, Vec4d p3, 70 | Tex2 uv1, Tex2 uv2, Tex2 uv3, 71 | const uint32_t* texture, const int& textureWidth, const int& textureHeight, 72 | const bool& fixDistortion = true); 73 | 74 | // orthographic projection: objects appear to have the same size regardless of their Z distance 75 | // receives a 3D vector and returns a projected 2D point 76 | Vec2d project(Vec3d p); 77 | 78 | private: 79 | void _fillFlatBottomTriangle(const int& x1, const int& y1, const int& x2, const int& y2, const int& x3, const int& y3, const uint32_t& color); 80 | void _fillFlatTopTriangle(const int& x1, const int& y1, const int& x2, const int& y2, const int& x3, const int& y3, const uint32_t& color); 81 | 82 | Vec3d _barycentricWeights(const Vec2d& a, const Vec2d& b, const Vec2d& c, const Vec2d& p); 83 | 84 | uint32_t* _colorBuffer; 85 | float* _depthBuffer; 86 | 87 | int _screenWidth; 88 | int _screenHeight; 89 | uint32_t _bkgColor; 90 | float _fovFactor; 91 | }; 92 | -------------------------------------------------------------------------------- /qt3DRenderer/face.cpp: -------------------------------------------------------------------------------- 1 | #include "face.h" 2 | 3 | Face::Face(const int& a, const int& b, const int& c, const uint32_t& color) 4 | { 5 | this->a = a; 6 | this->b = b; 7 | this->c = c; 8 | this->color = color; 9 | } 10 | 11 | Face::Face(const int& a, const int& b, const int& c, const Tex2& uv1, const Tex2& uv2, const Tex2& uv3, const uint32_t& color) 12 | { 13 | this->a = a; 14 | this->b = b; 15 | this->c = c; 16 | 17 | this->a_uv = uv1; 18 | this->b_uv = uv2; 19 | this->c_uv = uv3; 20 | 21 | this->color = color; 22 | } 23 | -------------------------------------------------------------------------------- /qt3DRenderer/face.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include "tex2.h" 5 | 6 | class Face 7 | { 8 | public: 9 | Face(const int& a, const int& b, const int& c, const uint32_t& color = 0xFF000000); 10 | Face(const int& a, const int& b, const int& c, const Tex2& uv1, const Tex2& uv2, const Tex2& uv3, const uint32_t& color = 0xFF000000); 11 | 12 | int a, b, c; // the indexes of a vertex array that define a single Face (triangle) 13 | 14 | Tex2 a_uv, b_uv, c_uv; // the texture coordinates associated with each vertex 15 | 16 | uint32_t color; 17 | }; 18 | -------------------------------------------------------------------------------- /qt3DRenderer/light.cpp: -------------------------------------------------------------------------------- 1 | #include "light.h" 2 | 3 | Light::Light() 4 | { 5 | } 6 | 7 | uint32_t Light::calcIntensity(const uint32_t& color, float intensityPercent) 8 | { 9 | // clamp range between 0.0 and 1.0 10 | if (intensityPercent < 0.f) intensityPercent = 0.f; 11 | if (intensityPercent > 1.f) intensityPercent = 1.f; 12 | 13 | uint32_t a = (color & 0xFF000000); 14 | uint32_t r = (uint32_t)((color & 0x00FF0000) * intensityPercent); 15 | uint32_t g = (uint32_t)((color & 0x0000FF00) * intensityPercent); 16 | uint32_t b = (uint32_t)((color & 0x000000FF) * intensityPercent); 17 | 18 | uint32_t newColor = a | (r & 0x00FF0000) | (g & 0x0000FF00) | (b & 0x000000FF); 19 | 20 | return newColor; 21 | } 22 | -------------------------------------------------------------------------------- /qt3DRenderer/light.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec3d.h" 3 | 4 | class Light 5 | { 6 | public: 7 | Light(); 8 | 9 | // calculate new color value based on a percentage factor that represents the light intensity 10 | static uint32_t calcIntensity(const uint32_t& color, float intensityPercent); 11 | 12 | Vec3d direction; 13 | }; 14 | -------------------------------------------------------------------------------- /qt3DRenderer/main.cpp: -------------------------------------------------------------------------------- 1 | #include "window.h" 2 | #include 3 | 4 | int main(int argc, char* argv[]) 5 | { 6 | QApplication app(argc, argv); 7 | 8 | Window win; 9 | //win.resize(1280, 900); 10 | 11 | win.show(); 12 | //win.showFullScreen(); 13 | //win.showMaximized(); 14 | 15 | return app.exec(); 16 | } 17 | -------------------------------------------------------------------------------- /qt3DRenderer/mat4.h: -------------------------------------------------------------------------------- 1 | /* matrix multiplication (multiply row by column) 2 | * 3 | * | 1 2 | * | 5 6 | = | (1+5)+(2*7) (1*6)+(2*8) | 4 | * | 3 4 | | 7 8 | | (3*5)+(4*7) (3*6)+(4*8) | 5 | * 6 | * = | 19 22 | 7 | * | 43 50 | 8 | * 9 | * Properties of matrix mult: 10 | * - Only allowed when the num cols of the Left matrix is equal to the num rows of the Right matrix: NxM * MxP = NxP 11 | * - Its not commutative: A*B != B*A 12 | * - Identify Matrix: a matrix multiplied by the I.M. returns the original matrix unchanged 13 | * 14 | * Rotation of 2D point (x,y) to point (x',y') by an angle α: 15 | * x' = x*cosα - y*sinα 16 | * y' = x*sinα + y*cosα 17 | * 18 | * The same equation appears in a Rotation Matrix: 19 | * |x'| = | cosα -sinα | * |x| 20 | * |y'| | sinα cosα | |y| 21 | * 22 | * We use 4x4 matrices for 3D transformations instead of 3x3 because Translation requires an extra row/column 23 | * to be performed. Also, to enable matrix-vector multiplication, an extra component W is added to the original 24 | * vector (think of W as being 1): 25 | * | m m m m | | x | 26 | * | m m m m | * | y | 27 | * | m m m m | | z | 28 | * | m m m m | | 1 | 29 | */ 30 | #pragma once 31 | //#include "vec3d.h" 32 | #include 33 | #include 34 | 35 | class Vec3d; 36 | 37 | /* A 4x4 matrix class that can be used for linear transformations. 38 | */ 39 | class Mat4 40 | { 41 | public: 42 | Mat4(); 43 | 44 | // return the identity matrix 45 | static Mat4 eye(); 46 | 47 | static Mat4 scale(const float& sx, const float& sy, const float& sz); 48 | 49 | static Mat4 translate(const float& tx, const float& ty, const float& tz); 50 | 51 | static Mat4 rotateX(const float& angle); 52 | 53 | static Mat4 rotateY(const float& angle); 54 | 55 | static Mat4 rotateZ(const float& angle); 56 | 57 | static Mat4 perspective(const float& fov, const float& aspect, const float& znear, const float& zfar); 58 | 59 | static Mat4 lookAt(Vec3d eye, Vec3d target, Vec3d up); 60 | 61 | // multiplication of Mat4 by Mat4 62 | Mat4 mul(const Mat4& m); 63 | 64 | // overload multiplication operator to execute mul() 65 | Mat4 operator*(const Mat4& m) 66 | { 67 | return mul(m); 68 | } 69 | 70 | // overload insertion operator 71 | friend std::ostream& operator<<(std::ostream& os, const Mat4& v) 72 | { 73 | std::cout.precision(4); 74 | os << "Mat4=( " << std::setw(5) << v.m[0][0] << " " << std::setw(5) << v.m[0][1] << " " << std::setw(5) << v.m[0][2] << " " << std::setw(5) << v.m[0][3] << "\n" << 75 | " " << std::setw(5) << v.m[1][0] << " " << std::setw(5) << v.m[1][1] << " " << std::setw(5) << v.m[1][2] << " " << std::setw(5) << v.m[1][3] << "\n" << 76 | " " << std::setw(5) << v.m[2][0] << " " << std::setw(5) << v.m[2][1] << " " << std::setw(5) << v.m[2][2] << " " << std::setw(5) << v.m[2][3] << "\n" << 77 | " " << std::setw(5) << v.m[3][0] << " " << std::setw(5) << v.m[3][1] << " " << std::setw(5) << v.m[3][2] << " " << std::setw(5) << v.m[3][3] << " )"; 78 | return os; 79 | } 80 | 81 | float m[4][4]; 82 | }; 83 | 84 | -------------------------------------------------------------------------------- /qt3DRenderer/mesh.cpp: -------------------------------------------------------------------------------- 1 | #include "mesh.h" 2 | 3 | #include 4 | 5 | 6 | Mesh::Mesh() 7 | { 8 | scale = Vec3d(1.f, 1.f, 1.f); 9 | rotation = Vec3d(0.f, 0.f, 0.f); 10 | translation = Vec3d(0.f, 0.f, 0.f); 11 | 12 | textureWidth = textureHeight = 0; 13 | } 14 | 15 | Mesh::Mesh(const uint32_t* texData, const int& texWidth, const int& texHeight) 16 | { 17 | scale = Vec3d(1.f, 1.f, 1.f); 18 | rotation = Vec3d(0.f, 0.f, 0.f); 19 | translation = Vec3d(0.f, 0.f, 0.f); 20 | 21 | setTexture(texData, texWidth, texHeight); 22 | } 23 | 24 | void Mesh::setTexture(const uint32_t* texData, const int& texWidth, const int& texHeight) 25 | { 26 | // deep copy texture data 27 | int texSize = texWidth * texHeight; 28 | texture = std::shared_ptr(new uint32_t[texSize]); 29 | std::memcpy(texture.get(), (uint32_t*)texData, texSize * sizeof(uint32_t)); 30 | 31 | // initialize texture dimensions 32 | textureWidth = texWidth; 33 | textureHeight = texHeight; 34 | } 35 | -------------------------------------------------------------------------------- /qt3DRenderer/mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec3d.h" 3 | #include "face.h" 4 | 5 | #include 6 | 7 | 8 | class Mesh 9 | { 10 | public: 11 | Mesh(); 12 | Mesh(const uint32_t* texData, const int& texWidth, const int& texHeight); 13 | void setTexture(const uint32_t* texData, const int& texWidth, const int& texHeight); 14 | 15 | std::vector vertices; 16 | std::vector faces; 17 | 18 | std::shared_ptr texture; 19 | int textureWidth; 20 | int textureHeight; 21 | 22 | Vec3d rotation; // current rotation of the mesh 23 | Vec3d scale; // current scale 24 | Vec3d translation; // current translation 25 | }; 26 | -------------------------------------------------------------------------------- /qt3DRenderer/objloader.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * mtllib cube.mtl 3 | * o cube 4 | * 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 -1.000000 10 | * v 1.000000 1.000000 -1.000000 11 | * v -1.000000 -1.000000 -1.000000 12 | * v 1.000000 -1.000000 -1.000000 13 | * 14 | * vt 1.000000 0.000000 15 | * vt 0.000000 0.000000 16 | * vt 1.000000 1.000000 17 | * vt 0.000000 1.000000 18 | * 19 | * vn 0.000000 0.000000 1.000000 20 | * vn 0.000000 1.000000 0.000000 21 | * vn 0.000000 0.000000 -1.000000 22 | * vn 0.000000 -1.000000 0.000000 23 | * vn 1.000000 0.000000 0.000000 24 | * vn -1.000000 0.000000 0.000000 25 | * 26 | * g cube 27 | * usemtl cube 28 | * s 1 29 | * f 1/1/1 2/2/1 3/3/1 30 | * f 3/3/1 2/2/1 4/4/1 31 | * s 2 32 | * f 3/1/2 4/2/2 5/3/2 33 | * f 5/3/2 4/2/2 6/4/2 34 | * s 3 35 | * f 5/4/3 6/3/3 7/2/3 36 | * f 7/2/3 6/3/3 8/1/3 37 | * s 4 38 | * f 7/1/4 8/2/4 1/3/4 39 | * f 1/3/4 8/2/4 2/4/4 40 | * s 5 41 | * f 2/1/5 8/2/5 4/3/5 42 | * f 4/3/5 8/2/5 6/4/5 43 | * s 6 44 | * f 7/1/6 1/2/6 5/3/6 45 | * f 5/3/6 1/2/6 3/4/6 46 | */ 47 | #include "objloader.h" 48 | #include "tex2.h" 49 | 50 | #include 51 | #include 52 | 53 | #include 54 | 55 | 56 | OBJLoader::OBJLoader(const std::string& filename) 57 | { 58 | FILE* file = fopen(filename.c_str(), "r"); 59 | if (!file) 60 | { 61 | std::cout << "!!! OBJLoader: unable to open file " << filename << std::endl; 62 | std::cout << "Have you updated ASSETS_DIR in window.cpp?" << std::endl; 63 | exit(-1); 64 | } 65 | 66 | // store the texture coordinates from the vt section 67 | std::vector texCoords; 68 | 69 | char line[1024]; 70 | while (fgets(line, 1024, file)) 71 | { 72 | // vertex data 73 | if (strncmp(line, "v ", 2) == 0) 74 | { 75 | Vec3d vertex; 76 | sscanf(line, "v %f %f %f", &vertex.x, &vertex.y, &vertex.z); // v -1.000000 -1.000000 1.000000 77 | _mesh.vertices.push_back(vertex); 78 | } 79 | 80 | // texture coordinates info 81 | if (strncmp(line, "vt ", 3) == 0) 82 | { 83 | Tex2 texCoord; 84 | sscanf(line, "vt %f %f", &texCoord.u, &texCoord.v); 85 | texCoords.push_back(texCoord); 86 | } 87 | 88 | /* f 5/4/3 6/3/3 7/2/3 89 | * - each one of these 3 sections describe the vertexIdx/texCoordIdx/NormalIdx for one vertex of the triangular face 90 | * - number 5: the first number. Its the 5th vertex index (stored in the v section) for the first vertex of this triangular face 91 | * - number 4: the second number. Its the 4th texture coord index (stored in the vt section) associated to this vertex 92 | */ 93 | if (strncmp(line, "f ", 2) == 0) 94 | { 95 | int vertexIdx[3]; 96 | int textureIdx[3]; 97 | int normalsIdx[3]; 98 | sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d", &vertexIdx[0], &textureIdx[0], &normalsIdx[0], // f 1/1/1 2/2/1 3/3/1 99 | &vertexIdx[1], &textureIdx[1], &normalsIdx[1], 100 | &vertexIdx[2], &textureIdx[2], &normalsIdx[2]); 101 | 102 | // store the 3 vertices of the face and its associated texture coord info 103 | Face face(vertexIdx[0]-1, vertexIdx[1]-1, vertexIdx[2]-1, 104 | texCoords[textureIdx[0]-1], texCoords[textureIdx[1]-1], texCoords[textureIdx[2]-1], 105 | 0xFFFFFFFF); 106 | 107 | _mesh.faces.push_back(face); 108 | } 109 | } 110 | } 111 | 112 | Mesh OBJLoader::mesh() 113 | { 114 | return _mesh; 115 | } 116 | -------------------------------------------------------------------------------- /qt3DRenderer/objloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "mesh.h" 3 | 4 | #include 5 | 6 | 7 | class OBJLoader 8 | { 9 | public: 10 | OBJLoader(const std::string& filename); 11 | Mesh mesh(); 12 | 13 | private: 14 | Mesh _mesh; 15 | }; 16 | -------------------------------------------------------------------------------- /qt3DRenderer/qt3DRenderer.pro: -------------------------------------------------------------------------------- 1 | QT += core widgets 2 | 3 | SOURCES += \ 4 | camera.cpp \ 5 | clipping.cpp \ 6 | cubemesh.cpp \ 7 | display.cpp \ 8 | face.cpp \ 9 | light.cpp \ 10 | main.cpp \ 11 | mat4.cpp \ 12 | mesh.cpp \ 13 | objloader.cpp \ 14 | tex2.cpp \ 15 | triangle.cpp \ 16 | vec2d.cpp \ 17 | vec3d.cpp \ 18 | vec4d.cpp \ 19 | window.cpp 20 | 21 | HEADERS += \ 22 | camera.h \ 23 | clipping.h \ 24 | cubemesh.h \ 25 | display.h \ 26 | face.h \ 27 | light.h \ 28 | mat4.h \ 29 | mesh.h \ 30 | objloader.h \ 31 | tex2.h \ 32 | triangle.h \ 33 | vec2d.h \ 34 | vec3d.h \ 35 | vec4d.h \ 36 | window.h 37 | -------------------------------------------------------------------------------- /qt3DRenderer/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qt3DRenderer/screenshot.gif -------------------------------------------------------------------------------- /qt3DRenderer/tex2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | class Tex2 5 | { 6 | public: 7 | Tex2(const float& u = 0, const float& v = 0); 8 | 9 | float u; 10 | float v; 11 | }; 12 | 13 | 14 | extern int REDBRICK_WIDTH; 15 | extern int REDBRICK_HEIGHT; 16 | extern uint8_t REDBRICK_TEXTURE[]; 17 | -------------------------------------------------------------------------------- /qt3DRenderer/triangle.cpp: -------------------------------------------------------------------------------- 1 | #include "triangle.h" 2 | 3 | Triangle::Triangle() 4 | { 5 | 6 | } 7 | 8 | Triangle::Triangle(const Vec4d& p1, const Vec4d& p2, const Vec4d& p3) 9 | { 10 | points[0] = p1; 11 | points[1] = p2; 12 | points[2] = p3; 13 | 14 | this->color = 0xFFFFFFFF; 15 | } 16 | 17 | Triangle::Triangle(const Vec4d& p1, const Vec4d& p2, const Vec4d& p3, 18 | const Tex2& t1, const Tex2& t2, const Tex2& t3, 19 | const std::shared_ptr& texData, 20 | const int texWidth, const int texHeight, 21 | const uint32_t& color) 22 | { 23 | points[0] = p1; 24 | points[1] = p2; 25 | points[2] = p3; 26 | 27 | texCoords[0] = t1; 28 | texCoords[1] = t2; 29 | texCoords[2] = t3; 30 | 31 | this->texture = texData; 32 | this->textureWidth = texWidth; 33 | this->textureHeight = texHeight; 34 | 35 | this->color = color; 36 | } 37 | -------------------------------------------------------------------------------- /qt3DRenderer/triangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec2d.h" 3 | #include "tex2.h" 4 | 5 | #include 6 | 7 | #include 8 | 9 | 10 | class Triangle 11 | { 12 | public: 13 | Triangle(); 14 | 15 | Triangle(const Vec4d& p1, const Vec4d& p2, const Vec4d& p3); 16 | 17 | Triangle(const Vec4d& p1, const Vec4d& p2, const Vec4d& p3, 18 | const Tex2& t1, const Tex2& t2, const Tex2& t3, 19 | const std::shared_ptr& texData = nullptr, 20 | const int texWidth = 0, const int texHeight = 0, 21 | const uint32_t& color = 0xFFFFFFFF); 22 | 23 | Vec4d points[3]; 24 | Tex2 texCoords[3]; 25 | 26 | std::shared_ptr texture; 27 | int textureWidth; 28 | int textureHeight; 29 | 30 | uint32_t color; 31 | }; 32 | 33 | -------------------------------------------------------------------------------- /qt3DRenderer/vec2d.cpp: -------------------------------------------------------------------------------- 1 | #include "vec2d.h" 2 | 3 | #include 4 | 5 | 6 | Vec2d::Vec2d() 7 | { 8 | x = y = 0; 9 | } 10 | 11 | Vec2d::Vec2d(const float& x1, const float& y1) 12 | { 13 | x = x1; 14 | y = y1; 15 | } 16 | 17 | float Vec2d::mag() const 18 | { 19 | // pythagoras theorem 20 | return std::sqrt(x*x + y*y); 21 | } 22 | 23 | Vec2d Vec2d::add(const Vec2d& v) const 24 | { 25 | return Vec2d(this->x + v.x, this->y + v.y); 26 | } 27 | 28 | Vec2d Vec2d::sub(const Vec2d& v) const 29 | { 30 | return Vec2d(this->x - v.x, this->y - v.y); 31 | } 32 | 33 | Vec2d Vec2d::mul(const float& factor) const 34 | { 35 | return Vec2d(this->x * factor, this->y * factor); 36 | } 37 | 38 | Vec2d Vec2d::div(const float& factor) const 39 | { 40 | return Vec2d(this->x / factor, this->y / factor); 41 | } 42 | 43 | float Vec2d::dot(const Vec2d& v) const 44 | { 45 | return (this->x * v.x) + (this->y * v.y); 46 | } 47 | 48 | void Vec2d::norm() 49 | { 50 | float magnitude = mag(); 51 | this->x /= magnitude; 52 | this->y /= magnitude; 53 | } 54 | -------------------------------------------------------------------------------- /qt3DRenderer/vec2d.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec3d.h" 3 | 4 | #include 5 | 6 | class Vec3d; 7 | 8 | 9 | class Vec2d 10 | { 11 | public: 12 | Vec2d(); 13 | Vec2d(const float& x1, const float& y1); 14 | 15 | // magnitude: length of the hypothenuse 16 | float mag() const; 17 | 18 | // addition 19 | Vec2d add(const Vec2d& v) const; 20 | 21 | // subtraction 22 | Vec2d sub(const Vec2d& v) const; 23 | 24 | // multiplication 25 | Vec2d mul(const float& factor) const; 26 | 27 | // division 28 | Vec2d div(const float& factor) const; 29 | 30 | // scalar dot product 31 | float dot(const Vec2d& v) const; 32 | 33 | // normalize 34 | void norm(); 35 | 36 | // overload insertion operator 37 | friend std::ostream& operator<<(std::ostream& os, const Vec2d& vec) 38 | { 39 | os << "Vec2d=(" << vec.x << ", " << vec.y << ")"; 40 | return os; 41 | } 42 | 43 | float x; 44 | float y; 45 | }; 46 | -------------------------------------------------------------------------------- /qt3DRenderer/vec3d.cpp: -------------------------------------------------------------------------------- 1 | #include "vec3d.h" 2 | #include "vec4d.h" 3 | 4 | #include 5 | 6 | 7 | Vec3d::Vec3d() 8 | { 9 | x = y = z = 0; 10 | } 11 | 12 | Vec3d::Vec3d(const float& x, const float& y, const float& z) 13 | { 14 | this->x = x; 15 | this->y = y; 16 | this->z = z; 17 | } 18 | 19 | /* Vector Rotation 20 | * 21 | * | cos(a) -sin(a) | * | x | x' = x*cos(a) - y*sin(a) 22 | * | sin(a) cos(a) | | y | y' = y*cos(a) + x*sin(a) 23 | */ 24 | 25 | // rotation around the Z axis 26 | Vec3d Vec3d::rotateZ(const float& angle) 27 | { 28 | Vec3d rotated(x * cos(angle) - y * sin(angle), 29 | x * sin(angle) + y * cos(angle), 30 | z); 31 | 32 | return rotated; 33 | } 34 | 35 | // rotation around the Y axis 36 | Vec3d Vec3d::rotateY(const float& angle) 37 | { 38 | Vec3d rotated(x * cos(angle) + z * sin(angle), 39 | y, 40 | -x * sin(angle) + z * cos(angle)); 41 | 42 | return rotated; 43 | } 44 | 45 | // rotation around the X axis 46 | Vec3d Vec3d::rotateX(const float& angle) 47 | { 48 | Vec3d rotated(x, 49 | y * cos(angle) - z * sin(angle), 50 | y * sin(angle) + z * cos(angle)); 51 | 52 | return rotated; 53 | } 54 | 55 | /* Angle Addition Property Proof 56 | * sin(a+B) = sin(a) * cos(B) + cos(a) * sin(B) 57 | * cos(a+B) = cos(a) * cos(B) - sin(a) * sin(B) 58 | */ 59 | 60 | 61 | float Vec3d::mag() 62 | { 63 | // pythagoras theorem 64 | return std::sqrt(x*x + y*y + z*z); 65 | } 66 | 67 | Vec3d Vec3d::add(const Vec3d& v) 68 | { 69 | return Vec3d(this->x + v.x, this->y + v.y, this->z + v.z); 70 | } 71 | 72 | Vec3d Vec3d::sub(const Vec3d& v) 73 | { 74 | return Vec3d(this->x - v.x, this->y - v.y, this->z - v.z); 75 | } 76 | 77 | Vec3d Vec3d::mul(const float& factor) 78 | { 79 | return Vec3d(this->x * factor, this->y * factor, this->z * factor); 80 | } 81 | 82 | Vec3d Vec3d::div(const float& factor) 83 | { 84 | return Vec3d(this->x / factor, this->y / factor, this->z / factor); 85 | } 86 | 87 | /* cross product: what is the perpendicular vector between 2 vectors? 88 | * 89 | * .o A 90 | * ' ' 91 | * . . 92 | * . . 93 | * . . 94 | * . . 95 | * . . 96 | * C o . . . o B 97 | * 98 | * Vector AB is given by the sides: B - A 99 | * Vector AC is given by the sides: C - A 100 | * 101 | * To calculate the cross product between them, do: 102 | * (B - A) x (C - A) 103 | * 104 | * It gives a vector perpendicular (90º) to AB and AC. 105 | * 106 | * The equation (B - A) x (C - A) only works because: 107 | * - this renderer uses a Left-Handed Coordinate System (LHCS) 108 | * - the vertices are defined clockwise 109 | * 110 | * CLOCKWISE: A/B/C 111 | * COUNTERCLOCKWISE: A/C/B 112 | * 113 | * B 114 | * . o 115 | * .´ ' 116 | * A o.´ ' 117 | * `. ' 118 | * `o 119 | * C 120 | */ 121 | Vec3d Vec3d::cross(const Vec3d& v) 122 | { 123 | return Vec3d(this->y * v.z - this->z * v.y, 124 | this->z * v.x - this->x * v.z, 125 | this->x * v.y - this->y * v.x); 126 | } 127 | 128 | /* dot product: how aligned are two vectors? 129 | * 130 | * b 131 | * /. 132 | * / . 133 | * / . 134 | * / . 135 | * o ======= - - - -> a 136 | * 137 | * Projection of B into A 138 | * 139 | * Curiosity: 140 | * - if both vectors are 90º from each other, their dot product is ZERO 141 | * - if both vectors are 180º from each other, their dot product is -1.0 142 | */ 143 | float Vec3d::dot(const Vec3d& v) 144 | { 145 | return (this->x * v.x) + (this->y * v.y) + (this->z * v.z); 146 | } 147 | 148 | 149 | void Vec3d::norm() 150 | { 151 | float magnitude = mag(); 152 | this->x /= magnitude; 153 | this->y /= magnitude; 154 | this->z /= magnitude; 155 | } 156 | 157 | Vec4d Vec3d::toVec4d(const Vec3d& v) 158 | { 159 | return Vec4d(v.x, v.y, v.z, 1.f); 160 | } 161 | -------------------------------------------------------------------------------- /qt3DRenderer/vec3d.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec4d.h" 3 | 4 | #include 5 | 6 | class Vec4d; 7 | 8 | class Vec3d 9 | { 10 | public: 11 | Vec3d(); 12 | Vec3d(const float& x, const float& y, const float& z); 13 | 14 | // data type conversion 15 | static Vec4d toVec4d(const Vec3d& v); 16 | 17 | Vec3d rotateZ(const float& angle); 18 | Vec3d rotateY(const float& angle); 19 | Vec3d rotateX(const float& angle); 20 | 21 | // magnitude: length of the hypothenuse 22 | float mag(); 23 | 24 | // addition 25 | Vec3d add(const Vec3d& v); 26 | 27 | // subtraction 28 | Vec3d sub(const Vec3d& v); 29 | 30 | // scalar multiplication 31 | Vec3d mul(const float& factor); 32 | 33 | // division 34 | Vec3d div(const float& factor); 35 | 36 | // vector cross product 37 | Vec3d cross(const Vec3d& v); 38 | 39 | // scalar dot product 40 | float dot(const Vec3d& v); 41 | 42 | // normalize 43 | void norm(); 44 | 45 | // overload addition operator to execute add() 46 | Vec3d operator+(const Vec3d& v) 47 | { 48 | return add(v); 49 | } 50 | 51 | // overload subtraction operator to execute sub() 52 | Vec3d operator-(const Vec3d& v) 53 | { 54 | return sub(v); 55 | } 56 | 57 | // overload multiplication operator to execute mul() 58 | Vec3d operator*(const float& factor) 59 | { 60 | return mul(factor); 61 | } 62 | 63 | // overload insertion operator 64 | friend std::ostream& operator<<(std::ostream& os, const Vec3d& v) 65 | { 66 | os << "Vec3d=(" << v.x << ", " << v.y << ", " << v.z << ")"; 67 | return os; 68 | } 69 | 70 | float x, y; 71 | float z; 72 | }; 73 | -------------------------------------------------------------------------------- /qt3DRenderer/vec4d.cpp: -------------------------------------------------------------------------------- 1 | #include "vec4d.h" 2 | 3 | 4 | Vec4d::Vec4d() 5 | { 6 | x = y = z = 0; 7 | w = 1; 8 | } 9 | 10 | Vec4d::Vec4d(const float& x, const float& y, const float& z, const float& w) 11 | { 12 | this->x = x; 13 | this->y = y; 14 | this->z = z; 15 | this->w = w; 16 | } 17 | 18 | Vec3d Vec4d::toVec3d(const Vec4d& v) 19 | { 20 | return Vec3d(v.x, v.y, v.z); 21 | } 22 | 23 | Vec2d Vec4d::toVec2d(const Vec4d& v) 24 | { 25 | return Vec2d(v.x, v.y); 26 | } 27 | 28 | Vec4d Vec4d::mul(const Mat4& mat) 29 | { 30 | Vec4d result; 31 | result.x = mat.m[0][0] * this->x + mat.m[0][1] * this->y + mat.m[0][2] * this->z + mat.m[0][3] * this->w; 32 | result.y = mat.m[1][0] * this->x + mat.m[1][1] * this->y + mat.m[1][2] * this->z + mat.m[1][3] * this->w; 33 | result.z = mat.m[2][0] * this->x + mat.m[2][1] * this->y + mat.m[2][2] * this->z + mat.m[2][3] * this->w; 34 | result.w = mat.m[3][0] * this->x + mat.m[3][1] * this->y + mat.m[3][2] * this->z + mat.m[3][3] * this->w; 35 | 36 | return result; 37 | } 38 | 39 | Vec3d Vec4d::normal(const Vec4d& a, const Vec4d& b, const Vec4d& c) 40 | { 41 | // part of the Face Culling computation 42 | Vec3d vectorA = Vec4d::toVec3d(a); 43 | Vec3d vectorB = Vec4d::toVec3d(b); 44 | Vec3d vectorC = Vec4d::toVec3d(c); 45 | 46 | // 1. Find vectors B-A and C-A 47 | Vec3d vectorAB = vectorB - vectorA; 48 | Vec3d vectorAC = vectorC - vectorA; 49 | 50 | // normalize: adjust lengths to unit vector since we only care about their direction 51 | vectorAB.norm(); 52 | vectorAC.norm(); 53 | 54 | // 2. Take their cross product and find the perpendicular normal 55 | Vec3d faceNormal = vectorAB.cross(vectorAC); // this order for Left-Handed Coordinate System 56 | faceNormal.norm(); // normalize: adjust lengths to unit vector since we only care about their direction 57 | 58 | return faceNormal; 59 | } 60 | -------------------------------------------------------------------------------- /qt3DRenderer/vec4d.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "vec2d.h" 3 | #include "vec3d.h" 4 | #include "mat4.h" 5 | 6 | #include 7 | 8 | class Vec2d; 9 | class Vec3d; 10 | 11 | 12 | class Vec4d 13 | { 14 | public: 15 | Vec4d(); 16 | Vec4d(const float& x, const float& y, const float& z, const float& w); 17 | 18 | // data type conversions 19 | static Vec3d toVec3d(const Vec4d& v); 20 | static Vec2d toVec2d(const Vec4d& v); 21 | 22 | // matrix multiplication of Vec4d with Mat4 23 | Vec4d mul(const Mat4& m); 24 | 25 | // overload multiplication operator to execute mul() 26 | Vec4d operator*(const Mat4& m) 27 | { 28 | return mul(m); 29 | } 30 | 31 | // normal: a helper function to calculate the Normal from 3 vectors 32 | static Vec3d normal(const Vec4d& a, const Vec4d& b, const Vec4d& c); 33 | 34 | // overload insertion operator 35 | friend std::ostream& operator<<(std::ostream& os, const Vec4d& vec) 36 | { 37 | os << "Vec4d=(" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ")"; 38 | return os; 39 | } 40 | 41 | float x, y; 42 | float z, w; 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /qt3DRenderer/window.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "mat4.h" 11 | #include "vec3d.h" 12 | #include "display.h" 13 | #include "light.h" 14 | #include "mesh.h" 15 | #include "cubemesh.h" 16 | #include "triangle.h" 17 | #include "camera.h" 18 | #include "clipping.h" 19 | 20 | 21 | enum RENDER_MODE { 22 | WIREFRAME, // draw only wireframe lines 23 | WIREFRAME_DOTS, // draw wireframe lines with small colored dots on each triangle vertex 24 | TRIANGLES, // fills triangles with a solid color 25 | TRIANGLES_WIREFRAME, // fills triangles and adds wireframe lines 26 | TEXTURED, // draw with textures 27 | TEXTURED_WIREFRAME // draw with textures and adds wireframe lines 28 | }; 29 | 30 | 31 | class Window : public QWidget 32 | { 33 | Q_OBJECT 34 | 35 | public: 36 | Window(); 37 | ~Window(); 38 | 39 | 40 | void updt(); 41 | void render(QPainter& p); 42 | 43 | void resizeEvent(QResizeEvent* event); 44 | void paintEvent(QPaintEvent* e); 45 | void keyPressEvent(QKeyEvent* event); 46 | 47 | private slots: 48 | void _tick(); 49 | 50 | private: 51 | void _renderColorBuffer(QPainter& p); 52 | void _initFrustumPlanes(const float& fovX, const float& fovY, const float& zNear, const float& zFar); 53 | void _processGraphicsPipeline(Mesh* mesh); 54 | 55 | int _width, _height; 56 | QImage _framebuffer; 57 | Display _gfx; 58 | 59 | std::vector _triangles2render; 60 | std::vector _meshObjects; 61 | 62 | Camera _camera; 63 | float _cameraOrbitAngle; 64 | float _cameraOrbitDistance; 65 | 66 | Mat4 _viewMatrix; 67 | float _deltaTime; 68 | 69 | QTimer* _timer; 70 | qint64 _tick_ms; 71 | qint64 _prevTime; 72 | RENDER_MODE _renderMode; 73 | 74 | Mat4 _projMatrix; 75 | Light _lightSource; 76 | 77 | Plane _frustumPlanes[6]; 78 | }; 79 | -------------------------------------------------------------------------------- /qtArduinoSerial/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013-2015 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "serialportreader.h" 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | QCoreApplication coreApplication(argc, argv); 21 | 22 | if (!QSerialPortInfo::availablePorts().count()) 23 | { 24 | std::cout << "!!! No serial ports found!" << std::endl; 25 | return 0; 26 | } 27 | 28 | int option = -1; 29 | while (1) 30 | { 31 | std::cout << "===== List of available serial ports (" << 32 | QSerialPortInfo::availablePorts().count() << ") =====" << std::endl; 33 | std::cout << "[0] - Exit" << std::endl; 34 | 35 | for (int i = 0; i < QSerialPortInfo::availablePorts().count(); i++) 36 | { 37 | QSerialPortInfo serial_info = QSerialPortInfo::availablePorts()[i]; 38 | std::cout << "[" << i+1 << "] - " << serial_info.portName().toStdString() << std::endl; 39 | 40 | std::cout << "\tLocation: " << serial_info.systemLocation().toStdString() << std::endl; 41 | std::cout << "\tDescription: " << serial_info.description().toStdString() << std::endl; 42 | std::cout << "\tManufacturer: " << serial_info.manufacturer().toStdString() << std::endl; 43 | std::cout << "\tVendor Identifier: " << (serial_info.hasVendorIdentifier() ? 44 | QString::number(serial_info.vendorIdentifier()).toStdString() : 45 | "") << std::endl; 46 | std::cout << "\tProduct Identifier: " << (serial_info.hasProductIdentifier() ? 47 | QString::number(serial_info.productIdentifier()).toStdString() : 48 | "") << std::endl; 49 | std::cout << "\tBusy: " << (serial_info.isBusy() ? "Yes" : "No") << std::endl; 50 | } 51 | 52 | std::cout << "\nYour choice: "; 53 | std::cin >> option; 54 | if (option >= 0 && option <= QSerialPortInfo::availablePorts().count()) 55 | break; 56 | std::cout << std::endl; 57 | } 58 | 59 | if (option == 0) 60 | { 61 | std::cout << "* OK, bye bye!" << std::endl; 62 | return 0; 63 | } 64 | 65 | QSerialPortInfo serial_info = QSerialPortInfo::availablePorts()[option-1]; 66 | std::cout << "* OK, " << serial_info.portName().toStdString() << 67 | " selected!" << std::endl; 68 | 69 | QSerialPort serial; 70 | serial.setPortName(serial_info.portName()); 71 | serial.setBaudRate(QSerialPort::Baud9600); 72 | serial.setDataBits(QSerialPort::Data8); 73 | serial.setStopBits(QSerialPort::OneStop); 74 | serial.setParity(QSerialPort::NoParity); 75 | serial.setFlowControl(QSerialPort::NoFlowControl); 76 | 77 | if (!serial.open(QIODevice::ReadOnly)) 78 | { 79 | std::cout << "!!! Failed to open port " << serial_info.portName().toStdString() << 80 | ". Error: " << serial.errorString().toStdString() << std::endl; 81 | return 1; 82 | } 83 | 84 | SerialPortReader reader(&serial); 85 | std::cout << "===== Output =====" << std::endl; 86 | 87 | return coreApplication.exec(); 88 | } 89 | -------------------------------------------------------------------------------- /qtArduinoSerial/qtArduinoSerial.pro: -------------------------------------------------------------------------------- 1 | # Go to the Project properties, 2 | # click on the Run tab, 3 | # and check the box "Run in terminal". 4 | CONFIG += console 5 | 6 | QT += core serialport 7 | 8 | SOURCES += \ 9 | main.cpp \ 10 | serialportreader.cpp 11 | 12 | HEADERS += \ 13 | serialportreader.h 14 | -------------------------------------------------------------------------------- /qtArduinoSerial/serialportreader.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013-2015 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "serialportreader.h" 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | SerialPortReader::SerialPortReader(QSerialPort* serial, QObject* parent) 20 | : QObject(parent), _serial(serial) 21 | { 22 | // The magic call that makes QSerialPort outputs from a serial connected with Arduino 23 | _serial->setDataTerminalReady(true); 24 | 25 | QObject::connect(_serial, SIGNAL(readyRead()), 26 | SLOT(_read_callback())); 27 | 28 | QObject::connect(_serial, SIGNAL(error(QSerialPort::SerialPortError)), 29 | SLOT(_error_callback(QSerialPort::SerialPortError))); 30 | } 31 | 32 | SerialPortReader::~SerialPortReader() 33 | { 34 | } 35 | 36 | void SerialPortReader::_read_callback() 37 | { 38 | if (!_serial) 39 | return; 40 | 41 | QByteArray data = _serial->readAll(); 42 | int sz = data.size(); 43 | 44 | /* On my Arduino data is always 3 bytes: 45 | * data[0]: is the value I'm interested at 46 | * data[1]: is always 13 (carriage return) 47 | * data[2]: is always 10 (new line) 48 | * 49 | * which causes std::cout to jump 2 lines, and I find it annoying, 50 | * hence the *if* statement below just to print the value I need. 51 | */ 52 | if (sz == 3 && (int)data[1] == 13 && (int)data[2] == 10) 53 | { 54 | std::cout << data[0] << std::endl; 55 | } 56 | else 57 | { 58 | // To print data from other serial devices 59 | QString str = QString::fromUtf8(data); 60 | std::cout << str.toStdString(); 61 | } 62 | } 63 | 64 | void SerialPortReader::_error_callback(QSerialPort::SerialPortError error) 65 | { 66 | if (error == QSerialPort::ReadError) 67 | { 68 | std::cout << "!!! An I/O error occurred while reading the data from port " << _serial->portName().toStdString() << 69 | ". Error: " << _serial->errorString().toStdString() << std::endl; 70 | QCoreApplication::exit(1); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /qtArduinoSerial/serialportreader.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013-2015 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | class SerialPortReader : public QObject 17 | { 18 | Q_OBJECT 19 | 20 | public: 21 | SerialPortReader(QSerialPort* serial, QObject* parent = 0); 22 | ~SerialPortReader(); 23 | 24 | private slots: 25 | void _read_callback(); 26 | void _error_callback(QSerialPort::SerialPortError error); 27 | 28 | private: 29 | QSerialPort* _serial; 30 | }; 31 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/README.md: -------------------------------------------------------------------------------- 1 | # qtFPSvsTIMEAnimation 2 | 3 | Screenshot -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/fps_anim.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "fps_anim.h" 11 | 12 | #include 13 | 14 | 15 | FrameAnimation::FrameAnimation(QWidget* parent) 16 | : QWidget(parent) 17 | { 18 | _max_fps = 60; 19 | _counter = 0; 20 | 21 | _black_canvas = new FpsCanvas((QFrame*)this); 22 | _blue_canvas = new FpsCanvas((QFrame*)this, Qt::blue); 23 | _red_canvas = new FpsCanvas((QFrame*)this, Qt::red); 24 | 25 | _black_label = new QLabel(this); 26 | _black_label->setText("60 FPS"); 27 | _blue_label = new QLabel(this); 28 | _blue_label->setText("30 FPS"); 29 | _red_label = new QLabel(this); 30 | _red_label->setText("10 FPS"); 31 | 32 | _h_layout = new QGridLayout(this); 33 | _h_layout->addWidget(_black_canvas, 0, 0, 1, 1); 34 | _h_layout->addWidget(_blue_canvas, 0, 1, 1, 1); 35 | _h_layout->addWidget(_red_canvas, 0, 2, 1, 1); 36 | _h_layout->addWidget(_black_label, 3, 0, 1, 1); 37 | _h_layout->addWidget(_blue_label, 3, 1, 1, 1); 38 | _h_layout->addWidget(_red_label, 3, 2, 1, 1); 39 | 40 | _group_box = new QGroupBox(this); 41 | _group_box->setTitle("Frame-based Animation"); 42 | _group_box->setLayout(_h_layout); 43 | 44 | _main_layout = new QVBoxLayout(this); 45 | _main_layout->addWidget(_group_box); 46 | setLayout(_main_layout); 47 | 48 | // Start timer 49 | QTimer::singleShot(1000/_max_fps, this, SLOT(_tick())); 50 | } 51 | 52 | void FrameAnimation::_tick() 53 | { 54 | /* Decide which canvas should be updated */ 55 | 56 | // 30 FPS canvas must be draw once every 2x 57 | if (_counter % 2 == 0) 58 | _blue_canvas->draw(); 59 | 60 | // 10 FPS canvas must be draw once every 6x 61 | if (_counter % 6 == 0) 62 | _red_canvas->draw(); 63 | 64 | _counter++; 65 | _counter = _counter % 60; // Ranges from 0 to 59 66 | 67 | // 60 FPS canvas must be draw every time, so we ignore _counter 68 | _black_canvas->draw(); 69 | 70 | // Reset the timer 71 | QTimer::singleShot(1000/_max_fps, this, SLOT(_tick())); 72 | } 73 | 74 | void FrameAnimation::reset() 75 | { 76 | _black_canvas->reset(); 77 | _blue_canvas->reset(); 78 | _red_canvas->reset(); 79 | } 80 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/fps_anim.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "fps_canvas.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | class FrameAnimation : public QWidget 20 | { 21 | Q_OBJECT 22 | public: 23 | FrameAnimation(QWidget* parent = NULL); 24 | 25 | public slots: 26 | void reset(); 27 | 28 | private slots: 29 | void _tick(); 30 | 31 | private: 32 | QGroupBox* _group_box; 33 | QVBoxLayout* _main_layout; 34 | QGridLayout* _h_layout; 35 | FpsCanvas* _black_canvas, *_blue_canvas, *_red_canvas; 36 | QLabel* _black_label, *_blue_label, *_red_label; 37 | int _max_fps; 38 | int _counter; 39 | }; 40 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/fps_canvas.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "fps_canvas.h" 11 | 12 | #include 13 | #include 14 | 15 | 16 | FpsCanvas::FpsCanvas(QFrame* parent, const QColor color) 17 | : QFrame(parent), _color(color) 18 | { 19 | // Initialize class members 20 | _x = _y = 50; 21 | _dx = 2; 22 | _dy = 1; 23 | _sq_sz = 10; 24 | 25 | // Set size of the canvas 26 | setMinimumSize(175, 175); 27 | } 28 | 29 | void FpsCanvas::paintEvent(QPaintEvent* event) 30 | { 31 | QFrame::paintEvent(event); 32 | 33 | QPainter painter(this); 34 | 35 | // Paint white background 36 | painter.fillRect(0, 0, width(), height(), Qt::white); 37 | 38 | // Paint black frame around the canvas 39 | painter.setPen(Qt::black); 40 | painter.drawRect(0, 0, width()-1, height()-1); 41 | 42 | /* Move square */ 43 | 44 | _x += _dx; 45 | _y += _dy; 46 | 47 | if ( _x <= 0 || (_x >= (width()-1) - _sq_sz) ) 48 | _dx = -_dx; 49 | 50 | if ( _y <= 0 || (_y >= (height()-1) - _sq_sz) ) 51 | _dy = -_dy; 52 | 53 | // Draw square 54 | painter.fillRect(_x, _y, _sq_sz, _sq_sz, _color); 55 | } 56 | 57 | void FpsCanvas::draw() 58 | { 59 | // Trigger paintEvent() 60 | repaint(); 61 | } 62 | 63 | void FpsCanvas::reset() 64 | { 65 | _x = _y = 50; 66 | _dx = 2; 67 | _dy = 1; 68 | } 69 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/fps_canvas.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include 12 | 13 | 14 | class FpsCanvas : public QFrame 15 | { 16 | Q_OBJECT 17 | public: 18 | FpsCanvas(QFrame* parent = NULL, const QColor color = Qt::black); 19 | 20 | void draw(); 21 | void reset(); 22 | 23 | void paintEvent(QPaintEvent* event); 24 | 25 | private: 26 | QColor _color; 27 | int _sq_sz; 28 | int _x, _y; 29 | int _dx, _dy; 30 | }; 31 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/main.cpp: -------------------------------------------------------------------------------- 1 | /* This application is based on the following tutorial by Steven Lambert: 2 | * "Why You Should be Using Time-based Animation and How to Implement it" 3 | * http://blog.sklambert.com/using-time-based-animation-implement/ 4 | */ 5 | #include "fps_anim.h" 6 | #include "time_anim.h" 7 | #include "time_anim_improved.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | int main(int argc, char* argv[]) 16 | { 17 | QApplication app(argc, argv); 18 | 19 | QWidget window; 20 | window.setWindowTitle("Frame-based VS Time-based Animation"); 21 | 22 | QPushButton reset_bt(&window); 23 | reset_bt.setText("Reset"); 24 | 25 | FrameAnimation fps_widget(&window); 26 | QObject::connect(&reset_bt, SIGNAL(clicked()), &fps_widget, SLOT(reset())); 27 | 28 | TimeAnimation time_widget(&window); 29 | QObject::connect(&reset_bt, SIGNAL(clicked()), &time_widget, SLOT(reset())); 30 | 31 | TimeAnimationImproved time_imp_widget(&window); 32 | QObject::connect(&reset_bt, SIGNAL(clicked()), &time_imp_widget, SLOT(reset())); 33 | 34 | QVBoxLayout main_layout(&window); 35 | main_layout.setAlignment(Qt::AlignCenter); 36 | main_layout.addWidget(&reset_bt, 0, Qt::AlignRight); 37 | main_layout.addWidget(&fps_widget); 38 | main_layout.addWidget(&time_widget); 39 | main_layout.addWidget(&time_imp_widget); 40 | 41 | window.setLayout(&main_layout); 42 | window.show(); 43 | 44 | return app.exec(); 45 | } 46 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/qtFPSvsTIMEAnimation.pro: -------------------------------------------------------------------------------- 1 | QT += widgets 2 | 3 | SOURCES += \ 4 | main.cpp \ 5 | time_anim_improved.cpp \ 6 | fps_canvas.cpp \ 7 | fps_anim.cpp \ 8 | time_anim.cpp \ 9 | time_canvas.cpp 10 | 11 | HEADERS += \ 12 | time_anim_improved.h \ 13 | time_anim.h \ 14 | fps_canvas.h \ 15 | fps_anim.h \ 16 | time_canvas.h 17 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qtFPSvsTIMEAnimation/screenshot.gif -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/time_anim.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "time_anim.h" 11 | 12 | #include 13 | 14 | 15 | TimeAnimation::TimeAnimation(QWidget* parent) 16 | : QWidget(parent) 17 | { 18 | _max_fps = 60; 19 | _counter = 0; 20 | _last_time_60fps = _last_time_30fps = _last_time_10fps = QDateTime::currentMSecsSinceEpoch(); 21 | 22 | _black_canvas = new TimeCanvas((QFrame*)this, Qt::black); 23 | _blue_canvas = new TimeCanvas((QFrame*)this, Qt::blue); 24 | _red_canvas = new TimeCanvas((QFrame*)this, Qt::red); 25 | 26 | _black_label = new QLabel(this); 27 | _black_label->setText("60 FPS"); 28 | _blue_label = new QLabel(this); 29 | _blue_label->setText("30 FPS"); 30 | _red_label = new QLabel(this); 31 | _red_label->setText("10 FPS"); 32 | 33 | _h_layout = new QGridLayout(this); 34 | _h_layout->addWidget(_black_canvas, 0, 0, 1, 1); 35 | _h_layout->addWidget(_blue_canvas, 0, 1, 1, 1); 36 | _h_layout->addWidget(_red_canvas, 0, 2, 1, 1); 37 | _h_layout->addWidget(_black_label, 3, 0, 1, 1); 38 | _h_layout->addWidget(_blue_label, 3, 1, 1, 1); 39 | _h_layout->addWidget(_red_label, 3, 2, 1, 1); 40 | 41 | _group_box = new QGroupBox(this); 42 | _group_box->setTitle("Time-based Animation"); 43 | _group_box->setLayout(_h_layout); 44 | 45 | _main_layout = new QVBoxLayout(this); 46 | _main_layout->addWidget(_group_box); 47 | setLayout(_main_layout); 48 | 49 | // Start timer 50 | QTimer::singleShot(1000/_max_fps, this, SLOT(_tick())); 51 | } 52 | 53 | // TODO: study how to remove cur_time_30fps 54 | void TimeAnimation::_tick() 55 | { 56 | /* Decide which canvas should be updated */ 57 | 58 | qint64 now = QDateTime::currentMSecsSinceEpoch(); 59 | 60 | // 30 FPS canvas must be draw once every 2x 61 | if (_counter % 2 == 0) 62 | { 63 | // Compute how much time passed since the last update 64 | qint64 passed = now - _last_time_30fps; 65 | _last_time_30fps = now; 66 | 67 | _blue_canvas->move(passed); 68 | _blue_canvas->draw(); 69 | } 70 | 71 | // 10 FPS canvas must be draw once every 6x 72 | if (_counter % 6 == 0) 73 | { 74 | // Compute how much time passed since the last update 75 | qint64 passed = now - _last_time_10fps; 76 | _last_time_10fps = now; 77 | 78 | _red_canvas->move(passed); 79 | _red_canvas->draw(); 80 | } 81 | 82 | // 60 FPS canvas must be draw every time, so we ignore _counter 83 | { 84 | // Compute how much time passed since the last update 85 | qint64 passed = now - _last_time_60fps; 86 | _last_time_60fps = now; 87 | 88 | _black_canvas->move(passed); 89 | _black_canvas->draw(); 90 | } 91 | 92 | ++_counter; 93 | _counter = _counter % 60; // Ranges from 0 to 59 94 | 95 | // Reset the timer 96 | QTimer::singleShot(1000/_max_fps, this, SLOT(_tick())); 97 | } 98 | 99 | void TimeAnimation::reset() 100 | { 101 | _black_canvas->reset(); 102 | _blue_canvas->reset(); 103 | _red_canvas->reset(); 104 | } 105 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/time_anim.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "time_canvas.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | class TimeAnimation : public QWidget 20 | { 21 | Q_OBJECT 22 | public: 23 | TimeAnimation(QWidget* parent = NULL); 24 | 25 | public slots: 26 | void reset(); 27 | 28 | private slots: 29 | void _tick(); 30 | 31 | private: 32 | QGroupBox* _group_box; 33 | QVBoxLayout* _main_layout; 34 | QGridLayout* _h_layout; 35 | TimeCanvas* _black_canvas, *_blue_canvas, *_red_canvas; 36 | QLabel* _black_label, *_blue_label, *_red_label; 37 | qint64 _last_time_60fps, _last_time_30fps, _last_time_10fps; 38 | int _max_fps; 39 | int _counter; 40 | }; 41 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/time_anim_improved.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "time_anim_improved.h" 11 | 12 | #include 13 | 14 | 15 | TimeAnimationImproved::TimeAnimationImproved(QWidget* parent) 16 | : QWidget(parent) 17 | { 18 | _counter = 0; 19 | _accumulator60 = _accumulator30 = _accumulator10 = 0; 20 | _max_fps = 60; 21 | _constant_dt = 1000 / _max_fps; 22 | _last_time_60fps = _last_time_30fps = _last_time_10fps = QDateTime::currentMSecsSinceEpoch(); 23 | 24 | _black_canvas = new TimeCanvas((QFrame*)this, Qt::black); 25 | _blue_canvas = new TimeCanvas((QFrame*)this, Qt::blue); 26 | _red_canvas = new TimeCanvas((QFrame*)this, Qt::red); 27 | 28 | _black_label = new QLabel(this); 29 | _black_label->setText("60 FPS"); 30 | _blue_label = new QLabel(this); 31 | _blue_label->setText("30 FPS"); 32 | _red_label = new QLabel(this); 33 | _red_label->setText("10 FPS"); 34 | 35 | _h_layout = new QGridLayout(this); 36 | _h_layout->addWidget(_black_canvas, 0, 0, 1, 1); 37 | _h_layout->addWidget(_blue_canvas, 0, 1, 1, 1); 38 | _h_layout->addWidget(_red_canvas, 0, 2, 1, 1); 39 | _h_layout->addWidget(_black_label, 3, 0, 1, 1); 40 | _h_layout->addWidget(_blue_label, 3, 1, 1, 1); 41 | _h_layout->addWidget(_red_label, 3, 2, 1, 1); 42 | 43 | _group_box = new QGroupBox(this); 44 | _group_box->setTitle("Time-based Animation Improved"); 45 | _group_box->setLayout(_h_layout); 46 | 47 | _main_layout = new QVBoxLayout(this); 48 | _main_layout->addWidget(_group_box); 49 | setLayout(_main_layout); 50 | 51 | // Start timer 52 | QTimer::singleShot(1000/_max_fps, this, SLOT(_tick())); 53 | } 54 | 55 | void TimeAnimationImproved::_tick() 56 | { 57 | /* Decide which canvas should be updated */ 58 | 59 | qint64 now = QDateTime::currentMSecsSinceEpoch(); 60 | 61 | // 30 FPS canvas must be draw once every 2x 62 | if (_counter % 2 == 0) 63 | { 64 | // Compute how much time passed since the last update 65 | qint64 passed = now - _last_time_30fps; 66 | 67 | _accumulator30 += passed; 68 | while (_accumulator30 >= _constant_dt) 69 | { 70 | _blue_canvas->move(_constant_dt); 71 | _accumulator30 -= _constant_dt; 72 | } 73 | 74 | _blue_canvas->draw(); 75 | _last_time_30fps = now; 76 | } 77 | 78 | // 10 FPS canvas must be draw once every 6x 79 | if (_counter % 6 == 0) 80 | { 81 | // Compute how much time passed since the last update 82 | qint64 passed = now - _last_time_10fps; 83 | 84 | _accumulator10 += passed; 85 | while (_accumulator10 >= _constant_dt) 86 | { 87 | _red_canvas->move(_constant_dt); 88 | _accumulator10 -= _constant_dt; 89 | } 90 | 91 | _red_canvas->draw(); 92 | _last_time_10fps = now; 93 | } 94 | 95 | // 60 FPS canvas must be draw every time, so we ignore _counter 96 | { 97 | // Compute how much time passed since the last update 98 | qint64 passed = now - _last_time_60fps; 99 | 100 | _accumulator60 += passed; 101 | while (_accumulator60 >= _constant_dt) 102 | { 103 | _black_canvas->move(_constant_dt); 104 | _accumulator60 -= _constant_dt; 105 | } 106 | 107 | _black_canvas->draw(); 108 | _last_time_60fps = now; 109 | } 110 | 111 | _counter++; 112 | _counter = _counter % 60; // Ranges from 0 to 59 113 | 114 | // Reset the timer 115 | QTimer::singleShot(1000/_max_fps, this, SLOT(_tick())); 116 | } 117 | 118 | void TimeAnimationImproved::reset() 119 | { 120 | _black_canvas->reset(); 121 | _blue_canvas->reset(); 122 | _red_canvas->reset(); 123 | } 124 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/time_anim_improved.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include "time_canvas.h" 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | 19 | class TimeAnimationImproved : public QWidget 20 | { 21 | Q_OBJECT 22 | public: 23 | TimeAnimationImproved(QWidget* parent = NULL); 24 | 25 | public slots: 26 | void reset(); 27 | 28 | private slots: 29 | void _tick(); 30 | 31 | private: 32 | QGroupBox* _group_box; 33 | QVBoxLayout* _main_layout; 34 | QGridLayout* _h_layout; 35 | TimeCanvas* _black_canvas, *_blue_canvas, *_red_canvas; 36 | QLabel* _black_label, *_blue_label, *_red_label; 37 | qint64 _last_time_60fps, _last_time_30fps, _last_time_10fps; 38 | qint64 _accumulator60, _accumulator30, _accumulator10; 39 | int _max_fps; 40 | int _counter; 41 | float _constant_dt; 42 | }; 43 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/time_canvas.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "time_canvas.h" 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | 17 | TimeCanvas::TimeCanvas(QFrame* parent, const QColor color) 18 | : QFrame(parent), _color(color) 19 | { 20 | // Initialize class members 21 | _x = _y = 50; 22 | _dx = 2; 23 | _dy = 1; 24 | _sq_sz = 10; 25 | 26 | // Set canvas size 27 | setMinimumSize(175, 175); 28 | } 29 | 30 | void TimeCanvas::move(float dt) 31 | { 32 | /* Update position of square */ 33 | 34 | /* Rounding _dx up/down can affect the horizontal movement of the square. 35 | * Rounding down when _dx is negative is essential to fix the slowness 36 | * that happens when going from right to left. 37 | */ 38 | if (_dx > 0) 39 | _x += std::ceil((_dx * dt * 60) / 1000); // (2 * 16 * 60) / 1000 = 1.92 = 2 40 | else 41 | _x += std::floor((_dx * dt * 60) / 1000); // (-2 * 16 * 60) / 1000 = -1.92 = -2 42 | 43 | /* Rounding _dy up/down can also affect the vertical move of the square. 44 | * If _dy is positive, round up, else the square will move sideways only. 45 | * If _dy is negative, round down, else the square won't go up after colliding. 46 | */ 47 | if (_dy > 0) 48 | _y += std::ceil((_dy * dt * 60) / 1000); // (1 * 16 * 60) / 1000 = 0.96 = 1 49 | else 50 | _y += std::floor((_dy * dt * 60) / 1000); // (-1 * 16 * 60) / 1000 = -0.96 = -1 51 | 52 | if ( _x <= 0 || (_x >= (width()-1) - _sq_sz) ) { 53 | _dx *= -1; 54 | } 55 | 56 | if ( _y <= 0 || (_y >= (height()-1) - _sq_sz) ) { 57 | _dy *= -1; 58 | } 59 | } 60 | 61 | void TimeCanvas::draw() 62 | { 63 | // Trigger paintEvent() 64 | repaint(); 65 | } 66 | 67 | void TimeCanvas::paintEvent(QPaintEvent* event) 68 | { 69 | QFrame::paintEvent(event); 70 | 71 | /* Paint white background */ 72 | 73 | QPainter painter(this); 74 | painter.fillRect(0, 0, width(), height(), Qt::white); 75 | 76 | /* Paint black frame around the canvas */ 77 | 78 | painter.setPen(Qt::black); 79 | painter.drawRect(0, 0, width()-1, height()-1); 80 | 81 | /* Draw square */ 82 | 83 | painter.fillRect(_x, _y, _sq_sz, _sq_sz, _color); 84 | } 85 | 86 | void TimeCanvas::reset() 87 | { 88 | _x = _y = 50; 89 | _dx = 2; 90 | _dy = 1; 91 | } 92 | -------------------------------------------------------------------------------- /qtFPSvsTIMEAnimation/time_canvas.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2014 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | #include 12 | #include 13 | #include 14 | 15 | 16 | class TimeCanvas : public QFrame 17 | { 18 | Q_OBJECT 19 | public: 20 | TimeCanvas(QFrame* parent = NULL, const QColor color = Qt::black); 21 | 22 | void move(float dt); 23 | void draw(); 24 | void reset(); 25 | 26 | void paintEvent(QPaintEvent* event); 27 | 28 | private: 29 | QColor _color; 30 | int _sq_sz; 31 | int _x, _y; 32 | int _dx, _dy; 33 | }; 34 | -------------------------------------------------------------------------------- /qtGLMdemo/README.md: -------------------------------------------------------------------------------- 1 | # qtGLMdemo 2 | 3 | A customized `QGLWidget` that loads a 3D model from the disk using [Nate Robins GLM library](https://user.xmission.com/~nate/tutors.html) and renders it using native OpenGL calls. 4 | 5 | Screenshot 6 | 7 | -------------------------------------------------------------------------------- /qtGLMdemo/data/porsche.mtl: -------------------------------------------------------------------------------- 1 | newmtl black 2 | Ka 0.4000 0.4000 0.4000 3 | Kd 0.0206 0.0202 0.0449 4 | Ks 0.3000 0.3000 0.3000 5 | illum 2 6 | Ns 60.0000 7 | 8 | 9 | newmtl blue 10 | Ka 0.4000 0.4000 0.4000 11 | Kd 0.1434 0.1329 0.7755 12 | Ks 0.3000 0.3000 0.3000 13 | illum 2 14 | Ns 60.0000 15 | 16 | 17 | newmtl glass 18 | Ka 0.4000 0.4000 0.4000 19 | Kd 0.3457 0.4549 0.6367 20 | Ks 0.3000 0.3000 0.3000 21 | illum 2 22 | d 0.8400 23 | Ns 60.0000 24 | 25 | 26 | newmtl white 27 | Ka 0.4000 0.4000 0.4000 28 | Kd 0.8082 0.8082 0.8082 29 | Ks 0.3000 0.3000 0.3000 30 | illum 2 31 | Ns 60.0000 32 | 33 | 34 | newmtl red 35 | Ka 0.4000 0.4000 0.4000 36 | Kd 0.7796 0.0318 0.0318 37 | Ks 0.3000 0.3000 0.3000 38 | illum 2 39 | Ns 60.0000 40 | 41 | 42 | -------------------------------------------------------------------------------- /qtGLMdemo/glwidget.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | /* extern "C" avoids linker errors related to: unresolved external symbol glmUnitize, glmFacetNormals, ... 5 | * GLM by Nate Robins is available at: https://user.xmission.com/~nate/tutors.html 6 | */ 7 | extern "C" { 8 | #include "glm.h" 9 | } 10 | 11 | 12 | class GLWidget : public QGLWidget 13 | { 14 | Q_OBJECT 15 | public: 16 | explicit GLWidget(QWidget* parent = 0); 17 | virtual ~GLWidget(); 18 | 19 | void initializeGL(); 20 | void paintGL(); 21 | void resizeGL( int width, int height); 22 | 23 | void _draw_terrain(); 24 | void _draw_model(); 25 | 26 | void keyPressEvent(QKeyEvent *e); 27 | 28 | private: 29 | int _width, _height; 30 | 31 | GLMmodel* _obj_model; 32 | GLuint _carList; 33 | 34 | int _orbitAngle; 35 | float _cameraPos[3]; 36 | 37 | protected slots: 38 | void _tick(); 39 | }; 40 | -------------------------------------------------------------------------------- /qtGLMdemo/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "glwidget.h" 3 | 4 | int main(int argc, char* argv[]) 5 | { 6 | QApplication app(argc, argv); 7 | 8 | GLWidget gl_widget; 9 | gl_widget.show(); 10 | 11 | return app.exec(); 12 | } 13 | -------------------------------------------------------------------------------- /qtGLMdemo/qtGLMdemo.pro: -------------------------------------------------------------------------------- 1 | QT += widgets opengl 2 | 3 | LIBS += -lopengl32 -lGlU32 4 | 5 | SOURCES += \ 6 | glm.c \ 7 | main.cpp \ 8 | glwidget.cpp 9 | 10 | HEADERS += \ 11 | glm.h \ 12 | glwidget.h 13 | -------------------------------------------------------------------------------- /qtGLMdemo/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qtGLMdemo/screenshot.gif -------------------------------------------------------------------------------- /qtKinectVideo/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2015-2020 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #include "window.h" 11 | #include 12 | 13 | #include 14 | 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | QApplication app(argc, argv); 19 | 20 | Window window; 21 | window.show(); 22 | 23 | return app.exec(); 24 | } 25 | -------------------------------------------------------------------------------- /qtKinectVideo/qtKinectVideo.pro: -------------------------------------------------------------------------------- 1 | # INSTALL 2 | # ------- 3 | # 4 | # 1- Microsoft Visual Studio 2013 Express (for Desktop, online installer) 5 | # https://www.visualstudio.com/downloads/download-visual-studio-vs 6 | # 7 | # 2- Qt 5.5.0 for Windows 32-bit (VS 2013, 633 MB) or later 8 | # http://download.qt.io/official_releases/qt/5.5/5.5.0/qt-opensource-windows-x86-msvc2013-5.5.0.exe 9 | # 10 | # 3- Kinect for Windows SDK v1.8 (222MB) 11 | # https://www.microsoft.com/en-us/download/confirmation.aspx?id=40278 12 | # 13 | # 4- Kinect for Windows Developer Toolkit v1.8 (384MB) 14 | # http://www.microsoft.com/en-us/download/confirmation.aspx?id=40276 15 | # 16 | 17 | QT += core gui widgets 18 | 19 | SOURCES += \ 20 | main.cpp \ 21 | window.cpp 22 | 23 | win32 { 24 | INCLUDEPATH += "C:\\Program Files\\Microsoft SDKs\\Kinect\\v1.8\\inc" 25 | LIBS += "C:\\Program Files\\Microsoft SDKs\\Kinect\\v1.8\\lib\\x86\\Kinect10.lib" 26 | } 27 | 28 | HEADERS += \ 29 | window.h 30 | 31 | -------------------------------------------------------------------------------- /qtKinectVideo/window.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2015-2020 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | */ 10 | #pragma once 11 | 12 | // Kinect for Windows Architecture https://msdn.microsoft.com/en-us/library/jj131023.aspx 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | 23 | class Window : public QMainWindow 24 | { 25 | Q_OBJECT 26 | 27 | public: 28 | Window(); 29 | ~Window(); 30 | 31 | void paintEvent(QPaintEvent* e); 32 | void keyPressEvent(QKeyEvent* event); 33 | 34 | 35 | private slots: 36 | void _tick(); 37 | 38 | private: 39 | bool _initKinect(); 40 | void _draw_video_frame(QPainter& painter); 41 | 42 | int _tick_ms; 43 | Qt::AspectRatioMode _ar_mode; 44 | int _fps; 45 | int _video_width; 46 | int _video_height; 47 | QImage _image; 48 | QTimer* _timer; 49 | 50 | INuiSensor* _nui_sensor; 51 | HANDLE _rgb_stream; //32bit 52 | }; 53 | -------------------------------------------------------------------------------- /qtLinearRegressionGD/README.md: -------------------------------------------------------------------------------- 1 | # qtLinearRegressionGD 2 | 3 | Screenshot -------------------------------------------------------------------------------- /qtLinearRegressionGD/qtLinearRegressionGD.pro: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += "C:\\eigen-3.3.7" 2 | 3 | QT += widgets charts 4 | 5 | SOURCES += \ 6 | main.cpp 7 | 8 | HEADERS += \ 9 | Madplotlib.h 10 | -------------------------------------------------------------------------------- /qtLinearRegressionGD/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qtLinearRegressionGD/screenshot.jpg -------------------------------------------------------------------------------- /qtLogoBlurGL/GLwindow.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2020 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | * 10 | * 11 | * Ingress logo with glowing effect, based on Nehe lesson 36. 12 | */ 13 | #pragma once 14 | 15 | #include 16 | 17 | class GLwindow : public QGLWidget 18 | { 19 | Q_OBJECT 20 | public: 21 | explicit GLwindow(QWidget* parent = 0); 22 | virtual ~GLwindow(); 23 | 24 | /* OpenGL initialization, viewport resizing, and painting */ 25 | 26 | void initializeGL(); 27 | void paintGL(); 28 | void resizeGL( int width, int height); 29 | 30 | /* Helper functions */ 31 | 32 | GLuint _gen_empty_texture(); 33 | void _render_to_texture(); 34 | void _draw_blur(int times, float inc); 35 | 36 | void _view_ortho(); 37 | void _view_perspective(); 38 | 39 | void _draw_ingress_logo(); 40 | void _draw_quad(); 41 | void _draw_triangle(); 42 | 43 | private: 44 | int _width; 45 | int _height; 46 | 47 | GLuint _blur_texture; 48 | 49 | protected slots: 50 | void _tick(); 51 | }; 52 | -------------------------------------------------------------------------------- /qtLogoBlurGL/README.md: -------------------------------------------------------------------------------- 1 | # qtLogoBlurGL 2 | 3 | Screenshot 4 | 5 | -------------------------------------------------------------------------------- /qtLogoBlurGL/main.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2012-2020 Karl Phillip Buhr 2 | * 3 | * This work is licensed under the Creative Commons Attribution-ShareAlike License. 4 | * To view a copy of this license, visit: 5 | * https://creativecommons.org/licenses/by-sa/2.5/legalcode 6 | * 7 | * Or to read the human-readable summary of the license: 8 | * https://creativecommons.org/licenses/by-sa/2.5/ 9 | * 10 | * 11 | * Ingress logo with glowing effect, based on Nehe lesson 36. 12 | */ 13 | #include 14 | #include "GLwindow.h" 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | QApplication app(argc, argv); 19 | 20 | GLwindow gl_win; 21 | gl_win.show(); 22 | 23 | return app.exec(); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /qtLogoBlurGL/qtLogoBlurGL.pro: -------------------------------------------------------------------------------- 1 | QT += core opengl 2 | 3 | contains(QT_VERSION, ^5\\.[0-8]\\..*) { 4 | message("* Using Qt $${QT_VERSION}.") 5 | QT += widgets 6 | 7 | # On my system I have to specify g++ as compiler else it will use clang++ by default 8 | QMAKE_CXX=g++ 9 | QMAKE_CC=gcc 10 | } 11 | 12 | unix { 13 | INCLUDEPATH += /usr/X11/include 14 | } 15 | 16 | LIBS += -lopengl32 17 | 18 | SOURCES += \ 19 | main.cpp \ 20 | GLwindow.cpp 21 | 22 | HEADERS += \ 23 | GLwindow.h 24 | -------------------------------------------------------------------------------- /qtLogoBlurGL/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qtLogoBlurGL/screenshot.jpg -------------------------------------------------------------------------------- /qtSmoothColorTransition/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | *.debug 25 | Makefile* 26 | *.prl 27 | *.app 28 | moc_*.cpp 29 | ui_*.h 30 | qrc_*.cpp 31 | Thumbs.db 32 | *.res 33 | *.rc 34 | /.qmake.cache 35 | /.qmake.stash 36 | 37 | # qtcreator generated files 38 | *.pro.user* 39 | 40 | # xemacs temporary files 41 | *.flc 42 | 43 | # Vim temporary files 44 | .*.swp 45 | 46 | # Visual Studio generated files 47 | *.ib_pdb_index 48 | *.idb 49 | *.ilk 50 | *.pdb 51 | *.sln 52 | *.suo 53 | *.vcproj 54 | *vcproj.*.*.user 55 | *.ncb 56 | *.sdf 57 | *.opensdf 58 | *.vcxproj 59 | *vcxproj.* 60 | 61 | # MinGW generated files 62 | *.Debug 63 | *.Release 64 | 65 | # Python byte code 66 | *.pyc 67 | 68 | # Binaries 69 | # -------- 70 | *.dll 71 | *.exe 72 | 73 | 74 | -------------------------------------------------------------------------------- /qtSmoothColorTransition/README.md: -------------------------------------------------------------------------------- 1 | # qtSmoothColorTransition 2 | 3 | Screenshot 4 | 5 | -------------------------------------------------------------------------------- /qtSmoothColorTransition/heightmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qtSmoothColorTransition/heightmap.jpg -------------------------------------------------------------------------------- /qtSmoothColorTransition/qtSmoothColorTransition.pro: -------------------------------------------------------------------------------- 1 | QT += widgets 2 | 3 | SOURCES += \ 4 | main.cpp 5 | -------------------------------------------------------------------------------- /qtSmoothColorTransition/screenshot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlphillip/GraphicsProgramming/a2c82b95c585f29401e7a9a9c8e280c833855f05/qtSmoothColorTransition/screenshot.jpg --------------------------------------------------------------------------------