├── .clang-format
├── .clang_complete
├── .github
    └── workflows
    │   └── default.yml
├── .gitignore
├── .gitmodules
├── .pre-commit-config.yaml
├── CMakeLists.txt
├── LICENSE
├── README.md
├── cmake
    ├── GitSemver.cmake
    └── StringToSemver.cmake
├── docs
    ├── building-android.md
    └── images
    │   ├── application
    │       ├── articated_application.jpg
    │       ├── articated_application_menu.jpg
    │       ├── articated_application_no_cam.jpg
    │       └── articated_application_test_video.jpg
    │   └── drawn_markers.jpg
├── res
    ├── mipmap-hdpi
    │   └── ic_launcher.png
    ├── mipmap-mdpi
    │   └── ic_launcher.png
    ├── mipmap-xhdpi
    │   └── ic_launcher.png
    ├── mipmap-xxhdpi
    │   └── ic_launcher.png
    └── mipmap-xxxhdpi
    │   └── ic_launcher.png
├── resources
    ├── 3D_models
    │   ├── 3D_models.qrc
    │   ├── articated.obj
    │   ├── nothing.obj
    │   ├── piramid.obj
    │   ├── shuttle.obj
    │   └── teapot.obj
    └── debug_samples
    │   ├── 3_markers_good.webm
    │   ├── debug_samples.qrc
    │   └── textest.png
├── source
    ├── CMakeLists.txt
    ├── augmentation_widget
    │   ├── CMakeLists.txt
    │   ├── augmentation_renderer.cpp
    │   ├── augmentation_renderer.hpp
    │   ├── augmentation_view.cpp
    │   ├── augmentation_view.hpp
    │   ├── model_loader.cpp
    │   ├── model_loader.hpp
    │   └── shaders
    │   │   ├── GL_shaders.qrc
    │   │   ├── background_fs.glsl
    │   │   ├── background_vs.glsl
    │   │   ├── object_fs.glsl
    │   │   └── object_vs.glsl
    ├── main.cpp
    ├── qml
    │   ├── Main.qml
    │   ├── MainView.qml
    │   ├── Settings.qml
    │   ├── SettingsView.qml
    │   └── qml.qrc
    ├── shared
    │   ├── CMakeLists.txt
    │   ├── frame_data.hpp
    │   └── movement3d
    │   │   ├── CMakeLists.txt
    │   │   ├── movement3d.cpp
    │   │   ├── movement3d.hpp
    │   │   ├── movement3d_filter.cpp
    │   │   └── movement3d_filter.hpp
    └── vision
    │   ├── CMakeLists.txt
    │   ├── algorithms
    │       ├── CMakeLists.txt
    │       ├── algorithm_interface.hpp
    │       ├── gpu
    │       │   ├── algorithm_gpu.cpp
    │       │   ├── algorithm_gpu.hpp
    │       │   └── shaders
    │       │   │   ├── blur_fs.glsl
    │       │   │   ├── passthrough_fs.glsl
    │       │   │   ├── passthrough_vs.glsl
    │       │   │   ├── segment_fs.glsl
    │       │   │   └── vision_gpu_shaders.qrc
    │       ├── original
    │       │   ├── algorithm_original.cpp
    │       │   └── algorithm_original.hpp
    │       ├── random
    │       │   ├── algorithm_random.cpp
    │       │   └── algorithm_random.hpp
    │       └── utils
    │       │   ├── classification.cpp
    │       │   ├── classification.hpp
    │       │   ├── frame_helper.cpp
    │       │   ├── frame_helper.hpp
    │       │   ├── image.hpp
    │       │   ├── operators.cpp
    │       │   ├── operators.hpp
    │       │   └── point.hpp
    │   ├── vision.cpp
    │   └── vision.hpp
└── tests
    ├── CMakeLists.txt
    ├── augmentation
        ├── AugmentationTest.qml
        ├── CMakeLists.txt
        ├── augmentation_test.qrc
        ├── main.cpp
        ├── mock_algorithm.cpp
        └── mock_algorithm.hpp
    ├── classification
        ├── CMakeLists.txt
        ├── demo.cpp
        └── test.cpp
    ├── movement3d
        ├── CMakeLists.txt
        └── test.cpp
    ├── movement3d_filter
        ├── CMakeLists.txt
        └── test.cpp
    └── vision
        ├── CMakeLists.txt
        ├── VisionTest.qml
        ├── frame_data_lister.cpp
        ├── frame_data_lister.hpp
        ├── main.cpp
        └── vision_test.qrc
/.clang-format:
--------------------------------------------------------------------------------
  1 | # clang-format
  2 | # Made by: Ingmar Delsink
  3 | # idelsink.com
  4 | # See http://clang.llvm.org/docs/ClangFormatStyleOptions.html
  5 | # Tested with: clang-format version 3.7.1
  6 | 
  7 | # General
  8 | #########
  9 | 
 10 | # The style used for all options not specifically set in the configuration.
 11 | # This option is supported only in the clang-format configuration (both within -style='{...}' and the .clang-format file).
 12 | # Possible values:
 13 | #   LLVM A style complying with the LLVM coding standards
 14 | #   Google A style complying with Google’s C++ style guide
 15 | #   Chromium A style complying with Chromium’s style guide
 16 | #   Mozilla A style complying with Mozilla’s style guide
 17 | #   WebKit A style complying with WebKit’s style guide
 18 | #BasedOnStyle:
 19 | 
 20 | # TabWidth (unsigned)
 21 | # The number of columns used for tab stops.
 22 | TabWidth: 4
 23 | 
 24 | # IndentWidth (unsigned)
 25 | # The number of columns to use for indentation.
 26 | IndentWidth: 4
 27 | 
 28 | # UseTab (UseTabStyle)
 29 | # The way to use tab characters in the resulting file.
 30 | # Possible values:
 31 | #   UT_Never (in configuration: Never) Never use tab.
 32 | #   UT_ForIndentation (in configuration: ForIndentation) Use tabs only for indentation.
 33 | #   UT_Always (in configuration: Always) Use tabs whenever we need to fill whitespace that spans at least from one tab stop to the next one.
 34 | UseTab: Never
 35 | 
 36 | # C++
 37 | #####
 38 | 
 39 | # Language (LanguageKind)
 40 | # Language, this format style is targeted at.
 41 | # Possible values:
 42 | #   LK_None (in configuration: None) Do not use.
 43 | #   LK_Cpp (in configuration: Cpp) Should be used for C, C++, ObjectiveC, ObjectiveC++.
 44 | #   LK_Java (in configuration: Java) Should be used for Java.
 45 | #   LK_JavaScript (in configuration: JavaScript) Should be used for JavaScript.
 46 | #   LK_Proto (in configuration: Proto) Should be used for Protocol Buffers (https://developers.google.com/protocol-buffers/).
 47 | #   LK_TableGen (in configuration: TableGen) Should be used for TableGen code.
 48 | Language: Cpp
 49 | 
 50 | # Standard (LanguageStandard)
 51 | # Format compatible with this standard, e.g. use A > instead of A> for LS_Cpp03.
 52 | # Possible values:
 53 | #   LS_Cpp03 (in configuration: Cpp03) Use C++03-compatible syntax.
 54 | #   LS_Cpp11 (in configuration: Cpp11) Use features of C++11 (e.g. A> instead of A >).
 55 | #   LS_Auto (in configuration: Auto) Automatic detection based on the input.
 56 | Standard: Cpp11
 57 | 
 58 | # Pointer and reference alignment style. Possible values: Left, Right, Middle.
 59 | PointerAlignment: Left
 60 | 
 61 | # AccessModifierOffset (int)
 62 | # The extra indent or outdent of access modifiers, e.g. public:.
 63 | AccessModifierOffset: 0
 64 | 
 65 | # AlignAfterOpenBracket (BracketAlignmentStyle)
 66 | # If true, horizontally aligns arguments after an open bracket.
 67 | # This applies to round brackets (parentheses), angle brackets and square brackets.
 68 | # Possible values:
 69 | #   BAS_Align (in configuration: Align) Align parameters on the open bracket, e.g.:
 70 | #   someLongFunction(argument1,
 71 | #                    argument2);
 72 | #   BAS_DontAlign (in configuration: DontAlign) Don’t align, instead use ContinuationIndentWidth, e.g.:
 73 | #   someLongFunction(argument1,
 74 | #   argument2);
 75 | #   BAS_AlwaysBreak (in configuration: AlwaysBreak) Always break after an open bracket, if the parameters don’t fit on a single line, e.g.:
 76 | #   someLongFunction(
 77 | #       argument1, argument2);
 78 | AlignAfterOpenBracket: false
 79 | 
 80 | # AlignConsecutiveAssignments (bool)
 81 | # If true, aligns consecutive assignments.
 82 | # This will align the assignment operators of consecutive lines. This will result in formattings like
 83 | # int aaaa = 12;
 84 | # int b    = 23;
 85 | # int ccc  = 23;
 86 | AlignConsecutiveAssignments: true
 87 | 
 88 | # AlignEscapedNewlinesLeft (bool)
 89 | # If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column.
 90 | AlignEscapedNewlinesLeft: true
 91 | 
 92 | # AlignOperands (bool)
 93 | # If true, horizontally align operands of binary and ternary expressions.
 94 | # Specifically, this aligns operands of a single expression that needs to be split over multiple lines, e.g.:
 95 | # int aaa = bbbbbbbbbbbbbbb +
 96 | #           ccccccccccccccc;
 97 | AlignOperands: false
 98 | 
 99 | # AlignTrailingComments (bool)
100 | # If true, aligns trailing comments.
101 | AlignTrailingComments: true
102 | 
103 | # AllowAllParametersOfDeclarationOnNextLine (bool)
104 | # Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false.
105 | AllowAllParametersOfDeclarationOnNextLine: false
106 | 
107 | # AllowShortBlocksOnASingleLine (bool)
108 | # Allows contracting simple braced statements to a single line.
109 | AllowShortBlocksOnASingleLine: false
110 | 
111 | # AllowShortCaseLabelsOnASingleLine (bool)
112 | # If true, short case labels will be contracted to a single line.
113 | AllowShortCaseLabelsOnASingleLine: true
114 | 
115 | # AllowShortFunctionsOnASingleLine (ShortFunctionStyle)
116 | # Dependent on the value, int f() { return 0; } can be put on a single line.
117 | # Possible values:
118 | #   SFS_None (in configuration: None) Never merge functions into a single line.
119 | #   SFS_Empty (in configuration: Empty) Only merge empty functions.
120 | #   SFS_Inline (in configuration: Inline) Only merge functions defined inside a class. Implies “empty”.
121 | #   SFS_All (in configuration: All) Merge all functions fitting on a single line.
122 | AllowShortFunctionsOnASingleLine: false
123 | 
124 | # AllowShortIfStatementsOnASingleLine (bool)
125 | # If true, if (a) return; can be put on a single line.
126 | AllowShortIfStatementsOnASingleLine: true
127 | 
128 | # AllowShortLoopsOnASingleLine (bool)
129 | # If true, while (true) continue; can be put on a single line.
130 | AllowShortLoopsOnASingleLine: true
131 | 
132 | # AlwaysBreakBeforeMultilineStrings (bool)
133 | # If true, always break before multiline string literals.
134 | # This flag is mean to make cases where there are multiple multiline strings in a file look more consistent. Thus, it will only take effect if wrapping the string at that point leads to it being indented ContinuationIndentWidth spaces from the start of the line.
135 | AlwaysBreakBeforeMultilineStrings: false
136 | 
137 | # AlwaysBreakTemplateDeclarations (bool)
138 | # If true, always break after the template<...> of a template declaration.
139 | AlwaysBreakTemplateDeclarations: false
140 | 
141 | # BinPackArguments (bool)
142 | # If false, a function call’s arguments will either be all on the same line or will have one line each.
143 | #BinPackArguments: false
144 | 
145 | # BinPackParameters (bool)
146 | # If false, a function declaration’s or function definition’s parameters will either all be on the same line or will have one line each.
147 | BinPackParameters: false
148 | 
149 | # BraceWrapping (BraceWrappingFlags)
150 | # Control of individual brace wrapping cases.
151 | # If BreakBeforeBraces is set to BS_Custom, use this to specify how each individual brace case should be handled. Otherwise, this is ignored.
152 | # Nested configuration flags:
153 | #   bool AfterClass Wrap class definitions.
154 | #   bool AfterControlStatement Wrap control statements (if/for/while/switch/..).
155 | #   bool AfterEnum Wrap enum definitions.
156 | #   bool AfterFunction Wrap function definitions.
157 | #   bool AfterNamespace Wrap namespace definitions.
158 | #   bool AfterObjCDeclaration Wrap ObjC definitions (@autoreleasepool, interfaces, ..).
159 | #   bool AfterStruct Wrap struct definitions.
160 | #   bool AfterUnion Wrap union definitions.
161 | #   bool BeforeCatch Wrap before catch.
162 | #   bool BeforeElse Wrap before else.
163 | #   bool IndentBraces Indent the wrapped braces themselves.
164 | #BraceWrapping:
165 | 
166 | # BreakAfterJavaFieldAnnotations (bool)
167 | # Break after each annotation on a field in Java files.
168 | #BreakAfterJavaFieldAnnotations:
169 | 
170 | # BreakBeforeBinaryOperators (BinaryOperatorStyle)
171 | # The way to wrap binary operators.
172 | # Possible values:
173 | #   BOS_None (in configuration: None) Break after operators.
174 | #   BOS_NonAssignment (in configuration: NonAssignment) Break before operators that aren’t assignments.
175 | #   BOS_All (in configuration: All) Break before operators.
176 | BreakBeforeBinaryOperators: false
177 | 
178 | # BreakBeforeBraces (BraceBreakingStyle)
179 | # The brace breaking style to use.
180 | # Possible values:
181 | #   BS_Attach (in configuration: Attach) Always attach braces to surrounding context.
182 | #   BS_Linux (in configuration: Linux) Like Attach, but break before braces on function, namespace and class definitions.
183 | #   BS_Mozilla (in configuration: Mozilla) Like Attach, but break before braces on enum, function, and record definitions.
184 | #   BS_Stroustrup (in configuration: Stroustrup) Like Attach, but break before function definitions, catch, and else.
185 | #   BS_Allman (in configuration: Allman) Always break before braces.
186 | #   BS_GNU (in configuration: GNU) Always break before braces and add an extra level of indentation to braces of control statements, not to those of class, function or other definitions.
187 | #   BS_WebKit (in configuration: WebKit) Like Attach, but break before functions.
188 | #   BS_Custom (in configuration: Custom) Configure each individual brace in BraceWrapping.
189 | BreakBeforeBraces: Attach
190 | 
191 | # BreakBeforeTernaryOperators (bool)
192 | # If true, ternary operators will be placed after line breaks.
193 | BreakBeforeTernaryOperators: false
194 | 
195 | # BreakConstructorInitializersBeforeComma (bool)
196 | # Always break constructor initializers before commas and align the commas with the colon.
197 | BreakConstructorInitializersBeforeComma: true
198 | 
199 | # BreakStringLiterals (bool)
200 | # Allow breaking string literals when formatting.
201 | #BreakStringLiterals:
202 | 
203 | # ColumnLimit (unsigned)
204 | # The column limit.
205 | # A column limit of 0 means that there is no column limit. In this case, clang-format will respect the input’s line breaking decisions within statements unless they contradict other rules.
206 | ColumnLimit: 80
207 | 
208 | # CommentPragmas (std::string)
209 | # A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed.
210 | CommentPragmas: ''
211 | 
212 | # ConstructorInitializerAllOnOneLineOrOnePerLine (bool)
213 | # If the constructor initializers don’t fit on a line, put each initializer on its own line.
214 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
215 | 
216 | # ConstructorInitializerIndentWidth (unsigned)
217 | # The number of characters to use for indentation of constructor initializer lists.
218 | ConstructorInitializerIndentWidth: 0
219 | 
220 | # ContinuationIndentWidth (unsigned)
221 | # Indent width for line continuations.
222 | ContinuationIndentWidth: 0
223 | 
224 | # Cpp11BracedListStyle (bool)
225 | # If true, format braced lists as best suited for C++11 braced lists.
226 | # Important differences: - No spaces inside the braced list. - No line break before the closing brace. - Indentation with the continuation indent, not with the block indent.
227 | # Fundamentally, C++11 braced lists are formatted exactly like function calls would be formatted in their place. If the braced list follows a name (e.g. a type or variable name), clang-format formats as if the {} were the parentheses of a function call with that name. If there is no name, a zero-length name is assumed.
228 | Cpp11BracedListStyle: false
229 | 
230 | # DerivePointerAlignment (bool)
231 | # If true, analyze the formatted file for the most common alignment of & and \*. PointerAlignment is then used only as fallback.
232 | DerivePointerBinding: false
233 | 
234 | # DisableFormat (bool)
235 | # Disables formatting completely.
236 | #DisableFormat:
237 | 
238 | # ExperimentalAutoDetectBinPacking (bool)
239 | # If true, clang-format detects whether function calls and definitions are formatted with one parameter per line.
240 | # Each call can be bin-packed, one-per-line or inconclusive. If it is inconclusive, e.g. completely on one line, but a decision needs to be made, clang-format analyzes whether there are other bin-packed cases in the input file and act accordingly.
241 | # NOTE: This is an experimental flag, that might go away or be renamed. Do not use this in config files, etc. Use at your own risk.
242 | #ExperimentalAutoDetectBinPacking:
243 | 
244 | # ForEachMacros (std::vector)
245 | # A vector of macros that should be interpreted as foreach loops instead of as function calls.
246 | # These are expected to be macros of the form:
247 | # FOREACH(, ...)
248 | #  
249 | # In the .clang-format configuration file, this can be configured like:
250 | # ForEachMacros: ['RANGES_FOR', 'FOREACH']
251 | # For example: BOOST_FOREACH.
252 | #ForEachMacros:
253 | 
254 | # IncludeCategories (std::vector)
255 | # Regular expressions denoting the different #include categories used for ordering #includes.
256 | # These regular expressions are matched against the filename of an include (including the <> or “”) in order. The value belonging to the first matching regular expression is assigned and #includes are sorted first according to increasing category number and then alphabetically within each category.
257 | # If none of the regular expressions match, INT_MAX is assigned as category. The main header for a source file automatically gets category 0. so that it is generally kept at the beginning of the #includes (http://llvm.org/docs/CodingStandards.html#include-style). However, you can also assign negative priorities if you have certain headers that always need to be first.
258 | # To configure this in the .clang-format file, use:
259 | # IncludeCategories:
260 | #   - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
261 | #     Priority:        2
262 | #   - Regex:           '^(<|"(gtest|isl|json)/)'
263 | #     Priority:        3
264 | #   - Regex:           '.\*'
265 | #     Priority:        1
266 | #IncludeCategories:
267 | 
268 | # IndentCaseLabels (bool)
269 | # Indent case labels one level from the switch statement.
270 | # When false, use the same indentation level as for the switch statement. Switch statement body is always indented one level more than case labels.
271 | IndentCaseLabels: true
272 | 
273 | # IndentFunctionDeclarationAfterType (bool)
274 | # If true, indent when breaking function declarations which are not also definitions after the type.
275 | IndentFunctionDeclarationAfterType: false
276 | 
277 | # IndentWrappedFunctionNames (bool)
278 | # Indent if a function definition or declaration is wrapped after the type.
279 | #IndentWrappedFunctionNames:
280 | 
281 | # KeepEmptyLinesAtTheStartOfBlocks (bool)
282 | # If true, empty lines at the start of blocks are kept.
283 | #KeepEmptyLinesAtTheStartOfBlocks:
284 | 
285 | # MacroBlockBegin (std::string)
286 | # A regular expression matching macros that start a block.
287 | #MacroBlockBegin:
288 | 
289 | # MacroBlockEnd (std::string)
290 | # A regular expression matching macros that end a block.
291 | #MacroBlockEnd:
292 | 
293 | # MaxEmptyLinesToKeep (unsigned)
294 | # The maximum number of consecutive empty lines to keep.
295 | MaxEmptyLinesToKeep: 2
296 | 
297 | # NamespaceIndentation (NamespaceIndentationKind)
298 | # The indentation used for namespaces.
299 | # Possible values:
300 | #   NI_None (in configuration: None) Don’t indent in namespaces.
301 | #   NI_Inner (in configuration: Inner) Indent only in inner namespaces (nested in other namespaces).
302 | #   NI_All (in configuration: All) Indent in all namespaces.
303 | NamespaceIndentation: None
304 | 
305 | # ObjCBlockIndentWidth (unsigned)
306 | # The number of characters to use for indentation of ObjC blocks.
307 | #ObjCBlockIndentWidth:
308 | 
309 | # ObjCSpaceAfterProperty (bool)
310 | # Add a space after @property in Objective-C, i.e. use @property (readonly) instead of @property(readonly).
311 | ObjCSpaceAfterProperty: true
312 | 
313 | # ObjCSpaceBeforeProtocolList (bool)
314 | # Add a space in front of an Objective-C protocol list, i.e. use Foo  instead of Foo.
315 | ObjCSpaceBeforeProtocolList: true
316 | 
317 | # PenaltyBreakBeforeFirstCallParameter (unsigned)
318 | # The penalty for breaking a function call after call(.
319 | PenaltyBreakBeforeFirstCallParameter: 100
320 | 
321 | # PenaltyBreakComment (unsigned)
322 | # The penalty for each line break introduced inside a comment.
323 | PenaltyBreakComment: 100
324 | 
325 | # PenaltyBreakFirstLessLess (unsigned)
326 | # The penalty for breaking before the first <<.
327 | PenaltyBreakFirstLessLess: 0
328 | 
329 | # PenaltyBreakString (unsigned)
330 | # The penalty for each line break introduced inside a string literal.
331 | PenaltyBreakString: 100
332 | 
333 | # PenaltyExcessCharacter (unsigned)
334 | # The penalty for each character outside of the column limit.
335 | PenaltyExcessCharacter: 1
336 | 
337 | # PenaltyReturnTypeOnItsOwnLine (unsigned)
338 | # Penalty for putting the return type of a function onto its own line.
339 | PenaltyReturnTypeOnItsOwnLine: 20
340 | 
341 | # PointerAlignment (PointerAlignmentStyle)
342 | # Pointer and reference alignment style.
343 | # Possible values:
344 | #   PAS_Left (in configuration: Left) Align pointer to the left.
345 | #   PAS_Right (in configuration: Right) Align pointer to the right.
346 | #   PAS_Middle (in configuration: Middle) Align pointer in the middle.
347 | #PointerAlignment:
348 | 
349 | # ReflowComments (bool)
350 | # If true, clang-format will attempt to re-flow comments.
351 | #ReflowComments: true (from v3.9)
352 | 
353 | # SortIncludes (bool)
354 | # If true, clang-format will sort #includes.
355 | #SortIncludes: false (from v3.9)
356 | 
357 | # SpaceAfterCStyleCast (bool)
358 | # If true, a space may be inserted after C style casts.
359 | SpaceAfterCStyleCast: false
360 | 
361 | # SpaceBeforeAssignmentOperators (bool)
362 | # If false, spaces will be removed before assignment operators.
363 | SpaceBeforeAssignmentOperators: true
364 | 
365 | # SpaceBeforeParens (SpaceBeforeParensOptions)
366 | # Defines in which cases to put a space before opening parentheses.
367 | # Possible values:
368 | #   SBPO_Never (in configuration: Never) Never put a space before opening parentheses.
369 | #   SBPO_ControlStatements (in configuration: ControlStatements) Put a space before opening parentheses only after control statement keywords (for/if/while...).
370 | #   SBPO_Always (in configuration: Always) Always put a space before opening parentheses, except when it’s prohibited by the syntax rules (in function-like macro definitions) or when determined by other style rules (after unary operators, opening parentheses, etc.)
371 | SpaceBeforeParens: Always
372 | 
373 | # SpaceInEmptyParentheses (bool)
374 | # If true, spaces may be inserted into ().
375 | SpaceInEmptyParentheses: false
376 | 
377 | # SpacesBeforeTrailingComments (unsigned)
378 | # The number of spaces before trailing line comments (// - comments).
379 | # This does not affect trailing block comments (/* - comments) as those commonly have different usage patterns and a number of special cases.
380 | SpacesBeforeTrailingComments: 1
381 | 
382 | # SpacesInAngles (bool)
383 | # If true, spaces will be inserted after < and before > in template argument lists.
384 | SpacesInAngles: false
385 | 
386 | # SpacesInCStyleCastParentheses (bool)
387 | # If true, spaces may be inserted into C style casts.
388 | SpacesInCStyleCastParentheses: false
389 | 
390 | # SpacesInContainerLiterals (bool)
391 | # If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals).
392 | SpacesInContainerLiterals: false
393 | 
394 | # SpacesInParentheses (bool)
395 | # If true, spaces will be inserted after ( and before ).
396 | SpacesInParentheses: false
397 | 
398 | # SpacesInSquareBrackets (bool)
399 | # If true, spaces will be inserted after [ and before ].
400 | SpacesInSquareBrackets: false
401 | 
--------------------------------------------------------------------------------
/.clang_complete:
--------------------------------------------------------------------------------
1 | -Isource
2 | 
--------------------------------------------------------------------------------
/.github/workflows/default.yml:
--------------------------------------------------------------------------------
 1 | name: Articated CI
 2 | 
 3 | on: [ push ]
 4 | 
 5 | jobs:
 6 |   lint:
 7 |     runs-on: ubuntu-latest
 8 |     container:
 9 |       image: ghcr.io/derpicated/articated-ci-qt6:latest
10 |     steps:
11 |       - uses: actions/checkout@v3
12 | 
13 |       - name: Run pre-commit
14 |         run: pre-commit run --all-files
15 | 
16 |       - uses: actions/cache@v3
17 |         with:
18 |           path: ~/.cache/pre-commit
19 |           key: pre-commit|${{ hashFiles('.pre-commit-config.yaml') }}
20 | 
21 |   build:
22 |     needs: [ lint ]
23 |     runs-on: ubuntu-latest
24 |     container:
25 |       image: ghcr.io/derpicated/articated-ci-qt6:latest
26 |     steps:
27 |       - uses: actions/checkout@v3
28 | 
29 |       - name: Checkout submodules
30 |         run: git submodule update --init --recursive
31 | 
32 |       - name: Create build dir
33 |         run: mkdir ./build
34 | 
35 |       - name: Configure
36 |         working-directory: ./build
37 |         run: cmake .. -DCMAKE_BUILD_TYPE=Debug -DTESTS=ON
38 | 
39 |       - name: Make
40 |         working-directory: ./build
41 |         run: make
42 | 
43 |       - name: Test
44 |         working-directory: ./build
45 |         run: make check
46 | 
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
  1 | ### C++ ###
  2 | # Prerequisites
  3 | *.d
  4 | 
  5 | # Compiled Object files
  6 | *.slo
  7 | *.lo
  8 | *.o
  9 | *.obj
 10 | 
 11 | # Precompiled Headers
 12 | *.gch
 13 | *.pch
 14 | 
 15 | # Compiled Dynamic libraries
 16 | *.so
 17 | *.dylib
 18 | *.dll
 19 | 
 20 | # Fortran module files
 21 | *.mod
 22 | *.smod
 23 | 
 24 | # Compiled Static libraries
 25 | *.lai
 26 | *.la
 27 | *.a
 28 | *.lib
 29 | 
 30 | # Executables
 31 | *.exe
 32 | *.out
 33 | *.app
 34 | 
 35 | 
 36 | ### OpenCV ###
 37 | #OpenCV for Mac and Linux
 38 | #build and release folders
 39 | */CMakeFiles
 40 | */CMakeCache.txt
 41 | */Makefile
 42 | */cmake_install.cmake
 43 | .DS_Store
 44 | 
 45 | 
 46 | ### Qt ###
 47 | # C++ objects and libs
 48 | 
 49 | *.slo
 50 | *.lo
 51 | *.o
 52 | *.a
 53 | *.la
 54 | *.lai
 55 | *.so
 56 | *.dll
 57 | *.dylib
 58 | 
 59 | # Qt-es
 60 | 
 61 | /.qmake.cache
 62 | /.qmake.stash
 63 | *.pro.user
 64 | *.pro.user.*
 65 | *.qbs.user
 66 | *.qbs.user.*
 67 | *.moc
 68 | *_automoc.cpp
 69 | *_automoc.cxx
 70 | moc_*.cpp
 71 | moc_*.cxx
 72 | moc_*.cxx_parameters
 73 | qrc_*.cpp
 74 | ui_*.h
 75 | Makefile*
 76 | *build-*
 77 | 
 78 | # QtCreator
 79 | 
 80 | *.autosave
 81 | 
 82 | # QtCtreator Qml
 83 | *.qmlproject.user
 84 | *.qmlproject.user.*
 85 | 
 86 | # QtCtreator CMake
 87 | CMakeLists.txt.user*
 88 | 
 89 | 
 90 | ### CMake ###
 91 | CMakeCache.txt
 92 | CMakeFiles
 93 | CMakeScripts
 94 | Makefile
 95 | cmake_install.cmake
 96 | install_manifest.txt
 97 | CTestTestfile.cmake
 98 | 
 99 | ### CLion ###
100 | .idea
101 | 
102 | # File-based project format
103 | *.iws
104 | 
105 | # IntelliJ
106 | out/
107 | 
108 | # Crashlytics plugin (for Android Studio and IntelliJ)
109 | com_crashlytics_export_strings.xml
110 | crashlytics.properties
111 | crashlytics-build.properties
112 | fabric.properties
113 | 
114 | ### output folders ###
115 | # Build
116 | cmake-build-*/
117 | build/*
118 | docs/build*
119 | build_*
120 | 
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "qt-android-cmake"]
2 | 	path = qt-android-cmake
3 | 	url = https://github.com/derpicated/qt-android-cmake.git
4 | 
--------------------------------------------------------------------------------
/.pre-commit-config.yaml:
--------------------------------------------------------------------------------
 1 | repos:
 2 | 
 3 |   - repo: https://github.com/pre-commit/pre-commit-hooks
 4 |     rev: v3.4.0
 5 |     hooks:
 6 |       - id: check-merge-conflict
 7 |       - id: check-added-large-files
 8 |       - id: check-merge-conflict
 9 |       - id: trailing-whitespace
10 | 
11 |   - repo: https://github.com/igorshubovych/markdownlint-cli
12 |     rev: v0.26.0
13 |     hooks:
14 |       - id: markdownlint
15 | 
16 | # - repo: https://github.com/cheshirekow/cmake-format-precommit
17 | #   rev: v0.6.13
18 | #   hooks:
19 | #   - id: cmake-lint
20 | 
21 | # - repo: https://github.com/pocc/pre-commit-hooks
22 | #   rev: v1.1.1
23 | #   hooks:
24 | #   - id: clang-tidy
25 | #   - id: cppcheck
26 | 
27 | # - repo: https://github.com/bmorcos/pre-commit-hooks-cpp
28 | #   rev: 9a5aa38207bf557961110d6a4f7e3a9d352911f9
29 | #   hooks:
30 | #   - id: cpplint
31 | 
32 | #- repo: https://github.com/Mercotui/pre-commit-qmllint
33 | #  rev: v1.0.0
34 | #  hooks:
35 | #  - id: qmllint
36 | 
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | cmake_minimum_required(VERSION 3.11)
 2 | 
 3 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING
 4 |   "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel.")
 5 | set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
 6 |   Debug Release RelWithDebInfo MinSizeRel)
 7 | 
 8 | # options
 9 | option(ANDROID "switch to android build" OFF)
10 | option(DISABLE_ARTICATED_TESTS "Disable the ARticated unittests" OFF)
11 | 
12 | if(ANDROID)
13 |   set(ANDROID_NATIVE_API_LEVEL "27" CACHE STRING
14 |     "Choose the Android NDK Native APIs version to use.")
15 | else(ANDROID)
16 | endif(ANDROID)
17 | 
18 | project(articated_app)
19 | include(cmake/GitSemver.cmake)
20 | include_directories(source)
21 | add_subdirectory(source)
22 | 
23 | if(NOT DISABLE_ARTICATED_TESTS)
24 |     enable_testing()
25 | 
26 |     include(FetchContent)
27 |     FetchContent_Declare(
28 |         googletest
29 |         GIT_REPOSITORY https://github.com/google/googletest.git
30 |         GIT_TAG main
31 |     )
32 |     FetchContent_GetProperties(googletest)
33 |     if(NOT googletest_POPULATED)
34 |         message("Downloading googletest")
35 |         FetchContent_Populate(googletest)
36 |         add_subdirectory(${googletest_SOURCE_DIR} ${googletest_BINARY_DIR})
37 |         include_directories(${googletest_SOURCE_DIR}/include ${googletest_SOURCE_DIR})
38 |     endif()
39 | 
40 |     add_subdirectory(tests)
41 |     add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --force-new-ctest-process --output-on-failure)
42 | endif(NOT DISABLE_ARTICATED_TESTS)
43 | 
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2016 Derpicated
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
 1 | # ARticated
 2 | 
 3 | [](./LICENSE)
 4 | 
 5 | 
 6 | An augmented reality application.
 7 | 
 8 | 
 9 | 
10 | This augmented reality application uses ONLY camera images and
11 | some fancy math to track markers across 3D space.
12 | It then draws virtual 3D objects as if they were part of reality.
13 | 
14 | ## Developers
15 | 
16 | This application was developed as an educational project for two
17 | Embedded Systems Engineering students, for their minor in Embedded Vision.
18 | All vision processing, 2D to 3D transformation maths,
19 | and rendering code has been written from scratch by:
20 | 
21 | - [Ingmar Delsink](https://github.com/idelsink)
22 | - [Menno van der Graaf](https://github.com/Mercotui)
23 | 
24 | ## Usage
25 | 
26 | Open the application, whether it be on desktop or an android phone,
27 | and point the camera so that at least 3 markers are clearly in view.
28 | Press the largest button to set the current position as reference.
29 | Now you can move the camera around, keeping at least 3 markers in view.
30 | 
31 | ## Markers
32 | 
33 | The application needs to track at least 3 unique markers to calculate
34 | the camera movement, although more can be used.
35 | 
36 | These markers are loosely defined groups of black dots on a white background.
37 | The markers are identified by their dot count, so these have to be unique.
38 | A minimum of 2 and a maximum of 9 dots are required for a marker to be valid.
39 | 
40 | See below, the markers can be drawn by hand.
41 | This configuration features marker #3, #4, and #5.
42 | Make sure to leave plenty of white-space between each marker,
43 | so they don't merge together.
44 | 
45 | 
46 | 
47 | ## Dependencies
48 | 
49 | To build ARticated, you need the following:
50 | 
51 | - Qt 5.14
52 | - OpenGL 4.1
53 | 
54 | ### On Fedora
55 | 
56 | Install the following libraries on Fedora:
57 | 
58 | ```sh
59 | dnf install \
60 |   qt5-qtbase-devel \
61 |   qt5-qtbase-gui \
62 |   qt5-qtquickcontrols2-devel \
63 |   qt5-qtmultimedia-devel
64 | 
65 | ```
66 | 
67 | ## Building
68 | 
69 | Also see [Building For Android](docs/building-android.md).
70 | 
71 | When building this application for desktop, pass the following CMake variables:
72 | 
73 | | Variable           | Type | Description                   |
74 | |:-------------------|:-----|:------------------------------|
75 | | Qt5_DIR (Optional) | PATH | Path to the Qt CMake directory|
76 | 
77 | ### Example
78 | 
79 | ```sh
80 | mkdir build && cd build
81 | 
82 | cmake .. -DQt5_DIR=/home/user/Qt/5.7/gcc_64/lib/cmake/Qt5
83 | 
84 | make
85 | ```
86 | 
87 | ## License
88 | 
89 | > You can check out the full license [here](./LICENSE)
90 | 
91 | This project is licensed under the terms of the **MIT** license.
92 | 
--------------------------------------------------------------------------------
/cmake/GitSemver.cmake:
--------------------------------------------------------------------------------
 1 | # Get the Semantic Versioning from git using CMake
 2 | #
 3 | # The idea was "taken" from:
 4 | #   The stlink project (github.com/texane/stlink)
 5 | #   See: https://github.com/texane/stlink/blob/master/LICENSE
 6 | #
 7 | # The following use cases work:
 8 | #  - Dirty (sources changed)
 9 | #  - No tags in repo (git hash is used)
10 | #  - Tags as: v1.0.0, 1.0.0
11 | 
12 | include(${CMAKE_CURRENT_LIST_DIR}/StringToSemver.cmake)
13 | 
14 | # Find the git program
15 | function(find_git)
16 |     find_program(git
17 |         NAMES
18 |             "git" # Linux, Windows
19 |     )
20 |     if(NOT git)
21 |         message(WARNING "Could not find the git executable")
22 |     endif()
23 | endfunction()
24 | 
25 | # Arguments:
26 | #  MAJOR: Variable name for the major version return value
27 | #  MINOR: Variable name for the minor version return value
28 | #  PATCH: Variable name for the patch version return value
29 | #  STRING: Variable name for the string version return value
30 | #  PATH: Path where the git command is executed
31 | function(git_semver)
32 |     set(options)
33 |     set(oneValueArgs MAJOR MINOR PATCH STRING PATH)
34 |     set(multiValueArgs)
35 |     cmake_parse_arguments(git_semver "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
36 | 
37 |     if(NOT git_semver_MAJOR)
38 |         message(WARNING "No MAJOR variable specified")
39 |         set(git_semver_MAJOR "__major")
40 |     endif()
41 |     if(NOT git_semver_MINOR)
42 |         message(WARNING "No MINOR variable specified")
43 |         set(git_semver_MINOR "__minor")
44 |     endif()
45 |     if(NOT git_semver_PATCH)
46 |         message(WARNING "No PATCH variable specified")
47 |         set(git_semver_PATCH "__patch")
48 |     endif()
49 |     if(NOT git_semver_STRING)
50 |         message(WARNING "No STRING variable specified")
51 |         set(git_semver_STRING "__string")
52 |     endif()
53 |     if(NOT git_semver_PATH)
54 |         message(WARNING "No PATH variable specified; Using CMAKE_CURRENT_LIST_DIR: (${CMAKE_CURRENT_LIST_DIR})")
55 |         set(git_semver_PATH "${CMAKE_CURRENT_LIST_DIR}")
56 |     endif()
57 | 
58 |     # Set default values for variables
59 |     set(${git_semver_MAJOR} "0")
60 |     set(${git_semver_MINOR} "0")
61 |     set(${git_semver_PATCH} "0")
62 |     set(${git_semver_STRING} "")
63 | 
64 |     find_git()
65 |     if(git)
66 |         # Check if HEAD is pointing to a tag
67 |         execute_process (
68 |             COMMAND             "${git}" describe --tags --always
69 |             WORKING_DIRECTORY   "${git_semver_PATH}"
70 |             OUTPUT_VARIABLE     "${git_semver_STRING}"
71 |             OUTPUT_STRIP_TRAILING_WHITESPACE)
72 |         # If the sources have been changed locally, add -dirty to the version.
73 |         execute_process (
74 |             COMMAND             "${git}" diff --quiet
75 |             WORKING_DIRECTORY   "${git_semver_PATH}"
76 |             RESULT_VARIABLE     res)
77 | 
78 |         if (res EQUAL 1)
79 |             set (${git_semver_STRING} "${${git_semver_STRING}}-dirty")
80 |         endif()
81 | 
82 |         semver(${${git_semver_STRING}} ${git_semver_MAJOR} ${git_semver_MINOR} ${git_semver_PATCH})
83 |     endif()
84 | 
85 |     # Apply variables to parent scope
86 |     set(${git_semver_MAJOR} ${${git_semver_MAJOR}} PARENT_SCOPE)
87 |     set(${git_semver_MINOR} ${${git_semver_MINOR}} PARENT_SCOPE)
88 |     set(${git_semver_PATCH} ${${git_semver_PATCH}} PARENT_SCOPE)
89 |     set(${git_semver_STRING} ${${git_semver_STRING}} PARENT_SCOPE)
90 | endfunction()
91 | 
--------------------------------------------------------------------------------
/cmake/StringToSemver.cmake:
--------------------------------------------------------------------------------
 1 | # Get the Semantic Version from a string in to form of:
 2 | #  - x1.2.3
 3 | #  - 1.2.3
 4 | #
 5 | 
 6 | # v_string_: The string where the version needs to be extracted
 7 | # v_major_: Variable name for the major version
 8 | # v_minor_: Variable name for the minor version
 9 | # v_patch_: Variable name for the patch version
10 | function(semver v_string_ v_major_ v_minor_ v_patch_)
11 |     # Set default values for variables
12 |     set(${v_major_} "0")
13 |     set(${v_minor_} "0")
14 |     set(${v_patch_} "0")
15 | 
16 |     # Get major, minor and patch versions
17 |     string(
18 |         REGEX REPLACE
19 |         "(0|[1-9][0-9]*)[.](0|[1-9][0-9]*)[.](0|[1-9][0-9]*)(-[.0-9A-Za-z-]+)?([+][.0-9A-Za-z-]+)?$"
20 |         "\\1;\\2;\\3"
21 |         match_version_list_
22 |         ${v_string_}
23 |     )
24 |     list(LENGTH match_version_list_ len)
25 |     if(len EQUAL 3)
26 |         list(GET match_version_list_ 0 ${v_major_})
27 |         list(GET match_version_list_ 1 ${v_minor_})
28 |         list(GET match_version_list_ 2 ${v_patch_})
29 |     endif()
30 |     # Drop character(s) before the version number of major
31 |     string(
32 |         REGEX REPLACE
33 |         "^[^[1-9]]*([1-9]+)"
34 |         "\\1;"
35 |         match_version_list_
36 |         ${${v_major_}}
37 |     )
38 |     list(GET match_version_list_ 0 ${v_major_})
39 | 
40 |     # Apply variables to parent scope
41 |     set(${v_major_} ${${v_major_}} PARENT_SCOPE)
42 |     set(${v_minor_} ${${v_minor_}} PARENT_SCOPE)
43 |     set(${v_patch_} ${${v_patch_}} PARENT_SCOPE)
44 |     set(${v_string_} ${${v_string_}} PARENT_SCOPE)
45 | endfunction()
46 | 
--------------------------------------------------------------------------------
/docs/building-android.md:
--------------------------------------------------------------------------------
 1 | # Building For Android
 2 | 
 3 | Building for android is currently untested and potentially problematic.
 4 | 
 5 | ## Dependencies
 6 | 
 7 | - Qt 5.14
 8 | - OpenGL-ES 3.0
 9 | - Android SDK + NDK
10 | 
11 | ## Building
12 | 
13 | When building this application for Android, pass the following CMake variables:
14 | 
15 | | Variable            | Type   | Description                     |
16 | |:--------------------|:-------|:--------------------------------|
17 | | Qt5_DIR             | PATH   | Path to the Qt CMake directory. |
18 | | QT_ANDROID_SDK_ROOT | PATH   | Path to the Android SDK root    |
19 | | ANDROID_NDK         | PATH   | Path to the Android NDK root    |
20 | | JAVA_HOME           | PATH   | Path to the Java root           |
21 | | ANDROID             | ON/OFF | Build for Android               |
22 | 
23 | ### Example
24 | 
25 | ```sh
26 | mkdir build-android && cd build-android
27 | 
28 | cmake .. \
29 | -DCMAKE_TOOLCHAIN_FILE=Sdk/ndk-bundle/build/cmake/android.toolchain.cmake \
30 | -DANDROID=ON \
31 | -DQt5_DIR=/home/user/Qt/5.14.1/android_armv7/lib/cmake/Qt5 \
32 | -DQT_ANDROID_SDK_ROOT=Sdk \
33 | -DANDROID_NDK=Sdk/ndk-bundle \
34 | -DJAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk
35 | 
36 | make
37 | ```
38 | 
39 | ## Extra note
40 | 
41 | When switching targets, make sure to delete the old build files. So an
42 | `rm -rf ./` on the build directory would suffice. Or for convenience, two build
43 | folders can be made, one for android and one for desktop. This way switching to
44 | a different target is a mere switching of directories.
45 | 
--------------------------------------------------------------------------------
/docs/images/application/articated_application.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/docs/images/application/articated_application.jpg
--------------------------------------------------------------------------------
/docs/images/application/articated_application_menu.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/docs/images/application/articated_application_menu.jpg
--------------------------------------------------------------------------------
/docs/images/application/articated_application_no_cam.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/docs/images/application/articated_application_no_cam.jpg
--------------------------------------------------------------------------------
/docs/images/application/articated_application_test_video.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/docs/images/application/articated_application_test_video.jpg
--------------------------------------------------------------------------------
/docs/images/drawn_markers.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/docs/images/drawn_markers.jpg
--------------------------------------------------------------------------------
/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/resources/3D_models/3D_models.qrc:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 |     articated.obj
 4 |     piramid.obj
 5 |     shuttle.obj
 6 |     teapot.obj
 7 |     nothing.obj
 8 | 
 9 | 
10 | 
--------------------------------------------------------------------------------
/resources/3D_models/articated.obj:
--------------------------------------------------------------------------------
  1 | # Blender v2.78 (sub 0) OBJ File: ''
  2 | # www.blender.org
  3 | mtllib articated.mtl
  4 | o articated_logo
  5 | v 1.769644 0.393449 -2.617397
  6 | v 1.706920 -0.002659 -2.157976
  7 | v 1.709536 0.392630 -2.156931
  8 | v 1.767029 -0.001840 -2.618441
  9 | v 0.881922 0.395250 -1.075888
 10 | v 1.247401 -0.001727 -1.360032
 11 | v 0.879306 -0.000039 -1.076932
 12 | v 1.250017 0.393563 -1.358987
 13 | v 1.708530 0.395070 -3.077727
 14 | v 1.705915 -0.000220 -3.078772
 15 | v 1.532300 0.392669 -1.727712
 16 | v 1.529685 -0.002621 -1.728756
 17 | v -0.471431 0.412811 -4.333142
 18 | v -0.902867 0.019888 -4.156003
 19 | v -0.474046 0.017522 -4.334186
 20 | v -0.900252 0.415178 -4.154959
 21 | v 0.878558 0.403413 -4.156932
 22 | v 0.446733 0.011432 -4.335208
 23 | v 0.875942 0.008123 -4.157977
 24 | v 0.449349 0.406721 -4.334164
 25 | v 1.530358 0.397382 -3.506554
 26 | v 1.527742 0.002092 -3.507598
 27 | v -1.730481 0.022508 -3.074959
 28 | v -1.787974 0.416979 -2.613450
 29 | v -1.790590 0.021689 -2.614494
 30 | v -1.727866 0.417798 -3.073915
 31 | v 1.247270 0.400228 -3.874650
 32 | v 1.244654 0.004938 -3.875694
 33 | v -1.551303 0.017757 -1.725338
 34 | v -1.265599 0.410201 -1.356197
 35 | v -1.268215 0.014911 -1.357241
 36 | v -1.548688 0.413046 -1.724293
 37 | v -1.726860 0.415358 -2.153119
 38 | v -1.729475 0.020069 -2.154163
 39 | v -0.013723 0.014637 -4.395309
 40 | v -0.011107 0.409927 -4.394265
 41 | v -1.553246 0.022469 -3.504179
 42 | v -1.550630 0.417759 -3.503135
 43 | v -1.270962 0.021576 -3.872903
 44 | v -1.268346 0.416866 -3.871859
 45 | v -0.899503 0.011726 -1.074959
 46 | v -0.896888 0.407015 -1.073914
 47 | v 0.847570 0.003633 -2.387222
 48 | v 0.761568 0.398942 -2.171567
 49 | v 0.758952 0.003652 -2.172612
 50 | v 0.850185 0.398922 -2.386177
 51 | v 0.616437 0.007431 -3.246081
 52 | v 0.760597 0.401298 -3.060988
 53 | v 0.757981 0.006008 -3.062033
 54 | v 0.619052 0.402721 -3.245037
 55 | v 0.620426 0.399388 -1.987205
 56 | v 0.617810 0.004099 -1.988250
 57 | v 0.433763 0.004943 -1.846700
 58 | v 0.436378 0.400232 -1.845656
 59 | v -0.453026 0.406115 -1.844669
 60 | v -0.639998 0.012418 -1.986854
 61 | v -0.455642 0.010825 -1.845713
 62 | v -0.637382 0.407708 -1.985810
 63 | v -0.779897 0.411487 -3.059279
 64 | v -0.871131 0.016216 -2.845714
 65 | v -0.868515 0.411506 -2.844669
 66 | v -0.782513 0.016197 -3.060324
 67 | v -0.868013 0.410286 -2.384271
 68 | v -0.781542 0.013841 -2.170903
 69 | v -0.778926 0.409130 -2.169858
 70 | v -0.870628 0.014997 -2.385315
 71 | v -0.898570 0.411097 -2.614437
 72 | v -0.901185 0.015807 -2.615481
 73 | v -0.638756 0.411040 -3.243641
 74 | v -0.641371 0.015750 -3.244685
 75 | v -0.457324 0.014906 -3.386235
 76 | v -0.454708 0.410196 -3.385191
 77 | v -0.242913 0.013723 -3.475327
 78 | v -0.240298 0.409013 -3.474283
 79 | v -0.010136 0.407571 -3.504845
 80 | v 0.217476 0.010678 -3.475838
 81 | v -0.012752 0.012281 -3.505889
 82 | v 0.220092 0.405968 -3.474793
 83 | v 0.849683 0.400142 -2.846576
 84 | v 0.847067 0.004852 -2.847620
 85 | v 0.432081 0.009024 -3.387222
 86 | v 0.434696 0.404314 -3.386178
 87 | v 0.880240 0.399332 -2.616410
 88 | v 0.877624 0.004042 -2.617455
 89 | v -4.096736 0.024871 1.956527
 90 | v -3.915947 0.417849 2.386397
 91 | v -3.918563 0.022560 2.385353
 92 | v -4.094121 0.420161 1.957572
 93 | v -3.267512 0.419981 -0.044268
 94 | v -3.638222 0.026379 0.237787
 95 | v -3.270127 0.024691 -0.045313
 96 | v -3.635606 0.421668 0.238832
 97 | v -3.632860 0.415004 2.754494
 98 | v -3.635475 0.019714 2.753449
 99 | v -3.266763 0.016528 3.035732
100 | v -3.264147 0.411818 3.036776
101 | v -1.485338 0.400053 3.034803
102 | v -1.119859 0.003076 2.750659
103 | v -1.487954 0.004763 3.033758
104 | v -1.117244 0.398366 2.751703
105 | v -0.834960 0.397472 2.382979
106 | v -0.837575 0.002182 2.381935
107 | v -2.837554 0.013220 3.212963
108 | v -2.834938 0.408510 3.214007
109 | v -2.374483 0.405304 3.274109
110 | v -1.916774 0.007130 3.211941
111 | v -2.377099 0.010014 3.273065
112 | v -1.914159 0.402420 3.212986
113 | v -3.920506 0.027272 0.606511
114 | v -4.095126 0.422601 1.036775
115 | v -4.097741 0.027311 1.035731
116 | v -3.917890 0.422562 0.607555
117 | v -4.157850 0.026492 1.496196
118 | v -4.155234 0.421782 1.497241
119 | v -0.657724 0.397433 1.953759
120 | v -0.660340 0.002144 1.952715
121 | v -0.597616 0.398252 1.493294
122 | v -0.600231 0.002962 1.492249
123 | v -1.119991 0.405030 0.236041
124 | v -1.491318 0.012926 -0.047286
125 | v -1.122606 0.009741 0.234996
126 | v -1.488702 0.408216 -0.046242
127 | v -0.839518 0.006895 0.603093
128 | v -0.836902 0.402185 0.604137
129 | v -0.658730 0.399873 1.032963
130 | v -0.661345 0.004583 1.031918
131 | v -3.235273 0.415089 1.726419
132 | v -3.148802 0.018643 1.939788
133 | v -3.146187 0.413933 1.940832
134 | v -3.237888 0.019799 1.725375
135 | v -2.375454 0.407661 2.384688
136 | v -2.608297 0.013974 2.353593
137 | v -2.378069 0.012371 2.383644
138 | v -2.605682 0.409263 2.354637
139 | v -1.608308 0.008455 1.938079
140 | v -1.746834 0.404191 2.123485
141 | v -1.749450 0.008902 2.122441
142 | v -1.605692 0.403744 1.939123
143 | v -1.519690 0.008435 1.723469
144 | v -1.517075 0.403725 1.724513
145 | v -1.932564 0.409116 0.724513
146 | v -1.750823 0.012234 0.864610
147 | v -1.935179 0.013827 0.723468
148 | v -1.748208 0.407524 0.865654
149 | v -1.489636 0.008845 1.493236
150 | v -1.487020 0.404135 1.494280
151 | v -1.930882 0.405035 2.265035
152 | v -2.147907 0.010929 2.353082
153 | v -1.933497 0.009745 2.263991
154 | v -2.145292 0.406218 2.354126
155 | v -2.820286 0.410918 2.266022
156 | v -3.007258 0.017221 2.123836
157 | v -2.822902 0.015628 2.264977
158 | v -3.004642 0.412510 2.124881
159 | v -1.520193 0.009655 1.263071
160 | v -1.517577 0.404945 1.264115
161 | v -3.265830 0.415899 1.496254
162 | v -3.268445 0.020610 1.495210
163 | v -3.006016 0.415843 0.867049
164 | v -3.149773 0.021000 1.050367
165 | v -3.147158 0.416290 1.051411
166 | v -3.008631 0.020553 0.866005
167 | v -1.609279 0.010811 1.048658
168 | v -1.606663 0.406101 1.049702
169 | v -3.238391 0.021019 1.264977
170 | v -3.235775 0.416309 1.266021
171 | v -2.824584 0.019709 0.724455
172 | v -2.821969 0.414999 0.725500
173 | v 1.921523 0.383626 0.720237
174 | v 0.014750 3.560277 0.131638
175 | v 2.367066 0.378644 1.490005
176 | v 1.475980 0.388608 -0.049531
177 | v -0.009165 0.405214 -2.615424
178 | v 0.881922 0.395250 -1.075888
179 | v 0.436378 0.400232 -1.845656
180 | v -1.932564 0.409116 0.724513
181 | v -2.376425 0.410017 1.495267
182 | v -1.488702 0.408216 -0.046242
183 | v -0.896888 0.407015 -1.073914
184 | v -0.453026 0.406115 -1.844669
185 | v 1.477662 0.384526 1.490991
186 | v 0.588257 0.390409 1.491978
187 | v -0.597616 0.398252 1.493294
188 | v -1.487020 0.404135 1.494280
189 | v 4.082146 -0.026790 1.026656
190 | v 4.083151 -0.029229 1.947452
191 | v 4.143260 -0.028411 1.486987
192 | v 3.905916 -0.029191 2.376672
193 | v 3.903974 -0.024478 0.597830
194 | v 3.623632 -0.028297 2.745396
195 | v 3.620886 -0.021632 0.229734
196 | v 3.255538 -0.026609 3.028496
197 | v 3.252173 -0.018447 -0.052549
198 | v 3.253856 -0.022528 1.487973
199 | v 3.223299 -0.021718 1.257808
200 | v 2.822964 -0.015138 -0.229780
201 | v 3.134212 -0.020562 1.043395
202 | v 2.992668 -0.019139 0.859347
203 | v 2.808312 -0.017546 0.718206
204 | v 2.362509 -0.011933 -0.289882
205 | v 2.593708 -0.015892 0.629590
206 | v 2.363480 -0.014289 0.599539
207 | v 2.133318 -0.012847 0.630101
208 | v 1.902185 -0.009049 -0.228758
209 | v 1.918908 -0.011664 0.719192
210 | v 1.473364 -0.006682 -0.050575
211 | v 3.223801 -0.022938 1.718206
212 | v 2.826717 -0.024243 3.206679
213 | v 3.135184 -0.022918 1.932816
214 | v 2.994042 -0.022471 2.117178
215 | v 2.809994 -0.021628 2.258728
216 | v 2.366393 -0.021358 3.267802
217 | v 2.595584 -0.020444 2.347819
218 | v 2.365422 -0.019002 2.378381
219 | v 1.905937 -0.018153 3.207700
220 | v 2.135194 -0.017399 2.348330
221 | v 1.920590 -0.015745 2.259715
222 | v 1.736234 -0.014152 2.118573
223 | v 1.476728 -0.014845 3.030469
224 | v 1.594689 -0.012730 1.934525
225 | v 1.505603 -0.011574 1.720112
226 | v 1.475046 -0.010763 1.489947
227 | v 1.108016 -0.011659 2.748187
228 | v 0.585642 -0.004881 1.490934
229 | v 0.824928 -0.008813 2.380090
230 | v 0.646756 -0.006501 1.951265
231 | v 3.258153 0.368680 3.029540
232 | v 3.226417 0.372352 1.719250
233 | v 3.256471 0.372762 1.489018
234 | v 2.829332 0.371047 3.207723
235 | v 3.137799 0.372372 1.933860
236 | v 2.996657 0.372818 2.118222
237 | v 2.812610 0.373662 2.259772
238 | v 2.369009 0.373931 3.268847
239 | v 2.598199 0.374846 2.348864
240 | v 2.368038 0.376288 2.379426
241 | v 1.908553 0.377137 3.208745
242 | v 2.137810 0.377890 2.349375
243 | v 1.923205 0.379545 2.260759
244 | v 1.738849 0.381137 2.119618
245 | v 1.479344 0.380445 3.031513
246 | v 1.597305 0.382560 1.935570
247 | v 1.508219 0.383716 1.721157
248 | v 1.477662 0.384526 1.490991
249 | v 1.110632 0.383631 2.749231
250 | v 0.588257 0.390409 1.491978
251 | v 0.827544 0.386476 2.381135
252 | v 0.649371 0.388788 1.952309
253 | v 4.085767 0.366060 1.948496
254 | v 4.084762 0.368500 1.027700
255 | v 4.145876 0.366879 1.488031
256 | v 3.908532 0.366099 2.377716
257 | v 3.906590 0.370812 0.598875
258 | v 3.626248 0.366993 2.746440
259 | v 3.623501 0.373657 0.230778
260 | v 3.254789 0.376843 -0.051504
261 | v 3.225914 0.373572 1.258852
262 | v 2.825580 0.380151 -0.228736
263 | v 3.136828 0.374728 1.044440
264 | v 2.995284 0.376151 0.860391
265 | v 2.810928 0.377744 0.719250
266 | v 2.365124 0.383357 -0.288837
267 | v 2.596323 0.379398 0.630634
268 | v 2.366095 0.381000 0.600584
269 | v 2.135934 0.382443 0.631145
270 | v 1.904801 0.386241 -0.227714
271 | v 1.921523 0.383626 0.720237
272 | v 1.475980 0.388608 -0.049531
273 | usemtl Mat_3_-1
274 | s 1
275 | f 1 2 3
276 | f 2 1 4
277 | f 5 6 7
278 | f 6 5 8
279 | f 9 4 1
280 | f 4 9 10
281 | f 11 6 8
282 | f 6 11 12
283 | f 3 12 11
284 | f 12 3 2
285 | f 13 14 15
286 | f 14 13 16
287 | f 17 18 19
288 | f 18 17 20
289 | f 21 10 9
290 | f 10 21 22
291 | f 23 24 25
292 | f 24 23 26
293 | f 27 19 28
294 | f 19 27 17
295 | f 29 30 31
296 | f 30 29 32
297 | f 25 33 34
298 | f 33 25 24
299 | f 20 35 18
300 | f 35 20 36
301 | f 37 26 23
302 | f 26 37 38
303 | f 27 22 21
304 | f 22 27 28
305 | f 16 39 14
306 | f 39 16 40
307 | f 39 38 37
308 | f 38 39 40
309 | f 30 41 31
310 | f 41 30 42
311 | f 36 15 35
312 | f 15 36 13
313 | f 34 32 29
314 | f 32 34 33
315 | f 43 44 45
316 | f 44 43 46
317 | f 47 48 49
318 | f 48 47 50
319 | f 45 51 52
320 | f 51 45 44
321 | f 51 53 52
322 | f 53 51 54
323 | f 55 56 57
324 | f 56 55 58
325 | f 59 60 61
326 | f 60 59 62
327 | f 63 64 65
328 | f 64 63 66
329 | f 67 66 63
330 | f 66 67 68
331 | f 61 68 67
332 | f 68 61 60
333 | f 69 62 59
334 | f 62 69 70
335 | f 69 71 70
336 | f 71 69 72
337 | f 72 73 71
338 | f 73 72 74
339 | f 75 76 77
340 | f 76 75 78
341 | f 49 79 80
342 | f 79 49 48
343 | f 65 56 58
344 | f 56 65 64
345 | f 74 77 73
346 | f 77 74 75
347 | f 78 81 76
348 | f 81 78 82
349 | f 82 47 81
350 | f 47 82 50
351 | f 80 83 84
352 | f 83 80 79
353 | f 84 46 43
354 | f 46 84 83
355 | f 53 5 7
356 | f 5 53 54
357 | f 55 41 42
358 | f 41 55 57
359 | f 10 2 4
360 | f 2 10 22
361 | f 2 22 12
362 | f 12 22 6
363 | f 6 22 28
364 | f 6 28 7
365 | f 7 28 84
366 | f 84 28 19
367 | f 84 19 80
368 | f 80 19 18
369 | f 80 18 49
370 | f 49 18 47
371 | f 47 18 81
372 | f 81 18 35
373 | f 81 35 76
374 | f 76 35 77
375 | f 77 35 73
376 | f 73 35 15
377 | f 73 15 71
378 | f 71 15 70
379 | f 70 15 14
380 | f 70 14 62
381 | f 62 14 60
382 | f 60 14 68
383 | f 68 14 39
384 | f 68 39 31
385 | f 31 39 29
386 | f 29 39 37
387 | f 29 37 23
388 | f 29 23 34
389 | f 34 23 25
390 | f 56 41 57
391 | f 41 56 64
392 | f 41 64 66
393 | f 41 66 68
394 | f 41 68 31
395 | f 7 52 53
396 | f 52 7 45
397 | f 45 7 43
398 | f 43 7 84
399 | f 5 46 83
400 | f 46 5 44
401 | f 44 5 51
402 | f 51 5 54
403 | f 42 58 55
404 | f 58 42 65
405 | f 65 42 63
406 | f 63 42 67
407 | f 67 42 30
408 | f 3 9 1
409 | f 9 3 21
410 | f 21 3 11
411 | f 21 11 8
412 | f 21 8 27
413 | f 27 8 5
414 | f 27 5 83
415 | f 27 83 17
416 | f 17 83 79
417 | f 17 79 20
418 | f 20 79 48
419 | f 20 48 50
420 | f 20 50 82
421 | f 20 82 36
422 | f 36 82 78
423 | f 36 78 75
424 | f 36 75 74
425 | f 36 74 13
426 | f 13 74 72
427 | f 13 72 69
428 | f 13 69 16
429 | f 16 69 59
430 | f 16 59 61
431 | f 16 61 67
432 | f 16 67 40
433 | f 40 67 30
434 | f 40 30 32
435 | f 40 32 38
436 | f 38 32 26
437 | f 26 32 33
438 | f 26 33 24
439 | usemtl Mat_1_-1
440 | f 85 86 87
441 | f 86 85 88
442 | f 89 90 91
443 | f 90 89 92
444 | f 87 93 94
445 | f 93 87 86
446 | f 93 95 94
447 | f 95 93 96
448 | f 97 98 99
449 | f 98 97 100
450 | f 101 98 100
451 | f 98 101 102
452 | f 96 103 95
453 | f 103 96 104
454 | f 105 106 107
455 | f 106 105 108
456 | f 104 107 103
457 | f 107 104 105
458 | f 109 110 111
459 | f 110 109 112
460 | f 113 88 85
461 | f 88 113 114
462 | f 115 102 101
463 | f 102 115 116
464 | f 117 116 115
465 | f 116 117 118
466 | f 108 99 106
467 | f 99 108 97
468 | f 90 112 109
469 | f 112 90 92
470 | f 111 114 113
471 | f 114 111 110
472 | f 119 120 121
473 | f 120 119 122
474 | f 119 123 124
475 | f 123 119 121
476 | f 125 118 117
477 | f 118 125 126
478 | f 124 126 125
479 | f 126 124 123
480 | f 127 128 129
481 | f 128 127 130
482 | f 131 132 133
483 | f 132 131 134
484 | f 135 136 137
485 | f 136 135 138
486 | f 139 138 135
487 | f 138 139 140
488 | f 141 142 143
489 | f 142 141 144
490 | f 145 140 139
491 | f 140 145 146
492 | f 147 148 149
493 | f 148 147 150
494 | f 151 152 153
495 | f 152 151 154
496 | f 129 152 154
497 | f 152 129 128
498 | f 155 146 145
499 | f 146 155 156
500 | f 136 149 137
501 | f 149 136 147
502 | f 157 130 127
503 | f 130 157 158
504 | f 150 133 148
505 | f 133 150 131
506 | f 159 160 161
507 | f 160 159 162
508 | f 163 156 155
509 | f 156 163 164
510 | f 134 153 132
511 | f 153 134 151
512 | f 142 164 163
513 | f 164 142 144
514 | f 161 165 166
515 | f 165 161 160
516 | f 159 167 162
517 | f 167 159 168
518 | f 166 158 157
519 | f 158 166 165
520 | f 120 141 143
521 | f 141 120 122
522 | f 115 146 117
523 | f 146 115 101
524 | f 146 101 100
525 | f 146 100 97
526 | f 146 97 140
527 | f 140 97 108
528 | f 140 108 138
529 | f 138 108 136
530 | f 136 108 147
531 | f 147 108 105
532 | f 147 105 150
533 | f 150 105 131
534 | f 131 105 134
535 | f 134 105 104
536 | f 134 104 151
537 | f 151 104 154
538 | f 154 104 96
539 | f 154 96 129
540 | f 129 96 127
541 | f 127 96 157
542 | f 157 96 93
543 | f 159 89 168
544 | f 89 159 161
545 | f 89 161 166
546 | f 89 166 157
547 | f 89 157 92
548 | f 92 157 93
549 | f 92 93 86
550 | f 92 86 112
551 | f 112 86 88
552 | f 112 88 110
553 | f 110 88 114
554 | f 89 167 168
555 | f 167 89 91
556 | f 126 116 118
557 | f 116 126 123
558 | f 116 123 102
559 | f 102 123 121
560 | f 102 121 98
561 | f 98 121 120
562 | f 98 120 145
563 | f 145 120 155
564 | f 155 120 163
565 | f 163 120 142
566 | f 142 120 143
567 | f 91 162 167
568 | f 162 91 160
569 | f 160 91 165
570 | f 165 91 158
571 | f 158 91 90
572 | f 158 90 94
573 | f 94 90 87
574 | f 87 90 109
575 | f 87 109 85
576 | f 85 109 111
577 | f 85 111 113
578 | f 145 99 98
579 | f 99 145 139
580 | f 99 139 106
581 | f 106 139 135
582 | f 106 135 137
583 | f 106 137 149
584 | f 106 149 107
585 | f 107 149 148
586 | f 107 148 133
587 | f 107 133 132
588 | f 107 132 103
589 | f 103 132 153
590 | f 103 153 152
591 | f 103 152 95
592 | f 95 152 128
593 | f 95 128 130
594 | f 95 130 158
595 | f 95 158 94
596 | f 146 125 117
597 | f 125 146 124
598 | f 124 146 119
599 | f 119 146 122
600 | f 122 146 156
601 | f 122 156 164
602 | f 122 164 144
603 | f 122 144 141
604 | usemtl Mat_4_-1
605 | f 185 186 187
606 | f 186 185 188
607 | f 188 185 189
608 | f 188 189 190
609 | f 190 189 191
610 | f 190 191 192
611 | f 192 191 193
612 | f 192 193 194
613 | f 194 193 195
614 | f 195 193 196
615 | f 195 196 197
616 | f 197 196 198
617 | f 198 196 199
618 | f 199 196 200
619 | f 199 200 201
620 | f 201 200 202
621 | f 202 200 203
622 | f 203 200 204
623 | f 203 204 205
624 | f 205 204 206
625 | f 192 207 208
626 | f 207 192 194
627 | f 208 207 209
628 | f 208 209 210
629 | f 208 210 211
630 | f 208 211 212
631 | f 212 211 213
632 | f 212 213 214
633 | f 212 214 215
634 | f 215 214 216
635 | f 215 216 217
636 | f 215 217 218
637 | f 215 218 219
638 | f 219 218 220
639 | f 219 220 221
640 | f 219 221 222
641 | f 219 222 223
642 | f 223 222 224
643 | f 223 224 225
644 | f 225 224 226
645 | f 227 228 229
646 | f 228 227 230
647 | f 228 230 231
648 | f 231 230 232
649 | f 232 230 233
650 | f 233 230 234
651 | f 233 234 235
652 | f 235 234 236
653 | f 236 234 237
654 | f 236 237 238
655 | f 238 237 239
656 | f 239 237 240
657 | f 240 237 241
658 | f 240 241 242
659 | f 242 241 243
660 | f 243 241 244
661 | f 244 241 245
662 | f 244 245 246
663 | f 246 245 247
664 | f 246 247 248
665 | f 249 250 251
666 | f 250 249 252
667 | f 250 252 253
668 | f 253 252 254
669 | f 253 254 255
670 | f 255 254 227
671 | f 255 227 256
672 | f 256 227 229
673 | f 256 229 257
674 | f 256 257 258
675 | f 258 257 259
676 | f 258 259 260
677 | f 258 260 261
678 | f 258 261 262
679 | f 262 261 263
680 | f 262 263 264
681 | f 262 264 265
682 | f 262 265 266
683 | f 266 265 267
684 | f 266 267 268
685 | f 244 224 222
686 | f 224 244 246
687 | f 267 203 205
688 | f 203 267 265
689 | f 238 217 216
690 | f 217 238 239
691 | f 232 211 210
692 | f 211 232 233
693 | f 195 229 194
694 | f 229 195 257
695 | f 265 202 203
696 | f 202 265 264
697 | f 198 259 197
698 | f 259 198 260
699 | f 197 257 195
700 | f 257 197 259
701 | f 244 221 243
702 | f 221 244 222
703 | f 261 198 199
704 | f 198 261 260
705 | f 207 231 209
706 | f 231 207 228
707 | f 235 214 213
708 | f 214 235 236
709 | f 194 228 207
710 | f 228 194 229
711 | f 236 216 214
712 | f 216 236 238
713 | f 209 232 210
714 | f 232 209 231
715 | f 243 220 242
716 | f 220 243 221
717 | f 263 199 201
718 | f 199 263 261
719 | f 233 213 211
720 | f 213 233 235
721 | f 239 218 217
722 | f 218 239 240
723 | f 264 201 202
724 | f 201 264 263
725 | f 242 218 240
726 | f 218 242 220
727 | f 206 267 205
728 | f 267 206 268
729 | f 249 188 252
730 | f 188 249 186
731 | f 230 192 208
732 | f 192 230 227
733 | f 237 212 215
734 | f 212 237 234
735 | f 225 245 223
736 | f 245 225 247
737 | f 226 247 225
738 | f 247 226 248
739 | f 258 200 196
740 | f 200 258 262
741 | f 266 206 204
742 | f 206 266 268
743 | f 255 189 253
744 | f 189 255 191
745 | f 253 185 250
746 | f 185 253 189
747 | f 252 190 254
748 | f 190 252 188
749 | f 224 248 226
750 | f 248 224 246
751 | f 245 219 223
752 | f 219 245 241
753 | f 241 215 219
754 | f 215 241 237
755 | f 250 187 251
756 | f 187 250 185
757 | f 234 208 212
758 | f 208 234 230
759 | f 251 186 249
760 | f 186 251 187
761 | f 256 196 193
762 | f 196 256 258
763 | f 255 193 191
764 | f 193 255 256
765 | f 227 190 192
766 | f 190 227 254
767 | f 262 204 200
768 | f 204 262 266
769 | usemtl Mat_2_-1
770 | f 169 170 171
771 | f 170 169 172
772 | f 170 172 173
773 | f 173 172 174
774 | f 173 174 175
775 | f 170 176 177
776 | f 176 170 178
777 | f 178 170 173
778 | f 178 173 179
779 | f 179 173 180
780 | f 170 181 171
781 | f 181 170 182
782 | f 182 170 183
783 | f 183 170 184
784 | f 184 170 177
785 | 
--------------------------------------------------------------------------------
/resources/3D_models/nothing.obj:
--------------------------------------------------------------------------------
1 | # its nothing
2 | 
--------------------------------------------------------------------------------
/resources/3D_models/piramid.obj:
--------------------------------------------------------------------------------
 1 | # Blender v2.78 (sub 0) OBJ File: ''
 2 | # www.blender.org
 3 | mtllib piramid.mtl
 4 | o piramid
 5 | v -1.000000 -0.000000 1.000000
 6 | v -1.000000 -0.000000 -1.000000
 7 | v 1.000000 0.000000 -1.000000
 8 | v 1.000000 0.000000 1.000000
 9 | v -0.000000 1.200000 0.000000
10 | vn -0.0000 0.5773 0.8165
11 | vn 0.8165 0.5773 0.0000
12 | vn -0.8165 0.5773 -0.0000
13 | vn 0.0000 -1.0000 0.0000
14 | vn 0.0000 0.5773 -0.8165
15 | usemtl red
16 | s 1
17 | f 1//1 4//1 5//1
18 | usemtl green
19 | f 4//2 3//2 5//2
20 | usemtl yellow
21 | f 2//3 1//3 5//3
22 | usemtl cyan
23 | f 1//4 2//4 3//4 4//4
24 | usemtl blue
25 | f 3//5 2//5 5//5
26 | 
--------------------------------------------------------------------------------
/resources/debug_samples/3_markers_good.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/resources/debug_samples/3_markers_good.webm
--------------------------------------------------------------------------------
/resources/debug_samples/debug_samples.qrc:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |     3_markers_good.webm
4 |     textest.png
5 | 
6 | 
7 | 
--------------------------------------------------------------------------------
/resources/debug_samples/textest.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/derpicated/articated/7a0175c2678ff88ede2854ee4292bb8c0bc5f473/resources/debug_samples/textest.png
--------------------------------------------------------------------------------
/source/CMakeLists.txt:
--------------------------------------------------------------------------------
  1 | #cmake_minimum_required(VERSION 2.8.11)
  2 | set(CMAKE_VERBOSE_MAKEFILE OFF)
  3 | 
  4 | ################################################################################
  5 | # C++ Options
  6 | ################################################################################
  7 | set(CMAKE_CXX_STANDARD 17)
  8 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
  9 | set(CMAKE_CXX_EXTENSIONS OFF)
 10 | add_compile_options(-Wall -Wextra -Wpedantic)
 11 | 
 12 | ################################################################################
 13 | # Qt library
 14 | ################################################################################
 15 | set(CMAKE_AUTOMOC ON)
 16 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
 17 | find_package(Qt6 REQUIRED COMPONENTS Core)
 18 | 
 19 | ################################################################################
 20 | # ARticated app
 21 | ################################################################################
 22 | add_subdirectory(augmentation_widget)
 23 | add_subdirectory(shared)
 24 | add_subdirectory(vision)
 25 | 
 26 | qt_add_resources(articated_app_rcc
 27 |     ${CMAKE_SOURCE_DIR}/source/qml/qml.qrc
 28 |     ${CMAKE_SOURCE_DIR}/resources/debug_samples/debug_samples.qrc)
 29 | 
 30 | 
 31 | set(articated_app_SOURCES   main.cpp)
 32 | include_directories(AFTER SYSTEM src ${CMAKE_BINARY_DIR})
 33 | 
 34 | if(ANDROID)
 35 |     add_library(articated_app SHARED ${articated_app_SOURCES} ${articated_app_HEADERS} ${articated_app_rcc} ${articated_app_qml} ${3D_models_rcc})
 36 | else()
 37 |     add_executable(articated_app ${articated_app_SOURCES} ${articated_app_HEADERS} ${articated_app_rcc} ${articated_app_qml} ${3D_models_rcc})
 38 | endif()
 39 | target_link_libraries(articated_app vision frame_data augmentation)
 40 | 
 41 | # Get git version
 42 | git_semver(
 43 |     MAJOR VERSION_MAJOR
 44 |     MINOR VERSION_MINOR
 45 |     PATCH VERSION_PATCH
 46 |     STRING VERSION_STRING
 47 |     PATH "${CMAKE_CURRENT_LIST_DIR}"
 48 | )
 49 | # Set version as a property to the ARticated target
 50 | set_target_properties(articated_app PROPERTIES VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")
 51 | 
 52 | if(ANDROID)
 53 |     # Used by the qt-android-cmake project
 54 |     set( ANDROID_PLATFORM_LEVEL ${ANDROID_NATIVE_API_LEVEL})
 55 |     # Using the LLVM from the latest Android SDK (NDK v19)
 56 |     # This is used in the qt-android-cmake project
 57 |     set( ANDROID_USE_LLVM TRUE)
 58 | 
 59 |     # The STL lib to use
 60 |     set(ANDROID_STL_SHARED_LIBRARIES "c++_shared")
 61 | 
 62 |     include(../qt-android-cmake/AddQtAndroidApk.cmake)
 63 | 
 64 |     # Define the app
 65 |     add_qt_android_apk(
 66 |         articated_apk
 67 |         articated_app
 68 |         NAME "ARticated"
 69 |         # VERSION_CODE is single number
 70 |         # Concatenate the version to single number
 71 |         # E.g.
 72 |         # 1.0.0 => 100
 73 |         # 10.25.1 => 10251
 74 |         VERSION_CODE "${VERSION_MAJOR}${VERSION_MINOR}${VERSION_PATCH}"
 75 |         PACKAGE_NAME "org.derpicated.articated"
 76 |     )
 77 | endif()
 78 | 
 79 | # copy over resource folder
 80 | add_custom_command(
 81 |         TARGET articated_app PRE_BUILD
 82 |         COMMAND ${CMAKE_COMMAND} -E copy_directory
 83 |                 ${CMAKE_SOURCE_DIR}/res
 84 |                 ${CMAKE_CURRENT_BINARY_DIR}/package/res)
 85 | 
 86 | if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/package/AndroidManifest.xml")
 87 |     # read manifest
 88 |     file(READ ${CMAKE_CURRENT_BINARY_DIR}/package/AndroidManifest.xml ANDROID_MANIFEST_TMP)
 89 |     # add icon
 90 |     STRING(REGEX REPLACE
 91 |             "\n :GLESv3>)
21 | target_include_directories(augmentation PUBLIC ${INCLUDE_DIR})
22 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/augmentation_renderer.cpp:
--------------------------------------------------------------------------------
  1 | // augmentation_renderer.cpp
  2 | 
  3 | #include "augmentation_renderer.hpp"
  4 | 
  5 | #ifdef ANDROID
  6 | #include 
  7 | #endif
  8 | 
  9 | #include 
 10 | #include 
 11 | #include 
 12 | #include 
 13 | 
 14 | Q_LOGGING_CATEGORY (augmentationRendererLog, "augmentation.renderer", QtInfoMsg)
 15 | 
 16 | AugmentationRenderer::AugmentationRenderer (QObject* parent)
 17 | : QObject (parent)
 18 | , window_ (nullptr)
 19 | , transform_ ()
 20 | , is_grayscale_ (0)
 21 | , vertex_count_ (0) {
 22 |     Q_INIT_RESOURCE (GL_shaders);
 23 | }
 24 | 
 25 | AugmentationRenderer::~AugmentationRenderer () {
 26 |     glDeleteBuffers (1, &object_vbo_);
 27 |     glDeleteVertexArrays (1, &object_vao_);
 28 |     Q_CLEANUP_RESOURCE (GL_shaders);
 29 | }
 30 | 
 31 | void AugmentationRenderer::SetObject (const QString& path) {
 32 |     if (is_initialized_) {
 33 |         if (path != object_path_) {
 34 |             object_path_ = path;
 35 |             if (LoadObject (object_path_)) {
 36 |                 qCDebug (augmentationRendererLog, "Loaded model from: %s",
 37 |                 path.toLocal8Bit ().data ());
 38 |             } else {
 39 |                 qCWarning (augmentationRendererLog,
 40 |                 "Failed to load model from: %s", path.toLocal8Bit ().data ());
 41 |             }
 42 |         }
 43 |     }
 44 | }
 45 | 
 46 | bool AugmentationRenderer::LoadObject (const QString& path) {
 47 |     window_->beginExternalCommands ();
 48 |     bool status = false;
 49 | 
 50 |     // extract model from resources into filesystem and parse it
 51 |     QString resource_path = ":/3D_models/" + path;
 52 |     QFile resource_file (resource_path);
 53 |     if (resource_file.exists ()) {
 54 |         auto temp_file  = QTemporaryFile::createNativeFile (resource_file);
 55 |         QString fs_path = temp_file->fileName ();
 56 | 
 57 |         if (!fs_path.isEmpty ()) {
 58 |             std::vector model_interleaved = object_.Load (fs_path.toStdString ());
 59 | 
 60 |             glBindBuffer (GL_ARRAY_BUFFER, object_vbo_);
 61 |             glBufferData (GL_ARRAY_BUFFER, sizeof (float) * model_interleaved.size (),
 62 |             model_interleaved.data (), GL_STATIC_DRAW);
 63 |             glBindBuffer (GL_ARRAY_BUFFER, 0);
 64 |             vertex_count_ = model_interleaved.size () / object_.DataPerVertex ();
 65 |             object_.Unload ();
 66 | 
 67 |             status = true;
 68 |         }
 69 |     }
 70 | 
 71 |     window_->endExternalCommands ();
 72 |     return status;
 73 | }
 74 | 
 75 | void AugmentationRenderer::SetBackground (GLuint tex, bool is_grayscale) {
 76 |     current_handle_ = tex;
 77 |     is_grayscale_   = is_grayscale;
 78 | }
 79 | 
 80 | GLuint AugmentationRenderer::Background () {
 81 |     return texture_background_;
 82 | }
 83 | 
 84 | void AugmentationRenderer::SetTransform (Movement3D transform) {
 85 |     transform_ = transform;
 86 |     transform_.pitch (-(transform_.pitch () - 90));
 87 |     transform_.yaw (-transform_.yaw ());
 88 |     transform_.roll (-transform_.roll ());
 89 | }
 90 | 
 91 | Movement3D AugmentationRenderer::Transform () {
 92 |     return transform_;
 93 | }
 94 | 
 95 | void AugmentationRenderer::init () {
 96 |     if (!is_initialized_) {
 97 |         // Check if we're using OpenGL
 98 |         QSGRendererInterface* rif = window_->rendererInterface ();
 99 |         Q_ASSERT (rif->graphicsApi () == QSGRendererInterface::OpenGL ||
100 |         rif->graphicsApi () == QSGRendererInterface::OpenGLRhi);
101 | 
102 |         initializeOpenGLFunctions ();
103 | 
104 |         glGenTextures (1, &texture_background_);
105 |         glBindTexture (GL_TEXTURE_2D, texture_background_);
106 |         glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
107 |         glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
108 |         glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
109 |         glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
110 |         glBindTexture (GL_TEXTURE_2D, 0);
111 | 
112 |         // generate a buffer to bind to textures
113 |         glGenFramebuffers (1, &readback_buffer_);
114 | 
115 |         // compile and link shaders
116 |         CompileShaders ();
117 | 
118 |         // generate vertex array buffers
119 |         GenerateBuffers ();
120 | 
121 |         // TODO is this needed here?
122 |         // setup projection matrix
123 |         mat_projection_.ortho (-2.0f, +2.0f, -2.0f, +2.0f, 1.0f, 25.0f);
124 | 
125 |         is_initialized_ = true;
126 |         emit InitializedOpenGL ();
127 |     }
128 | }
129 | 
130 | void AugmentationRenderer::GenerateBuffers () {
131 |     // setup background vao
132 |     {
133 |         glGenVertexArrays (1, &background_vao_);
134 |         glGenBuffers (1, &background_vbo_);
135 | 
136 |         glBindVertexArray (background_vao_);
137 |         glBindBuffer (GL_ARRAY_BUFFER, background_vbo_);
138 | 
139 |         int pos_location = program_background_.attributeLocation ("position");
140 |         glVertexAttribPointer (pos_location, 2, GL_FLOAT, GL_FALSE,
141 |         4 * sizeof (float), reinterpret_cast (0));
142 |         glEnableVertexAttribArray (pos_location);
143 | 
144 |         int tex_location = program_background_.attributeLocation ("tex");
145 |         glVertexAttribPointer (tex_location, 2, GL_FLOAT, GL_FALSE,
146 |         4 * sizeof (float), reinterpret_cast (2 * sizeof (float)));
147 |         glEnableVertexAttribArray (tex_location);
148 | 
149 |         // fill buffer with data
150 |         GLfloat interleaved_background_buff[6 * 4] = {
151 |             -1.0, 1.0,  // poly 1 a
152 |             0.0, 0.0,   // poly 1 a tex
153 |             -1.0, -1.0, // poly 1 b
154 |             0.0, 1.0,   // poly 1 b tex
155 |             1.0, 1.0,   // poly 1 c
156 |             1.0, 0.0,   // poly 1 c tex
157 |             1.0, 1.0,   // poly 2 a
158 |             1.0, 0.0,   // poly 2 a tex
159 |             -1.0, -1.0, // poly 2 b
160 |             0.0, 1.0,   // poly 2 b tex
161 |             1.0, -1.0,  // poly 2 c
162 |             1.0, 1.0    // poly 2 c tex
163 |         };
164 |         glBufferData (GL_ARRAY_BUFFER, sizeof (float) * 6 * 4,
165 |         interleaved_background_buff, GL_STATIC_DRAW);
166 |     }
167 | 
168 |     // setup object vao
169 |     {
170 |         glGenVertexArrays (1, &object_vao_);
171 |         glGenBuffers (1, &object_vbo_);
172 | 
173 |         glBindVertexArray (object_vao_);
174 |         glBindBuffer (GL_ARRAY_BUFFER, object_vbo_);
175 | 
176 |         int pos_location = program_object_.attributeLocation ("position");
177 |         glVertexAttribPointer (pos_location, 3, GL_FLOAT, GL_FALSE,
178 |         10 * sizeof (float), reinterpret_cast (0));
179 |         glEnableVertexAttribArray (pos_location);
180 | 
181 |         int nor_location = program_object_.attributeLocation ("normal");
182 |         glVertexAttribPointer (nor_location, 3, GL_FLOAT, GL_FALSE,
183 |         10 * sizeof (float), reinterpret_cast (3 * sizeof (float)));
184 |         glEnableVertexAttribArray (nor_location);
185 | 
186 |         int col_location = program_object_.attributeLocation ("color");
187 |         glVertexAttribPointer (col_location, 4, GL_FLOAT, GL_FALSE,
188 |         10 * sizeof (float), reinterpret_cast (6 * sizeof (float)));
189 |         glEnableVertexAttribArray (col_location);
190 | 
191 |         glBindBuffer (GL_ARRAY_BUFFER, 0);
192 |         glBindVertexArray (0);
193 |     }
194 | }
195 | 
196 | void AugmentationRenderer::CompileShaders () {
197 |     // background shaders
198 |     {
199 |         QFile vs_file (":/GL_shaders/background_vs.glsl");
200 |         QFile fs_file (":/GL_shaders/background_fs.glsl");
201 |         vs_file.open (QIODevice::ReadOnly);
202 |         fs_file.open (QIODevice::ReadOnly);
203 |         QByteArray vs_source = vs_file.readAll ();
204 |         QByteArray fs_source = fs_file.readAll ();
205 | 
206 |         if (QOpenGLContext::currentContext ()->isOpenGLES ()) {
207 |             vs_source.prepend (QByteArrayLiteral ("#version 300 es\n"));
208 |             fs_source.prepend (QByteArrayLiteral ("#version 300 es\n"));
209 |         } else {
210 |             vs_source.prepend (QByteArrayLiteral ("#version 410\n"));
211 |             fs_source.prepend (QByteArrayLiteral ("#version 410\n"));
212 |         }
213 | 
214 |         program_background_.addShaderFromSourceCode (QOpenGLShader::Vertex, vs_source);
215 |         program_background_.addShaderFromSourceCode (QOpenGLShader::Fragment, fs_source);
216 |         program_background_.link ();
217 | 
218 |         program_background_.bind ();
219 |         program_background_.setUniformValue ("u_tex_background", 0);
220 |         program_background_.release ();
221 |     }
222 |     // object shaders
223 |     {
224 |         QFile vs_file (":/GL_shaders/object_vs.glsl");
225 |         QFile fs_file (":/GL_shaders/object_fs.glsl");
226 |         vs_file.open (QIODevice::ReadOnly);
227 |         fs_file.open (QIODevice::ReadOnly);
228 |         QByteArray vs_source = vs_file.readAll ();
229 |         QByteArray fs_source = fs_file.readAll ();
230 | 
231 |         if (QOpenGLContext::currentContext ()->isOpenGLES ()) {
232 |             vs_source.prepend (QByteArrayLiteral ("#version 300 es\n"));
233 |             fs_source.prepend (QByteArrayLiteral ("#version 300 es\n"));
234 |         } else {
235 |             vs_source.prepend (QByteArrayLiteral ("#version 410\n"));
236 |             fs_source.prepend (QByteArrayLiteral ("#version 410\n"));
237 |         }
238 | 
239 |         program_object_.addShaderFromSourceCode (QOpenGLShader::Vertex, vs_source);
240 |         program_object_.addShaderFromSourceCode (QOpenGLShader::Fragment, fs_source);
241 |         program_object_.link ();
242 |     }
243 | }
244 | 
245 | void AugmentationRenderer::setViewportSize (const QSize& size) {
246 |     view_width_  = size.width ();
247 |     view_height_ = size.height ();
248 | 
249 |     mat_projection_.setToIdentity ();
250 |     // TODO: replace with perspective, or possibly intrinsic camera matrix
251 |     mat_projection_.ortho (-2.0f, +2.0f, -2.0f, +2.0f, 1.0f, 25.0f);
252 | }
253 | 
254 | void AugmentationRenderer::setWindow (QQuickWindow* window) {
255 |     window_ = window;
256 | }
257 | 
258 | void AugmentationRenderer::paint () {
259 |     window_->beginExternalCommands ();
260 | 
261 |     glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
262 |     glViewport (0, 0, view_width_, view_height_);
263 |     glEnable (GL_BLEND);
264 |     glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
265 | 
266 |     DrawBackground ();
267 |     DrawObject ();
268 | 
269 |     window_->endExternalCommands ();
270 | 
271 |     glClear (GL_DEPTH_BUFFER_BIT);
272 | }
273 | 
274 | void AugmentationRenderer::DrawBackground () {
275 |     program_background_.bind ();
276 |     program_background_.setUniformValue ("is_GLRED", is_grayscale_);
277 | 
278 |     glDisable (GL_DEPTH_TEST);
279 | 
280 |     // draw the 2 triangles that form the background
281 |     glBindVertexArray (background_vao_);
282 |     glActiveTexture (GL_TEXTURE0);
283 |     glBindTexture (GL_TEXTURE_2D, current_handle_);
284 |     glDrawArrays (GL_TRIANGLES, 0, 6);
285 |     glBindTexture (GL_TEXTURE_2D, 0);
286 |     glBindVertexArray (0);
287 | }
288 | 
289 | void AugmentationRenderer::DrawObject () {
290 |     QMatrix4x4 mat_modelview;
291 |     mat_modelview.translate (
292 |     transform_.translation ().x, transform_.translation ().y, -10.0);
293 |     mat_modelview.scale (transform_.scale ());
294 |     mat_modelview.rotate (transform_.pitch (), 1, 0, 0);
295 |     mat_modelview.rotate (transform_.yaw (), 0, 1, 0);
296 |     mat_modelview.rotate (transform_.roll (), 0, 0, 1);
297 |     mat_modelview = mat_projection_ * mat_modelview;
298 | 
299 |     program_object_.bind ();
300 |     program_object_.setUniformValue ("view_matrix", mat_modelview);
301 | 
302 |     glEnable (GL_DEPTH_TEST);
303 |     // glEnable (GL_CULL_FACE);
304 | 
305 |     // draw the object
306 |     glBindVertexArray (object_vao_);
307 |     glDrawArrays (GL_TRIANGLES, 0, vertex_count_);
308 |     glBindVertexArray (0);
309 | }
310 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/augmentation_renderer.hpp:
--------------------------------------------------------------------------------
 1 | // augmentation_renderer.hpp
 2 | 
 3 | #ifndef AUGMENTATION_RENDERER_HPP
 4 | #define AUGMENTATION_RENDERER_HPP
 5 | 
 6 | #include 
 7 | #include 
 8 | #include 
 9 | #include 
10 | #include 
11 | #include 
12 | #include 
13 | #include 
14 | #include 
15 | #include 
16 | 
17 | #include "model_loader.hpp"
18 | #include "shared/movement3d/movement3d.hpp"
19 | 
20 | Q_DECLARE_LOGGING_CATEGORY(augmentationRendererLog)
21 | 
22 | class AugmentationRenderer : public QObject, protected QOpenGLExtraFunctions {
23 |     Q_OBJECT
24 |     public:
25 |     AugmentationRenderer (QObject* parent = 0);
26 |     ~AugmentationRenderer ();
27 | 
28 |     // QOpenGLWidget reimplemented functions
29 |     void init ();
30 |     void setViewportSize (const QSize& size);
31 |     void setWindow (QQuickWindow* window);
32 |     void paint ();
33 | 
34 |     public slots:
35 |     void SetObject (const QString& path);
36 |     void SetBackground (GLuint tex, bool is_grayscale);
37 |     GLuint Background ();
38 |     void SetTransform (Movement3D transform);
39 |     Movement3D Transform ();
40 | 
41 |     signals:
42 |     void InitializedOpenGL ();
43 | 
44 |     private:
45 |     bool LoadObject (const QString& path);
46 |     void GenerateBuffers ();
47 |     void CompileShaders ();
48 |     void DrawObject ();
49 |     void DrawBackground ();
50 | 
51 |     bool is_initialized_{ false };
52 |     ModelLoader object_;
53 |     QString object_path_;
54 |     QQuickWindow* window_;
55 |     int view_width_;
56 |     int view_height_;
57 |     Movement3D transform_;
58 |     QMatrix4x4 mat_projection_;
59 |     GLuint is_grayscale_;
60 |     GLuint texture_background_;
61 |     GLuint current_handle_;
62 |     GLuint readback_buffer_;
63 |     GLuint background_vao_;
64 |     GLuint object_vao_;
65 |     GLuint background_vbo_;
66 |     GLuint object_vbo_;
67 |     GLuint vertex_count_;
68 |     QOpenGLShaderProgram program_background_;
69 |     QOpenGLShaderProgram program_object_;
70 | };
71 | 
72 | #endif // AUGMENTATION_RENDERER_HPP
73 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/augmentation_view.cpp:
--------------------------------------------------------------------------------
 1 | #include "augmentation_view.hpp"
 2 | 
 3 | #include 
 4 | #include 
 5 | 
 6 | #include "shared/movement3d/movement3d.hpp"
 7 | 
 8 | AugmentationView::AugmentationView ()
 9 | : renderer_ (nullptr) {
10 |     Q_INIT_RESOURCE (3D_models);
11 |     readModels ();
12 |     setModel (0);
13 |     connect (this, &QQuickItem::windowChanged, this, &AugmentationView::handleWindowChanged);
14 | }
15 | 
16 | AugmentationView::~AugmentationView () {
17 |     Q_CLEANUP_RESOURCE (3D_models);
18 | }
19 | 
20 | void AugmentationView::readModels () {
21 |     models_ = QDir (":/3D_models/").entryList (QDir::Files);
22 |     emit modelsChanged ();
23 | }
24 | 
25 | void AugmentationView::handleWindowChanged (QQuickWindow* win) {
26 |     if (win) {
27 |         connect (win, &QQuickWindow::beforeSynchronizing, this,
28 |         &AugmentationView::sync, Qt::DirectConnection);
29 |         connect (win, &QQuickWindow::sceneGraphInvalidated, this,
30 |         &AugmentationView::cleanup, Qt::DirectConnection);
31 |         win->setColor ("magenta");
32 |     }
33 | }
34 | 
35 | void AugmentationView::drawFrame (FrameData frame) {
36 |     auto& data = frame.data;
37 | 
38 |     try {
39 |         transform_          = std::any_cast (data["transform"]);
40 |         background_texture_ = std::any_cast (data["background"]);
41 | 
42 |         if (auto is_grayscale_it = data.find ("backgroundIsGrayscale");
43 |             is_grayscale_it != data.end ()) {
44 |             background_is_grayscale_ = std::any_cast (is_grayscale_it->second);
45 |         } else {
46 |             background_is_grayscale_ = false;
47 |         }
48 |     } catch (const std::bad_any_cast& e) {
49 |         std::cout << e.what () << '\n';
50 |     }
51 | 
52 |     if (window ()) {
53 |         window ()->update ();
54 |     }
55 | }
56 | 
57 | void AugmentationView::setModel (int model) {
58 |     model_       = model;
59 |     object_path_ = models_[model];
60 |     emit modelChanged ();
61 | }
62 | 
63 | void AugmentationView::sync () {
64 |     if (!renderer_) {
65 |         renderer_ = new AugmentationRenderer ();
66 |         connect (window (), &QQuickWindow::beforeRendering, renderer_,
67 |         &AugmentationRenderer::init, Qt::DirectConnection);
68 |         connect (window (), &QQuickWindow::beforeRenderPassRecording, renderer_,
69 |         &AugmentationRenderer::paint, Qt::DirectConnection);
70 |     }
71 | 
72 |     renderer_->setViewportSize (window ()->size () * window ()->devicePixelRatio ());
73 |     renderer_->setWindow (window ());
74 |     renderer_->SetTransform (transform_);
75 |     renderer_->SetBackground (background_texture_, background_is_grayscale_);
76 |     renderer_->SetObject (object_path_);
77 | }
78 | 
79 | void AugmentationView::cleanup () {
80 |     delete renderer_;
81 |     renderer_ = nullptr;
82 | }
83 | 
84 | void AugmentationView::releaseResources () {
85 |     window ()->scheduleRenderJob (
86 |     new CleanupJob (renderer_), QQuickWindow::BeforeSynchronizingStage);
87 |     renderer_ = nullptr;
88 | }
89 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/augmentation_view.hpp:
--------------------------------------------------------------------------------
 1 | // augmentation_view.hpp
 2 | 
 3 | #ifndef AUGMENTATION_VIEW_HPP
 4 | #define AUGMENTATION_VIEW_HPP
 5 | 
 6 | #include 
 7 | #include 
 8 | #include 
 9 | 
10 | #include "augmentation_renderer.hpp"
11 | #include "shared/frame_data.hpp"
12 | 
13 | class CleanupJob : public QRunnable {
14 |     public:
15 |     CleanupJob (AugmentationRenderer* renderer)
16 |     : renderer_ (renderer) {
17 |     }
18 |     void run () override {
19 |         delete renderer_;
20 |     }
21 | 
22 |     private:
23 |     AugmentationRenderer* renderer_;
24 | };
25 | 
26 | class AugmentationView : public QQuickItem {
27 |     Q_OBJECT
28 | 
29 |     Q_PROPERTY (QStringList models MEMBER models_ NOTIFY modelsChanged)
30 |     Q_PROPERTY (int model MEMBER model_ WRITE setModel NOTIFY modelChanged)
31 | 
32 |     public:
33 |     AugmentationView ();
34 |     ~AugmentationView ();
35 | 
36 |     void setModel (int model);
37 | 
38 |     signals:
39 |     void modelsChanged ();
40 |     void modelChanged ();
41 | 
42 |     public slots:
43 |     void sync ();
44 |     void cleanup ();
45 |     void drawFrame (FrameData frame);
46 | 
47 |     private slots:
48 |     void handleWindowChanged (QQuickWindow* win);
49 | 
50 |     private:
51 |     void releaseResources () override;
52 |     void readModels ();
53 | 
54 |     AugmentationRenderer* renderer_;
55 |     QString object_path_;
56 |     QStringList models_;
57 |     int model_{ 0 };
58 |     Movement3D transform_;
59 |     GLuint background_texture_{ 0 };
60 |     bool background_is_grayscale_;
61 | };
62 | 
63 | #endif // AUGMENTATION_VIEW_HPP
64 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/model_loader.cpp:
--------------------------------------------------------------------------------
  1 | #include "model_loader.hpp"
  2 | 
  3 | #include 
  4 | #include 
  5 | #include 
  6 | #include 
  7 | #include 
  8 | #include 
  9 | #include 
 10 | #include 
 11 | 
 12 | #define DATA_PER_VERTEX 10 // 3 coords + 3 normal + 4 color
 13 | #define MAX_COORDINATE 1
 14 | 
 15 | ModelLoader::ModelLoader ()
 16 | : is_loaded_ (false)
 17 | , scale_factor_ (1.0f)
 18 | , current_rgba_{ { 1, 1, 1, 1 } } {
 19 | }
 20 | 
 21 | void ModelLoader::Unload () {
 22 |     is_loaded_    = false;
 23 |     scale_factor_ = 1.0f;
 24 |     vertices_.clear ();
 25 |     normals_.clear ();
 26 |     faces_.clear ();
 27 |     faces_normals_.clear ();
 28 |     faces_colors_.clear ();
 29 |     interleaved_faces_.clear ();
 30 |     current_rgba_ = { { 1, 1, 1, 1 } };
 31 | }
 32 | 
 33 | int ModelLoader::DataPerVertex () {
 34 |     return DATA_PER_VERTEX;
 35 | }
 36 | 
 37 | void ModelLoader::CalculateNormals (const std::vector& vertices,
 38 | std::vector& normals) {
 39 |     // calculate Vector1 and Vector2
 40 |     float norm[3], va[3], vb[3], vr[3], val;
 41 |     va[0] = vertices[0] - vertices[3];
 42 |     va[1] = vertices[1] - vertices[4];
 43 |     va[2] = vertices[2] - vertices[5];
 44 | 
 45 |     vb[0] = vertices[0] - vertices[6];
 46 |     vb[1] = vertices[1] - vertices[7];
 47 |     vb[2] = vertices[2] - vertices[8];
 48 | 
 49 |     // cross product
 50 |     vr[0] = va[1] * vb[2] - vb[1] * va[2];
 51 |     vr[1] = vb[0] * va[2] - va[0] * vb[2];
 52 |     vr[2] = va[0] * vb[1] - vb[0] * va[1];
 53 | 
 54 |     // normalization factor
 55 |     val = sqrt (vr[0] * vr[0] + vr[1] * vr[1] + vr[2] * vr[2]);
 56 | 
 57 |     norm[0] = vr[0] / val;
 58 |     norm[1] = vr[1] / val;
 59 |     norm[2] = vr[2] / val;
 60 | 
 61 |     // push back the norms for all 3 vertices
 62 |     normals.push_back (norm[0]);
 63 |     normals.push_back (norm[1]);
 64 |     normals.push_back (norm[2]);
 65 | 
 66 |     normals.push_back (norm[0]);
 67 |     normals.push_back (norm[1]);
 68 |     normals.push_back (norm[2]);
 69 | 
 70 |     normals.push_back (norm[0]);
 71 |     normals.push_back (norm[1]);
 72 |     normals.push_back (norm[2]);
 73 | }
 74 | 
 75 | float ModelLoader::CalculateScale () {
 76 |     // ensure that every vertex fits into range -1 to 1
 77 |     float max_val = 0.0f;
 78 |     for (float val : faces_) {
 79 |         float abs_val = std::fabs (val);
 80 |         if (max_val < abs_val) {
 81 |             max_val = abs_val;
 82 |         }
 83 |     }
 84 |     return (MAX_COORDINATE / max_val);
 85 | }
 86 | 
 87 | void ModelLoader::NormalizeVertices () {
 88 |     float scale_factor = CalculateScale ();
 89 | 
 90 |     for (float& val : faces_) {
 91 |         val = val * scale_factor;
 92 |     }
 93 | 
 94 |     scale_factor_ = scale_factor;
 95 | }
 96 | 
 97 | void ModelLoader::Interleave () {
 98 |     int vertex_count = faces_.size () / 3;
 99 | 
100 |     for (int vert_idx = 0; vert_idx < vertex_count; vert_idx++) {
101 |         int position_idx = vert_idx * 3;
102 |         int normal_idx   = vert_idx * 3;
103 |         int color_idx    = vert_idx * 4;
104 | 
105 |         interleaved_faces_.push_back (faces_.at (position_idx));
106 |         interleaved_faces_.push_back (faces_.at (position_idx + 1));
107 |         interleaved_faces_.push_back (faces_.at (position_idx + 2));
108 | 
109 |         interleaved_faces_.push_back (faces_normals_.at (normal_idx));
110 |         interleaved_faces_.push_back (faces_normals_.at (normal_idx + 1));
111 |         interleaved_faces_.push_back (faces_normals_.at (normal_idx + 2));
112 | 
113 |         interleaved_faces_.push_back (faces_colors_.at (color_idx));
114 |         interleaved_faces_.push_back (faces_colors_.at (color_idx + 1));
115 |         interleaved_faces_.push_back (faces_colors_.at (color_idx + 2));
116 |         interleaved_faces_.push_back (faces_colors_.at (color_idx + 3));
117 |     }
118 | }
119 | 
120 | const std::vector& ModelLoader::Load (const std::string filename, bool normalize) {
121 |     bool status = true;
122 |     std::string line;
123 | 
124 |     if (is_loaded_) {
125 |         Unload ();
126 |     }
127 | 
128 |     std::ifstream objFile (filename);
129 |     if (objFile.is_open ()) // If obj file is open, continue
130 |     {
131 |         while ((!objFile.eof ()) && status) {
132 |             getline (objFile, line);
133 |             if (!line.empty ()) {
134 |                 status = ParseLine (line);
135 |             }
136 |         }
137 |         objFile.close (); // Close OBJ file
138 |     } else {
139 |         status = false;
140 |     }
141 | 
142 | 
143 |     if (status == true) {
144 |         if (normalize) {
145 |             NormalizeVertices ();
146 |         }
147 | 
148 |         Interleave ();
149 |         is_loaded_ = true;
150 |     }
151 | 
152 |     return interleaved_faces_;
153 | }
154 | 
155 | bool ModelLoader::ParseLine (const std::string& line) {
156 |     bool status = true;
157 | 
158 |     std::string value;
159 |     std::string keyword;
160 |     size_t split_pos = line.find (' ');
161 |     if (split_pos != std::string::npos) {
162 |         keyword = line.substr (0, split_pos);
163 |         value   = line.substr (split_pos);
164 |     } else {
165 |         keyword = line;
166 |         value   = "";
167 |     }
168 | 
169 |     if (keyword == "#" || keyword.empty ()) {
170 |         ; // comment line, ignore
171 |     } else if (keyword == "v") {
172 |         status = ParseVertex (value);
173 |     } else if (keyword == "vn") {
174 |         status = ParseNormal (value);
175 |     } else if (keyword == "f") {
176 |         status = ParseFace (value);
177 |     } else if (keyword == "usemtl") {
178 |         status = ParseUseMTL (value);
179 |     } else {
180 |         if (unknown_options_.find (keyword) == unknown_options_.end ()) {
181 |             // std::cout << "unsupporterd keyword: " << keyword << std::endl;
182 |             unknown_options_.insert (keyword);
183 |         }
184 |     }
185 |     return status;
186 | }
187 | 
188 | bool ModelLoader::ParseVertex (const std::string& line) {
189 |     bool status = true;
190 | 
191 |     std::vector values = TokenizeString (line, " ");
192 | 
193 |     if (values.size () == 3) {
194 |         std::array vertex;
195 | 
196 |         try {
197 |             vertex[0] = std::atof (values[0].c_str ());
198 |             vertex[1] = std::atof (values[1].c_str ());
199 |             vertex[2] = std::atof (values[2].c_str ());
200 |         } catch (std::invalid_argument const&) {
201 |             status = false;
202 |             // std::cout << "failed line" << line << std::endl;
203 |         }
204 |         if (status == true) {
205 |             vertices_.insert (std::end (vertices_), std::begin (vertex), std::end (vertex));
206 |         }
207 |     } else {
208 |         status = false;
209 |     }
210 |     return status;
211 | }
212 | 
213 | bool ModelLoader::ParseNormal (const std::string& line) {
214 |     bool status = true;
215 | 
216 |     std::vector values = TokenizeString (line, " ");
217 | 
218 |     if (values.size () == 3) {
219 |         std::array normal;
220 | 
221 |         try {
222 |             normal[0] = std::atof (values[0].c_str ());
223 |             normal[1] = std::atof (values[1].c_str ());
224 |             normal[2] = std::atof (values[2].c_str ());
225 |         } catch (std::invalid_argument const&) {
226 |             status = false;
227 |             // std::cout << "failed line" << line << std::endl;
228 |         }
229 |         if (status == true) {
230 |             normals_.insert (std::end (normals_), std::begin (normal), std::end (normal));
231 |         }
232 |     } else {
233 |         status = false;
234 |     }
235 |     return status;
236 | }
237 | 
238 | 
239 | bool ModelLoader::ParseFace (const std::string& line) {
240 |     bool status = true;
241 | 
242 |     std::vector values = TokenizeString (line, " ");
243 | 
244 |     if (values.size () == 3) {
245 |         // create triangle ABC
246 |         status = ParseTriangle (values);
247 |     } else if (values.size () == 4) {
248 |         // create triangles ABC and ACD from quad ABCD
249 |         std::vector triangle_2 = { values[0], values[2], values[3] };
250 |         values.pop_back ();
251 |         status = ParseTriangle (values); // ABC
252 |         if (status == true) {
253 |             status = ParseTriangle (triangle_2); // ACD
254 |         }
255 |     } else {
256 |         status = false;
257 |     }
258 | 
259 |     return status;
260 | }
261 | 
262 | bool ModelLoader::ParseTriangle (const std::vector& vertices_str) {
263 |     bool status           = true;
264 |     bool normals_provided = true;
265 |     int vert_idx          = 0; // vertex indices
266 |     int text_idx          = 0; // texture point indices
267 |     int norm_idx          = 0; // normal indices
268 |     std::vector vertices;
269 |     std::vector normals;
270 | 
271 |     for (auto vertex_str : vertices_str) {
272 |         // each vertex can be in format v or v//vn or v/vt/vn
273 |         // TODO: use regex instead
274 |         std::vector values = TokenizeString (vertex_str, "/");
275 | 
276 |         if (values.size () == 1) {
277 |             normals_provided = false;
278 |             vert_idx         = std::atoi (values[0].c_str ());
279 |         } else if (values.size () == 2) {
280 |             vert_idx = std::atoi (values[0].c_str ());
281 |             norm_idx = std::atoi (values[1].c_str ());
282 |         } else if (values.size () == 3) {
283 |             vert_idx = std::atoi (values[0].c_str ());
284 |             text_idx = std::atoi (values[1].c_str ());
285 |             norm_idx = std::atoi (values[2].c_str ());
286 |         } else {
287 |             status = false;
288 |         }
289 | 
290 |         if (status) {
291 |             // OBJ index starts at 1, and 3 floats per vertex
292 |             vert_idx = (vert_idx - 1) * 3;
293 |             text_idx = (text_idx - 1) * 3;
294 |             norm_idx = (norm_idx - 1) * 3;
295 | 
296 |             // retrieve the XYZ coords
297 |             vertices.push_back (vertices_.at (vert_idx));
298 |             vertices.push_back (vertices_.at (vert_idx + 1));
299 |             vertices.push_back (vertices_.at (vert_idx + 2));
300 | 
301 |             if (normals_provided == true) { // retrieve the XYZ angles
302 |                 normals.push_back (normals_.at (norm_idx));
303 |                 normals.push_back (normals_.at (norm_idx + 1));
304 |                 normals.push_back (normals_.at (norm_idx + 2));
305 |             }
306 | 
307 |             // push back color per vertex
308 |             faces_colors_.insert (std::end (faces_colors_),
309 |             std::begin (current_rgba_), std::end (current_rgba_));
310 |         }
311 |     }
312 | 
313 |     // push back all vertices
314 |     faces_.insert (std::end (faces_), std::begin (vertices), std::end (vertices));
315 | 
316 |     // if any of the normals are missing, recalculate all
317 |     if (normals_provided == false) {
318 |         normals.clear ();
319 |         CalculateNormals (vertices, normals);
320 |     }
321 | 
322 |     // push back all normals
323 |     faces_normals_.insert (
324 |     std::end (faces_normals_), std::begin (normals), std::end (normals));
325 | 
326 |     return status;
327 | }
328 | 
329 | bool ModelLoader::ParseUseMTL (const std::string& value) {
330 |     bool status = true; // TODO: check status
331 | 
332 |     std::string mat = value.substr (value.find (" ")); // get from space
333 |     mat             = TrimString (mat);
334 | 
335 |     if (mat == "black") { // shuttle materials
336 |         current_rgba_ = { { 0.0, 0.0, 0.0, 1.0 } };
337 |     } else if (mat == "glass") {
338 |         current_rgba_ = { { 0.5, 0.65, 0.75, 1.0 } };
339 |     } else if (mat == "bone") {
340 |         current_rgba_ = { { 0.75, 0.75, 0.65, 1.0 } };
341 |     } else if (mat == "brass") {
342 |         current_rgba_ = { { 0.45, 0.35, 0.12, 1.0 } };
343 |     } else if (mat == "dkdkgrey") {
344 |         current_rgba_ = { { 0.30, 0.35, 0.35, 1.0 } };
345 |     } else if (mat == "fldkdkgrey") {
346 |         current_rgba_ = { { 0.30, 0.35, 0.35, 1.0 } };
347 |     } else if (mat == "redbrick") {
348 |         current_rgba_ = { { 0.61, 0.16, 0.0, 1.0 } };
349 |     } else if (mat == "Mat_1_-1") { // articated materials
350 |         current_rgba_ = { { 0.0, 0.0, 1.0, 1.0 } };
351 |     } else if (mat == "Mat_2_-1") {
352 |         current_rgba_ = { { 0.2, 1.0, 1.0, 0.4 } };
353 |     } else if (mat == "Mat_3_-1") {
354 |         current_rgba_ = { { 1.0, 0.0, 0.0, 1.0 } };
355 |     } else if (mat == "Mat_4_-1") {
356 |         current_rgba_ = { { 0.0, 1.0, 0.0, 1.0 } };
357 |     } else if (mat == "Black") { // dino materials
358 |         current_rgba_ = { { 0.09, 0.09, 0.09, 1.0 } };
359 |     } else if (mat == "LightBlue") {
360 |         current_rgba_ = { { 0.57, 0.73, 0.92, 1.0 } };
361 |     } else if (mat == "DarkBlue") {
362 |         current_rgba_ = { { 0.16, 0.40, 0.67, 1.0 } };
363 |     } else if (mat == "red") { // general collors
364 |         current_rgba_ = { { 1.0, 0.0, 0.0, 1.0 } };
365 |     } else if (mat == "green") {
366 |         current_rgba_ = { { 0.0, 1.0, 0.0, 1.0 } };
367 |     } else if (mat == "blue") {
368 |         current_rgba_ = { { 0.0, 0.0, 1.0, 1.0 } };
369 |     } else if (mat == "cyan") {
370 |         current_rgba_ = { { 0.0, 1.0, 1.0, 1.0 } };
371 |     } else if (mat == "yellow") {
372 |         current_rgba_ = { { 1.0, 1.0, 0.0, 1.0 } };
373 |     } else {
374 |         // default to dark purple
375 |         current_rgba_ = { { 0.2, 0, 0.2, 1 } };
376 | 
377 |         if (unknown_options_.find (mat) == unknown_options_.end ()) {
378 |             std::cout << "unknown material: " << mat << std::endl;
379 |             unknown_options_.insert (mat);
380 |         }
381 |     }
382 |     return status;
383 | }
384 | 
385 | inline std::vector
386 | ModelLoader::TokenizeString (const std::string& in, const std::string& delim) {
387 |     size_t split_pos;
388 |     std::string right = in;
389 |     std::string left;
390 |     std::vector ret;
391 | 
392 |     do {
393 |         split_pos = right.find (delim);
394 |         if (split_pos != std::string::npos) {
395 |             left  = right.substr (0, split_pos);
396 |             right = right.substr (split_pos + 1);
397 |             left  = TrimString (left);
398 |             right = TrimString (right);
399 |             if (!left.empty ()) {
400 |                 ret.push_back (left);
401 |             }
402 |         }
403 |     } while (split_pos != std::string::npos);
404 | 
405 |     // the last token
406 |     if (!right.empty ()) {
407 |         ret.push_back (right);
408 |     }
409 | 
410 |     return ret;
411 | }
412 | 
413 | inline std::string ModelLoader::TrimString (const std::string& s) {
414 |     auto wsfront = std::find_if_not (
415 |     s.begin (), s.end (), [] (int c) { return std::isspace (c); });
416 |     auto wsback = std::find_if_not (s.rbegin (), s.rend (), [] (int c) {
417 |         return std::isspace (c);
418 |     }).base ();
419 |     return (wsback <= wsfront ? std::string () : std::string (wsfront, wsback));
420 | }
421 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/model_loader.hpp:
--------------------------------------------------------------------------------
 1 | // model_loader.hpp
 2 | #ifndef MODEL_LOADER_HPP
 3 | #define MODEL_LOADER_HPP
 4 | 
 5 | #include 
 6 | #include 
 7 | #include 
 8 | #include 
 9 | 
10 | class ModelLoader {
11 |     public:
12 |     ModelLoader ();
13 |     const std::vector& Load (const std::string filename, bool normalize = true);
14 |     int DataPerVertex ();
15 |     void Unload ();
16 | 
17 |     private:
18 |     void CalculateNormals (const std::vector& vertices, std::vector& normals);
19 |     float CalculateScale ();
20 |     void NormalizeVertices ();
21 |     void Interleave ();
22 |     bool ParseLine (const std::string& line);
23 |     bool ParseVertex (const std::string& line);
24 |     bool ParseNormal (const std::string& line);
25 |     bool ParseFace (const std::string& line);
26 |     bool ParseTriangle (const std::vector& values);
27 |     bool ParseUseMTL (const std::string& line);
28 |     inline std::string TrimString (const std::string& s);
29 |     inline std::vector
30 |     TokenizeString (const std::string& in, const std::string& delim);
31 | 
32 |     bool is_loaded_;
33 |     float scale_factor_;
34 |     std::array current_rgba_;
35 |     std::vector vertices_;
36 |     std::vector normals_;
37 |     std::vector faces_;
38 |     std::vector faces_normals_;
39 |     std::vector faces_colors_;
40 |     std::vector interleaved_faces_;
41 |     std::set unknown_options_;
42 | };
43 | 
44 | #endif // MODEL_LOADER_HPP
45 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/shaders/GL_shaders.qrc:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |     object_vs.glsl
4 |     object_fs.glsl
5 |     background_vs.glsl
6 |     background_fs.glsl
7 | 
8 | 
9 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/shaders/background_fs.glsl:
--------------------------------------------------------------------------------
 1 | #ifdef GL_ES
 2 |     precision mediump int;
 3 |     precision mediump float;
 4 | #endif
 5 | 
 6 | uniform sampler2D u_tex_background;
 7 | flat in int vtf_is_GLRED;
 8 | in vec2 vtf_texcoord;
 9 | 
10 | out highp vec4 frag_color;
11 | 
12 | void main() {
13 |     vec4 tex_sample = texture(u_tex_background, vtf_texcoord);
14 |     if (vtf_is_GLRED == 1) {
15 |         frag_color = vec4(tex_sample.r, tex_sample.r, tex_sample.r, 1.0);
16 |     } else {
17 |         frag_color = tex_sample;
18 |     }
19 | }
20 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/shaders/background_vs.glsl:
--------------------------------------------------------------------------------
 1 | in vec2 position;
 2 | in vec2 tex;
 3 | 
 4 | uniform int is_GLRED;
 5 | 
 6 | flat out int vtf_is_GLRED;
 7 | out vec2 vtf_texcoord;
 8 | 
 9 | void main()
10 | {
11 |     gl_Position = vec4(position, 0.0, 1.0);
12 |     vtf_texcoord = tex;
13 |     vtf_is_GLRED = is_GLRED;
14 | }
15 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/shaders/object_fs.glsl:
--------------------------------------------------------------------------------
 1 | #ifdef GL_ES
 2 |     precision mediump int;
 3 |     precision mediump float;
 4 | #endif
 5 | 
 6 | in vec3 vtf_normal;
 7 | in highp vec4 vtf_color;
 8 | out highp vec4 frag_color;
 9 | 
10 | void main()
11 | {
12 |     float dot_product = dot( vtf_normal, vec3(0.17, 0.98, 0) );
13 |     float cosTheta = clamp(dot_product, 0.0, 1.0);
14 |     vec3 diffuse = vtf_color.rgb * cosTheta;
15 |     vec3 ambient = vtf_color.rgb * 0.5;
16 |     frag_color = vec4(vec3(diffuse + ambient), vtf_color.a);
17 | }
18 | 
--------------------------------------------------------------------------------
/source/augmentation_widget/shaders/object_vs.glsl:
--------------------------------------------------------------------------------
 1 | uniform mat4 view_matrix;
 2 | in vec3 position;
 3 | in vec3 normal;
 4 | in vec4 color;
 5 | 
 6 | out vec4 vtf_color;
 7 | out vec3 vtf_normal;
 8 | 
 9 | void main()
10 | {
11 |     vtf_color = color;
12 |     vtf_normal = normal;
13 |     gl_Position = view_matrix * vec4(position, 1.0);
14 | }
15 | 
--------------------------------------------------------------------------------
/source/main.cpp:
--------------------------------------------------------------------------------
 1 | #include 
 2 | #include 
 3 | #include 
 4 | #include 
 5 | #include 
 6 | 
 7 | #include "augmentation_widget/augmentation_view.hpp"
 8 | #include "vision/vision.hpp"
 9 | 
10 | namespace {
11 | void configureOpengl (bool force_gles) {
12 |     // set GL version
13 |     QSurfaceFormat glFormat;
14 |     if (QOpenGLContext::openGLModuleType () == QOpenGLContext::LibGL && !force_gles) {
15 |         // on desktop, require opengl 4.1
16 |         glFormat.setVersion (4, 1);
17 |     } else {
18 |         // on mobile, require opengles 3.0
19 |         glFormat.setRenderableType (QSurfaceFormat::OpenGLES);
20 |         glFormat.setVersion (3, 0);
21 |     }
22 | 
23 |     glFormat.setProfile (QSurfaceFormat::CoreProfile);
24 |     QSurfaceFormat::setDefaultFormat (glFormat);
25 | 
26 |     QCoreApplication::setAttribute (Qt::AA_ShareOpenGLContexts);
27 | }
28 | } // namespace
29 | 
30 | int main (int argc, char* argv[]) {
31 |     QCommandLineParser parser;
32 |     parser.addHelpOption ();
33 |     parser.setApplicationDescription (
34 |     "ARticated: an augmented reality application");
35 |     QCommandLineOption force_gles_option ("force-gles", "force usage of openGLES");
36 |     parser.addOption (force_gles_option);
37 | 
38 |     // parse arguments
39 |     QStringList arguments;
40 |     for (int i = 0; i < argc; ++i) {
41 |         arguments.append (argv[i]);
42 |     }
43 |     parser.process (arguments);
44 | 
45 |     // configure opengl
46 |     bool force_gles = parser.isSet (force_gles_option);
47 |     configureOpengl (force_gles);
48 | 
49 |     // create the main app & window
50 |     QGuiApplication app (argc, argv);
51 |     setlocale (LC_NUMERIC, "C");
52 |     QQmlApplicationEngine engine;
53 | 
54 |     // register custom qml components
55 |     qmlRegisterType ("articated.vision", 1, 0, "Vision");
56 |     qmlRegisterType (
57 |     "articated.augmentation.augmentation_view", 1, 0, "AugmentationView");
58 |     engine.load (QUrl (QStringLiteral ("qrc:/qml/Main.qml")));
59 | 
60 |     return app.exec ();
61 | }
62 | 
--------------------------------------------------------------------------------
/source/qml/Main.qml:
--------------------------------------------------------------------------------
 1 | import QtQuick 2.14
 2 | import QtQuick.Controls 2.14
 3 | import QtQuick.Controls.Material 2.14
 4 | import QtQuick.Layouts 1.14
 5 | 
 6 | ApplicationWindow {
 7 |     id: appWindow
 8 |     height: 350
 9 |     title: "ARticated"
10 |     visible: true
11 |     width: 600
12 | 
13 |     StackView {
14 |         id: mainStack
15 |         anchors.fill: parent
16 |         focus: true
17 | 
18 |         initialItem: MainView {
19 |             id: mainView
20 |             onOpenSettings: {
21 |                 mainStack.push("SettingsView.qml", {
22 |                         "settings": settings
23 |                     });
24 |                 mainStack.currentItem.onExit.connect(function () {
25 |                         mainStack.pop();
26 |                     });
27 |             }
28 |         }
29 |     }
30 |     Shortcut {
31 |         sequence: "Ctrl+W"
32 | 
33 |         onActivated: Qt.quit()
34 |     }
35 | }
36 | 
--------------------------------------------------------------------------------
/source/qml/MainView.qml:
--------------------------------------------------------------------------------
  1 | import QtQuick 2.14
  2 | import QtQuick.Controls 2.14
  3 | import QtQuick.Controls.Material 2.14
  4 | import QtQuick.Layouts 1.14
  5 | import articated.vision 1.0
  6 | import articated.augmentation.augmentation_view 1.0
  7 | import "." as Components
  8 | 
  9 | Item {
 10 |     property alias settings: settings_instance
 11 | 
 12 |     signal openSettings
 13 | 
 14 |     function loadModel(model_index) {
 15 |         augmentation.model = model_index;
 16 |     }
 17 |     function selectAlgorithm(algorithm) {
 18 |         vision.algorithm = algorithm;
 19 |     }
 20 |     function selectSource(source) {
 21 |         vision.source = source;
 22 |     }
 23 |     function setDebugLevel(level) {
 24 |         vision.debugLevel = level;
 25 |     }
 26 | 
 27 |     Layout.fillHeight: true
 28 |     Layout.fillWidth: true
 29 | 
 30 |     Keys.onEscapePressed: openSettings()
 31 |     Keys.onPressed: event => {
 32 |         if (event.key == Qt.Key_Space) {
 33 |             vision.SetReference();
 34 |             referenceButton.down = true;
 35 |             event.accepted = true;
 36 |         } else if (event.key == Qt.Key_Plus) {
 37 |             settings_instance.currentDebugLevel = Math.min(settings.debugLevels, settings_instance.currentDebugLevel + 1);
 38 |             event.accepted = true;
 39 |         } else if (event.key == Qt.Key_Minus) {
 40 |             settings_instance.currentDebugLevel = Math.max(0, settings_instance.currentDebugLevel - 1);
 41 |             event.accepted = true;
 42 |         }
 43 |     }
 44 |     Keys.onReleased: event => {
 45 |         if (event.key == Qt.Key_Space) {
 46 |             referenceButton.down = false;
 47 |             event.accepted = true;
 48 |         }
 49 |     }
 50 | 
 51 |     Components.Settings {
 52 |         id: settings_instance
 53 |         algorithms: vision.algorithms
 54 |         debugLevels: vision.maxDebugLevel
 55 |         models: augmentation.models
 56 |     }
 57 |     Vision {
 58 |         id: vision
 59 |         algorithm: settings_instance.currentAlgorithm
 60 |         debugLevel: settings_instance.currentDebugLevel
 61 |         isPaused: false
 62 |         source: settings_instance.currentSource
 63 |     }
 64 |     Connections {
 65 |         function onFrameProcessed(frame_data) {
 66 |             augmentation.drawFrame(frame_data);
 67 |         }
 68 | 
 69 |         target: vision
 70 |     }
 71 |     AugmentationView {
 72 |         id: augmentation
 73 |         anchors.fill: parent
 74 |         model: settings_instance.currentModel
 75 |         z: 0
 76 |     }
 77 |     ColumnLayout {
 78 |         anchors.bottom: parent.bottom
 79 |         anchors.right: parent.right
 80 |         anchors.rightMargin: height / 40
 81 |         anchors.top: parent.top
 82 |         width: height / 4
 83 |         z: 5 // don't be shy, come closer to people
 84 | 
 85 |         RoundButton {
 86 |             Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
 87 |             implicitHeight: width
 88 |             implicitWidth: parent.width / 1.5
 89 |             text: vision.isPaused ? "⏵" : "⏸"
 90 |             z: 6
 91 | 
 92 |             background: Rectangle {
 93 |                 opacity: parent.down ? 0.5 : 0.1
 94 |                 radius: parent.width
 95 |             }
 96 | 
 97 |             onPressed: vision.isPaused = !vision.isPaused
 98 |         }
 99 |         RoundButton {
100 |             id: referenceButton
101 |             Layout.fillWidth: true
102 |             implicitHeight: width
103 |             z: 6
104 | 
105 |             background: Rectangle {
106 |                 opacity: parent.down ? 0.7 : 0.5
107 |                 radius: parent.width
108 |             }
109 | 
110 |             onPressed: vision.SetReference()
111 |         }
112 |         RoundButton {
113 |             Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
114 |             implicitHeight: width
115 |             implicitWidth: parent.width / 1.5
116 |             text: "⚙️"
117 |             z: 6
118 | 
119 |             background: Rectangle {
120 |                 opacity: parent.down ? 0.5 : 0.1
121 |                 radius: parent.width
122 |             }
123 | 
124 |             onPressed: openSettings()
125 |         }
126 |     }
127 | }
128 | 
--------------------------------------------------------------------------------
/source/qml/Settings.qml:
--------------------------------------------------------------------------------
 1 | import QtQuick 2.14
 2 | 
 3 | QtObject {
 4 |     property var algorithms
 5 |     property int currentAlgorithm
 6 |     property int currentDebugLevel
 7 |     property int currentModel
 8 |     property string currentSource
 9 |     property int debugLevels
10 |     property var models
11 | }
12 | 
--------------------------------------------------------------------------------
/source/qml/SettingsView.qml:
--------------------------------------------------------------------------------
  1 | import QtQuick 2.14
  2 | import QtQuick.Controls 2.14
  3 | import QtQuick.Controls.Material 2.14
  4 | import QtQuick.Layouts 1.14
  5 | import QtMultimedia 6.4
  6 | import "." as Components
  7 | 
  8 | Page {
  9 |     id: settingsPage
 10 | 
 11 |     property Components.Settings settings
 12 | 
 13 |     signal exit
 14 | 
 15 |     Layout.fillHeight: true
 16 |     Layout.fillWidth: true
 17 |     title: "Settings"
 18 | 
 19 |     header: ToolBar {
 20 |         RowLayout {
 21 |             anchors.fill: parent
 22 | 
 23 |             ToolButton {
 24 |                 text: "‹"
 25 | 
 26 |                 onClicked: exit()
 27 |             }
 28 |             Label {
 29 |                 Layout.fillWidth: true
 30 |                 elide: Label.ElideRight
 31 |                 horizontalAlignment: Qt.AlignHCenter
 32 |                 text: settingsPage.title
 33 |                 verticalAlignment: Qt.AlignVCenter
 34 |             }
 35 |         }
 36 |     }
 37 | 
 38 |     Keys.onEscapePressed: exit()
 39 | 
 40 |     GridLayout {
 41 |         anchors.fill: parent
 42 |         anchors.margins: 20
 43 |         columns: 2
 44 | 
 45 |         Button {
 46 |             Layout.columnSpan: 2
 47 |             Layout.fillWidth: true
 48 |             text: "Load Demo Video"
 49 | 
 50 |             onPressed: settings.currentSource = ":/debug_samples/3_markers_good.webm"
 51 |         }
 52 |         Text {
 53 |             text: "Input:"
 54 |         }
 55 |         ComboBox {
 56 |             Layout.fillWidth: true
 57 |             currentIndex: -1
 58 |             model: devices.videoInputs
 59 |             textRole: "description"
 60 | 
 61 |             delegate: ItemDelegate {
 62 |                 text: modelData.description
 63 |                 width: parent.width
 64 |             }
 65 | 
 66 |             Component.onCompleted: {
 67 |                 // find current selected camera, if any
 68 |                 for (var i = 0; i < model.length; i++) {
 69 |                     if (model[i].deviceId == settings.currentSource) {
 70 |                         currentIndex = i;
 71 |                     }
 72 |                 }
 73 |             }
 74 |             onActivated: index => {
 75 |                 settings.currentSource = model[index].id;
 76 |             }
 77 | 
 78 |             MediaDevices {
 79 |                 id: devices
 80 |             }
 81 |         }
 82 |         Text {
 83 |             text: "Algorithm:"
 84 |         }
 85 |         ComboBox {
 86 |             Layout.fillWidth: true
 87 |             currentIndex: settings.currentAlgorithm
 88 |             model: settings.algorithms
 89 | 
 90 |             onActivated: index => {
 91 |                 settings.currentAlgorithm = index;
 92 |             }
 93 |         }
 94 |         Text {
 95 |             text: "Model:"
 96 |         }
 97 |         ComboBox {
 98 |             Layout.fillWidth: true
 99 |             currentIndex: settings.currentModel
100 |             model: settings.models
101 | 
102 |             onActivated: inxed => {
103 |                 settings.currentModel = index;
104 |             }
105 |         }
106 |         Text {
107 |             text: "Debug Level:"
108 |         }
109 |         SpinBox {
110 |             to: settings.debugLevels
111 |             value: settings.currentDebugLevel
112 | 
113 |             onValueModified: {
114 |                 settings.currentDebugLevel = value;
115 |             }
116 |         }
117 |     }
118 | }
119 | 
--------------------------------------------------------------------------------
/source/qml/qml.qrc:
--------------------------------------------------------------------------------
1 | 
2 | 
3 |   Main.qml
4 |   MainView.qml
5 |   SettingsView.qml
6 |   Settings.qml
7 | 
8 | 
9 | 
--------------------------------------------------------------------------------
/source/shared/CMakeLists.txt:
--------------------------------------------------------------------------------
 1 | # Shared
 2 | find_package(Qt6 REQUIRED COMPONENTS Core)
 3 | 
 4 | add_subdirectory(movement3d)
 5 | 
 6 | set(CMAKE_AUTOMOC ON)
 7 | 
 8 | add_library(frame_data STATIC frame_data.hpp)
 9 | target_link_libraries( frame_data Qt::Core)
10 | 
--------------------------------------------------------------------------------
/source/shared/frame_data.hpp:
--------------------------------------------------------------------------------
 1 | // frame_data.hpp
 2 | #ifndef FRAME_DATA_HPP
 3 | #define FRAME_DATA_HPP
 4 | 
 5 | #include 
 6 | #include 
 7 | #include