├── Build ├── Linux │ └── build.sh └── Windows │ ├── EULA.txt │ ├── InstallerReadme.txt │ ├── License.txt │ ├── Microsoft.VC80.CRT.manifest │ ├── Microsoft.VC80.CRT │ ├── Microsoft.VC80.CRT.manifest │ ├── msvcm80.dll │ ├── msvcp80.dll │ └── msvcr80.dll │ ├── Microsoft.VC90.CRT │ ├── Microsoft.VC90.CRT.manifest │ ├── msvcm90.dll │ ├── msvcp90.dll │ └── msvcr90.dll │ ├── ReadMe.txt │ ├── copyWin32Files.bat │ └── installer2.iss ├── BuildProcedure.txt ├── Examples ├── Arc Sphere.es ├── Ball.es ├── BinaryKite.es ├── City of Glass.es ├── Default.es ├── Frame In Frame.es ├── Grinder.es ├── Konstrukt.es ├── Menger.es ├── MeshTest.es ├── Moduli Creatures.es ├── Mondrian.es ├── Nabla.es ├── NablaSystem.es ├── NineWorthies.es ├── Nouveau.es ├── Nouveau2.es ├── Nouveau3.es ├── Octopod II.es ├── Pure Structure.es ├── Reflection.es ├── RoundTree.es ├── SpiralTree2D.es ├── Synctor.es ├── Thingy.es ├── Torus2.es ├── Torus3.es ├── Trees 3d.es └── Tutorials │ ├── Blend.es │ ├── CSG test.es │ ├── JavaScript - Movie.es │ ├── NouveauMovie.es │ ├── Preprocessor.es │ ├── PreprocessorGUI.es │ ├── Primitives.es │ ├── RandomColor.es │ ├── Raytracer - Light.es │ └── TriangleComposites.es ├── LICENSE.GPL3 ├── LICENSE.LGPL ├── LICENSE.README ├── Main.cpp ├── Misc ├── Blender_Importer_2.py ├── Blender_Importer_2.rendertemplate ├── SunFlow-Monochrome.rendertemplate ├── Sunflow-Colored.rendertemplate ├── Sunflow-Meta-Neon22.rendertemplate ├── Sunflow-Textured.rendertemplate ├── Sunflow-Ultimate-Groovelock.rendertemplate ├── Sunflow-Ward.rendertemplate ├── about.html ├── appleseed.rendertemplate ├── cube.obj ├── icon.jpg ├── povray.rendertemplate ├── povray2.rendertemplate ├── renderman.rendertemplate ├── sphere.obj └── splash.png ├── StructureSynth.ico ├── StructureSynth.qrc ├── StructureSynth.sln ├── StructureSynth.vcproj ├── StructureSynth ├── GUI │ ├── MainWindow.cpp │ ├── MainWindow.h │ ├── TemplateExportDialog.cpp │ ├── TemplateExportDialog.h │ ├── VariableEditor.cpp │ └── VariableEditor.h ├── JavaScriptSupport │ ├── Debug.cpp │ ├── Debug.h │ ├── JavaScriptBuilder.cpp │ ├── JavaScriptBuilder.h │ ├── JavaScriptParser.cpp │ └── JavaScriptParser.h ├── Model │ ├── Action.cpp │ ├── Action.h │ ├── AmbiguousRule.cpp │ ├── AmbiguousRule.h │ ├── Builder.cpp │ ├── Builder.h │ ├── ColorPool.cpp │ ├── ColorPool.h │ ├── CustomRule.cpp │ ├── CustomRule.h │ ├── ExecutionStack.cpp │ ├── ExecutionStack.h │ ├── PrimitiveClass.cpp │ ├── PrimitiveClass.h │ ├── PrimitiveRule.cpp │ ├── PrimitiveRule.h │ ├── RandomStreams.cpp │ ├── RandomStreams.h │ ├── Rendering │ │ ├── ObjRenderer.cpp │ │ ├── ObjRenderer.h │ │ ├── OpenGLRenderer.cpp │ │ ├── OpenGLRenderer.h │ │ ├── Renderer.cpp │ │ ├── Renderer.h │ │ ├── TemplateRenderer.cpp │ │ └── TemplateRenderer.h │ ├── Rule.cpp │ ├── Rule.h │ ├── RuleRef.cpp │ ├── RuleRef.h │ ├── RuleSet.cpp │ ├── RuleSet.h │ ├── State.cpp │ ├── State.h │ ├── Transformation.cpp │ ├── Transformation.h │ ├── TransformationLoop.cpp │ └── TransformationLoop.h └── Parser │ ├── EisenParser.cpp │ ├── EisenParser.h │ ├── Preprocessor.cpp │ ├── Preprocessor.h │ ├── Tokenizer.cpp │ └── Tokenizer.h ├── StructureSynthDoc.ico ├── SyntopiaCore ├── Exceptions │ └── Exception.h ├── GLEngine │ ├── Box.cpp │ ├── Box.h │ ├── Dot.cpp │ ├── Dot.h │ ├── EngineWidget.cpp │ ├── EngineWidget.h │ ├── Grid.cpp │ ├── Grid.h │ ├── Line.cpp │ ├── Line.h │ ├── Mesh.cpp │ ├── Mesh.h │ ├── Object3D.cpp │ ├── Object3D.h │ ├── RaytraceTriangle.cpp │ ├── RaytraceTriangle.h │ ├── Raytracer │ │ ├── AtomicCounter.cpp │ │ ├── AtomicCounter.h │ │ ├── ProgressiveOutput.h │ │ ├── RayTracer.cpp │ │ ├── RayTracer.h │ │ ├── RenderThread.cpp │ │ ├── RenderThread.h │ │ ├── Sampler.cpp │ │ ├── Sampler.h │ │ ├── VoxelStepper.cpp │ │ └── VoxelStepper.h │ ├── Sphere.cpp │ ├── Sphere.h │ ├── Triangle.cpp │ └── Triangle.h ├── Logging │ ├── ListWidgetLogger.cpp │ ├── ListWidgetLogger.h │ ├── Logging.cpp │ └── Logging.h ├── Math │ ├── Matrix4.cpp │ ├── Matrix4.h │ ├── Random.cpp │ ├── Random.h │ ├── Vector3.cpp │ └── Vector3.h └── Misc │ ├── ColorUtils.cpp │ ├── ColorUtils.h │ ├── MiniParser.cpp │ ├── MiniParser.h │ ├── Persistence.cpp │ ├── Persistence.h │ ├── Version.cpp │ └── Version.h ├── ThirdPartyCode └── MersenneTwister │ └── MersenneTwister.h ├── bugs.txt ├── changelog.txt ├── images ├── agt_internet.png ├── copy.png ├── cut.png ├── documentinfo.png ├── exit.png ├── fileclose.png ├── fileicons │ ├── Structure Synth.icns │ ├── Structure Synth.ico │ ├── StructureSynth-16.png │ ├── StructureSynth-256.png │ ├── StructureSynthDoc-256.png │ ├── StructureSynthDoc.icns │ ├── StructureSynthDoc.ico │ ├── icon.pdn │ └── icon2.pdn ├── filesaveas.png ├── folder.png ├── mail_new.png ├── new.png ├── open.png ├── paste.png ├── render.png ├── save.png ├── saveas.png └── structuresynth.png ├── notes.txt ├── resource.h ├── roadmap.txt ├── structure-synth.desktop └── structuresynth.rc /Build/Linux/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cd ../.. 4 | qmake-qt4 -project -after "CONFIG+=opengl" -after "QT+=xml opengl script" 5 | qmake-qt4 6 | make 7 | 8 | cd Build/Linux 9 | 10 | mkdir "Structure Synth" 11 | mkdir "Structure Synth/Examples" 12 | mkdir "Structure Synth/Misc" 13 | cp ../../trunk "Structure Synth/structuresynth" 14 | cp ../../LICENSE* "Structure Synth" 15 | cp -r ../../Examples/* "Structure Synth/Examples" 16 | cp -r ../../Misc/* "Structure Synth/Misc" 17 | 18 | cd "Structure Synth" 19 | rm -rf `find . -type d -name .svn` 20 | cd .. 21 | 22 | 23 | -------------------------------------------------------------------------------- /Build/Windows/EULA.txt: -------------------------------------------------------------------------------- 1 | END USER LICENSE AGREEMENT. 2 | 3 | Version 1.1. 4 | 5 | This software is provided with NO WARRANTY. 6 | 7 | That's right: not even if the software is loaded with viruses or crashes your hard-drive, can the author be held responsible. I would never intentionally include malware in the distribution, but I do not control the servers hosting the software, and will not make any guarantees. 8 | 9 | If you do not like this, do not run the software. 10 | 11 | If you are okay with this, feel free to run the software on any number of computers and use it any way you want to. 12 | 13 | If you do modify or redistribute this software make sure you respect the included GPL license (license.txt). 14 | 15 | If you found that this EULA did not exactly ease your mind and you are worried about running this software, here is a few general suggestions: 16 | (1) Run the software in a sandboxed environment. (VM-Ware Player provides excellent and free virtualization) 17 | (2) Do not run as administrator, but as a non-privileged user. 18 | (3) Compile the sources yourself. 19 | (4) Check the MD5/SHA1 checksums to see if the files have been tampered with. 20 | (5) Search Google to see if anyone has experienced problems with the software. 21 | -------------------------------------------------------------------------------- /Build/Windows/InstallerReadme.txt: -------------------------------------------------------------------------------- 1 | Notice: 2 | 3 | If you install Structure Synth into the 'Program Files' folder, you will most likely not have privileges to modify the examples and export templates. 4 | 5 | Consider installing into a non-protected directory, e.g. "c:\structure synth" 6 | -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC80.CRT.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC80.CRT/Microsoft.VC80.CRT.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC80.CRT/msvcm80.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Build/Windows/Microsoft.VC80.CRT/msvcm80.dll -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC80.CRT/msvcp80.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Build/Windows/Microsoft.VC80.CRT/msvcp80.dll -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC80.CRT/msvcr80.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Build/Windows/Microsoft.VC80.CRT/msvcr80.dll -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC90.CRT/Microsoft.VC90.CRT.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC90.CRT/msvcm90.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Build/Windows/Microsoft.VC90.CRT/msvcm90.dll -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC90.CRT/msvcp90.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Build/Windows/Microsoft.VC90.CRT/msvcp90.dll -------------------------------------------------------------------------------- /Build/Windows/Microsoft.VC90.CRT/msvcr90.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Build/Windows/Microsoft.VC90.CRT/msvcr90.dll -------------------------------------------------------------------------------- /Build/Windows/ReadMe.txt: -------------------------------------------------------------------------------- 1 | If the executable complains about missing libraries such as msvcr90.dll, msvcp90.dll or msvcm90.dll, you will need to install the 2 | Microsoft Visual C++ C Runtime Libraries: 3 | 4 | Microsoft Visual C++ 2008 Redistributable Package (x86): 5 | http://www.microsoft.com/downloads/details.aspx?FamilyID=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF&displaylang=en -------------------------------------------------------------------------------- /Build/Windows/copyWin32Files.bat: -------------------------------------------------------------------------------- 1 | rmdir /S "Structure Synth" 2 | mkdir "Structure Synth" 3 | xcopy ..\..\Examples\*.* "Structure Synth"\Examples\ /E 4 | rmdir /S "Structure Synth"\Examples\DontDeploy 5 | xcopy ..\..\Misc\*.* "Structure Synth"\Misc\ /E 6 | xcopy Microsoft.VC90.CRT\*.* "Structure Synth"\Microsoft.VC90.CRT\ /E 7 | copy ..\..\Release\structuresynth.exe "Structure Synth"\ 8 | copy %QT4DIR%\bin\QtOpenGl4.dll "Structure Synth"\ 9 | copy %QT4DIR%\bin\QtGUI4.dll "Structure Synth"\ 10 | copy %QT4DIR%\bin\QtCore4.dll "Structure Synth"\ 11 | copy %QT4DIR%\bin\QtXml4.dll "Structure Synth"\ 12 | copy %QT4DIR%\bin\QtScript4.dll "Structure Synth"\ 13 | rem copy *.manifest "Structure Synth"\ 14 | copy EULA.txt "Structure Synth"\ 15 | copy License.txt "Structure Synth"\ 16 | copy ReadMe.txt "Structure Synth"\ 17 | @rem copy C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_6b128700\msvcr80.dll "Structure Synth"\ 18 | @rem copy C:\WINDOWS\WinSxS\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.762_x-ww_6b128700\msvcp80.dll "Structure Synth"\ 19 | pause 20 | 21 | -------------------------------------------------------------------------------- /Build/Windows/installer2.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | [Setup] 5 | ; NOTE: The value of AppId uniquely identifies this application. 6 | ; Do not use the same AppId value in installers for other applications. 7 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 8 | AppId={{E4CDF523-5418-47F2-8C82-3AA9688270BE} 9 | AppName=Structure Synth 10 | AppVersion=1.5 11 | ;AppVerName=Structure Synth 1.5 12 | AppPublisher=Syntopia 13 | AppPublisherURL=http://structuresynth.sourceforge.net/ 14 | AppSupportURL=http://structuresynth.sourceforge.net/ 15 | AppUpdatesURL=http://structuresynth.sourceforge.net/ 16 | DefaultDirName={pf}\Structure Synth 17 | DefaultGroupName=Structure Synth 18 | AllowNoIcons=yes 19 | LicenseFile=F:\Structure Synth\trunk\Build\Windows\Structure Synth\EULA.txt 20 | InfoBeforeFile=F:\Structure Synth\trunk\Build\Windows\InstallerReadme.txt 21 | OutputBaseFilename=StructureSynth-Windows_Binary-v1.5.0 22 | Compression=lzma 23 | SolidCompression=yes 24 | 25 | [Registry] 26 | Root: HKCR; Subkey: "StructureSynth.Document"; ValueType: string; ValueName: ""; ValueData: "StructureSynth EisenScript File"; Flags: uninsdeletekey; Tasks: associate1 27 | Root: HKCR; Subkey: "StructureSynth.Document\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\StructureSynth.exe,1"; Tasks: associate1 28 | Root: HKCR; Subkey: "StructureSynth.Document\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\StructureSynth.exe"" ""%1"""; Tasks: associate1 29 | Root: HKCR; Subkey: ".es"; ValueType: string; ValueName: ""; ValueData: "StructureSynth.Document"; Flags: uninsdeletevalue; Tasks: associate1 30 | 31 | 32 | [Languages] 33 | Name: "english"; MessagesFile: "compiler:Default.isl" 34 | 35 | [Tasks] 36 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 37 | Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1 38 | Name: associate1; Description: "Associate EisenScript (.es) files with Structure Synth"; GroupDescription: "File Associations:" 39 | 40 | [Files] 41 | Source: "F:\Structure Synth\trunk\Build\Windows\Structure Synth\StructureSynth.exe"; DestDir: "{app}"; Flags: ignoreversion 42 | Source: "F:\Structure Synth\trunk\Build\Windows\Structure Synth\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 43 | ; NOTE: Don't use "Flags: ignoreversion" on any shared system files 44 | 45 | [Icons] 46 | Name: "{group}\Structure Synth"; Filename: "{app}\StructureSynth.exe" 47 | Name: "{group}\{cm:ProgramOnTheWeb,Structure Synth}"; Filename: "http://structuresynth.sourceforge.net/" 48 | Name: "{group}\{cm:UninstallProgram,Structure Synth}"; Filename: "{uninstallexe}" 49 | Name: "{commondesktop}\Structure Synth"; Filename: "{app}\StructureSynth.exe"; Tasks: desktopicon 50 | Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Structure Synth"; Filename: "{app}\StructureSynth.exe"; Tasks: quicklaunchicon 51 | 52 | [Run] 53 | Filename: "{app}\StructureSynth.exe"; Description: "{cm:LaunchProgram,Structure Synth}"; Flags: nowait postinstall skipifsilent 54 | 55 | -------------------------------------------------------------------------------- /BuildProcedure.txt: -------------------------------------------------------------------------------- 1 | Build Procedure: 2 | 3 | - Update Version object in MainWindow.cpp 4 | - 5 | 6 | Windows: 7 | - Change to 'Release'. Build in VS 2008. 8 | - Check dependencies in Process Explorer - update Build\Windows\copyWin32Files.bat to reflect this. 9 | - Run copyWin32Files.bat 10 | - Zip the content of 'Structure Synth' and name the files after the following template: "StructureSynth-Windows_Binary_v0.8.0.zip" 11 | - Run the Inno Setup installer. 12 | - Make an 'export' of the Trunk SVN directory (e.g. right-mouse-button-drag the directory to a new location, and use the context menu) into a directory named 'Structure Synth Source Code' and zip the contents into an archive named "StructureSynth-Source-v0.8.0.zip". 13 | - Log onto SourceForge choose 'Admin | File Releases'. Choose 'Structure Synth | Add Release'. Choose a suitable name: "Version 0.8.0 (Exonautica)" 14 | 15 | - Update the SourceForge web pages. 16 | - Send out SourceForge news. 17 | - Mention on Syntopia Blog. 18 | 19 | 20 | 21 | 22 | Template for SourceForge news updates: 23 | 24 | Structure Synth 0.9.0 ("Glasnost") Released 25 | ------------------------------------------- 26 | 27 | Binaries for Windows XP and Vista. Source for Linux and Mac. 28 | (Mac binaries will be available shortly) 29 | 30 | New features: 31 | - Template renderers: camera export is now working. 32 | - Implemented a 'Triangle' primitive. E.g.: 'Triangle[0,0,0;1,0,0;0.5,0.5,0.5]' is now a valid primitive. 33 | - Added support for '#define varname value' preprocessor substitutions (useful for declaring constant variables). 34 | 35 | Minor changes and bug fixes: 36 | - Added 'FastRotate' button (draws a subset while rotating/translating the view). 37 | - Template Renderer: Missing primitives no longer cancels the renderer, but only warns. 38 | - OpenGL renderer now turns off GLWidget when rendering (makes build phase faster). 39 | - Fixed CR+CR+LF export bug. 40 | - Enabled the Cut,Paste,Copy main menu 41 | - Removed an extensive memory leak (leaked 16 bytes per created state). 42 | - When resizing the OpenGL window, width/height/aspect ratio is shown. 43 | - Corrected some syntax highlighter bugs 44 | - Fixed a bug when going into full screen mode (not all chrome was hidden) 45 | 46 | Download instructions at: 47 | http://structuresynth.sourceforge.net/download.php 48 | 49 | 50 | -------------------------------------------------------------------------------- /Examples/Arc Sphere.es: -------------------------------------------------------------------------------- 1 | // Arc Sphere.es 2 | // Inspired by Marius Watz spheres: 3 | // http://www.flickr.com/photos/watz/363931023/ 4 | 5 | set maxobjects 10400 6 | set background #454 7 | 8 | // Camera settings. Place these before first rule call. 9 | set translation [-3.33009 0.0259899 -20] 10 | set rotation [0.147791 -0.237766 -0.960012 -0.822766 -0.568209 0.014066 -0.548833 0.787786 -0.279602] 11 | set pivot [0 0 0] 12 | set scale 0.18957 13 | 14 | 7 * { s 0.9 z -2 y 0.5 } 1 * { color #5a5 s 0.92 rz 0 } r1 15 | 7 * { s 0.9 z -2 y 0.5 } 1 * { color #aaa s 0.87 rz 0 } r1 16 | 7 * { s 0.9 z -2 y 0.5 } 1 * { color #fff } r1 17 | 18 | rule r1 w 40 { 19 | ubox 20 | dbox 21 | { x 1 ry 3 } r1 22 | } 23 | 24 | rule r1 w 14 { r2 } 25 | 26 | rule r2 w 10 { 27 | { x 1 ry 3 } r2 28 | } 29 | 30 | rule r2 { r1 } 31 | 32 | rule dbox w 8 maxdepth 15 { 33 | { y -1 rx 2.9 } dbox 34 | sbox 35 | } 36 | 37 | rule dbox { } 38 | 39 | rule ubox w 8 maxdepth 15 { 40 | { y 1 rx -2.9 } ubox 41 | sbox 42 | } 43 | 44 | rule ubox { } 45 | 46 | rule sbox { 47 | { s 1.2 1.2 0.6 ry 5 } box 48 | } -------------------------------------------------------------------------------- /Examples/Ball.es: -------------------------------------------------------------------------------- 1 | set maxdepth 2000 2 | { a 0.9 hue 30 } R1 3 | 4 | rule R1 w 10 { 5 | { x 1 rz 3 ry 5 } R1 6 | { s 1 1 0.1 sat 0.9 } box 7 | } 8 | 9 | rule R1 w 10 { 10 | { x 1 rz -3 ry 5 } R1 11 | { s 1 1 0.1 } box 12 | } 13 | 14 | -------------------------------------------------------------------------------- /Examples/BinaryKite.es: -------------------------------------------------------------------------------- 1 | set maxobjects 16000 2 | 10 * { y 1 } 10 * { z 1 } 1 * { a 0.8 sat 0.9 } r1 3 | set background #fff 4 | 5 | 6 | rule r1 { 7 | { x 1 ry 4 } r1 8 | xbox 9 | } 10 | 11 | rule r1 { 12 | { x 1 ry -4 } r1 13 | xbox 14 | } 15 | 16 | rule r1 { 17 | { x 1 rz -8 s 0.95 } r1 18 | xbox 19 | } 20 | 21 | rule r1 { 22 | { x 1 rz 8 s 0.95 } r1 23 | xbox 24 | } 25 | 26 | 27 | 28 | rule r2 maxdepth 36 { 29 | { ry 1 ry -13 x 1.2 b 0.99 h 12 } r2 30 | xbox 31 | } 32 | 33 | rule xbox { 34 | { s 1.1 color #000 } grid 35 | { b 0.7 color #000 } box 36 | } 37 | 38 | rule xbox { 39 | { s 1.1 color #000 } grid 40 | { b 0.7 color #fff } box 41 | } 42 | -------------------------------------------------------------------------------- /Examples/City of Glass.es: -------------------------------------------------------------------------------- 1 | set maxobjects 117600 2 | { a 0.4 sat 0.5 } grinder 3 | 4 | rule grinder { 5 | 36 * { ry 10 z 1.2 b 0.99 h 2 } arm 6 | } 7 | 8 | rule arm { 9 | xbox 10 | { rz -1 rx 3 z 0.22 x 0.3 ry 10 s 0.998 x 0.5 sat 0.9995 hue 0.05 } arm 11 | } 12 | 13 | rule arm { 14 | xbox 15 | { rz 1 rx 3 z 0.22 x 0.3 ry 10 s 0.99 x -0.5 sat 0.9995 hue 0.15 } arm 16 | } 17 | 18 | rule xbox { 19 | box 20 | } 21 | 22 | rule xbox { 23 | { s 0.9 } grid 24 | { b 0.7 } box 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Default.es: -------------------------------------------------------------------------------- 1 | // ------ Camera settings. 2 | set translation [0 -0.367113 -20] 3 | set rotation [0.963994 0.0575931 -0.259613 0.0514549 0.917418 0.394584 0.260899 -0.393735 0.881422] 4 | set pivot [0 0 0] 5 | set scale 0.408795 6 | 7 | // ------ The actual EisenScript 8 | set background #fff 9 | set maxdepth 400 10 | 11 | r0 12 | 13 | rule r0 { 14 | 3 * { rz 120 } R1 15 | 3 * { rz 120 } R2 16 | } 17 | 18 | rule R1 { 19 | { x 1.3 rx 1.57 rz 6 ry 3 s 0.99 hue 0.4 sat 0.99 } R1 20 | { s 4 } sphere::shiny 21 | } 22 | 23 | rule R2 { 24 | { x -1.3 rz 6 ry 3 s 0.99 hue 0.4 sat 0.99 } R2 25 | { s 4 } sphere 26 | } 27 | 28 | // ----- Settings for internal raytracer 29 | 30 | set raytracer::shadows false 31 | 32 | // the number of samples controls the quality 33 | // '6' means 6x6 samples per pixels, and is the default. 34 | set raytracer::samples 6 35 | 36 | // dof is depth-of-field. 37 | // Use 'Edit | Show 3D Object Information' to find the correct plane 38 | // comment the line below to disable this. 39 | set raytracer::dof [0.23,0.07] 40 | 41 | // Set materials either globally, 42 | // or for a selected tag (e.g. 'shiny') 43 | set raytracer::shiny::reflection 0.3 44 | set raytracer::phong [0.5,0.6,0.2] 45 | -------------------------------------------------------------------------------- /Examples/Frame In Frame.es: -------------------------------------------------------------------------------- 1 | { hue 20 sat 0.8 } r2 2 | 3 | rule r2 maxdepth 20 { 4 | { s 0.75 rz 10 b 0.9 } r2 5 | frame 6 | } 7 | 8 | rule frame { 9 | { s 0.1 1.1 0.1 x 5 z 5 } box 10 | { s 0.1 1.1 0.1 x 5 z -5 } box 11 | { s 0.1 1.1 0.1 x -5 z 5 } box 12 | { s 0.1 1.1 0.1 x -5 z -5 } box 13 | 14 | { s 1 0.1 0.1 y 5 z 5 } box 15 | { s 1 0.1 0.1 y 5 z -5 } box 16 | { s 1 0.1 0.1 y -5 z 5 } box 17 | { s 1 0.1 0.1 y -5 z -5 } box 18 | 19 | { s 0.1 0.1 1 y 5 x 5 } box 20 | { s 0.1 0.1 1 y 5 x -5 } box 21 | { s 0.1 0.1 1 y -5 x 5 } box 22 | { s 0.1 0.1 1 y -5 x -5 } box 23 | } -------------------------------------------------------------------------------- /Examples/Grinder.es: -------------------------------------------------------------------------------- 1 | // Grinder.es 2 | 3 | set maxobjects 117600 4 | grinder 5 | 6 | rule grinder { 7 | 36 * { ry 10 z 1.2 b 0.99 } 1 * { ry 34 rx 34 } arm 8 | } 9 | 10 | rule arm { 11 | xbox 12 | { rz 2 rx 3 z 0.22 x 0.3 ry 10 s 0.999 x 0.5 sat 0.9995 hue 0.05 } arm 13 | } 14 | 15 | rule arm { 16 | xbox 17 | { rz 2 rx 3 z 0.22 x 0.3 ry 10 s 0.99 x 0.5 sat 0.9995 hue 0.15 } arm 18 | } 19 | 20 | rule xbox { 21 | { b 0.7 } box 22 | } 23 | -------------------------------------------------------------------------------- /Examples/Konstrukt.es: -------------------------------------------------------------------------------- 1 | set background #000 2 | #define _md 400 3 | #define _rz 0 4 | #define _zoom 1 5 | 6 | set maxdepth _md 7 | 8 | { rz _rz s _zoom } r0 9 | 10 | rule r0 { 11 | 3 * { rz 120 } R1 12 | 3 * { rz 120 } R2 13 | } 14 | 15 | rule R1 { 16 | { x -1.3 rz 1.57 rz 6 ry 13 s 0.99 hue 1 sat 0.99 } R1 17 | { s 4 color black } box 18 | } 19 | 20 | rule R2 { 21 | { x -1.3 rz 6 ry 13 s 0.99 hue 1 sat 0.99 } R2 22 | { s 4 a 1 color white } box 23 | } -------------------------------------------------------------------------------- /Examples/Menger.es: -------------------------------------------------------------------------------- 1 | R1 2 | 3 | rule R1 maxdepth 3 > c2 { 4 | { s 1/3 x -1 y -1 } R1 5 | { s 1/3 x -1 y -1 z -1 } R1 6 | { s 1/3 x -1 y -1 z +1 } R1 7 | { s 1/3 x 1 y -1 } R1 8 | { s 1/3 x 1 y -1 z -1 } R1 9 | { s 1/3 x 1 y -1 z +1 } R1 10 | { s 1/3 y -1 z -1 } R1 11 | { s 1/3 y -1 z +1 } R1 12 | { s 1/3 x -1 y 1 } R1 13 | { s 1/3 x -1 y 1 z -1 } R1 14 | { s 1/3 x -1 y 1 z +1 } R1 15 | { s 1/3 x 1 y 1 } R1 16 | { s 1/3 x 1 y 1 z -1 } R1 17 | { s 1/3 x 1 y 1 z +1 } R1 18 | { s 1/3 y 1 z -1 } R1 19 | { s 1/3 y 1 z +1 } R1 20 | { s 1/3 x -1 z -1 } R1 21 | { s 1/3 x -1 z +1 } R1 22 | { s 1/3 x 1 z -1 } R1 23 | { s 1/3 x 1 z +1 } R1 24 | } 25 | 26 | rule c2 { 27 | box 28 | } 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Examples/MeshTest.es: -------------------------------------------------------------------------------- 1 | set maxobjects 52222 2 | set background #a00 3 | R1 4 | { x 3 s 0.9 } R1 5 | { y 3 s 0.7 } R1 6 | { y -3 s 0.6 } R1 7 | { x -3 s 0.5 } R1 8 | 9 | // Camera settings. Place these before first rule call. 10 | set translation [-2.59764 -5.03937 -20] 11 | set rotation [0.946021 0.279788 0.163595 -0.166082 -0.0149648 0.985998 0.278318 -0.959945 0.0323107] 12 | set pivot [0 0 0] 13 | set scale 1.1874 14 | 15 | 16 | rule R1 maxdepth 30 > endrule { 17 | { z 1 ry 6 s 0.91 hue 5 y 0.01 } R1 18 | mesh 19 | } 20 | 21 | rule R1 w 0.2 { 22 | { z 1 ry 6 s 0.99 hue 1 } R1 23 | { rz 90 } R1 24 | mesh 25 | } 26 | 27 | rule endrule { 28 | { s 3 } sphere 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /Examples/Moduli Creatures.es: -------------------------------------------------------------------------------- 1 | // Moduli Creatures. Syntopia 2010. 2 | // This one works best when raytraced in e.g. Sunflow. 3 | 4 | // Camera settings. Place these before first rule call. 5 | set translation [-8.07939 -6.42262 -20] 6 | set rotation [-0.608586 0.78168 -0.136359 0.78734 0.616241 0.0185897 0.0985613 -0.0960483 -0.99048] 7 | set pivot [0 0 0] 8 | set scale 0.625595 9 | 10 | set background grey 11 | 50 * { x 1 rz 5 s 0.99 color red } 20 * { y 1 rz 3 hue 1 } d 12 | 13 | rule d md 30 { 14 | { z 1 rx 5 } d 15 | { s 0.01 1 1.2 sat 0.4 } box 16 | } 17 | 18 | rule d w 0.1 { 19 | e 20 | } 21 | 22 | rule e md 5 { 23 | { z 1 rx 5 } e 24 | { s 0.01 1 1.2 sat 0.4 } box 25 | } -------------------------------------------------------------------------------- /Examples/Mondrian.es: -------------------------------------------------------------------------------- 1 | // Mondrian Cube. 2 | 3 | mondrian 4 | 5 | rule mondrian { 6 | // The six faces of the cube 7 | a2 8 | { x -0.5 z -0.5 ry 90 } a2 9 | { x +0.5 z -0.5 ry 90 } a2 10 | { z -1 } a2 11 | { y +0.5 z -0.5 rx 90 } a2 12 | { y -0.5 z -0.5 rx 90 } a2 13 | } 14 | 15 | rule a2 w 2 maxdepth 2 > d { 16 | // Split into two halves in x direction 17 | { s 0.333 1 1 x -1 } a2 18 | { s 0.666 1 1 x 0.26 } a2 19 | } 20 | 21 | rule a2 w 2 maxdepth 2 > d { 22 | // Split into two halves in y direction 23 | { s 1 0.333 1 y -1 } a2 24 | { s 1 0.666 1 y 0.26 } a2 25 | } 26 | 27 | 28 | rule a2 { d } 29 | 30 | // This rule chooses a random color. 31 | rule d { { s 1 1 0.02 color #F00 } square } 32 | rule d { { s 1 1 0.02 color #0404A2 } square } 33 | rule d { { s 1 1 0.02 color #FFFE33 } square } 34 | rule d w 2 { { s 1 1 0.02 color #FFF } square } 35 | 36 | // Draws a framed square 37 | rule square { 38 | { s 0.95 0.95 1 } box 39 | { s 0.05 1 1 b 0 x -10 } box 40 | { s 0.05 1 1 b 0 x 10 } box 41 | { s 1.05 0.05 1 b 0 y -10 } box 42 | { s 1.05 0.05 1 b 0 y 10 } box 43 | } -------------------------------------------------------------------------------- /Examples/Nabla.es: -------------------------------------------------------------------------------- 1 | set maxdepth 30 2 | 3 | { ry -90 color white } R1 4 | {rx -90 color white } R1 5 | { x 30 y 30 z -3 s 900 900 1 color white } box 6 | 7 | Rule R1 { 8 | dbox 9 | { z 0.6 rx 5 } R1 10 | } 11 | 12 | Rule R1 { 13 | dbox 14 | { z 0.6 rx -5 } R1 15 | } 16 | 17 | Rule R1 { 18 | dbox 19 | { z 0.6 rz 5 } R1 20 | } 21 | 22 | Rule R1 { 23 | dbox 24 | { z 0.6 rz -5 } R1 25 | } 26 | 27 | Rule R1 weight 0.01 { 28 | 29 | } 30 | 31 | Rule dbox { 32 | { s 1.5 1.6 0.5 } box 33 | } 34 | 35 | Rule dbox weight 0.5 { 36 | { ry 90 s 0.5 } R1 37 | } 38 | 39 | Rule dbox weight 0.5 { 40 | { rx 90 s 0.5 } R1 41 | } -------------------------------------------------------------------------------- /Examples/NablaSystem.es: -------------------------------------------------------------------------------- 1 | // 10, 20 , 21, 23, 33 , 104, 106, 118, 119, 127, 128, 133, 136, 138, 139 2 | //1, 66,69,70,73, 79 3 | 4 | set maxdepth 30 5 | 6 | { ry -90 b 0.2 } R1 7 | 8 | // Floor box 9 | //{ x 30 y 30 z -3 s 900 900 1 color red } box 10 | 11 | Rule R1 { 12 | dbox 13 | set seed initial 14 | { z 0.6 rx 5 } R1 15 | } 16 | 17 | Rule R1 { 18 | dbox 19 | { z 0.5 rx -90 } R1 20 | } 21 | 22 | Rule R1 { 23 | dbox 24 | { z 0.6 rz 90 } R1 25 | } 26 | 27 | Rule R1 { 28 | dbox 29 | { z 0.6 rz -90 } R1 30 | } 31 | 32 | Rule R1 weight 0.01 { 33 | 34 | } 35 | 36 | Rule dbox { 37 | { color random s 2 2 0.5 } box 38 | } 39 | 40 | Rule dbox weight 0.5 { 41 | { ry 90 s 0.5 1 1 } R1 42 | } 43 | 44 | Rule dbox weight 0.5 { 45 | { rx 90 s 0.5 2 1 } R1 46 | } -------------------------------------------------------------------------------- /Examples/NineWorthies.es: -------------------------------------------------------------------------------- 1 | /// The Nine Worthies 2 | /// Syntopia 2009 3 | 4 | set maxobjects 52200 5 | set maxdepth 3000 6 | set background #232 7 | 9 * { x 5 } 1 * { b 0.4 color #0a0 color white } r1 8 | // { s 1000 1000 1 color white } box 9 | 10 | // Camera settings. Place these before first rule call. 11 | set translation [-4.50383 -2.80381 -20] 12 | set rotation [0.993991 0.0947988 -0.0545559 0.0140638 0.383866 0.923278 0.108471 -0.918504 0.380229] 13 | set pivot [0 0 0] 14 | set scale 0.209524 15 | 16 | rule r1 w 10 { 17 | { rz 15 h 1 y 1 h 4 z 0.01 s 0.999 } r1 18 | r2 19 | } 20 | 21 | rule r1 w 0.1 { 22 | { rx 10 z 1 s 0.99 } r1 23 | r2 24 | } 25 | 26 | rule r2 { 27 | box 28 | { s 1.1 0.2 0.2 color orange } box 29 | grid 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /Examples/Nouveau.es: -------------------------------------------------------------------------------- 1 | #define shrink s 0.996 2 | 3 | set seed 9 4 | // Camera settings. Place these before first rule call. 5 | set translation [-2.66914 -1.23905 -20] 6 | set rotation [0.707436 -0.702911 -0.0738339 0.542177 0.472696 0.694696 -0.453408 -0.531484 0.715504] 7 | set pivot [0 0 0] 8 | set scale 0.953754 9 | 10 | set raytracer::dof [0.245,0.09] 11 | 12 | set maxdepth 1000 13 | set background #fff 14 | 16 * { rz 20 color white } hbox 15 | 16 | rule hbox { r} 17 | rule r { forward } 18 | rule r { turn } 19 | rule r { turn2 } 20 | rule r { turn4 } 21 | rule r { turn3 } 22 | //rule r { turn5 } 23 | //rule r { turn6 } 24 | 25 | rule forward md 90 > r { 26 | dbox 27 | { rz 2 x 0.1 shrink } forward 28 | } 29 | 30 | rule turn md 90 > r { 31 | dbox 32 | { rz 2 x 0.1 shrink } turn 33 | } 34 | 35 | rule turn2 md 90 > r { 36 | dbox 37 | { rz -2 x 0.1 shrink } turn2 38 | } 39 | 40 | rule turn3 md 90 > r { 41 | dbox 42 | { ry -2 x 0.1 shrink } turn3 43 | } 44 | 45 | rule turn4 md 90 > r { 46 | dbox 47 | { ry -2 x 0.1 shrink } turn4 48 | } 49 | 50 | rule turn5 md 90 > r { 51 | dbox 52 | { rx -2 x 0.1 shrink } turn5 53 | } 54 | 55 | rule turn6 md 90 > r { 56 | dbox 57 | { rx -2 x 0.1 shrink } turn6 58 | } 59 | 60 | rule dbox { 61 | { s 0.2 1 1 } box 62 | } -------------------------------------------------------------------------------- /Examples/Nouveau2.es: -------------------------------------------------------------------------------- 1 | // Nouveau system variant. 2 | 3 | #define shrink s 0.999 4 | 5 | set maxdepth 1000 6 | set background #888 7 | 6 * { rz 60 color white } hbox 8 | //{ s 80 80 0.1 color white } box 9 | //set raytracer::light [0,0,-20] 10 | 11 | rule hbox { set seed initial r} 12 | rule r { { rx 90 } forward } 13 | rule r { { rx -90 }forward } 14 | rule r { forward } 15 | rule r { forward } 16 | rule r { turn } 17 | rule r { turn2 } 18 | 19 | rule forward md 90 > r { 20 | dbox 21 | { rz 2 x 0.1 shrink } forward 22 | } 23 | 24 | rule turn md 90 > r { 25 | dbox 26 | { rz 2 x 0.1 shrink } turn 27 | } 28 | 29 | rule turn2 md 90 > r { 30 | dbox 31 | { rz -2 x 0.1 shrink } turn2 32 | } 33 | 34 | rule turn3 md 90 > r { 35 | dbox 36 | { ry -2 x 0.1 shrink } turn3 37 | } 38 | 39 | rule turn4 md 90 > r { 40 | dbox 41 | { ry -2 x 0.1 shrink } turn4 42 | } 43 | 44 | rule turn5 md 90 > r { 45 | dbox 46 | { rx -2 x 0.1 shrink } turn5 47 | } 48 | 49 | rule turn6 md 90 > r { 50 | dbox 51 | { rx -2 x 0.1 shrink } turn6 52 | } 53 | 54 | rule dbox { 55 | { s 0.2 1 1 } box 56 | { rx 10 s 0.2 1 1 color black } box 57 | } -------------------------------------------------------------------------------- /Examples/Nouveau3.es: -------------------------------------------------------------------------------- 1 | // Nouveau variant (Rounded tubes) 2 | 3 | #define shrink s 0.996 4 | 5 | 6 | set maxdepth 1000 7 | set background #fff 8 | 10 * { x 0 color white ry 10 } 2 * { rz 180 } hbox 9 | 10 | rule hbox { r} 11 | rule r { forward } 12 | rule r { turn } 13 | rule r { turn2 } 14 | rule r { turn4 } 15 | rule r { turn3 } 16 | rule r { turn5 } 17 | rule r { turn6 } 18 | 19 | rule forward md 90 > r { 20 | dbox 21 | { rz 2 x 0.1 shrink } forward 22 | } 23 | 24 | rule turn md 90 > r { 25 | dbox 26 | { rz 2 x 0.1 shrink } turn 27 | } 28 | 29 | rule turn2 md 90 > r { 30 | dbox 31 | { rz -2 x 0.1 shrink } turn2 32 | } 33 | 34 | rule turn3 md 90 > r { 35 | dbox 36 | { ry -2 x 0.1 shrink } turn3 37 | } 38 | 39 | rule turn4 md 90 > r { 40 | dbox 41 | { ry -2 x 0.1 shrink } turn4 42 | } 43 | 44 | rule turn5 md 90 > r { 45 | dbox 46 | { ry -2 x 0.1 shrink } turn5 47 | } 48 | 49 | rule turn6 md 90 > r { 50 | dbox 51 | { ry -2 x 0.1 shrink } turn6 52 | } 53 | 54 | rule dbox { 55 | { s 0.2 1 1 } sphere 56 | } -------------------------------------------------------------------------------- /Examples/Octopod II.es: -------------------------------------------------------------------------------- 1 | set maxdepth 100 2 | 3 | 10 * { ry 36 sat 0.9 } 30 * { ry 10 } 1 * { h 30 b 0.8 sat 0.8 a 0.3 } r1 4 | 5 | rule r1 w 20 { 6 | { s 0.9 rz 5 h 5 rx 5 x 1 } r1 7 | { s 1 0.2 0.5 } box 8 | } 9 | 10 | rule r1 w 20 { 11 | { s 0.99 rz -5 h 5 rx -5 x 1 } r1 12 | { s 1 0.2 0.5 } box 13 | } 14 | 15 | rule r1 { 16 | } -------------------------------------------------------------------------------- /Examples/Pure Structure.es: -------------------------------------------------------------------------------- 1 | #define shrink s 0.996 2 | 3 | set maxdepth 1000 4 | set background white 5 | set syncrandom true 6 | 7 | //set colorpool image:001.jpg 8 | 9 | set colorpool list:white,white,white,orange 10 | set minsize 0.5 11 | 12 | 5 * { x 2 } 1 * { s 0.2 0.2 1 } s2 13 | 14 | rule s2 md 25 { 15 | { z 1 } s2 16 | start 17 | } 18 | 19 | 20 | 21 | rule start { 6 * { rz 60 } hbox } 22 | 23 | rule hbox md 10 { r } 24 | 25 | rule r { 26 | set seed initial 27 | forward 28 | } 29 | 30 | rule r { turn } 31 | rule r { turn2 } 32 | 33 | rule forward md 90 > r { 34 | dbox 35 | { rz 2 x 0.1 shrink } forward 36 | } 37 | 38 | rule turn md 90 > r { 39 | dbox 40 | { rz 2 x 0.1 shrink } turn 41 | } 42 | 43 | rule turn2 md 90 > r { 44 | dbox 45 | { rz -2 x 0.1 shrink } turn2 46 | } 47 | 48 | rule turn3 md 90 > r { 49 | dbox 50 | { ry -2 x 0.1 shrink } turn3 51 | } 52 | 53 | rule turn4 md 90 > r { 54 | dbox 55 | { ry -2 x 0.1 shrink } turn4 56 | } 57 | 58 | rule turn5 md 90 > r { 59 | dbox 60 | { rx -2 x 0.1 shrink } turn5 61 | } 62 | 63 | rule turn6 md 90 > r { 64 | dbox 65 | { rx -2 x 0.1 shrink } turn6 66 | } 67 | 68 | rule dbox { 69 | { s 0.2 1 1 color random } box 70 | } -------------------------------------------------------------------------------- /Examples/Reflection.es: -------------------------------------------------------------------------------- 1 | // Reflection.es 2 | 3 | set raytracer::shadows false 4 | set raytracer::reflection 0.2 5 | set raytracer::phong [0.5,0.4,0.2] 6 | set raytracer::max-depth 5 7 | set background #fff 8 | set maxdepth 400 9 | 2 * { rx 38 color white } R1 10 | 11 | rule R1 { 12 | { x 1.3 rz 6 ry 3 s 0.99 hue 1 sat 0.99 blend red 0.02 } R1 13 | { s 6 a 1 } sphere 14 | { s 7 hue 120 a 0.2 } sphere 15 | } 16 | 17 | rule R2 { 18 | { x -1.3 rz 6 ry 3 s 0.99 hue 1 sat 0.99 blend red 0.02 } R2 19 | { s 6 a 1 } sphere 20 | { s 7 hue 120 a 0.2 } sphere 21 | } -------------------------------------------------------------------------------- /Examples/RoundTree.es: -------------------------------------------------------------------------------- 1 | set maxdepth 400 2 | 1 * { ry 90 x 6 } 10 * { rx 36 color white } R1 3 | { s 200 200 0.1 color white } box 4 | 5 | rule R1 { 6 | { x 1 rz -4 ry 6 s 0.99 } R1 7 | { s 2 } sphere 8 | } 9 | 10 | rule R1 { 11 | { x 1 rz 4 ry 6 s 0.99 } R1 12 | { s 2 } sphere 13 | } 14 | -------------------------------------------------------------------------------- /Examples/SpiralTree2D.es: -------------------------------------------------------------------------------- 1 | set maxdepth 600 2 | { h 30 sat 0.7 } spiral 3 | { ry 180 h 30 sat 0.7 } spiral 4 | 5 | rule spiral w 100 { 6 | box 7 | { y 0.4 rx 1 s 0.995 b 0.995 } spiral 8 | } 9 | 10 | rule spiral w 1 { 11 | spiral 12 | { ry 180 h 3 } spiral 13 | } 14 | -------------------------------------------------------------------------------- /Examples/Synctor.es: -------------------------------------------------------------------------------- 1 | set maxdepth 600 2 | 3 | set background #f94 4 | 5 | { sat 0.7 color green } start 6 | 7 | rule spiral w 100 { 8 | box 9 | { y 0.4 rx 5 hue 1 s 0.995 b 0.999 } spiral 10 | } 11 | 12 | rule spiral w 100 { 13 | box 14 | { y 0.4 rx 5 hue -1 rz -5 s 0.995 b 0.999 } spiral 15 | } 16 | 17 | rule spiral w 100 { 18 | box 19 | { y 0.4 rx 5 hue 0 rz 5 s 0.995 b 0.995 } spiral 20 | } 21 | 22 | rule spiral w 3 { 23 | start 24 | } 25 | 26 | rule start { 27 | set seed initial 28 | { rx 15 } spiral 29 | { ry 180 h 3 } spiral 30 | } -------------------------------------------------------------------------------- /Examples/Thingy.es: -------------------------------------------------------------------------------- 1 | #define steps 30 2 | set minsize 0.01 3 | set background white 4 | 5 | 10 * { s 0.8 rx 36 ry 10 } steps * { h 1 rz 360/steps } 1 * { x 10 rz 180} dspawn 6 | 7 | rule dspawn { 8 | spawn 9 | m 10 | } 11 | 12 | rule m { 13 | } 14 | 15 | rule spawn { 16 | set seed initial 17 | dbox 18 | } 19 | 20 | rule dbox { 21 | { x 0.1 s 0.99 sat 0.99 } dbox 22 | box 23 | } 24 | 25 | rule dbox { 26 | { x 0.1 s 0.99 ry 1 } dbox 27 | box 28 | } 29 | 30 | rule dbox { 31 | { x 0.1 s 0.99 ry -1 } dbox 32 | box 33 | } 34 | 35 | rule dbox { 36 | { x 0.1 s 0.99 ry 1 } dbox 37 | box 38 | } 39 | 40 | rule dbox { 41 | { x 0.1 s 0.99 rz -3 } dbox 42 | box 43 | } -------------------------------------------------------------------------------- /Examples/Torus2.es: -------------------------------------------------------------------------------- 1 | set maxobjects 160000 2 | { a 0.3 sat 0.5 } grinder 3 | 4 | set background #fff 5 | rule grinder { 6 | 36 * { rz 10 y 0.1 } 36 * { ry 10 z 1.2 b 0.99 h 12 } xbox 7 | } 8 | 9 | rule xbox { 10 | { s 1.1 } frame 11 | { b 0.7 color #eee a 0.2 } box 12 | } 13 | 14 | rule xbox { 15 | { s 1.1 } frame 16 | { b 0.7 color #fff a 0.3 } box 17 | } 18 | 19 | #define _f3 10 20 | #define _f1 0.05 21 | #define _f2 1.05 22 | 23 | rule frame { 24 | { s _f1 _f2 _f1 x _f3 z _f3 } box 25 | {s _f1 _f2 _f1 x _f3 z -_f3 } box 26 | { s _f1 _f2 _f1 x -_f3 z _f3} box 27 | {s _f1 _f2 _f1 x -_f3 z -_f3} box 28 | 29 | 30 | { s _f2 _f1 _f1 y _f3 z _f3 } box 31 | { s _f2 _f1 _f1 y _f3 z -_f3 } box 32 | { s _f2 _f1 _f1 y -_f3 z _f3 } box 33 | { s _f2 _f1 _f1 y -_f3 z -_f3 } box 34 | 35 | { s _f1 _f1 _f2 y _f3 x _f3 } box 36 | { s _f1 _f1 _f2 y _f3 x -_f3 } box 37 | { s _f1 _f1 _f2 y -_f3 x _f3 } box 38 | { s _f1 _f1 _f2 y -_f3 x -_f3} box 39 | 40 | } -------------------------------------------------------------------------------- /Examples/Torus3.es: -------------------------------------------------------------------------------- 1 | set maxobjects 160000 2 | { a 1.0 sat 0.5 } grinder 3 | set background #fff 4 | 5 | rule grinder { 6 | 36 * { rz 5 rz 2 y 0.1 } 36 * { ry 10 rz 3 z 1.2 b 0.99 h 12 } xbox 7 | } 8 | 9 | rule xbox { 10 | { s 1.1 } frame 11 | { b 0.7 color #eee a 1.0 } box 12 | } 13 | 14 | rule xbox { 15 | { s 1.1 } frame 16 | { b 0.7 color #fff a 1.0 } box 17 | } 18 | 19 | #define _f3 10 20 | #define _f1 0.05 21 | #define _f2 1.05 22 | 23 | rule frame { 24 | { s _f1 _f2 _f1 x _f3 z _f3 } box 25 | {s _f1 _f2 _f1 x _f3 z -_f3 } box 26 | { s _f1 _f2 _f1 x -_f3 z _f3} box 27 | {s _f1 _f2 _f1 x -_f3 z -_f3} box 28 | 29 | 30 | { s _f2 _f1 _f1 y _f3 z _f3 } box 31 | { s _f2 _f1 _f1 y _f3 z -_f3 } box 32 | { s _f2 _f1 _f1 y -_f3 z _f3 } box 33 | { s _f2 _f1 _f1 y -_f3 z -_f3 } box 34 | 35 | { s _f1 _f1 _f2 y _f3 x _f3 } box 36 | { s _f1 _f1 _f2 y _f3 x -_f3 } box 37 | { s _f1 _f1 _f2 y -_f3 x _f3 } box 38 | { s _f1 _f1 _f2 y -_f3 x -_f3} box 39 | 40 | } -------------------------------------------------------------------------------- /Examples/Trees 3d.es: -------------------------------------------------------------------------------- 1 | 2 | set background white 3 | 4 | { h 30 sat 0.7 } seed 5 | { ry 180 h 30 sat 0.7 } seed 6 | 7 | rule seed weight 100 { 8 | box 9 | { y 0.4 rx 1 s 0.995 b 0.995 } seed 10 | } 11 | 12 | rule seed weight 100 { 13 | box 14 | { y 0.4 rx 1 ry 1 s 0.995 b 0.995 } seed 15 | } 16 | 17 | rule seed weight 100 { 18 | box 19 | { y 0.4 rx 1 rz -1 s 0.995 b 0.995 } seed 20 | } 21 | 22 | rule seed weight 6 { 23 | { rx 15 } seed 24 | { ry 180 h 3 } seed 25 | } 26 | -------------------------------------------------------------------------------- /Examples/Tutorials/Blend.es: -------------------------------------------------------------------------------- 1 | // Demonstration of Blend 2 | // 3 | // The blend operator blends the current color 4 | // with the specified color. 5 | // 6 | // Notice that colors are blended in HSV space, 7 | // explaining why blending from red to blue will 8 | // go through green and yellow. 9 | 10 | 11 | set maxdepth 400 12 | R1 13 | R2 14 | 15 | rule R1 { 16 | { x 1 rz 6 ry 6 s 0.99 blend blue 0.04 } R1 17 | { s 2 } sphere 18 | } 19 | 20 | rule R2 { 21 | { x -1 rz 6 ry 6 s 0.99 blend green 0.04 } R2 22 | { s 2 } sphere 23 | } -------------------------------------------------------------------------------- /Examples/Tutorials/CSG test.es: -------------------------------------------------------------------------------- 1 | // Example of a CSG (Constructive Solid Geometry) system 2 | // Should be used with a PovRay template. 3 | // 4 | // See: 5 | // http://www.flickr.com/photos/syntopia/3644799200/ 6 | // for more information. 7 | set maxdepth 17 8 | set recursion depth 9 | 10 | template::intersection-begin 11 | { y 0.5 s 5 1 1 color white } box 12 | template::union-begin 13 | r1 14 | template::union-end 15 | template::intersection-end 16 | 17 | rule r1 md 17 { 18 | template::difference-begin 19 | sphere 20 | { s 0.99 x -0.1 } sphere 21 | template::difference-end 22 | 1 * { s 0.95 x -0.1 } 1 * { s 0.95 x -0.1 } r1 23 | } 24 | 25 | rule r1 md 17 { 26 | template::difference-begin 27 | sphere 28 | { s 0.99 x -0.1 } sphere 29 | template::difference-end 30 | 1 * { s 0.95 x -0.1 } 1 * { s 0.95 x -0.1 } r1 31 | } -------------------------------------------------------------------------------- /Examples/Tutorials/JavaScript - Movie.es: -------------------------------------------------------------------------------- 1 | #javascript 2 | 3 | function pad(number) { 4 | number = number + ''; // convert to string 5 | while (number.length < 4) { 6 | number = "0" + number; 7 | } 8 | return number; 9 | } 10 | 11 | 12 | Builder.load("NouveauMovie.es"); 13 | max =1000 ; 14 | for (i = 0; i <= max; i+=1) { 15 | c = i/max; 16 | 17 | Builder.reset(); 18 | Builder.setSize(0,100); 19 | Builder.define("_rz",c*360); 20 | Builder.define("_md",20+c*3000); 21 | Builder.define("_dofa",0.2+ 0.1*Math.sin(c*3.1415*2)); 22 | 23 | Builder.build(); 24 | 25 | // ---- Sunflow raytrace ----- 26 | /* 27 | name = "f:/Test/out" + pad(i); 28 | Builder.templateRenderToFile("Sunflow-Colored.rendertemplate", name + ".sc",true); 29 | Builder.execute('"C:/Program Files/Java/jdk1.6.0_21/bin/java"', '-Xmx1G -server -jar "%SUNFLOW%/sunflow.jar" ' + name + ".sc -nogui -o " + name + ".png", true); 30 | */ 31 | 32 | // ---- Internal raytrace ------ 33 | Builder.raytraceToFile("N" + pad(i) + ".png",true); 34 | } 35 | -------------------------------------------------------------------------------- /Examples/Tutorials/NouveauMovie.es: -------------------------------------------------------------------------------- 1 | // This system is meant to used 2 | // by the 'JavaScript - Movie.es' example. 3 | 4 | #define shrink s 0.996 5 | #define _rz 0 6 | #define _dofa 0.245 7 | #define _dofb 0.09 8 | #define _md 1000 9 | set seed 14 10 | 11 | // Camera settings. Place these before first rule call. 12 | set translation [-1.54217 -1.76221 -20] 13 | set rotation [0.530172 -0.847845 -0.00877037 0.100004 0.0522555 0.993614 -0.841972 -0.527663 0.112492] 14 | set pivot [0 0 0] 15 | set scale 1.13904 16 | 17 | set raytracer::dof [_dofa,_dofb] 18 | 19 | set maxdepth _md 20 | set background #fff 21 | 1 * { rz _rz } 16 * { rz 20 color white } hbox 22 | 23 | rule hbox { r} 24 | rule r { forward } 25 | rule r { turn } 26 | rule r { turn2 } 27 | rule r { turn4 } 28 | rule r { turn3 } 29 | //rule r { turn5 } 30 | //rule r { turn6 } 31 | 32 | rule forward md 90 > r { 33 | dbox 34 | { rz 2 x 0.1 shrink } forward 35 | } 36 | 37 | rule turn md 90 > r { 38 | dbox 39 | { rz 2 x 0.1 shrink } turn 40 | } 41 | 42 | rule turn2 md 90 > r { 43 | dbox 44 | { rz -2 x 0.1 shrink } turn2 45 | } 46 | 47 | rule turn3 md 90 > r { 48 | dbox 49 | { ry -2 x 0.1 shrink } turn3 50 | } 51 | 52 | rule turn4 md 90 > r { 53 | dbox 54 | { ry -2 x 0.1 shrink } turn4 55 | } 56 | 57 | rule turn5 md 90 > r { 58 | dbox 59 | { rx -2 x 0.1 shrink } turn5 60 | } 61 | 62 | rule turn6 md 90 > r { 63 | dbox 64 | { rx -2 x 0.1 shrink } turn6 65 | } 66 | 67 | rule dbox { 68 | { s 0.2 1 1 } box 69 | } -------------------------------------------------------------------------------- /Examples/Tutorials/Preprocessor.es: -------------------------------------------------------------------------------- 1 | /* 2 | An example of using preprocessor defines. 3 | 4 | A preprocessor '#define' makes it easier 5 | to explore parameter settings that are used 6 | multiple times in the script. 7 | */ 8 | 9 | #define sizeStep 0.98 10 | #define angle 6 11 | 12 | set maxdepth 100 13 | set background black 14 | 15 | 18 * { rx 10 x 0.2 sat 0.95 } R 16 | 17 | 18 | rule R { R1 } 19 | 20 | rule R1 { 21 | { x 0.6 rz angle ry angle s sizeStep hue 1 a 0.99 } R1 22 | { s 1 1 0.1 } sbox 23 | } 24 | 25 | rule R2 { 26 | { x -0.6 rz angle ry angle s sizeStep hue 1 sat 1 a 0.99 } R2 27 | { s 1 1 0.1 } sbox 28 | } 29 | 30 | rule sbox { 31 | { color black } grid 32 | { b 0.8 hue 67 } box 33 | } 34 | -------------------------------------------------------------------------------- /Examples/Tutorials/PreprocessorGUI.es: -------------------------------------------------------------------------------- 1 | /* 2 | An example of using GUI preprocessor defines. 3 | 4 | The "float" suffix makes it possible to control variables via sliders. 5 | The 'int' suffix is identical to the above, but only accepts natural numbers. 6 | */ 7 | 8 | #define sizeStep 0.94 (float:0-1) 9 | #define angle1 20 (float:0-90) 10 | #define angle2 6 (float:0-90) 11 | #define iterations 6 (int:1-90) 12 | 13 | 14 | set maxdepth 100 15 | set background black 16 | 17 | iterations * { rx 10 x 0.2 sat 0.95 } R 18 | 19 | 20 | rule R { 21 | set seed initial 22 | R1 23 | } 24 | 25 | rule R1 { 26 | { x 0.6 rz 0 ry angle1 s sizeStep hue 1 a 0.99 } R1 27 | { s 1 1 0.1 color green } sbox 28 | } 29 | 30 | rule R1 { 31 | { x 0.6 rz angle2 ry 0 s sizeStep hue 1 a 0.99 } R1 32 | { s 1 1 0.1 color red } sbox 33 | } 34 | 35 | rule sbox { 36 | { color black } grid 37 | { b 0.8 hue 67 } box 38 | } 39 | -------------------------------------------------------------------------------- /Examples/Tutorials/Primitives.es: -------------------------------------------------------------------------------- 1 | /* 2 | This is just a simple demonstration 3 | of the various primitives in Structure Synth. 4 | */ 5 | 6 | set maxdepth 20 7 | set background white 8 | 9 | // Camera settings. Place these before first rule call. 10 | set translation [4.6096 -1.3831 -20] 11 | set rotation [-0.923481 0.370221 -0.100283 -0.119863 -0.0301876 0.992333 0.364361 0.928431 0.0722537] 12 | set pivot [0 0 0] 13 | set scale 0.38721 14 | 15 | R6 16 | { x 4 } R2 17 | { x 8 } R3 18 | { x 12 } R4 19 | { x 16 } R5 20 | { x 20 } R1 21 | 22 | rule R1 maxdepth 8 { 23 | { z 1 rz 0 rx 10 s 1.2 h 20 } R1 24 | sphere 25 | } 26 | 27 | 28 | rule R2 maxdepth 8 { 29 | { z 1 rz 0 rx 10 s 1.2 h 20 } R2 30 | box 31 | } 32 | 33 | rule R3 maxdepth 8 { 34 | { z 1 rz 0 rx 10 s 1.2 h 20 } R3 35 | dot 36 | } 37 | 38 | rule R4 maxdepth 8 { 39 | { z 1 rz 0 rx 10 s 1.2 h 20 } R4 40 | line 41 | } 42 | 43 | rule R5 maxdepth 8 { 44 | { z 1 rz 0 rx 10 s 1.2 h 20 } R5 45 | grid 46 | } 47 | 48 | rule R6 maxdepth 8 { 49 | { z 1 rz 0 rx 10 s 1.2 h 20 } R6 50 | mesh 51 | } -------------------------------------------------------------------------------- /Examples/Tutorials/RandomColor.es: -------------------------------------------------------------------------------- 1 | /* 2 | A demonstration of random colors in Structure Synth 3 | 4 | Use the 'color random' to select a random color. 5 | 6 | There a different schemes for creating random colors: 7 | 8 | 'randomhue' - HSV color with random hue, max brigthness and saturation. 9 | 'randomrgb' - random R,G,B. 10 | 'greyscale' - random R=G=B. 11 | 'image' - samples a random pixel from the specified image 12 | the image must be located relative to the current path 13 | (look at error message to see where Structure Synth tries to find the file.) 14 | 'list:xxx' - chooses a random color from the list. 15 | 16 | */ 17 | 18 | //set colorpool randomhue 19 | //set colorpool randomrgb 20 | //set colorpool greyscale 21 | //set colorpool image:001.jpg 22 | set colorpool list:red,orange,yellow,white,white 23 | 24 | 25 | face 26 | { rx 90 } face 27 | { ry -90 } face 28 | 29 | rule face { 30 | 10 * { x 1 } 10 * { y 1 } 1 * { x -1 y -1 } mybox 31 | } 32 | 33 | rule mybox { 34 | { rz 5 ry 5 s 1 1 0.1 color random } box 35 | } 36 | 37 | rule mybox { 38 | { rz 5 ry -5 s 1 1 0.1 color random } box 39 | } 40 | 41 | rule mybox { 42 | { rz 5 rx -5 s 1 1 0.1 color random } box 43 | } -------------------------------------------------------------------------------- /Examples/Tutorials/Raytracer - Light.es: -------------------------------------------------------------------------------- 1 | // Use the light command to control the lightning 2 | // Only one light source is possible, and it controls 3 | // both hard shadows and specular and diffuse lightning. 4 | set raytracer::light [0,0,5] 5 | 6 | // Camera settings. Place these before first rule call. 7 | set translation [-0.0593143 0.0238477 -20] 8 | set rotation [-0.00666739 0.999819 0.0178465 -0.999778 -0.00630773 -0.0201334 -0.0200167 -0.0179761 0.999636] 9 | set pivot [0 0 0] 10 | set scale 0.379953 11 | 12 | 1 * { x 2.5 } 20 * { rz 18 y 1 } 1 * { z 1 s 0.2 0.2 2 color white } box 13 | 1 * { x 5 } 20 * { rz 18 y 2 } 1 * { z 1 s 0.2 0.2 2 color white } box 14 | 1 * { x 7.5 } 20 * { rz 18 y 3 } 1 * { z 1 s 0.2 0.2 2 color white } box 15 | { s 50 50 0.1 color white } box -------------------------------------------------------------------------------- /Examples/Tutorials/TriangleComposites.es: -------------------------------------------------------------------------------- 1 | // This example shows how to build 2 | // custom primitives from individual polygons. 3 | // Note that the Triangle primitives are NOT supported 4 | // by most of the templates. 5 | 6 | 5 * { x 2 } 5 * { y 2 hue 20 } house 7 | 8 | rule house { 9 | { color black s 1.01 } grid 10 | box 11 | { z 1 sat 0.4 } pyramid 12 | } 13 | 14 | rule house { 15 | { color black s 1.01 } grid 16 | box 17 | { z 1 } bar 18 | } 19 | 20 | rule pyramid { 21 | triangle[0,0,0;1,0,0;0.5,0.5,0.5] 22 | triangle[1,0,0;1,1,0;0.5,0.5,0.5] 23 | triangle[1,1,0;0,1,0;0.5,0.5,0.5] 24 | triangle[0,1,0;0,0,0;0.5,0.5,0.5] 25 | } 26 | 27 | rule bar { 28 | triangle[0,0,0;1,0,0;0.5,0,0.5] 29 | triangle[1,0,0;1,1,0;0.5,0,0.5] 30 | triangle[0.5,0,0.5;1,1,0;0.5,1,0.5] 31 | triangle[0,1,0;0.5,1,0.5;1,1,0] 32 | triangle[0,0,0;0.5,0,0.5;0,1,0] 33 | triangle[0.5,0,0.5;0.5,1,0.5;0,1,0] 34 | } -------------------------------------------------------------------------------- /LICENSE.README: -------------------------------------------------------------------------------- 1 | This software is licensed under either LGPL 2.1 ("LICENSE.LGPL") or GPL 3 ("LICENSE.GPL3"). 2 | 3 | The choice of license is determined and inherited from the version of Qt used. 4 | See: http://www.qtsoftware.com/products/licensing for more info. 5 | -------------------------------------------------------------------------------- /Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "StructureSynth/GUI/MainWindow.h" 4 | 5 | // Needed for unicode commandline below. 6 | #ifdef Q_WS_WIN 7 | #define WIN32_LEAN_AND_MEAN 8 | #include "windows.h" 9 | #endif 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | Q_INIT_RESOURCE(StructureSynth); 14 | //QApplication::setStyle("cleanlooks"); 15 | QApplication app(argc, argv); 16 | 17 | QCoreApplication::setOrganizationName("Syntopia Software"); 18 | QCoreApplication::setApplicationName("Structure Synth"); 19 | 20 | QPixmap pixmap(QDir(StructureSynth::GUI::MainWindow::getMiscDir()).absoluteFilePath("splash.png")); 21 | QSplashScreen splash(pixmap, Qt::WindowStaysOnTopHint); 22 | splash.setMask(pixmap.mask()); 23 | splash.show(); 24 | qApp->processEvents(); 25 | 26 | // We will parse for filenames. 27 | // On Windows 'argv*' is not of much use, since it fails for Unicode paths. 28 | // We will fetch the unicode strings... 29 | QStringList args; 30 | 31 | #ifdef Q_WS_WIN 32 | // On Windows we call this Win32 call... 33 | int nArgs = 0; 34 | LPWSTR* wargv = CommandLineToArgvW(GetCommandLineW(), &nArgs); 35 | for (int i = 0; i < nArgs; i++) { args.append(QString::fromUtf16((const ushort *)wargv[i])); } 36 | #else 37 | // Other platforms must implement their unicode parsing here... 38 | // I believe Linux and Unix will store UTF8 in the argv array. 39 | for (int i = 0; i < argc; i++) { 40 | args.append(QString::fromUtf8(argv[i])); 41 | } 42 | #endif 43 | 44 | StructureSynth::GUI::MainWindow *mainWin; 45 | if (args.size() <= 1) { 46 | mainWin = new StructureSynth::GUI::MainWindow(); 47 | } else { 48 | // We ignore more then one argument 49 | mainWin = new StructureSynth::GUI::MainWindow(args[1]); 50 | } 51 | mainWin->show(); 52 | splash.show(); 53 | return app.exec(); 54 | } 55 | 56 | -------------------------------------------------------------------------------- /Misc/Blender_Importer_2.rendertemplate: -------------------------------------------------------------------------------- 1 | 4 | 37 | -------------------------------------------------------------------------------- /Misc/SunFlow-Monochrome.rendertemplate: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Misc/Sunflow-Colored.rendertemplate: -------------------------------------------------------------------------------- 1 | 129 | -------------------------------------------------------------------------------- /Misc/Sunflow-Ward.rendertemplate: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /Misc/about.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Misc/about.html -------------------------------------------------------------------------------- /Misc/appleseed.rendertemplate: -------------------------------------------------------------------------------- 1 | 80 | -------------------------------------------------------------------------------- /Misc/cube.obj: -------------------------------------------------------------------------------- 1 | # Exported from Wings 3D 1.3.0.1 2 | mtllib cube.mtl 3 | o cube 4 | #8 vertices, 6 faces 5 | v -0.50000000 0.0000000e+0 -0.50000000 6 | v 0.50000000 0.0000000e+0 -0.50000000 7 | v -0.50000000 1.00000000 -0.50000000 8 | v 0.50000000 1.00000000 -0.50000000 9 | v -0.50000000 0.0000000e+0 0.50000000 10 | v 0.50000000 0.0000000e+0 0.50000000 11 | v -0.50000000 1.00000000 0.50000000 12 | v 0.50000000 1.00000000 0.50000000 13 | vt 4.9500000e-3 4.9500000e-3 14 | vt 4.9500000e-3 0.99504900 15 | vt 0.99504900 4.9500000e-3 16 | vt 0.99504900 0.99504900 17 | vn 0.0000000e+0 0.0000000e+0 -1.00000000 18 | vn 0.0000000e+0 -1.00000000 0.0000000e+0 19 | vn -1.00000000 0.0000000e+0 0.0000000e+0 20 | vn 0.0000000e+0 0.0000000e+0 -1.00000000 21 | vn 0.0000000e+0 -1.00000000 0.0000000e+0 22 | vn 1.00000000 0.0000000e+0 0.0000000e+0 23 | vn 0.0000000e+0 0.0000000e+0 -1.00000000 24 | vn 0.0000000e+0 1.00000000 0.0000000e+0 25 | vn -1.00000000 0.0000000e+0 0.0000000e+0 26 | vn 0.0000000e+0 0.0000000e+0 -1.00000000 27 | vn 1.00000000 0.0000000e+0 0.0000000e+0 28 | vn 0.0000000e+0 1.00000000 0.0000000e+0 29 | vn 0.0000000e+0 0.0000000e+0 1.00000000 30 | vn 0.0000000e+0 -1.00000000 0.0000000e+0 31 | vn -1.00000000 0.0000000e+0 0.0000000e+0 32 | vn 0.0000000e+0 0.0000000e+0 1.00000000 33 | vn 0.0000000e+0 -1.00000000 0.0000000e+0 34 | vn 1.00000000 0.0000000e+0 0.0000000e+0 35 | vn 0.0000000e+0 0.0000000e+0 1.00000000 36 | vn 0.0000000e+0 1.00000000 0.0000000e+0 37 | vn -1.00000000 0.0000000e+0 0.0000000e+0 38 | vn 0.0000000e+0 0.0000000e+0 1.00000000 39 | vn 1.00000000 0.0000000e+0 0.0000000e+0 40 | vn 0.0000000e+0 1.00000000 0.0000000e+0 41 | g cube 42 | usemtl Default 43 | s 1 44 | f 1/2/1 3/2/7 4/4/10 2/4/4 45 | f 6/3/16 8/3/22 7/1/19 5/1/13 46 | s 2 47 | f 1/2/3 5/1/15 7/1/21 3/2/9 48 | f 4/4/11 8/3/23 6/3/18 2/4/6 49 | s 3 50 | f 2/4/5 6/3/17 5/1/14 1/2/2 51 | f 3/2/8 7/1/20 8/3/24 4/4/12 52 | -------------------------------------------------------------------------------- /Misc/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Misc/icon.jpg -------------------------------------------------------------------------------- /Misc/povray.rendertemplate: -------------------------------------------------------------------------------- 1 | 83 | -------------------------------------------------------------------------------- /Misc/povray2.rendertemplate: -------------------------------------------------------------------------------- 1 | 86 | -------------------------------------------------------------------------------- /Misc/renderman.rendertemplate: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Misc/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/Misc/splash.png -------------------------------------------------------------------------------- /StructureSynth.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/StructureSynth.ico -------------------------------------------------------------------------------- /StructureSynth.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/copy.png 4 | images/cut.png 5 | images/new.png 6 | images/open.png 7 | images/paste.png 8 | images/save.png 9 | images/filesaveas.png 10 | images/folder.png 11 | images/mail_new.png 12 | images/render.png 13 | images/agt_internet.png 14 | images/exit.png 15 | images/fileclose.png 16 | images/documentinfo.png 17 | images/structuresynth.png 18 | 19 | 20 | -------------------------------------------------------------------------------- /StructureSynth.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual C++ Express 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StructureSynth", "StructureSynth.vcproj", "{D41D8CD9-8F00-3204-A980-0998ECF8427E}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {D41D8CD9-8F00-3204-A980-0998ECF8427E}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {D41D8CD9-8F00-3204-A980-0998ECF8427E}.Debug|Win32.Build.0 = Debug|Win32 14 | {D41D8CD9-8F00-3204-A980-0998ECF8427E}.Release|Win32.ActiveCfg = Release|Win32 15 | {D41D8CD9-8F00-3204-A980-0998ECF8427E}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /StructureSynth/GUI/TemplateExportDialog.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "../Model/Rendering/TemplateRenderer.h" 31 | 32 | namespace StructureSynth { 33 | namespace GUI { 34 | 35 | 36 | class MainWindow; // Forward declaration. 37 | 38 | /// The Variable Editor window. 39 | class TemplateExportDialog : public QDialog { 40 | Q_OBJECT 41 | public: 42 | TemplateExportDialog(MainWindow* parent, QStringList primitives); 43 | ~TemplateExportDialog(); 44 | 45 | 46 | void setTemplatePath(QString templatePath); 47 | void setDefaultSize(int width, int height); 48 | void changeFileNameExtension(QString extension); 49 | 50 | 51 | public slots: 52 | void multiplySize(double d); 53 | void halfSize(); 54 | void doubleSize(); 55 | void defaultSize(); 56 | void accept(); 57 | void reject(); 58 | void templateChanged(const QString &); 59 | void saveModifications(); 60 | void undo(); 61 | void textChanged(); 62 | void tabChanged(int i); 63 | 64 | 65 | void lockAspectChanged(); 66 | void heightChanged(int); 67 | void widthChanged(int); 68 | void selectFileName(); 69 | void uniqueToggled(bool); 70 | void updateUniqueFileName(const QString &); 71 | 72 | 73 | void fileRadioButtonToggled(bool); 74 | void changeTemplatePath(); 75 | 76 | protected: 77 | void retranslateUi(); 78 | 79 | void setupUi(); 80 | 81 | private: 82 | void setAspectLabel(double ratio) ; 83 | Model::Rendering::Template currentTemplate; 84 | 85 | QStringList primitives; 86 | QString path; 87 | QVBoxLayout *verticalLayout; 88 | QHBoxLayout *horizontalLayout; 89 | QLabel *label; 90 | QComboBox *templateComboBox; 91 | QPushButton *templatePathButton; 92 | QTabWidget *tabWidget; 93 | QWidget *settingstab; 94 | QVBoxLayout *verticalLayout_3; 95 | QLabel *descriptionLabel; 96 | QTextBrowser *descriptionTextBrowser; 97 | QLabel *primitivesLabel; 98 | QTableWidget *primitivesTableWidget; 99 | QGroupBox *templateOutputGroupBox; 100 | QVBoxLayout *verticalLayout_2; 101 | QHBoxLayout *horizontalLayout_2; 102 | QRadioButton *fileRadioButton; 103 | QLineEdit *fileNameLineEdit; 104 | QPushButton *filePushButton; 105 | QHBoxLayout *horizontalLayout_3; 106 | QSpacerItem *horizontalSpacer; 107 | QCheckBox *uniqueCheckBox; 108 | QCheckBox *autoSaveCheckBox; 109 | QRadioButton *clipboardRadioButton; 110 | QGroupBox *postProcessingGroupBox; 111 | QVBoxLayout *verticalLayout_4; 112 | QCheckBox *runAfterCheckBox; 113 | QHBoxLayout *horizontalLayout_4; 114 | QSpacerItem *horizontalSpacer_2; 115 | QLineEdit *afterCommandLineEdit; 116 | QWidget *advancedTab; 117 | QVBoxLayout *verticalLayout_5; 118 | QHBoxLayout *horizontalLayout_5; 119 | QLabel *label_4; 120 | QSpinBox *widthSpinBox; 121 | double aspectRatio; 122 | QLabel *label_5; 123 | QSpinBox *heightSpinBox; 124 | QFrame *line; 125 | QCheckBox *lockAspectRatioCheckBox; 126 | QSpacerItem *horizontalSpacer_4; 127 | QLabel *modifyTemplateLabel; 128 | QTextEdit *templateTextEdit; 129 | QHBoxLayout *horizontalLayout_6; 130 | QSpacerItem *horizontalSpacer_3; 131 | QPushButton *saveModificationsButton; 132 | QPushButton *undoButton; 133 | QCheckBox * modifyOutputCheckBox; 134 | QDialogButtonBox *buttonBox; 135 | QString modifiedTemplate; 136 | MainWindow* mainWindow; 137 | QString uniqueFileName; 138 | int screenWidth; 139 | int screenHeight; 140 | }; 141 | 142 | 143 | } 144 | } 145 | 146 | -------------------------------------------------------------------------------- /StructureSynth/GUI/VariableEditor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../Parser/Preprocessor.h" 11 | 12 | /// Classes for the GUI Editor for the preprocessor constant variables. 13 | /// E.g. the line: #define angle 45 (float:0.0-360.0) 14 | /// will make a simple editor widget appear. 15 | namespace StructureSynth { 16 | namespace GUI { 17 | 18 | class VariableWidget; // Forward decl... 19 | 20 | /// The Variable Editor window. 21 | class VariableEditor : public QWidget { 22 | public: 23 | VariableEditor(QWidget* parent); 24 | 25 | QString updateFromPreprocessor(Parser::Preprocessor* pp, QString in, bool* showGUI); 26 | 27 | private: 28 | 29 | QSpacerItem* spacer; 30 | QVector variables; 31 | QVBoxLayout* layout; 32 | }; 33 | 34 | // A helper class (combined float slider+spinner) 35 | class ComboSlider : public QWidget { 36 | Q_OBJECT 37 | public: 38 | ComboSlider(QWidget* parent, double defaultValue, double minimum, double maximum) 39 | : QWidget(parent), defaultValue(defaultValue), minimum(minimum), maximum(maximum){ 40 | setLayout(new QHBoxLayout()); 41 | slider = new QSlider(Qt::Horizontal,this); 42 | slider->setRange(0,1000); 43 | double val = (defaultValue-minimum)/(maximum-minimum); 44 | slider->setValue(val*1000); 45 | spinner = new QDoubleSpinBox(this); 46 | spinner->setMaximum(maximum); 47 | spinner->setMinimum(minimum); 48 | spinner->setValue(defaultValue); 49 | layout()->addWidget(slider); 50 | layout()->addWidget(spinner); 51 | connect(spinner, SIGNAL(valueChanged(double)), this, SLOT(spinnerChanged(double))); 52 | connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); 53 | } 54 | 55 | double getValue() { return spinner->value(); } 56 | 57 | protected slots: 58 | void spinnerChanged(double) { 59 | double val = (spinner->value()-minimum)/(maximum-minimum); 60 | slider->setValue(val*1000); 61 | } 62 | 63 | void sliderChanged(int) { 64 | double val = (slider->value()/1000.0)*(maximum-minimum)+minimum; 65 | spinner->setValue(val); 66 | } 67 | 68 | private: 69 | 70 | QSlider* slider; 71 | QDoubleSpinBox* spinner; 72 | double defaultValue; 73 | double minimum; 74 | double maximum; 75 | }; 76 | 77 | // A helper class (combined int slider+spinner) 78 | class IntComboSlider : public QWidget { 79 | Q_OBJECT 80 | public: 81 | IntComboSlider(QWidget* parent, int defaultValue, int minimum, int maximum) 82 | : QWidget(parent), defaultValue(defaultValue), minimum(minimum), maximum(maximum){ 83 | setLayout(new QHBoxLayout()); 84 | slider = new QSlider(Qt::Horizontal,this); 85 | slider->setRange(minimum,maximum); 86 | slider->setValue(defaultValue); 87 | spinner = new QSpinBox(this); 88 | spinner->setMaximum(maximum); 89 | spinner->setMinimum(minimum); 90 | spinner->setValue(defaultValue); 91 | layout()->addWidget(slider); 92 | layout()->addWidget(spinner); 93 | connect(spinner, SIGNAL(valueChanged(int)), this, SLOT(spinnerChanged(int))); 94 | connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int))); 95 | } 96 | 97 | int getValue() { return spinner->value(); } 98 | 99 | protected slots: 100 | void spinnerChanged(int) { 101 | int val = spinner->value(); 102 | slider->setValue(val); 103 | } 104 | 105 | void sliderChanged(int) { 106 | double val = slider->value(); 107 | spinner->setValue(val); 108 | } 109 | 110 | private: 111 | 112 | QSlider* slider; 113 | QSpinBox* spinner; 114 | int defaultValue; 115 | int minimum; 116 | int maximum; 117 | }; 118 | 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /StructureSynth/JavaScriptSupport/Debug.cpp: -------------------------------------------------------------------------------- 1 | #if defined(_MSC_VER) 2 | // disable warning "'QtConcurrent::BlockSizeManager' : assignment operator could not be generated" 3 | #pragma warning( disable : 4512 ) 4 | #endif 5 | 6 | #include "Debug.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "SyntopiaCore/Logging/Logging.h" 15 | #include "../../SyntopiaCore/Exceptions/Exception.h" 16 | #include "../../SyntopiaCore/GLEngine/Sphere.h" 17 | 18 | using namespace SyntopiaCore::Logging; 19 | using namespace SyntopiaCore::Exceptions; 20 | 21 | 22 | namespace StructureSynth { 23 | namespace JavaScriptSupport { 24 | 25 | namespace { 26 | // Dont know why Qt has chosen to make 'sleep' protected. 27 | class MyThread : public QThread { 28 | public: 29 | static void sleep(unsigned long msecs) { msleep(msecs); } 30 | }; 31 | 32 | 33 | }; 34 | 35 | Debug::Debug(QStatusBar* statusBar) : statusBar(statusBar) { 36 | progress = 0; 37 | } 38 | 39 | Debug::~Debug() { 40 | } 41 | 42 | void Debug::Info(QString input) { 43 | INFO(input); 44 | } 45 | 46 | void Debug::Message(QString input) { 47 | QMessageBox::information(0, "JavaScript Message", input); 48 | } 49 | 50 | void Debug::ShowProgress(QString caption) { 51 | delete(progress); 52 | progress = new QProgressDialog(caption, "Cancel", 0, 1000, 0); 53 | progress->setWindowModality(Qt::WindowModal); 54 | progress->show(); 55 | 56 | } 57 | 58 | void Debug::SetProgress(double percentage) { 59 | if (progress) progress->setValue(percentage*1000.0); 60 | qApp->processEvents(); 61 | } 62 | 63 | void Debug::HideProgress() { 64 | delete(progress); 65 | progress = 0; 66 | } 67 | 68 | void Debug::Sleep(int ms) { 69 | MyThread::sleep(ms); 70 | } 71 | 72 | 73 | void Debug::waitForMouseButton() { 74 | while (true) { 75 | 76 | statusBar->showMessage("Left Mousebutton to continue, right to quit.", 4000); 77 | if (QApplication::mouseButtons() == Qt::LeftButton) { 78 | //statusBar->showMessage(""); 79 | 80 | break; 81 | } else if (QApplication::mouseButtons() == Qt::RightButton) { 82 | //statusBar->showMessage(""); 83 | throw Exception(""); 84 | break; 85 | } 86 | qApp->processEvents(); 87 | //QThread::msleep(100); 88 | 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /StructureSynth/JavaScriptSupport/Debug.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../../SyntopiaCore/Math/Vector3.h" 8 | #include "../../SyntopiaCore/GLEngine/EngineWidget.h" 9 | #include "../GUI/MainWindow.h" 10 | 11 | namespace StructureSynth { 12 | namespace JavaScriptSupport { 13 | 14 | /// Write info to console (available as a Global object field in the JavaScript environment). 15 | class Debug : public QObject { 16 | Q_OBJECT 17 | 18 | public: 19 | Debug(QStatusBar* statusBar); 20 | ~Debug(); 21 | 22 | public slots: 23 | void Info(QString input); 24 | void Message(QString input); 25 | void ShowProgress(QString caption); 26 | void SetProgress(double percentage); // between 0 and 1 27 | void HideProgress(); 28 | void Sleep(int ms); 29 | void waitForMouseButton(); 30 | 31 | private: 32 | QProgressDialog* progress; 33 | QStatusBar* statusBar; 34 | }; 35 | 36 | 37 | } 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /StructureSynth/JavaScriptSupport/JavaScriptParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "../GUI/MainWindow.h" 6 | 7 | 8 | namespace StructureSynth { 9 | namespace JavaScriptSupport { 10 | 11 | /// Responsible for setting up the JavaScript environment and parsing 12 | class JavaScriptParser { 13 | public: 14 | JavaScriptParser(StructureSynth::GUI::MainWindow* mainWindow, QStatusBar* statusBar); 15 | ~JavaScriptParser(); 16 | 17 | void parse(QString input, QString dir); 18 | private: 19 | StructureSynth::GUI::MainWindow* mainWindow; 20 | QStatusBar* statusBar; 21 | }; 22 | 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /StructureSynth/Model/Action.cpp: -------------------------------------------------------------------------------- 1 | #include "Action.h" 2 | #include "ExecutionStack.h" 3 | #include "Builder.h" 4 | 5 | #include "../../SyntopiaCore/Logging/Logging.h" 6 | 7 | using namespace SyntopiaCore::Logging; 8 | 9 | namespace StructureSynth { 10 | namespace Model { 11 | void Action::apply(Builder* b, const Rule* callingRule, int ruleDepth) const { 12 | bool rememberPreviousMatrix = true; // at some point we might make this optional -> only needed for grid meshes... 13 | 14 | if (set != 0) { 15 | b->setCommand(set->key, set->value); 16 | return; 17 | } 18 | 19 | State s = b->getState(); 20 | 21 | 22 | QList counters; 23 | for (int i = 0; i < loops.size(); i++) counters.append(1); 24 | 25 | if (counters.size() == 0) { 26 | if (callingRule) { 27 | s.maxDepths[callingRule] = ruleDepth; 28 | } 29 | b->getNextStack().append(RuleState(rule->rule(), s)); 30 | return; 31 | } 32 | 33 | bool done = false; 34 | while (!done) { 35 | 36 | // create state 37 | State s0 = s; 38 | if (rememberPreviousMatrix) { 39 | // Copy the old matrix... 40 | s0.setPreviousState(s.matrix, s.hsv, s.alpha); 41 | } 42 | for (int i = 0; i < counters.size(); i++) { 43 | for (int j = 0; j < counters[i]; j++) { 44 | s0 = loops[i].transformation.apply(s0, b->getColorPool()); 45 | } 46 | } 47 | if (callingRule) { 48 | s0.maxDepths[callingRule] = ruleDepth; 49 | } 50 | b->getNextStack().append(RuleState(rule->rule(), s0)); 51 | 52 | // increase lowest counter... 53 | counters[0]++; 54 | for (int i = 0; i < counters.size(); i++) { 55 | if (counters[i] > loops[i].repetitions) { 56 | if (i == counters.size()-1) { 57 | done = true; 58 | } else { 59 | counters[i] = 1; 60 | counters[i+1]++; 61 | } 62 | } 63 | } 64 | 65 | } 66 | } 67 | 68 | Action::Action(QString key, QString value) { 69 | set = new SetAction(); 70 | set->key = key; 71 | set->value = value; 72 | rule = 0; 73 | } 74 | 75 | Action::~Action() { 76 | // TODO: Handle leaks (Actions are treated as value types, and hence rule,set ptrs are duped) 77 | //delete(rule); 78 | //delete(set); 79 | } 80 | 81 | 82 | void Action::addTransformationLoop(TransformationLoop tl) { 83 | loops.append(tl); 84 | } 85 | 86 | void Action::setRule(QString ruleName) { 87 | rule = new RuleRef(ruleName); 88 | set = 0; 89 | } 90 | 91 | Action::Action(Transformation t, QString ruleName) { 92 | loops.append(TransformationLoop(1, t)); 93 | rule = new RuleRef(ruleName); 94 | set = 0; 95 | } 96 | 97 | Action::Action(QString ruleName) { 98 | rule = new RuleRef(ruleName); 99 | set = 0; 100 | } 101 | 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /StructureSynth/Model/Action.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "RuleRef.h" 4 | #include "TransformationLoop.h" 5 | 6 | namespace StructureSynth { 7 | namespace Model { 8 | 9 | struct SetAction { 10 | QString key; 11 | QString value; 12 | }; 13 | 14 | /// An actions is a number of loops, that is applied to a rule. 15 | /// 16 | /// Rules with only one transformation, e.g.: 17 | /// { x 1 } R1 18 | /// are represented as a loop transformation with one repetitions. 19 | class Action { 20 | public: 21 | Action(Transformation t, QString ruleName); 22 | Action(QString ruleName); 23 | Action(QString key, QString value); 24 | Action() { rule = 0; set = 0; } 25 | 26 | void addTransformationLoop(TransformationLoop tl); 27 | void setRule(QString rule); 28 | 29 | ~Action(); 30 | 31 | /// If 'callingRule' != 0 the new states generated will be set with 32 | /// a depth equal to 'ruleDepth' 33 | void apply(Builder* b, const Rule* callingRule, int ruleDepth) const; 34 | RuleRef* getRuleRef() const { return rule; } 35 | 36 | private: 37 | QList loops; 38 | RuleRef* rule; // The rule that will be called after all transformations. 39 | SetAction* set; 40 | }; 41 | 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /StructureSynth/Model/AmbiguousRule.cpp: -------------------------------------------------------------------------------- 1 | #include "AmbiguousRule.h" 2 | 3 | #include "Builder.h" 4 | #include "RandomStreams.h" 5 | 6 | #include "../../SyntopiaCore/Logging/Logging.h" 7 | 8 | using namespace SyntopiaCore::Logging; 9 | 10 | 11 | namespace StructureSynth { 12 | namespace Model { 13 | 14 | QList AmbiguousRule::getRuleRefs() const { 15 | QList list; 16 | for (int i = 0; i < rules.size(); i++) { 17 | for (int j = 0; j < rules[i]->getRuleRefs().size(); j++) { 18 | list.append(rules[i]->getRuleRefs()[j]); 19 | } 20 | } 21 | return list; 22 | } 23 | 24 | void AmbiguousRule::apply(Builder* builder) const { 25 | // Calc sum of weigths 26 | double totalWeight = 0; 27 | for (int i = 0; i < rules.size(); i++) { 28 | totalWeight += rules[i]->getWeight(); 29 | } 30 | 31 | 32 | double random = totalWeight*RandomStreams::Geometry()->getDouble(); 33 | 34 | 35 | // Choose a random rule according to weights 36 | double accWeight = 0; 37 | for (int i = 0; i < rules.size(); i++) { 38 | accWeight += rules[i]->getWeight(); 39 | if (random <= accWeight) { 40 | rules[i]->apply(builder); 41 | return; 42 | } 43 | } 44 | rules[rules.size()-1]->apply(builder); 45 | 46 | WARNING("Assertion failed: in AmbiguousRule::apply"); 47 | 48 | }; 49 | 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /StructureSynth/Model/AmbiguousRule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rule.h" 4 | #include "CustomRule.h" 5 | 6 | namespace StructureSynth { 7 | namespace Model { 8 | 9 | 10 | /// If several definitions for the same rule exists, 11 | /// an Ambiguous Rule is created which contains the multiple definitions. 12 | /// 13 | /// When the rule is executed, a random rule is chosen from the multiple definitions, 14 | /// taking their weights into account. 15 | class AmbiguousRule : public Rule { 16 | public: 17 | AmbiguousRule(QString name) : Rule(name) {}; 18 | 19 | virtual void apply(Builder* builder) const; 20 | 21 | /// Returns a list over rules that this rule references. 22 | virtual QList getRuleRefs() const; 23 | 24 | QList getRules() { return rules; }; 25 | 26 | void appendRule(CustomRule* r) { rules.append(r); } 27 | 28 | virtual void setMaxDepth(int maxDepth) { for (int i = 0; i < rules.size(); i++) rules[i]->setMaxDepth(maxDepth); } 29 | 30 | private: 31 | QList rules; 32 | }; 33 | 34 | 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /StructureSynth/Model/Builder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "Rendering/Renderer.h" 6 | #include "RuleSet.h" 7 | #include "State.h" 8 | #include "ColorPool.h" 9 | #include "ExecutionStack.h" 10 | 11 | #include "../../SyntopiaCore/Math/Matrix4.h" 12 | #include "../../SyntopiaCore/GLEngine/EngineWidget.h" 13 | 14 | 15 | namespace StructureSynth { 16 | namespace Model { 17 | 18 | 19 | using namespace SyntopiaCore; 20 | 21 | /// A Builder executes the rule set on a Renderer object 22 | class Builder { 23 | public: 24 | Builder(Rendering::Renderer* renderTarget, RuleSet* ruleSet, bool verbose); 25 | ~Builder(); 26 | void build(); 27 | 28 | void setCommand(QString command, QString param); 29 | ExecutionStack& getNextStack(); 30 | State& getState() { return state; }; 31 | Rendering::Renderer* getRenderer() { return renderTarget; }; 32 | void increaseObjectCount() { objects++; }; 33 | 34 | // True, if the random seed was changed by the builder (by 'set seed ') 35 | bool seedChanged() { return hasSeedChanged; } 36 | int getNewSeed() { return newSeed; } 37 | ColorPool* getColorPool() { return colorPool; } 38 | QVector getRaytracerCommands() { return raytracerCommands; }; 39 | bool wasCancelled() { return userCancelled; } 40 | 41 | private: 42 | void recurseBreadthFirst(QProgressDialog& progressDialog, int& maxTerminated, int& minTerminated, int& generationCounter); 43 | void recurseDepthFirst(QProgressDialog& progressDialog, int& maxTerminated, int& minTerminated, int& generationCounter); 44 | 45 | State state; 46 | 47 | bool userCancelled; 48 | 49 | ExecutionStack stack; 50 | ExecutionStack nextStack; 51 | Rendering::Renderer* renderTarget; 52 | RuleSet* ruleSet; 53 | bool verbose; 54 | int maxGenerations; 55 | int maxObjects; 56 | int objects; 57 | int newSeed; 58 | bool hasSeedChanged; 59 | float minDim; 60 | float maxDim; 61 | bool syncRandom; 62 | int initialSeed; 63 | State* currentState; 64 | ColorPool* colorPool; 65 | QVector raytracerCommands; 66 | }; 67 | 68 | 69 | 70 | 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /StructureSynth/Model/ColorPool.cpp: -------------------------------------------------------------------------------- 1 | #include "ColorPool.h" 2 | 3 | #include "../../SyntopiaCore/Logging/Logging.h" 4 | #include "../../SyntopiaCore/Exceptions/Exception.h" 5 | #include "Builder.h" 6 | #include "RandomStreams.h" 7 | 8 | 9 | #include 10 | #include 11 | 12 | 13 | using namespace SyntopiaCore::Logging; 14 | using namespace SyntopiaCore::Exceptions; 15 | 16 | namespace StructureSynth { 17 | namespace Model { 18 | 19 | ColorPool::ColorPool(QString initString) { 20 | initString = initString.toLower(); 21 | picture = 0; 22 | 23 | if (initString == "randomhue") { 24 | type = RandomHue; 25 | } else if (initString == "greyscale" || initString == "grayscale" ) { 26 | type = GreyScale; 27 | } else if (initString == "randomrgb") { 28 | type = RandomRGB; 29 | } else if (initString.startsWith("image:")) { 30 | initString = initString.remove("image:"); 31 | type = Picture; 32 | 33 | if (!QFile::exists(initString)) { 34 | throw Exception(QString("Could not open file: %1").arg(QFileInfo(initString).absoluteFilePath())); 35 | } 36 | 37 | picture = new QImage(initString); 38 | if (picture->isNull()) { 39 | throw Exception(QString("Could not parse image file: %1").arg(QFileInfo(initString).absoluteFilePath())); 40 | } 41 | 42 | } else if (initString.startsWith("list:")) { 43 | initString = initString.remove("list:"); 44 | QStringList l = initString.split(","); 45 | for (int i = 0; i < l.count(); i++) { 46 | QColor c(l[i]); 47 | if (!c.isValid()) { 48 | throw Exception(QString("Could not parse color in colorlist: %1").arg(initString)); 49 | } 50 | colorList.append(c); 51 | } 52 | type = ColorList; 53 | } else { 54 | throw Exception(QString("Could not understand the color pool: %1. Try: RandomHue, RandomRGB, GrayScale, Image:test.png, List:#234,Red,Blue").arg(initString)); 55 | } 56 | } 57 | 58 | ColorPool::~ColorPool() { 59 | delete picture; 60 | } 61 | 62 | QColor ColorPool::drawColor() { 63 | if (type == RandomHue) { 64 | return QColor::fromHsv(RandomStreams::Color()->getInt(359),255,255); 65 | } else if (type == GreyScale) { 66 | int r = RandomStreams::Color()->getInt(255); 67 | return QColor(r,r,r).toHsv(); 68 | } else if (type == RandomRGB) { 69 | // We can only pull one random number, so we must use a few tricks to get three ints 70 | int r = RandomStreams::Color()->getInt(255); 71 | int g = RandomStreams::Color()->getInt(255); 72 | int b = RandomStreams::Color()->getInt(255); 73 | return QColor(r,g,b).toHsv(); 74 | } else if (type == Picture) { 75 | int x = RandomStreams::Color()->getInt(picture->width()-1); 76 | int y = RandomStreams::Color()->getInt(picture->height()-1); 77 | QRgb rgb = picture->pixel(x,y); 78 | return QColor(rgb).toHsv(); 79 | } else if (type == ColorList) { 80 | int id = RandomStreams::Color()->getInt(colorList.count()-1); 81 | return colorList[id]; 82 | } 83 | return QColor(); 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /StructureSynth/Model/ColorPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace StructureSynth { 9 | namespace Model { 10 | 11 | /// A ColorPool is a set or colors. It is used for drawing random colors using the 'color random' operator. 12 | /// The Builder maintainse single color pool in a project. 13 | class ColorPool { 14 | enum PoolType { RandomHue, GreyScale, RandomRGB, Picture, ColorList }; 15 | public: 16 | ColorPool(QString initString); 17 | ~ColorPool(); 18 | QColor drawColor(); // returns a random color from the pool (in HSV) 19 | private: 20 | PoolType type; 21 | QVector colorList; // only used by type: ColorList. 22 | QImage* picture; // Only used by type: Picture. 23 | }; 24 | 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /StructureSynth/Model/CustomRule.cpp: -------------------------------------------------------------------------------- 1 | #include "CustomRule.h" 2 | 3 | #include "../../SyntopiaCore/Logging/Logging.h" 4 | #include "Builder.h" 5 | 6 | using namespace SyntopiaCore::Logging; 7 | 8 | namespace StructureSynth { 9 | namespace Model { 10 | 11 | CustomRule::CustomRule(QString name) : Rule(name) { 12 | weight = 1.0; 13 | retirementRule = 0; 14 | } 15 | 16 | CustomRule::~CustomRule() { 17 | //delete (retirementRule); 18 | } 19 | 20 | void CustomRule::apply(Builder* b) const { 21 | 22 | int newDepth = -1; 23 | /// If there is a maxdepth set for this object check it. 24 | if (getMaxDepth() != -1) { 25 | if (!b->getState().maxDepths.contains(this)) { 26 | /// We will add a new maxdepth for this rule to the state. 27 | newDepth = getMaxDepth()-1; 28 | 29 | } else { 30 | int depth = b->getState().maxDepths[this]; 31 | if (depth <= 0) { 32 | /// This rule is retired. 33 | if (retirementRule) { 34 | b->getState().maxDepths[this] = maxDepth; 35 | retirementRule->rule()->apply(b); 36 | 37 | } 38 | return; 39 | } else { 40 | /// Decrease depth. 41 | newDepth = depth-1; 42 | } 43 | } 44 | } 45 | 46 | /// Apply all actions. 47 | for (int i = 0; i < actions.size(); i++) { 48 | if (getMaxDepth() != -1) { 49 | actions[i].apply(b, this, newDepth); 50 | } else { 51 | actions[i].apply(b, 0 ,0); 52 | } 53 | } 54 | } 55 | 56 | QList CustomRule::getRuleRefs() const { 57 | QList list; 58 | for (int i = 0; i < actions.size(); i++) { 59 | RuleRef* a = actions[i].getRuleRef(); 60 | if (a) list.append(a); 61 | } 62 | if (retirementRule) list.append(retirementRule); 63 | 64 | return list; 65 | } 66 | 67 | 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /StructureSynth/Model/CustomRule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rule.h" 4 | #include "Action.h" 5 | 6 | namespace StructureSynth { 7 | namespace Model { 8 | 9 | /// A custom rule is a user defined rule. 10 | /// It consist of a number of actions, 11 | /// and a weight that is used if the rule definition is ambiguous (see 'AmbiguousRule'). 12 | class CustomRule : public Rule { 13 | public: 14 | CustomRule(QString name); 15 | virtual ~CustomRule(); 16 | 17 | virtual void apply(Builder* builder) const; 18 | 19 | /// Returns a list over rules that this rule references. 20 | virtual QList getRuleRefs() const; 21 | 22 | void appendAction(Action a) { actions.append(a); } 23 | 24 | double getWeight() const { return weight; } 25 | void setWeight(double w) { weight = w; } 26 | 27 | void setRetirementRule(QString ruleName) { retirementRule = new RuleRef(ruleName); }; 28 | 29 | private: 30 | QList actions; 31 | double weight; 32 | RuleRef* retirementRule; 33 | }; 34 | 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /StructureSynth/Model/ExecutionStack.cpp: -------------------------------------------------------------------------------- 1 | #include "Rule.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /StructureSynth/Model/ExecutionStack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rule.h" 4 | #include "State.h" 5 | 6 | namespace StructureSynth { 7 | namespace Model { 8 | 9 | struct RuleState { 10 | RuleState() {}; 11 | RuleState(Rule* rule, State state) : rule(rule), state(state) {}; 12 | 13 | Rule* rule; 14 | State state; 15 | }; 16 | 17 | /// The ExecutionStack keeps track of which operations to perform next. 18 | /// Rules are executed in generations: 19 | /// The rules on the stack are all executed in each generation, 20 | /// and each rule will add a number of new rules to the next generation of the stack. 21 | /// Only one level is recursion is followed at each generation. 22 | typedef QVector ExecutionStack; 23 | 24 | /* 25 | struct ExecutionStack { 26 | QList< RuleState > currentStack; 27 | }; 28 | */ 29 | 30 | 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /StructureSynth/Model/PrimitiveClass.cpp: -------------------------------------------------------------------------------- 1 | #include "PrimitiveClass.h" 2 | 3 | namespace StructureSynth { 4 | namespace Model { 5 | 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /StructureSynth/Model/PrimitiveClass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace StructureSynth { 6 | namespace Model { 7 | 8 | /// Every PrimitiveRule can be assigned a class. 9 | 10 | } 11 | } 12 | 13 | -------------------------------------------------------------------------------- /StructureSynth/Model/PrimitiveRule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rule.h" 4 | #include "PrimitiveClass.h" 5 | #include "../../SyntopiaCore/GLEngine/Object3D.h" 6 | 7 | namespace StructureSynth { 8 | namespace Model { 9 | 10 | using namespace SyntopiaCore::GLEngine; 11 | 12 | /// These are the built-in primitives, 13 | /// for drawing boxes, spheres and other simple geometric shapes. 14 | class PrimitiveRule : public Rule { 15 | public: 16 | enum PrimitiveType { Box, Sphere, Dot, Grid, Cylinder, Line, Mesh, Template, Other } ; 17 | 18 | PrimitiveRule(PrimitiveType type, PrimitiveClass* primitiveClass); 19 | virtual void apply(Builder* builder) const; 20 | 21 | /// Returns a list over rules that this rule references. 22 | /// (Empty for all PrimitiveRules!) 23 | virtual QList getRuleRefs() const { return QList(); } 24 | 25 | /// 'class' is an identifier used for distinguishing between 26 | /// different forms of the the same PrimiteType. 27 | /// This is used together with Template Renderers. 28 | /// 29 | /// For instance 'box::metal' will be parsed in to a 'box' primitive with a 'metal' class identifier. 30 | void setClass(PrimitiveClass* primitiveClass) { this->primitiveClass = primitiveClass; } 31 | PrimitiveClass* getClass() { return primitiveClass; } 32 | 33 | 34 | protected: 35 | PrimitiveClass* primitiveClass; 36 | private: 37 | PrimitiveType type; 38 | 39 | 40 | }; 41 | 42 | /// Triangle rules are special, since they have explicit coordinate representation. 43 | class TriangleRule : public PrimitiveRule { 44 | public: 45 | 46 | TriangleRule(SyntopiaCore::Math::Vector3f p1, 47 | SyntopiaCore::Math::Vector3f p2, 48 | SyntopiaCore::Math::Vector3f p3, 49 | PrimitiveClass* primitiveClass); 50 | 51 | virtual void apply(Builder* builder) const; 52 | 53 | private: 54 | SyntopiaCore::Math::Vector3f p1; 55 | SyntopiaCore::Math::Vector3f p2; 56 | SyntopiaCore::Math::Vector3f p3; 57 | 58 | }; 59 | 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /StructureSynth/Model/RandomStreams.cpp: -------------------------------------------------------------------------------- 1 | #include "RandomStreams.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | SyntopiaCore::Math::RandomNumberGenerator* RandomStreams::geometry = new SyntopiaCore::Math::RandomNumberGenerator(false); 7 | SyntopiaCore::Math::RandomNumberGenerator* RandomStreams::color = new SyntopiaCore::Math::RandomNumberGenerator(false); 8 | 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /StructureSynth/Model/RandomStreams.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../../SyntopiaCore/Math/Random.h" 4 | 5 | namespace StructureSynth { 6 | namespace Model { 7 | 8 | /// These two independent random number generator streams are used in Structure Synth 9 | class RandomStreams { 10 | public: 11 | static SyntopiaCore::Math::RandomNumberGenerator* Geometry() { return geometry; } 12 | static SyntopiaCore::Math::RandomNumberGenerator* Color() { return color; } 13 | static void SetSeed(int seed) { geometry->setSeed(seed); color->setSeed(seed); } 14 | static void UseOldRandomGenerators(bool useOld) { geometry->useStdLib(useOld); color->useStdLib(useOld); } 15 | private: 16 | static SyntopiaCore::Math::RandomNumberGenerator* geometry; 17 | static SyntopiaCore::Math::RandomNumberGenerator* color; 18 | }; 19 | 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /StructureSynth/Model/Rendering/ObjRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../../../SyntopiaCore/Math/Vector3.h" 5 | #include "../../../SyntopiaCore/Math/Matrix4.h" 6 | #include "../../../SyntopiaCore/GLEngine/Object3D.h" 7 | #include "Renderer.h" 8 | 9 | namespace StructureSynth { 10 | namespace Model { 11 | namespace Rendering { 12 | 13 | using namespace SyntopiaCore::Math; 14 | using namespace SyntopiaCore::GLEngine; 15 | 16 | struct VertexNormal { 17 | VertexNormal() {}; 18 | VertexNormal(int vID, int nID) : vID(vID), nID(nID) {}; 19 | int vID; 20 | int nID; 21 | }; 22 | 23 | struct ObjGroup { 24 | QString groupName; 25 | QVector vertices; 26 | QVector normals; 27 | QVector > faces; 28 | 29 | void addGroup(ObjGroup g); 30 | void reduceVertices(); 31 | }; 32 | 33 | /// Obj file renderer 34 | class ObjRenderer : public Renderer { 35 | public: 36 | ObjRenderer(int sphereDT, int sphereDP, bool groupByTagging, bool groupByColor) 37 | : sphereDT(sphereDT), sphereDP(sphereDP), groupByTagging(groupByTagging), groupByColor(groupByColor) {}; 38 | virtual ~ObjRenderer() {}; 39 | 40 | /// Flow 41 | virtual void begin(); 42 | virtual void end(); 43 | 44 | /// This defines the identifier for our renderer. 45 | virtual QString renderClass() { return "ObjRenderer"; } 46 | 47 | /// The primitives 48 | virtual void drawBox(Vector3f base, 49 | Vector3f dir1, 50 | Vector3f dir2, 51 | Vector3f dir3, 52 | PrimitiveClass* classID); 53 | 54 | virtual void drawMesh( Vector3f startBase, 55 | Vector3f startDir1, 56 | Vector3f startDir2, 57 | Vector3f endBase, 58 | Vector3f endDir1, 59 | Vector3f endDir2, 60 | PrimitiveClass* classID); 61 | 62 | virtual void drawGrid(Vector3f base, 63 | Vector3f dir1, 64 | Vector3f dir2, 65 | Vector3f dir3, 66 | PrimitiveClass* classID); 67 | 68 | virtual void drawLine(Vector3f from, 69 | Vector3f to, 70 | PrimitiveClass* classID); 71 | 72 | virtual void drawDot(Vector3f pos, 73 | PrimitiveClass* classID); 74 | 75 | virtual void drawSphere(Vector3f center, float radius, 76 | PrimitiveClass* classID); 77 | 78 | virtual void drawTriangle(Vector3f p1, 79 | Vector3f p2, 80 | Vector3f p3, 81 | PrimitiveClass* classID); 82 | 83 | virtual void callGeneric(PrimitiveClass* ) {}; 84 | 85 | // Color 86 | // RGB in [0;1] intervals. 87 | virtual void setColor(Vector3f rgb) { this->rgb = rgb; } 88 | virtual void setBackgroundColor(Vector3f /*rgb*/) {}; 89 | virtual void setAlpha(double alpha) { this->alpha = alpha; } 90 | 91 | virtual void setPreviousColor(Vector3f /*rgb*/) {}; 92 | virtual void setPreviousAlpha(double /*alpha*/) {}; 93 | 94 | 95 | // Camera settings 96 | virtual void setTranslation(Vector3f /*translation*/) {}; 97 | virtual void setScale(double /*scale*/) {}; 98 | virtual void setRotation(Matrix4f /*rotation*/) {}; 99 | virtual void setPivot(Vector3f /*pivot*/) {}; 100 | virtual void setPerspectiveAngle(double /*angle*/) {}; 101 | 102 | // Issues a command for a specific renderclass such as 'template' or 'opengl' 103 | virtual void callCommand(const QString& /*renderClass*/, const QString& /*command*/) {}; 104 | 105 | void addQuad(ObjGroup& group, Vector3f v1,Vector3f v2,Vector3f v3,Vector3f v4); 106 | void addLineQuad(ObjGroup& group, Vector3f v1,Vector3f v2,Vector3f v3,Vector3f v4); 107 | void setClass(QString classID, Vector3f rgb, double alpha); 108 | 109 | void writeToStream(QTextStream& ts); 110 | 111 | private: 112 | QMap groups; 113 | QString currentGroup; 114 | SyntopiaCore::Math::Vector3f rgb; 115 | double alpha; 116 | int sphereDT; 117 | int sphereDP; 118 | bool groupByTagging; 119 | bool groupByColor; 120 | 121 | }; 122 | 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /StructureSynth/Model/Rendering/OpenGLRenderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../../../SyntopiaCore/GLEngine/EngineWidget.h" 5 | #include "Renderer.h" 6 | 7 | #include "../../../SyntopiaCore/Math/Vector3.h" 8 | 9 | 10 | namespace StructureSynth { 11 | namespace Model { 12 | namespace Rendering { 13 | 14 | using namespace SyntopiaCore::GLEngine; 15 | 16 | 17 | /// A renderer implementation based on the SyntopiaCore openGL widget. 18 | class OpenGLRenderer : public Renderer { 19 | public: 20 | OpenGLRenderer(SyntopiaCore::GLEngine::EngineWidget* engine) : engine(engine) {}; 21 | virtual ~OpenGLRenderer() {}; 22 | 23 | /// The primitives 24 | virtual void drawBox(SyntopiaCore::Math::Vector3f base, 25 | SyntopiaCore::Math::Vector3f dir1 , 26 | SyntopiaCore::Math::Vector3f dir2, 27 | SyntopiaCore::Math::Vector3f dir3, 28 | PrimitiveClass* classID); 29 | 30 | 31 | virtual void drawMesh( SyntopiaCore::Math::Vector3f startBase, 32 | SyntopiaCore::Math::Vector3f startDir1, 33 | SyntopiaCore::Math::Vector3f startDir2, 34 | SyntopiaCore::Math::Vector3f endBase, 35 | SyntopiaCore::Math::Vector3f endDir1, 36 | SyntopiaCore::Math::Vector3f endDir2, 37 | PrimitiveClass* classID); 38 | 39 | virtual void drawSphere(SyntopiaCore::Math::Vector3f center, float radius, 40 | PrimitiveClass* classID); 41 | 42 | virtual void drawGrid(SyntopiaCore::Math::Vector3f base, 43 | SyntopiaCore::Math::Vector3f dir1, 44 | SyntopiaCore::Math::Vector3f dir2, 45 | SyntopiaCore::Math::Vector3f dir3, 46 | PrimitiveClass* classID); 47 | 48 | virtual void drawLine(SyntopiaCore::Math::Vector3f from, 49 | SyntopiaCore::Math::Vector3f to, 50 | PrimitiveClass* classID); 51 | 52 | virtual void drawDot(SyntopiaCore::Math::Vector3f pos, 53 | PrimitiveClass* classID); 54 | 55 | virtual void drawTriangle(SyntopiaCore::Math::Vector3f p1, 56 | SyntopiaCore::Math::Vector3f p2, 57 | SyntopiaCore::Math::Vector3f p3, 58 | PrimitiveClass* classID); 59 | 60 | virtual void begin(); 61 | virtual void end(); 62 | 63 | virtual void setColor(SyntopiaCore::Math::Vector3f rgb) { this->rgb = rgb; } 64 | virtual void setBackgroundColor(SyntopiaCore::Math::Vector3f rgb); 65 | virtual void setAlpha(double alpha) { this->alpha = alpha; } 66 | 67 | virtual void setPreviousColor(SyntopiaCore::Math::Vector3f rgb) { this->oldRgb = rgb; } 68 | virtual void setPreviousAlpha(double alpha) { this->oldAlpha = alpha; } 69 | 70 | 71 | virtual void setTranslation(SyntopiaCore::Math::Vector3f /*translation*/); 72 | virtual void setScale(double /*scale*/); 73 | virtual void setRotation(SyntopiaCore::Math::Matrix4f /*rotation*/); 74 | virtual void setPivot(SyntopiaCore::Math::Vector3f /*pivot*/); 75 | virtual void setPerspectiveAngle(double /*angle*/); 76 | 77 | // Issues a command for a specific renderclass such as 'template' or 'opengl' 78 | virtual void callCommand(const QString& renderClass, const QString& command); 79 | private: 80 | SyntopiaCore::GLEngine::EngineWidget* engine; 81 | SyntopiaCore::Math::Vector3f rgb; 82 | double alpha; 83 | SyntopiaCore::Math::Vector3f oldRgb; 84 | double oldAlpha; 85 | }; 86 | 87 | } 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /StructureSynth/Model/Rendering/Renderer.cpp: -------------------------------------------------------------------------------- 1 | #include "Renderer.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | namespace Renderer { 7 | } 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /StructureSynth/Model/Rendering/Renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../../../SyntopiaCore/Math/Vector3.h" 5 | #include "../../../SyntopiaCore/Math/Matrix4.h" 6 | #include "../../../SyntopiaCore/GLEngine/Object3D.h" 7 | 8 | namespace StructureSynth { 9 | namespace Model { 10 | namespace Rendering { 11 | 12 | 13 | using namespace SyntopiaCore::GLEngine; 14 | 15 | /// Abstract base class for implementing a renderer 16 | class Renderer { 17 | public: 18 | Renderer() {}; 19 | virtual ~Renderer() {}; 20 | 21 | /// Flow 22 | virtual void begin() {}; 23 | virtual void end() {}; 24 | 25 | /// This defines the identifier for our renderer. 26 | virtual QString renderClass() { return ""; } 27 | 28 | /// The primitives 29 | virtual void drawBox(SyntopiaCore::Math::Vector3f base, 30 | SyntopiaCore::Math::Vector3f dir1, 31 | SyntopiaCore::Math::Vector3f dir2, 32 | SyntopiaCore::Math::Vector3f dir3, 33 | PrimitiveClass* classID) = 0; 34 | 35 | virtual void drawMesh( SyntopiaCore::Math::Vector3f startBase, 36 | SyntopiaCore::Math::Vector3f startDir1, 37 | SyntopiaCore::Math::Vector3f startDir2, 38 | SyntopiaCore::Math::Vector3f endBase, 39 | SyntopiaCore::Math::Vector3f endDir1, 40 | SyntopiaCore::Math::Vector3f endDir2, 41 | PrimitiveClass* classID) = 0; 42 | 43 | virtual void drawGrid(SyntopiaCore::Math::Vector3f base, 44 | SyntopiaCore::Math::Vector3f dir1, 45 | SyntopiaCore::Math::Vector3f dir2, 46 | SyntopiaCore::Math::Vector3f dir3, 47 | PrimitiveClass* classID) = 0; 48 | 49 | virtual void drawLine(SyntopiaCore::Math::Vector3f from, 50 | SyntopiaCore::Math::Vector3f to, 51 | PrimitiveClass* classID) = 0; 52 | 53 | virtual void drawDot(SyntopiaCore::Math::Vector3f pos, 54 | PrimitiveClass* classID) = 0; 55 | 56 | virtual void drawSphere(SyntopiaCore::Math::Vector3f center, float radius, 57 | PrimitiveClass* classID) = 0; 58 | 59 | virtual void drawTriangle(SyntopiaCore::Math::Vector3f p1, 60 | SyntopiaCore::Math::Vector3f p2, 61 | SyntopiaCore::Math::Vector3f p3, 62 | PrimitiveClass* classID) = 0; 63 | 64 | virtual void callGeneric(PrimitiveClass* ) {}; 65 | 66 | // Color 67 | // RGB in [0;1] intervals. 68 | virtual void setColor(SyntopiaCore::Math::Vector3f rgb) = 0; 69 | virtual void setBackgroundColor(SyntopiaCore::Math::Vector3f rgb) = 0; 70 | virtual void setAlpha(double alpha) = 0; 71 | 72 | virtual void setPreviousColor(SyntopiaCore::Math::Vector3f rgb) = 0; 73 | virtual void setPreviousAlpha(double alpha) = 0; 74 | 75 | 76 | // Camera settings 77 | virtual void setTranslation(SyntopiaCore::Math::Vector3f /*translation*/) {}; 78 | virtual void setScale(double /*scale*/) {}; 79 | virtual void setRotation(SyntopiaCore::Math::Matrix4f /*rotation*/) {}; 80 | virtual void setPivot(SyntopiaCore::Math::Vector3f /*pivot*/) {}; 81 | virtual void setPerspectiveAngle(double /*angle*/) {}; 82 | 83 | // Issues a command for a specific renderclass such as 'template' or 'opengl' 84 | virtual void callCommand(const QString& /*renderClass*/, const QString& /*command*/) {}; 85 | }; 86 | 87 | } 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /StructureSynth/Model/Rule.cpp: -------------------------------------------------------------------------------- 1 | #include "Rule.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /StructureSynth/Model/Rule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rendering/Renderer.h" 4 | #include "State.h" 5 | 6 | namespace StructureSynth { 7 | namespace Model { 8 | 9 | 10 | class RuleRef; // forward decl. 11 | class Builder; // forward decl. 12 | 13 | /// (Abstract) Base class for rules. 14 | class Rule { 15 | public: 16 | /// Every rule must have a name. 17 | Rule(QString name) : name(name) { maxDepth = -1; }; 18 | Rule() { maxDepth = -1; }; 19 | 20 | virtual ~Rule() {}; 21 | 22 | QString getName() const { return name; } 23 | 24 | /// When applied the rule will add new pending rules to the ExecutionStack for execution. 25 | /// Only PrimitiveRules will make use of the renderer. 26 | virtual void apply(Builder* builder) const = 0; 27 | 28 | /// Returns a list over rules that this rule references. 29 | virtual QList getRuleRefs() const { return QList(); } 30 | 31 | virtual void setMaxDepth(int maxDepth) { this->maxDepth = maxDepth; } 32 | virtual int getMaxDepth() const { return maxDepth; } 33 | 34 | protected: 35 | QString name; 36 | int maxDepth; 37 | }; 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /StructureSynth/Model/RuleRef.cpp: -------------------------------------------------------------------------------- 1 | #include "Rule.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /StructureSynth/Model/RuleRef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rule.h" 4 | 5 | namespace StructureSynth { 6 | namespace Model { 7 | 8 | /// A RuleRef holds a pointer to a rule. 9 | /// Its is a placeholder, since rule are parsed as symbolic references, 10 | /// and need to be resolved into actual pointers after the complete parsing of the script. 11 | class RuleRef { 12 | public: 13 | RuleRef(QString namedReference) : reference(namedReference) { rulePtr = 0; }; 14 | ~RuleRef() {}; 15 | 16 | Rule* rule() { return rulePtr; } 17 | 18 | QString getReference() const { return reference; } 19 | 20 | void setRef(Rule* rule) { rulePtr = rule; } 21 | 22 | private: 23 | Rule* rulePtr; 24 | QString reference; 25 | }; 26 | 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /StructureSynth/Model/RuleSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Rule.h" 4 | #include "PrimitiveClass.h" 5 | #include "CustomRule.h" 6 | 7 | #include "../../SyntopiaCore/GLEngine/Object3D.h" 8 | 9 | namespace StructureSynth { 10 | namespace Model { 11 | 12 | using namespace SyntopiaCore::GLEngine; 13 | 14 | /// Container for all rules. 15 | class RuleSet { 16 | public: 17 | /// Constructor. Automatically adds built-in rules. 18 | RuleSet(); 19 | 20 | /// Deletes rules 21 | ~RuleSet(); 22 | 23 | /// Added rules belong to the RuleSet and will be deleted by the RuleSet destructor. 24 | void addRule(Rule* rule); 25 | 26 | /// Resolve symbolic names into pointers 27 | /// Returns a list of the primitives used 28 | QStringList resolveNames(); 29 | 30 | /// TODO: Implement 31 | QStringList getUnreferencedNames(); 32 | 33 | Rule* getStartRule() const ; 34 | 35 | CustomRule* getTopLevelRule() const { return topLevelRule; } 36 | 37 | /// For debug 38 | void dumpInfo() const; 39 | 40 | void setRecurseDepthFirst(bool value) { recurseDepth = value; }; 41 | bool recurseDepthFirst() { return recurseDepth; } 42 | void setRulesMaxDepth(int maxDepth); 43 | 44 | /// Returns the PrimitiveClass with this name. Constructs a new one if missing. 45 | PrimitiveClass* getPrimitiveClass(QString classLabel); 46 | bool existsPrimitiveClass(QString classLabel); 47 | PrimitiveClass* getDefaultClass() { return defaultClass; } 48 | 49 | private: 50 | QList rules; 51 | QVector primitiveClasses; 52 | PrimitiveClass* defaultClass; 53 | CustomRule* topLevelRule; 54 | bool recurseDepth; 55 | }; 56 | 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /StructureSynth/Model/State.cpp: -------------------------------------------------------------------------------- 1 | #include "State.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | 7 | State::State() : 8 | matrix(SyntopiaCore::Math::Matrix4f::Identity()), 9 | hsv(SyntopiaCore::Math::Vector3f(0,1.0f,1.0f)), 10 | alpha(1.0f), previous(0), seed(0) { 11 | 12 | } 13 | 14 | State& State::operator=(const State& rhs){ 15 | this->matrix = rhs.matrix; 16 | this->hsv = rhs.hsv; 17 | this->alpha = rhs.alpha; 18 | this->maxDepths = rhs.maxDepths; 19 | this->seed = rhs.seed; 20 | if (rhs.previous) { 21 | delete(this->previous); 22 | this->previous = new PreviousState(); 23 | *(this->previous) = *rhs.previous; 24 | } else { 25 | delete(this->previous); 26 | this->previous = 0; 27 | } 28 | return *this; 29 | } 30 | 31 | void State::setPreviousState(SyntopiaCore::Math::Matrix4f matrix,SyntopiaCore::Math::Vector3f hsv, float alpha) { 32 | if (previous) {delete (previous); } 33 | 34 | this->previous = new PreviousState(); 35 | this->previous->matrix = matrix; 36 | this->previous->hsv = hsv; 37 | this->previous->alpha = alpha; 38 | } 39 | 40 | 41 | State::State(const State& rhs) : matrix(rhs.matrix), 42 | hsv(rhs.hsv), 43 | alpha(rhs.alpha), maxDepths(rhs.maxDepths), previous(0), seed(rhs.seed) { 44 | 45 | if (rhs.previous) { 46 | delete(this->previous); 47 | this->previous = new PreviousState(); 48 | *(this->previous) = *rhs.previous; 49 | } else { 50 | delete(this->previous); 51 | this->previous = 0; 52 | } 53 | } 54 | 55 | 56 | 57 | State::~State() { 58 | delete(previous); 59 | } 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /StructureSynth/Model/State.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "../../SyntopiaCore/Math/Matrix4.h" 6 | 7 | namespace StructureSynth { 8 | namespace Model { 9 | 10 | class Rule; // Forward 11 | 12 | // A slight trimmed version of a State. 13 | struct PreviousState { 14 | SyntopiaCore::Math::Matrix4f matrix; // Transformation matrix (4x4 homogenous representation) 15 | SyntopiaCore::Math::Vector3f hsv; // Hue, Saturation, Value colorspace state 16 | float alpha; // Transparency 17 | 18 | }; 19 | 20 | /// A state represent the current rendering projection matrix and other rendering settings. 21 | struct State { 22 | State(); 23 | State(const State& rhs); 24 | ~State(); 25 | 26 | State& operator=(const State& rhs); 27 | 28 | void setPreviousState(SyntopiaCore::Math::Matrix4f matrix,SyntopiaCore::Math::Vector3f hsv,float alpha); 29 | 30 | SyntopiaCore::Math::Matrix4f matrix; // Transformation matrix (4x4 homogenous representation) 31 | SyntopiaCore::Math::Vector3f hsv; // Hue, Saturation, Value colorspace state 32 | float alpha; // Transparency 33 | QMap maxDepths; // Rules may have a max. recursion depth before they are retired. 34 | // We need to keep track of this in the state. 35 | PreviousState* previous; 36 | int seed; 37 | }; 38 | 39 | 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /StructureSynth/Model/Transformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "State.h" 6 | #include "ColorPool.h" 7 | #include "../../SyntopiaCore/Math/Matrix4.h" 8 | 9 | namespace StructureSynth { 10 | namespace Model { 11 | 12 | class Transformation { 13 | public: 14 | Transformation(); 15 | ~Transformation(); 16 | 17 | /// 'Applies' the transformation 'T' to this transformation. 18 | /// (For the matrix this corresponds to matrix multiplication). 19 | void append(const Transformation& T); 20 | State apply(const State& s, ColorPool* colorPool) const; 21 | 22 | // The predefined operators 23 | // Translations 24 | static Transformation createX(double offset); 25 | static Transformation createY(double offset); 26 | static Transformation createZ(double offset); 27 | 28 | // Rotations 29 | static Transformation createRX(double angle); 30 | static Transformation createRY(double angle); 31 | static Transformation createRZ(double angle); 32 | 33 | // Plane reflection 34 | static Transformation createPlaneReflection(SyntopiaCore::Math::Vector3f normal); 35 | 36 | // Scaling 37 | static Transformation createScale(double x, double y, double z); 38 | 39 | // Free transformation 40 | static Transformation createMatrix(QVector vals); 41 | 42 | // Color stuff 43 | static Transformation createHSV(float h, float s, float v, float a); 44 | static Transformation createColor(QString color); 45 | static Transformation createBlend(QString color, double strength); 46 | 47 | 48 | private: 49 | // Matrix and Color transformations here. 50 | SyntopiaCore::Math::Matrix4f matrix; 51 | 52 | // For color alterations 53 | float deltaH; 54 | float scaleS; 55 | float scaleV; 56 | float scaleAlpha; 57 | bool absoluteColor; 58 | 59 | // For color blends. 60 | QColor blendColor; 61 | double strength; 62 | }; 63 | 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /StructureSynth/Model/TransformationLoop.cpp: -------------------------------------------------------------------------------- 1 | #include "TransformationLoop.h" 2 | 3 | 4 | namespace StructureSynth { 5 | namespace Model { 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /StructureSynth/Model/TransformationLoop.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Transformation.h" 4 | 5 | namespace StructureSynth { 6 | namespace Model { 7 | 8 | /// A loop is a transformation which is repeated a number of times: 9 | /// e.g.: 10 | /// 20 * { x 1 } R1 11 | /// will create twenty R1 objects each succesively moved one unit in the x-directions. 12 | struct TransformationLoop { 13 | TransformationLoop() {}; 14 | TransformationLoop(int repetitions, Transformation transformation) : repetitions(repetitions), transformation(transformation) {}; 15 | 16 | int repetitions; 17 | Transformation transformation; 18 | }; 19 | 20 | 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /StructureSynth/Parser/EisenParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Tokenizer.h" 4 | #include "../Model/Transformation.h" 5 | #include "../Model/Rule.h" 6 | #include "../Model/CustomRule.h" 7 | #include "../Model/RuleSet.h" 8 | #include "../Model/Action.h" 9 | 10 | namespace StructureSynth { 11 | namespace Parser { 12 | 13 | 14 | /// The' Eisenstein Engine' is a simple recursive descent parser, 15 | /// for parsing 'EisenScript'. 16 | class EisenParser { 17 | 18 | public: 19 | /// Constructor. 20 | EisenParser(Tokenizer* tokenizer); 21 | 22 | /// Destructor, The tokenizer is not deleted. 23 | ~EisenParser(); 24 | 25 | /// Parses the input, and returns the corresponding ruleset. 26 | /// Throws a ParseError if any errors are encountered 27 | Model::RuleSet* parseRuleset(); 28 | bool recurseDepthFirst() { return recurseDepth; } 29 | 30 | private: 31 | bool recurseDepth; 32 | void getSymbol(); 33 | Model::Rule* rule(); 34 | Model::RuleSet* ruleset(); 35 | Model::Action action(); 36 | Model::Action setAction(); 37 | Model::Transformation transformationList(); 38 | Model::Transformation transformation(); 39 | void ruleModifierList(Model::CustomRule* customRule); 40 | 41 | bool accept(Symbol::SymbolType st); 42 | bool expect(Symbol::SymbolType st); 43 | Symbol symbol; 44 | 45 | Tokenizer* tokenizer; 46 | }; 47 | 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /StructureSynth/Parser/Preprocessor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../../SyntopiaCore/Exceptions/Exception.h" 8 | 9 | namespace StructureSynth { 10 | namespace Parser { 11 | 12 | class GuiParameter { 13 | public: 14 | GuiParameter(QString name) : name(name) {}; 15 | virtual QString getName() { return name; } 16 | protected: 17 | QString name; 18 | }; 19 | 20 | class FloatParameter : public GuiParameter { 21 | public: 22 | FloatParameter(QString name, double from, double to, double defaultValue) : 23 | GuiParameter(name), from(from), to(to), defaultValue(defaultValue) {}; 24 | 25 | double getFrom() { return from; } 26 | double getTo() { return to; } 27 | double getDefaultValue() { return defaultValue; } 28 | private: 29 | double from; 30 | double to; 31 | double defaultValue; 32 | }; 33 | 34 | class IntParameter : public GuiParameter { 35 | public: 36 | IntParameter(QString name, int from, int to, int defaultValue) : 37 | GuiParameter(name), from(from), to(to), defaultValue(defaultValue) {}; 38 | 39 | int getFrom() { return from; } 40 | int getTo() { return to; } 41 | int getDefaultValue() { return defaultValue; } 42 | private: 43 | int from; 44 | int to; 45 | int defaultValue; 46 | }; 47 | 48 | /// The preprocessor is responsible for expanding '#define' 49 | /// 50 | class Preprocessor { 51 | 52 | public: 53 | Preprocessor() {}; 54 | 55 | // The preprocess replaces 'random[2,4]' statements with random numbers. 56 | // This requires a seed. Using the same seed as controls the EisenScript is probably the best idea her. 57 | QString Process(QString input, int seed = 0); 58 | QVector getParameters() { return params; } 59 | 60 | private: 61 | QVector params; 62 | }; 63 | 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /StructureSynth/Parser/Tokenizer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "../../SyntopiaCore/Exceptions/Exception.h" 7 | 8 | namespace StructureSynth { 9 | namespace Parser { 10 | 11 | class ParseError : public SyntopiaCore::Exceptions::Exception { 12 | public: 13 | ParseError(QString message, int position) : Exception(message), position(position) {}; 14 | int getPosition() { return position; } 15 | private: 16 | int position; 17 | }; 18 | 19 | struct Symbol { 20 | enum SymbolType { Undefined, LeftBracket, RightBracket, MoreThan, End, Number, Multiply, UserString, Rule, Set, Operator } ; 21 | 22 | 23 | 24 | Symbol() : floatValue(0), intValue(0), isInteger(false),pos(-1), type(Undefined) { }; 25 | Symbol(int pos, SymbolType s, QString original) : text(original),floatValue(0), intValue(0),isInteger(false), pos(pos), type(s) { }; 26 | 27 | 28 | /// yes, yes, it is a bloated representation. (I don't like unions...) 29 | QString text; // The original text-string we parsed. Notice userstrings are converted to lower-case 30 | double floatValue; 31 | int intValue; 32 | bool isInteger; 33 | int pos; // the position (char-index) of the original text parsed. 34 | SymbolType type; 35 | 36 | 37 | double getNumerical() { 38 | if (isInteger) return intValue; 39 | return floatValue; 40 | } 41 | }; 42 | 43 | /// The Tokenizer divides an input stream into distinct symbols, 44 | /// for subsequent parsing. 45 | class Tokenizer { 46 | 47 | public: 48 | /// Constructor. 49 | Tokenizer(QString input); 50 | 51 | /// Destructor 52 | ~Tokenizer(); 53 | 54 | /// Returns the next symbol 55 | Symbol getSymbol(); 56 | 57 | private: 58 | 59 | QList symbols; 60 | int currentSymbol; 61 | }; 62 | 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /StructureSynthDoc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/StructureSynthDoc.ico -------------------------------------------------------------------------------- /SyntopiaCore/Exceptions/Exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace SyntopiaCore { 4 | namespace Exceptions { 5 | 6 | /// A base exception class. 7 | /// 8 | /// When using Exceptions: 9 | /// (1) Throw temporaries (throw Exception("Error occoured");) 10 | /// (2) Catch by reference ( try {} catch (Exception& e) {} ) 11 | /// 12 | /// (Perhaps this ought to inherit from std::exception?) 13 | class Exception { 14 | 15 | public: 16 | /// Constructor. 17 | Exception(QString message) : message(message) {}; 18 | 19 | /// Returns the error message. 20 | QString getMessage() const { return message; } 21 | 22 | private: 23 | QString message; 24 | 25 | }; 26 | 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Box.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | #include "RaytraceTriangle.h" 6 | 7 | 8 | namespace SyntopiaCore { 9 | namespace GLEngine { 10 | 11 | class Box : public Object3D { 12 | public: 13 | Box(SyntopiaCore::Math::Vector3f base, 14 | SyntopiaCore::Math::Vector3f dir1 , 15 | SyntopiaCore::Math::Vector3f dir2, 16 | SyntopiaCore::Math::Vector3f dir3); 17 | 18 | virtual ~Box(); 19 | 20 | virtual QString name() { return "Box"; } 21 | 22 | virtual void draw() const; 23 | 24 | virtual bool intersectsRay(RayInfo* /*rayInfo*/); 25 | virtual bool intersectsAABB(SyntopiaCore::Math::Vector3f /*from*/, SyntopiaCore::Math::Vector3f /*to*/); 26 | virtual void prepareForRaytracing(); 27 | 28 | private: 29 | bool useTriangles; 30 | QVector triangles; 31 | SyntopiaCore::Math::Vector3f base; 32 | 33 | SyntopiaCore::Math::Vector3f v1; 34 | SyntopiaCore::Math::Vector3f v2; 35 | SyntopiaCore::Math::Vector3f v3; 36 | 37 | SyntopiaCore::Math::Vector3f n21 ; 38 | SyntopiaCore::Math::Vector3f n32; 39 | SyntopiaCore::Math::Vector3f n13; 40 | SyntopiaCore::Math::Vector3f ac; 41 | SyntopiaCore::Math::Vector3f a[3]; 42 | float h[3]; 43 | 44 | }; 45 | 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Dot.cpp: -------------------------------------------------------------------------------- 1 | #include "Dot.h" 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | 5 | using namespace SyntopiaCore::Math; 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | Dot::Dot(SyntopiaCore::Math::Vector3f pos) : pos(pos) 11 | { 12 | /// Bounding box 13 | from = pos; 14 | to = pos; 15 | }; 16 | 17 | Dot::~Dot() { }; 18 | 19 | void Dot::draw() const { 20 | glDisable (GL_LIGHTING); 21 | glColor4fv(primaryColor); 22 | glBegin(GL_POINTS); 23 | glVertex3f(pos.x(), pos.y(), pos.z()); 24 | glEnd(); 25 | 26 | glEnable (GL_LIGHTING); 27 | 28 | }; 29 | 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Dot.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | class Dot : public Object3D { 10 | public: 11 | Dot(SyntopiaCore::Math::Vector3f pos); 12 | 13 | virtual QString name() { return "Dot"; } 14 | 15 | virtual ~Dot(); 16 | 17 | virtual void draw() const; 18 | 19 | private: 20 | SyntopiaCore::Math::Vector3f pos; 21 | }; 22 | 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Grid.cpp: -------------------------------------------------------------------------------- 1 | #include "Grid.h" 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | 5 | using namespace SyntopiaCore::Math; 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | Grid::Grid(SyntopiaCore::Math::Vector3f base, 11 | SyntopiaCore::Math::Vector3f dir1 , 12 | SyntopiaCore::Math::Vector3f dir2, 13 | SyntopiaCore::Math::Vector3f dir3) : base(base), v1(dir1), v2(dir2), v3(dir3) 14 | { 15 | /// Bounding box 16 | from = base; 17 | to = base + dir1 + dir2 + dir3; 18 | }; 19 | 20 | 21 | Grid::~Grid() { }; 22 | 23 | void Grid::draw() const { 24 | glPushMatrix(); 25 | glTranslatef( base.x(), base.y(), base.z() ); 26 | glLineWidth( 1.0 ); 27 | 28 | glDisable (GL_LIGHTING); 29 | glColor4fv( primaryColor ); 30 | 31 | glBegin( GL_LINE_LOOP ); 32 | Vector3f O(0,0,0); 33 | vertex(O); 34 | vertex(v2); 35 | vertex(v2+v1); 36 | vertex(v1); 37 | glEnd(); 38 | 39 | glBegin( GL_LINE_LOOP ); 40 | vertex(v3); 41 | vertex(v2+v3); 42 | vertex(v2+v1+v3); 43 | vertex(v1+v3); 44 | glEnd(); 45 | 46 | glBegin( GL_LINES ); 47 | vertex( v3 ); vertex( O ); 48 | vertex( v2 ); vertex( v2+v3 ); 49 | vertex( v1+v2 ); vertex( v1+v2+v3 ); 50 | vertex( v1 ); vertex( v1+v3 ); 51 | glEnd(); 52 | 53 | glEnable (GL_LIGHTING); 54 | 55 | glPopMatrix(); 56 | }; 57 | 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Grid.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | class Grid : public Object3D { 10 | public: 11 | Grid(SyntopiaCore::Math::Vector3f base, 12 | SyntopiaCore::Math::Vector3f dir1 , 13 | SyntopiaCore::Math::Vector3f dir2, 14 | SyntopiaCore::Math::Vector3f dir3); 15 | 16 | virtual ~Grid(); 17 | 18 | virtual QString name() { return "Grid"; } 19 | 20 | virtual void draw() const; 21 | 22 | private: 23 | SyntopiaCore::Math::Vector3f base; 24 | SyntopiaCore::Math::Vector3f v1; 25 | SyntopiaCore::Math::Vector3f v2; 26 | SyntopiaCore::Math::Vector3f v3; 27 | }; 28 | 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Line.cpp: -------------------------------------------------------------------------------- 1 | #include "Line.h" 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | 5 | using namespace SyntopiaCore::Math; 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | 11 | //GLUquadric* Sphere::myQuad = 0; 12 | 13 | Line::Line(SyntopiaCore::Math::Vector3f from, SyntopiaCore::Math::Vector3f to) : from(from), to(to) 14 | { 15 | /// Bounding box 16 | from = from; 17 | to = to; 18 | }; 19 | 20 | Line::~Line() { 21 | }; 22 | 23 | void vertex(Vector3f v) { 24 | glVertex3f(v.x(), v.y(), v.z()); 25 | } 26 | 27 | void Line::draw() const { 28 | 29 | glLineWidth( 1.0 ); 30 | glDisable (GL_LIGHTING); 31 | glColor4fv(primaryColor); 32 | 33 | glBegin(GL_LINES); 34 | vertex(from); 35 | vertex(to); 36 | glEnd(); 37 | 38 | glEnable (GL_LIGHTING); 39 | 40 | }; 41 | 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Line.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | class Line : public Object3D { 10 | public: 11 | Line(SyntopiaCore::Math::Vector3f from, SyntopiaCore::Math::Vector3f to); 12 | 13 | virtual ~Line(); 14 | 15 | virtual QString name() { return "Line"; } 16 | 17 | virtual void draw() const; 18 | 19 | private: 20 | SyntopiaCore::Math::Vector3f from; 21 | SyntopiaCore::Math::Vector3f to; 22 | }; 23 | 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | #include "RaytraceTriangle.h" 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | class Mesh : public Object3D { 11 | public: 12 | Mesh(SyntopiaCore::Math::Vector3f startBase, 13 | SyntopiaCore::Math::Vector3f startDir1 , 14 | SyntopiaCore::Math::Vector3f startDir2, 15 | SyntopiaCore::Math::Vector3f endBase, 16 | SyntopiaCore::Math::Vector3f endDir1 , 17 | SyntopiaCore::Math::Vector3f endDir2 18 | ); 19 | 20 | virtual ~Mesh(); 21 | 22 | virtual QString name() { return "Mesh"; } 23 | 24 | virtual void draw() const; 25 | void initTriangles(); 26 | 27 | virtual bool intersectsRay(RayInfo* /*rayInfo*/); 28 | virtual bool intersectsAABB(SyntopiaCore::Math::Vector3f /*from*/, SyntopiaCore::Math::Vector3f /*to*/); 29 | virtual void prepareForRaytracing() {initTriangles(); }; 30 | void setPreviousColor(SyntopiaCore::Math::Vector3f oldRgb, float oldAlpha) { this->oldRgb = oldRgb; this->oldAlpha = oldAlpha; } 31 | 32 | 33 | 34 | private: 35 | SyntopiaCore::Math::Vector3f startBase; 36 | SyntopiaCore::Math::Vector3f startDir1; 37 | SyntopiaCore::Math::Vector3f startDir2; 38 | SyntopiaCore::Math::Vector3f endBase; 39 | SyntopiaCore::Math::Vector3f endDir1; 40 | SyntopiaCore::Math::Vector3f endDir2; 41 | QVector triangles; 42 | SyntopiaCore::Math::Vector3f oldRgb; 43 | float oldAlpha; 44 | }; 45 | 46 | } 47 | } 48 | 49 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Object3D.cpp: -------------------------------------------------------------------------------- 1 | #include "Object3D.h" 2 | 3 | 4 | using namespace SyntopiaCore::Math; 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | void Object3D::setColor(SyntopiaCore::Math::Vector3f rgb, float alpha) { 10 | primaryColor[0] = rgb[0]; 11 | primaryColor[1] = rgb[1]; 12 | primaryColor[2] = rgb[2]; 13 | primaryColor[3] = alpha; 14 | } 15 | 16 | void Object3D::Expand(Vector3f& from, Vector3f& to, Vector3f test) { 17 | if (test.x()to.x()) to.x() = test.x(); 21 | if (test.y()>to.y()) to.y() = test.y(); 22 | if (test.z()>to.z()) to.z() = test.z(); 23 | } 24 | 25 | void Object3D::vertex4n(SyntopiaCore::Math::Vector3f v1,SyntopiaCore::Math::Vector3f v2,SyntopiaCore::Math::Vector3f v3,SyntopiaCore::Math::Vector3f v4) const { 26 | Vector3f n = (v2-v1).cross(v4-v1); 27 | n.normalize(); 28 | normal(n); 29 | vertex(v1); 30 | vertex(v2); 31 | vertex(v3); 32 | vertex(v4); 33 | } 34 | 35 | void Object3D::vertex4(const GLfloat* col1, SyntopiaCore::Math::Vector3f c1, SyntopiaCore::Math::Vector3f v1,SyntopiaCore::Math::Vector3f v2, const GLfloat* col2, SyntopiaCore::Math::Vector3f c2, SyntopiaCore::Math::Vector3f v3,SyntopiaCore::Math::Vector3f v4, bool reverse) const { 36 | /* 37 | Vector3f n = (v2-v1).cross(v4-v1); 38 | n.normalize(); 39 | if (reverse) n =-n; 40 | 41 | normal(n); 42 | */ 43 | 44 | 45 | glColor4fv(col1); 46 | if (reverse) { 47 | normal((c1-v1).normalized()); 48 | } else { 49 | normal((v1-c1).normalized()); 50 | } 51 | vertex(v1); 52 | if (reverse) { 53 | normal((c1-v2).normalized()); 54 | } else { 55 | normal((v2-c1).normalized()); 56 | } 57 | vertex(v2); 58 | glColor4fv(col2); 59 | if (reverse) { 60 | normal((c2-v3).normalized()); 61 | } else { 62 | normal((v3-c2).normalized()); 63 | } 64 | vertex(v3); 65 | if (reverse) { 66 | normal((c2-v4).normalized()); 67 | } else { 68 | normal((v4-c2).normalized()); 69 | } 70 | vertex(v4); 71 | } 72 | 73 | void Object3D::vertex3n(SyntopiaCore::Math::Vector3f v1,SyntopiaCore::Math::Vector3f v2,SyntopiaCore::Math::Vector3f v3) const { 74 | Vector3f n = (v2-v1).cross(v3-v1); 75 | n.normalize(); 76 | normal(n); 77 | vertex(v1); 78 | vertex(v2); 79 | vertex(v3); 80 | } 81 | 82 | void Object3D::vertex4rn(SyntopiaCore::Math::Vector3f v1,SyntopiaCore::Math::Vector3f v2,SyntopiaCore::Math::Vector3f v3,SyntopiaCore::Math::Vector3f v4) const { 83 | Vector3f n = (v1-v2).cross(v4-v1); 84 | n.normalize(); 85 | normal(n); 86 | vertex(v4); 87 | vertex(v3); 88 | vertex(v2); 89 | vertex(v1); 90 | } 91 | 92 | void Object3D::vertex4nc(SyntopiaCore::Math::Vector3f v1,SyntopiaCore::Math::Vector3f v2,SyntopiaCore::Math::Vector3f v3,SyntopiaCore::Math::Vector3f v4,SyntopiaCore::Math::Vector3f center) const { 93 | normal((v1-center).normalized()); 94 | vertex(v1); 95 | normal((v2-center).normalized()); 96 | vertex(v2); 97 | normal((v3-center).normalized()); 98 | vertex(v3); 99 | normal((v4-center).normalized()); 100 | vertex(v4); 101 | } 102 | 103 | void Object3D::vertex4rnc(SyntopiaCore::Math::Vector3f v1,SyntopiaCore::Math::Vector3f v2,SyntopiaCore::Math::Vector3f v3,SyntopiaCore::Math::Vector3f v4,SyntopiaCore::Math::Vector3f center) const { 104 | normal((v4-center).normalized()); 105 | vertex(v4); 106 | normal((v3-center).normalized()); 107 | vertex(v3); 108 | normal((v2-center).normalized()); 109 | vertex(v2); 110 | normal((v1-center).normalized()); 111 | vertex(v1); 112 | } 113 | 114 | 115 | void Object3D::getBoundingBox(SyntopiaCore::Math::Vector3f& from, SyntopiaCore::Math::Vector3f& to) const { 116 | from = this->from; 117 | to = this->to; 118 | }; 119 | 120 | void Object3D::expandBoundingBox(SyntopiaCore::Math::Vector3f& from, SyntopiaCore::Math::Vector3f& to) const { 121 | for (unsigned int i = 0; i < 3; i++) if (this->from[i] < from[i]) from[i] = this->from[i]; 122 | for (unsigned int i = 0; i < 3; i++) if (this->to[i] > to[i]) to[i] = this->to[i]; 123 | }; 124 | 125 | 126 | } 127 | 128 | } 129 | 130 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/RaytraceTriangle.cpp: -------------------------------------------------------------------------------- 1 | #include "RaytraceTriangle.h" 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | 5 | using namespace SyntopiaCore::Math; 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | using namespace SyntopiaCore::Math; 10 | 11 | 12 | RaytraceTriangle::RaytraceTriangle(Vector3f p1, Vector3f p2, Vector3f p3, Vector3f n1, Vector3f n2, Vector3f n3) 13 | : p1(p1),p2(p2),p3(p3),n1(n1),n2(n2),n3(n3) , cullBackFaces(true) 14 | { 15 | 16 | // We will use barycentric coordiantes. 17 | Vector3f p12 = p2-p1; 18 | Vector3f p13 = p3-p1; 19 | Vector3f p312 = (p12/p12.sqrLength())*Vector3f::dot(p12,p13); 20 | Vector3f pn3 = p13-p312; 21 | npn3 = pn3/pn3.sqrLength(); 22 | 23 | Vector3f p32 = p2-p3; 24 | Vector3f p31 = p1-p3; 25 | Vector3f p132 = (p32/p32.sqrLength())*Vector3f::dot(p32,p31); 26 | Vector3f pn1 = p31-p132; 27 | npn1 = pn1/pn1.sqrLength(); 28 | 29 | Vector3f p213 = (p13/p13.sqrLength())*Vector3f::dot(p13,p12); 30 | Vector3f pn2 = p12-p213; 31 | npn2 = pn2/pn2.sqrLength(); 32 | 33 | if (npn1.sqrLength() * 0 != 0 || npn2.sqrLength() * 0 != 0 || npn3.sqrLength() * 0 != 0 || 34 | p13.sqrLength() < 1E-8 || p12.sqrLength() < 1E-8 || p32.sqrLength() < 1E-8) { 35 | //INFO(QString("Bad Triangle (%0): %1, %2, %3").arg((p3-p2).sqrLength()).arg(p1.toString()).arg(p2.toString()).arg(p3.toString())); 36 | bad = true; 37 | } else { 38 | bad = false; 39 | } 40 | 41 | n1.normalize(); 42 | n2.normalize(); 43 | n3.normalize(); 44 | 45 | n = Vector3f::cross(p13,p12); 46 | } 47 | 48 | 49 | 50 | 51 | void RaytraceTriangle::expandBoundingBox(Vector3f& from,Vector3f& to) { 52 | Vector3f p = p1; 53 | for (int i = 0; i < 3; i++) { 54 | if (i==1) p=p2; 55 | if (i==2) p=p3; 56 | if ( p.x() < from.x()) from.x() = p.x(); 57 | if ( p.y() < from.y()) from.y() = p.y(); 58 | if ( p.z() < from.z()) from.z() = p.z(); 59 | if ( p.x() > to.x()) to.x() = p.x(); 60 | if ( p.y() > to.y()) to.y() = p.y(); 61 | if ( p.z() > to.z()) to.z() = p.z(); 62 | } 63 | } 64 | 65 | 66 | 67 | //bool RayTraceTriangle::getIntersectionAndNormal(const Vector3f& startPoint, const Vector3f& lineDirection, double& intersection, Vector3f& normal, Vector3f& color, float& alpha ) { 68 | 69 | bool RaytraceTriangle::intersectsRay(RayInfo* ri) { 70 | if (bad) return false; 71 | 72 | if (cullBackFaces && Vector3f::dot(n,ri->lineDirection)>0) return false; 73 | 74 | float is = Vector3f::dot(n, p1-ri->startPoint)/Vector3f::dot(n, ri->lineDirection); 75 | Vector3f ip = ri->startPoint + ri->lineDirection * is; 76 | 77 | float k312 = Vector3f::dot((ip-p1),npn3); 78 | if (k312 > 1 || k312 <= 0) return false; 79 | float k132 = Vector3f::dot((ip-p3),npn1); 80 | if (k132 > 1 || k132 <= 0) return false; 81 | float k213 = Vector3f::dot((ip-p1),npn2); 82 | if (k213 > 1 || k213 <= 0) return false; 83 | 84 | ri->intersection = is; 85 | ri->normal = n3*k312+ n1*k132+n2*k213; 86 | if (!cullBackFaces && Vector3f::dot( ri->normal , ri->lineDirection)>0) ri->normal=-ri->normal; 87 | 88 | float c0 = k312*color3[0]+k132*color1[0]+k213*color2[0]; 89 | float c1 = k312*color3[1]+k132*color1[1]+k213*color2[1]; 90 | float c2 = k312*color3[2]+k132*color1[2]+k213*color2[2]; 91 | float a = 1; //k312*color3[3]+k132*color1[3]+k213*color2[3]; 92 | ri->color[0] = c0; 93 | ri->color[1] = c1; 94 | ri->color[2] = c2; 95 | ri->color[3] = a; 96 | return true; 97 | } 98 | 99 | 100 | 101 | 102 | RaytraceTriangle::~RaytraceTriangle(void) { } 103 | 104 | void RaytraceTriangle::Vertex4(Vector3f p1,Vector3f p2,Vector3f p3,Vector3f p4,bool reverse, QVector& list, float r, float g, float b, float a) { 105 | Vector3f n = -Vector3f::cross(p2-p1, p4-p1); 106 | if (reverse) n=-n; 107 | n.normalize(); 108 | RaytraceTriangle r1(p1,p2,p4,n,n,n); 109 | r1.n = n; 110 | r1.setColor(r,g,b,a); 111 | list.append(r1); 112 | RaytraceTriangle r2(p3,p4,p2,n,n,n); 113 | r2.setColor(r,g,b,a); 114 | r2.n = n; 115 | list.append(r2); 116 | } 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/RaytraceTriangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | using namespace SyntopiaCore::Math; 10 | 11 | // Helper class for tesselated objects 12 | class RaytraceTriangle { 13 | public: 14 | RaytraceTriangle(Vector3f p1, Vector3f p2, Vector3f p3, Vector3f n1, Vector3f n2, Vector3f n3); 15 | RaytraceTriangle() : cullBackFaces(false) {}; 16 | ~RaytraceTriangle(void); 17 | void expandBoundingBox(Vector3f& from,Vector3f& to); 18 | void setColor(float r, float g, float b, float a) { 19 | color1[0] = r; color1[1] = g; color1[2] = b; color1[3] = a; 20 | color2[0] = r; color2[1] = g; color2[2] = b; color2[3] = a; 21 | color3[0] = r; color3[1] = g; color3[2] = b; color3[3] = a; 22 | } 23 | virtual bool intersectsRay(RayInfo* /*rayInfo*/); 24 | 25 | static void Vertex4(Vector3f p1,Vector3f p2,Vector3f p3,Vector3f p4,bool reverse, QVector& list, float r, float b, float g, float a); 26 | 27 | Vector3f p1; 28 | Vector3f p2; 29 | Vector3f p3; 30 | Vector3f n1; 31 | Vector3f n2; 32 | Vector3f n3; 33 | GLfloat color1[4]; 34 | GLfloat color2[4]; 35 | GLfloat color3[4]; 36 | Vector3f npn1; 37 | Vector3f npn2; 38 | Vector3f npn3; 39 | 40 | Vector3f to; 41 | Vector3f from; 42 | Vector3f n; 43 | bool bad; 44 | bool cullBackFaces; 45 | 46 | }; 47 | 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/AtomicCounter.cpp: -------------------------------------------------------------------------------- 1 | #include "AtomicCounter.h" 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | 5 | #include "AtomicCounter.h" 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/AtomicCounter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | class AtomicCounter { 10 | public: 11 | AtomicCounter() : current(0) { }; 12 | 13 | int increase() { 14 | mutex.lock(); 15 | int i = ++current; 16 | mutex.unlock(); 17 | wc.wakeAll(); 18 | return i; 19 | } 20 | 21 | void setValue(int value) { 22 | mutex.lock(); 23 | current = value; 24 | mutex.unlock(); 25 | wc.wakeAll(); 26 | } 27 | 28 | bool wait(unsigned long time = ULONG_MAX) { wcm.lock(); bool w = wc.wait(&wcm,time); wcm.unlock(); return w; } 29 | int value() { mutex.lock(); int i = current; mutex.unlock(); return i; } 30 | private: 31 | int current; 32 | QMutex mutex; 33 | QMutex wcm; 34 | QWaitCondition wc; 35 | }; 36 | 37 | 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/ProgressiveOutput.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "SyntopiaCore/Math/Vector3.h" 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | using namespace SyntopiaCore::Math; 11 | 12 | class ProgressiveOutput { 13 | public: 14 | ProgressiveOutput(int w, int h) : w(w), h(h) { 15 | mutex = new QMutex(); 16 | colors = new Vector3f[w*h]; 17 | weights = new double[w*h]; 18 | for (int x = 0; x < w; x++) { 19 | for (int y = 0; y < h; y++) { 20 | colors[x+y*w] = Vector3f(0,0,0); 21 | weights[x+y*w] = 0.0; 22 | } 23 | } 24 | } 25 | 26 | ~ProgressiveOutput() { 27 | delete mutex; 28 | delete[] colors; 29 | delete[] weights; 30 | } 31 | 32 | void addIteration(Vector3f* newColors, double* newWeights) { 33 | mutex->lock(); 34 | for (int x = 0; x < w; x++) { 35 | for (int y = 0; y < h; y++) { 36 | colors[x+y*w] = colors[x+y*w] + newColors[x+y*w]; 37 | weights[x+y*w] = weights[x+y*w] + newWeights[x+y*w]; 38 | } 39 | } 40 | mutex->unlock(); 41 | }; 42 | 43 | void addColumn(int x, Vector3f* newColors) { 44 | mutex->lock(); 45 | for (int y = 0; y < h; y++) { 46 | colors[x+y*w] = colors[x+y*w] + newColors[y]; 47 | weights[x+y*w] = 1.0; 48 | } 49 | mutex->unlock(); 50 | }; 51 | 52 | // This function is responsible for tonemapping and gamma-conversion. 53 | // I prefer not converting to sRGB encode 54 | // and a simply clipping functions works better than an 'exposure'-simulation 55 | int encode(float c, float /*exposure*/) 56 | { 57 | 58 | // Enable below for sRGB encoding 59 | /* 60 | float out = 1.0f - expf(c * exposure); 61 | if (out <= 0.0031308f) 62 | { 63 | out = 12.92f * out; 64 | } 65 | else 66 | { 67 | out = 1.055f * powf(out, 0.4166667f) - 0.055f; // Inverse gamma 2.4 68 | } 69 | float out = 1.0f - expf(c * exposure); 70 | out = powf(c, 1); 71 | */ 72 | if (c>1) c = 1; // Simple clipping... 73 | c *= 255; 74 | return (int)c; 75 | } 76 | 77 | 78 | QImage getImage() { 79 | QImage im(w,h, QImage::Format_RGB32); 80 | 81 | //mutex->lock(); 82 | float exposure = -2; 83 | for (int y = 0; y < h; y++) { 84 | QRgb* s = (QRgb*) im.scanLine(y); 85 | for (int x = 0; x < w; x++) { 86 | Vector3f c = colors[x+y*w]/weights[x+y*w]; 87 | *s = qRgb(encode(c.x(),exposure), encode(c.y(),exposure), encode(c.z(),exposure)); 88 | s++; 89 | //im.setPixel(x,y,qRgb(c.x()*255, c.y()*255, c.z()*255)); 90 | } 91 | } 92 | //mutex->unlock(); 93 | return im; 94 | } 95 | 96 | private: 97 | int w; 98 | int h; 99 | Vector3f* colors; 100 | double* weights; 101 | QMutex* mutex; 102 | }; 103 | 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/RayTracer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Object3D.h" 4 | #include "../EngineWidget.h" 5 | #include 6 | #include "SyntopiaCore/Math/Vector3.h" 7 | #include "SyntopiaCore/Math/Matrix4.h" 8 | #include "SyntopiaCore/Math/Random.h" 9 | #include "VoxelStepper.h" 10 | #include "RenderThread.h" 11 | #include "ProgressiveOutput.h" 12 | 13 | namespace SyntopiaCore { 14 | namespace GLEngine { 15 | 16 | using namespace SyntopiaCore::Math; 17 | 18 | class RayTracer { 19 | public: 20 | RayTracer(EngineWidget* widget, ProgressBox* progressBox, bool inGUI); 21 | QImage calculateImage(int width, int height); 22 | void setParameter(QString param, QString value); 23 | bool wasCancelled() { return userCancelled; } 24 | private: 25 | bool progressiveGUI; 26 | ProgressiveOutput* progressiveOutput; 27 | EngineWidget* engine; 28 | void startJobs(ProgressBox* progress); 29 | QList objects; 30 | float xmin; 31 | float ymin; 32 | float xmax; 33 | float ymax; 34 | 35 | int voxelSteps; 36 | int windowWidth; 37 | int windowHeight; 38 | 39 | // Matrices from the OpenGL view. 40 | GLdouble modelView[16]; 41 | GLdouble projection[16]; 42 | GLint viewPort[16]; 43 | long aaPixels; 44 | bool userCancelled; 45 | int sizeX; 46 | int sizeY; 47 | int maxThreads; 48 | QVector threads; 49 | AtomicCounter nextUnit; 50 | AtomicCounter completedUnits; 51 | int maxUnits; 52 | RenderThread rt; 53 | bool progressiveRender; 54 | ProgressBox* progressBox; 55 | }; 56 | 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/RenderThread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "../Object3D.h" 5 | #include "AtomicCounter.h" 6 | #include "VoxelStepper.h" 7 | #include "Sampler.h" 8 | #include "ProgressiveOutput.h" 9 | #include "SyntopiaCore/Math/Random.h" 10 | 11 | namespace SyntopiaCore { 12 | namespace GLEngine { 13 | 14 | using namespace SyntopiaCore::Math; 15 | 16 | 17 | class RenderThread : public QThread { 18 | public: 19 | enum Task { Raytrace, RaytraceProgressive } ; 20 | RenderThread(); 21 | ~RenderThread(); 22 | void setTask(Task task) { this->task = task; }; 23 | RenderThread(const RenderThread& other); 24 | void raytrace(int newUnit); 25 | void raytraceProgressive(int newUnit); 26 | void setCounters(AtomicCounter* nextUnit, AtomicCounter* completedUnits, int maxUnits); 27 | void alloc(int w, int h); 28 | void setObjects(int count); 29 | static void msleep(int i) { QThread::msleep(i); } 30 | void run(); 31 | Vector3f rayCastPixel(float x, float y); 32 | void setTerminated(bool value) { terminated = value; } 33 | void seed(int value) { rg.setSeed(value); }; 34 | double getAOStrength(Object3D* object, Vector3f objectNormal, Vector3f objectIntersection); 35 | Vector3f rayCast(Vector3f startPoint, Vector3f direction, Object3D* excludeThis, int level = 0); 36 | 37 | private: 38 | Task task; 39 | AtomicCounter* nextUnit; 40 | AtomicCounter* completedUnits; 41 | int maxUnits; 42 | int w; 43 | int h; 44 | 45 | bool terminated; 46 | 47 | Vector3f frontStart; 48 | Vector3f frontX; 49 | Vector3f frontY; 50 | Vector3f backStart; 51 | Vector3f backX; 52 | Vector3f backY; 53 | 54 | Vector3f lightPos; 55 | Vector3f backgroundColor; 56 | int rayID; 57 | QVector rayIDs; 58 | int pixels; 59 | int maxDepth; 60 | int checks; 61 | VoxelStepper* accelerator; 62 | 63 | int aoSamples; 64 | int totalAOCasts; 65 | int aaSamples; 66 | int width; 67 | int height; 68 | bool useShadows; 69 | double dofCenter; 70 | double dofFalloff; 71 | 72 | Math::RandomNumberGenerator rg; 73 | 74 | Vector3f color; 75 | bool copy; 76 | 77 | Sampler* sampler; 78 | ProgressiveOutput* progressiveOutput; 79 | friend class RayTracer; 80 | int rayNumber; 81 | Filter* filter; 82 | }; 83 | 84 | 85 | 86 | } 87 | } 88 | 89 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/Sampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Random.h" 4 | #include "SyntopiaCore/Math/Vector3.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | using namespace SyntopiaCore::Math; 10 | 11 | class Filter { 12 | public: 13 | Filter() {}; 14 | virtual float getWeight(float xSqr, float ySqr) = 0; 15 | virtual int getExtent() = 0; 16 | }; 17 | 18 | class BoxFilter : public Filter { 19 | public: 20 | BoxFilter() {}; 21 | virtual float getWeight(float, float) { return 1.0; } 22 | virtual int getExtent() { return 0; }; 23 | }; 24 | 25 | class GaussianFilter : public Filter { 26 | public: 27 | GaussianFilter(double ext, double alpha) : extent(extent), alpha(alpha) { 28 | this->extent = int(0.5+ext); 29 | s = -exp(-alpha*(ext*ext)); 30 | }; 31 | 32 | virtual float getWeight(float xSqr, float ySqr) { 33 | return (gaussian(xSqr)*gaussian(ySqr)); 34 | }; 35 | 36 | float gaussian(float v) { 37 | float a= exp(-alpha*v)+s; 38 | return a > 0 ? a : 0; 39 | } 40 | 41 | virtual int getExtent() { return extent; }; 42 | private: 43 | int extent; 44 | double s; 45 | double alpha; 46 | }; 47 | 48 | class TriangleFilter : public Filter { 49 | public: 50 | TriangleFilter(double halfwidth) : halfwidth(halfwidth) { 51 | this->extent = int(halfwidth-0.5+1); 52 | }; 53 | 54 | virtual float getWeight(float xSqr, float ySqr) { 55 | return (triangle(sqrt(xSqr))*triangle(sqrt(ySqr))); 56 | }; 57 | 58 | float triangle(float v) { 59 | float a= 1-v/halfwidth; 60 | return a > 0 ? a : 0; 61 | } 62 | 63 | virtual int getExtent() { return extent; }; 64 | private: 65 | int extent; 66 | double halfwidth; 67 | }; 68 | 69 | 70 | // A simple sampler. Draws uniform numbers, but no stratification. 71 | class Sampler { 72 | public: 73 | Sampler(Math::RandomNumberGenerator* rg); 74 | virtual ~Sampler(); 75 | virtual Vector3f getAASample(int /*index*/) { return Vector3f(rg->getDouble(-0.5,0.5), rg->getDouble(-0.5,0.5),1.0); } 76 | virtual Vector3f getAODirection(int /*index*/) { return rg->getUniform3D(); } 77 | virtual Vector3f getLensSample(int /*index*/) { return rg->getUniform2D(); } 78 | virtual void prepareSamples(int /*nSamplesSqrt*/, int /*nAOSamplesSqrt*/) {}; 79 | virtual Sampler* clone(Math::RandomNumberGenerator* rg) { return new Sampler(rg); } 80 | protected: 81 | Math::RandomNumberGenerator* rg; 82 | }; 83 | 84 | // Stratified sampling 85 | class StratifiedSampler : public Sampler { 86 | public: 87 | StratifiedSampler(Math::RandomNumberGenerator* rg) : Sampler(rg) {}; 88 | virtual Vector3f getAASample(int index); 89 | virtual Vector3f getAODirection(int index); 90 | virtual Vector3f getLensSample(int index); 91 | Vector3f sampleSphere(double u1, double u2); 92 | virtual void prepareSamples(int nSamplesSqrt, int nAOSamplesSqrt); 93 | virtual Sampler* clone(Math::RandomNumberGenerator* rg) { return new StratifiedSampler(rg); } 94 | 95 | private: 96 | QVector aoSamples; 97 | QVector aaSamples; 98 | QVector lensSamples; 99 | }; 100 | 101 | // Stratified sampling 102 | class ProgressiveStratifiedSampler : public Sampler { 103 | public: 104 | ProgressiveStratifiedSampler(Math::RandomNumberGenerator* rg) : 105 | Sampler(rg) {} 106 | virtual Vector3f getAASample(int index); 107 | virtual Vector3f getAODirection(int index); 108 | virtual Vector3f getLensSample(int index); 109 | Vector3f sampleSphere(double u1, double u2); 110 | virtual void prepareSamples(int nSamplesSqrt, int nAOSamplesSqrt); 111 | virtual Sampler* clone(Math::RandomNumberGenerator* rg); 112 | void setAAOrder(QVector aaOrder) { this->aaOrder = aaOrder; } 113 | private: 114 | int aoSamplesSqrt; 115 | int aaSamplesSqrt; 116 | QVector aaOrder; 117 | 118 | }; 119 | 120 | 121 | } 122 | } 123 | 124 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Raytracer/VoxelStepper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "../Object3D.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | using namespace SyntopiaCore::Math; 9 | 10 | /// See here for details about this approach: 11 | /// http://www.devmaster.net/articles/raytracing_series/part4.php 12 | class VoxelStepper { 13 | public: 14 | VoxelStepper(Vector3f minPos, Vector3f maxPos, int steps) ; 15 | ~VoxelStepper(); 16 | 17 | void registerObject(Object3D* obj) ; 18 | QList* setupRay(Vector3f pos, Vector3f dir, double& maxT); 19 | 20 | inline double minn(double a, double b, double c) { 21 | if (a* advance(double& maxT); 26 | void setCopy(bool value) { this->copy = value; } 27 | 28 | private: 29 | bool copy; 30 | double currentT; 31 | double tDeltaX; 32 | double tDeltaY; 33 | double tDeltaZ; 34 | double tMaxX; 35 | double tMaxY; 36 | double tMaxZ; 37 | int stepX; 38 | int stepY; 39 | int stepZ; 40 | int cx; 41 | int cy; 42 | int cz; 43 | 44 | Vector3f pos; 45 | Vector3f dir; 46 | int steps; 47 | Vector3f minPos; 48 | Vector3f maxPos; 49 | const Vector3f size; 50 | QList* grid; 51 | }; 52 | 53 | 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Sphere.cpp: -------------------------------------------------------------------------------- 1 | #include "Sphere.h" 2 | 3 | using namespace SyntopiaCore::Math; 4 | 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | 10 | //GLUquadric* Sphere::myQuad = 0; 11 | int Sphere::displayListIndex = 0; 12 | 13 | Sphere::Sphere(SyntopiaCore::Math::Vector3f center, float radius) : center(center), radius(radius) { 14 | myQuad = gluNewQuadric(); 15 | gluQuadricDrawStyle(myQuad, GLU_FILL); 16 | 17 | /// Bounding box 18 | Vector3f v = Vector3f(radius,radius,radius); 19 | from = center-v; 20 | to = center+v; 21 | 22 | if (displayListIndex == 0) { 23 | displayListIndex = glGenLists(1); 24 | glNewList(displayListIndex, GL_COMPILE); 25 | gluSphere(myQuad, 1, 7,7); 26 | glEndList(); 27 | } 28 | 29 | 30 | }; 31 | 32 | Sphere::~Sphere() { 33 | gluDeleteQuadric(myQuad); 34 | }; 35 | 36 | void Sphere::draw() const { 37 | glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, primaryColor ); 38 | if (primaryColor[3] < 1) { 39 | glEnable( GL_BLEND ); 40 | } 41 | 42 | glPushMatrix(); 43 | glTranslatef( center.x(), center.y(), center.z() ); 44 | if (displayListIndex!=0) { 45 | glScalef(radius,radius,radius); 46 | glCallList(displayListIndex); 47 | } else { 48 | gluSphere(myQuad, radius, 7, 7); 49 | } 50 | glPopMatrix(); 51 | }; 52 | 53 | 54 | 55 | 56 | bool Sphere::intersectsRay(RayInfo* ri) { 57 | // Following: http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/ 58 | 59 | double a = ri->lineDirection.sqrLength(); 60 | double b = 2*(Vector3f::dot(ri->lineDirection, (ri->startPoint - center))); 61 | double c = (center-ri->startPoint).sqrLength() - radius*radius; 62 | 63 | double d = b*b-4*a*c; 64 | 65 | if (d<0) { 66 | ri->intersection = -1; 67 | return false; 68 | } else { 69 | // We always choose the negative solution, since it will be closest to the startPoint. (If intersection is positive) 70 | ri->intersection = (b - sqrt(d))/(-2*a); 71 | double intersection2 = (b + sqrt(d))/(-2*a); 72 | if (intersection2intersection) ri->intersection = intersection2; 73 | 74 | ri->normal = (ri->startPoint + ri->lineDirection*ri->intersection)-center; 75 | ri->normal.normalize(); 76 | for (int i = 0; i < 4; i++) ri->color[i] = primaryColor[i]; 77 | return true; 78 | } 79 | }; 80 | 81 | bool Sphere::intersectsAABB(Vector3f from, Vector3f to) { 82 | // Based on http://www.gamasutra.com/features/19991018/Gomez_4.htm 83 | float s, d = 0; 84 | 85 | //find the square of the distance 86 | //from the sphere to the box 87 | for( long i=0 ; i<3 ; i++ ) 88 | { 89 | if( center[i] < from[i] ) 90 | { 91 | s = center[i] - from[i]; 92 | d += s*s; 93 | } else if( center[i] > to[i] ) { 94 | s = center[i] - to[i]; 95 | d += s*s; 96 | } 97 | } 98 | return d <= radius*radius; 99 | }; 100 | 101 | 102 | 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Sphere.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | 6 | namespace SyntopiaCore { 7 | namespace GLEngine { 8 | 9 | class Sphere : public Object3D { 10 | public: 11 | Sphere(SyntopiaCore::Math::Vector3f center, float radius); 12 | virtual ~Sphere(); 13 | 14 | virtual QString name() { return "Sphere"; } 15 | 16 | virtual void draw() const; 17 | void setCenter(SyntopiaCore::Math::Vector3f center) { this->center = center; } 18 | 19 | virtual bool intersectsRay(RayInfo* /*rayInfo*/); 20 | virtual bool intersectsAABB(SyntopiaCore::Math::Vector3f /*from*/, SyntopiaCore::Math::Vector3f /*to*/); 21 | 22 | private: 23 | SyntopiaCore::Math::Vector3f center; 24 | float radius; 25 | GLUquadric* myQuad; 26 | static int displayListIndex; 27 | }; 28 | 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Triangle.cpp: -------------------------------------------------------------------------------- 1 | #include "Triangle.h" 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | 5 | using namespace SyntopiaCore::Math; 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | 11 | Triangle::Triangle(SyntopiaCore::Math::Vector3f p1 , 12 | SyntopiaCore::Math::Vector3f p2, 13 | SyntopiaCore::Math::Vector3f p3) : p1(p1), p2(p2), p3(p3) 14 | { 15 | from = p1; 16 | to = p3; 17 | 18 | Vector3f n1 = Vector3f::cross(p3-p1, p2-p1); 19 | n1.normalize(); 20 | rt = RaytraceTriangle(p1,p2,p3,n1,n1,n1); 21 | rt.expandBoundingBox(from,to); 22 | rt.cullBackFaces = false; 23 | }; 24 | 25 | Triangle::~Triangle() { }; 26 | 27 | void Triangle::prepareForRaytracing() { 28 | rt.setColor(primaryColor[0],primaryColor[1],primaryColor[2], primaryColor[3]); 29 | } 30 | 31 | void Triangle::draw() const { 32 | glPushMatrix(); 33 | 34 | glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, primaryColor ); 35 | glPolygonMode(GL_FRONT, GL_FILL); 36 | 37 | glEnable(GL_CULL_FACE); 38 | glEnable (GL_LIGHTING); 39 | 40 | glEnable (GL_BLEND); 41 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 42 | 43 | glMateriali(GL_FRONT, GL_SPECULAR, 30); 44 | glMateriali(GL_FRONT, GL_SHININESS, 127); 45 | 46 | glBegin(GL_TRIANGLES); 47 | vertex3n(p1,p2,p3); 48 | glEnd(); 49 | 50 | glPopMatrix(); 51 | }; 52 | 53 | 54 | bool Triangle::intersectsRay(RayInfo* ri) { 55 | return rt.intersectsRay(ri); 56 | }; 57 | 58 | 59 | bool Triangle::intersectsAABB(Vector3f from2, Vector3f to2) { 60 | return (from.x() < to2.x()) && (to.x() > from2.x()) && 61 | (from.y() < to2.y()) && (to.y() > from2.y()) && 62 | (from.z() < to2.z()) && (to.z() > from2.z()); 63 | }; 64 | 65 | 66 | 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /SyntopiaCore/GLEngine/Triangle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SyntopiaCore/Math/Vector3.h" 4 | #include "Object3D.h" 5 | #include "RaytraceTriangle.h" 6 | 7 | namespace SyntopiaCore { 8 | namespace GLEngine { 9 | 10 | class Triangle : public Object3D { 11 | public: 12 | Triangle(SyntopiaCore::Math::Vector3f p1 , 13 | SyntopiaCore::Math::Vector3f p2, 14 | SyntopiaCore::Math::Vector3f p3); 15 | 16 | virtual ~Triangle(); 17 | 18 | virtual QString name() { return "Triangle"; } 19 | virtual void draw() const; 20 | virtual void prepareForRaytracing(); 21 | virtual bool intersectsRay(RayInfo* /*rayInfo*/); 22 | virtual bool intersectsAABB(SyntopiaCore::Math::Vector3f /*from*/, SyntopiaCore::Math::Vector3f /*to*/); 23 | 24 | private: 25 | RaytraceTriangle rt; 26 | SyntopiaCore::Math::Vector3f p1; 27 | SyntopiaCore::Math::Vector3f p2; 28 | SyntopiaCore::Math::Vector3f p3; 29 | }; 30 | 31 | } 32 | } 33 | 34 | -------------------------------------------------------------------------------- /SyntopiaCore/Logging/ListWidgetLogger.cpp: -------------------------------------------------------------------------------- 1 | #include "ListWidgetLogger.h" 2 | 3 | 4 | 5 | namespace SyntopiaCore { 6 | namespace Logging { 7 | 8 | ListWidgetLogger::ListWidgetLogger(QWidget* parent) : parent(parent) { 9 | listWidget = new QListWidget(parent); 10 | } 11 | 12 | ListWidgetLogger::~ListWidgetLogger() { 13 | } 14 | 15 | void ListWidgetLogger::log(QString message, LogLevel priority) { 16 | QListWidgetItem* i = new QListWidgetItem(message, listWidget); 17 | 18 | // Levels: NoneLevel, DebugLevel, TimingLevel, InfoLevel, WarningLevel, CriticalLevel, AllLevel 19 | 20 | if ( priority == InfoLevel ) { 21 | i->setBackgroundColor(QColor(255,255,255)); 22 | } else if ( priority == WarningLevel ) { 23 | parent->show(); 24 | i->setBackgroundColor(QColor(255,243,73)); 25 | } else if ( priority == CriticalLevel ) { 26 | parent->show(); 27 | i->setBackgroundColor(QColor(255,2,0)); 28 | } else if ( priority == TimingLevel ) { 29 | parent->show(); 30 | i->setBackgroundColor(QColor(25,255,0)); 31 | } else { 32 | i->setBackgroundColor(QColor(220,220,220)); 33 | } 34 | listWidget->scrollToItem(i); 35 | 36 | } 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /SyntopiaCore/Logging/ListWidgetLogger.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Logging.h" 8 | 9 | namespace SyntopiaCore { 10 | namespace Logging { 11 | 12 | class ListWidgetLogger : public Logger { 13 | public: 14 | ListWidgetLogger(QWidget* parent); 15 | 16 | virtual ~ListWidgetLogger(); 17 | 18 | /// This method all loggers must implement 19 | void log(QString message, LogLevel priority); 20 | 21 | QListWidget* getListWidget() { return listWidget; } 22 | 23 | private: 24 | QListWidget* listWidget; 25 | QWidget* parent; 26 | }; 27 | 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /SyntopiaCore/Logging/Logging.cpp: -------------------------------------------------------------------------------- 1 | #include "Logging.h" 2 | 3 | 4 | #ifdef WIN32 5 | #include "windows.h" 6 | #endif 7 | 8 | /// TODO's 9 | /// - Nested log entris 10 | /// - Time 11 | /// - Setting a log view level 12 | 13 | 14 | namespace SyntopiaCore { 15 | namespace Logging { 16 | QVector Logger::loggers; 17 | QStack Logger::timeStack; 18 | QStack Logger::timeStringStack; 19 | 20 | void LOG(QString message, LogLevel priority) { 21 | 22 | // On Windows this allows us to see debug in the Output::Debug window while running. 23 | #ifdef WIN32 24 | OutputDebugString((LPCWSTR) (message+"\r\n").utf16()); 25 | #endif 26 | 27 | for (int i = 0; i < Logger::loggers.size(); i++) { 28 | Logger::loggers[i]->log(message, priority); 29 | } 30 | } 31 | 32 | /// Useful aliases 33 | void Debug(QString text) { LOG(text, DebugLevel); } 34 | void INFO(QString text) { LOG(text, InfoLevel); } 35 | void WARNING(QString text) { LOG(text, WarningLevel); } 36 | void CRITICAL(QString text) { LOG(text, CriticalLevel); } 37 | 38 | void TIME(QString text) { 39 | LOG(text, TimingLevel); 40 | 41 | Logger::timeStack.push(QTime::currentTime()); 42 | Logger::timeStringStack.push(text); 43 | } ; 44 | 45 | void TIME(int repetitions) { 46 | QTime t = Logger::timeStack.pop(); 47 | QString s = Logger::timeStringStack.pop(); 48 | int secs = t.msecsTo(QTime::currentTime()); 49 | if (repetitions == 0) { 50 | LOG(QString("Time: %1s for ").arg(secs/1000.0f) + s, TimingLevel); 51 | } else { 52 | LOG(QString("Time: %1s for %2. %3 repetitions, %4s per repetition.").arg(secs/1000.0f).arg(s) 53 | .arg(repetitions).arg((secs/repetitions)/1000.0f), TimingLevel); 54 | } 55 | }; // End time... 56 | 57 | 58 | 59 | } 60 | } 61 | 62 | -------------------------------------------------------------------------------- /SyntopiaCore/Logging/Logging.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace SyntopiaCore { 9 | namespace Logging { 10 | /// Predefined logging levels 11 | enum LogLevel { NoneLevel, DebugLevel, TimingLevel, InfoLevel, WarningLevel, CriticalLevel, AllLevel }; 12 | 13 | /// Abstract base class for all loggers 14 | class Logger { 15 | public: 16 | /// The destructors and constructors automatically add to the list of installed loggers. 17 | Logger() { 18 | loggers.append(this); 19 | } 20 | 21 | virtual ~Logger() { 22 | // Remove from list of available loggers. 23 | for (int i = loggers.size()-1; i >= 0; i--) { 24 | if (loggers[i] == this) loggers.remove(i); 25 | } 26 | } 27 | 28 | /// This method all loggers must implement 29 | virtual void log(QString message, LogLevel priority) = 0; 30 | 31 | /// Log messages are sent to this list of loggers. 32 | static QVector loggers; 33 | static QStack timeStack; 34 | static QStack timeStringStack; 35 | private: 36 | 37 | }; 38 | 39 | 40 | void LOG(QString message, LogLevel priority); 41 | 42 | /// Useful aliases 43 | void Debug(QString text); 44 | void INFO(QString text); 45 | void TIME(QString text); 46 | void TIME(int repetitions = 0); // End time... 47 | void WARNING(QString text); 48 | void CRITICAL(QString text); 49 | 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /SyntopiaCore/Math/Matrix4.cpp: -------------------------------------------------------------------------------- 1 | #include "Matrix4.h" 2 | 3 | 4 | namespace SyntopiaCore { 5 | namespace Math { 6 | 7 | 8 | 9 | } 10 | } 11 | 12 | -------------------------------------------------------------------------------- /SyntopiaCore/Math/Random.cpp: -------------------------------------------------------------------------------- 1 | #include "Random.h" 2 | 3 | 4 | namespace SyntopiaCore { 5 | namespace Math { 6 | 7 | namespace { 8 | struct SortPair { 9 | SortPair() {}; 10 | SortPair(int index, double sortValue) : index(index), sortValue(sortValue) {}; 11 | int index; 12 | double sortValue; 13 | bool operator< (const SortPair& rhs) const { return sortValue < rhs.sortValue; } 14 | }; 15 | } 16 | 17 | QVector RandomNumberGenerator::getRandomIndices(int count) { 18 | QVector sp(count); 19 | for (int i = 0; i < count; i++) sp[i] = SortPair(i, getDouble()); 20 | qSort(sp); 21 | QVector out(count); 22 | for (int i = 0; i < count; i++) out[i] = sp[i].index; 23 | return out; 24 | } 25 | 26 | Vector3f RandomNumberGenerator::getUniform2D() { 27 | Vector3f v; 28 | do { 29 | v = Vector3f(getDouble(-1,1),getDouble(-1,1),0); 30 | } while (v.sqrLength()>1.0); 31 | return v; 32 | } 33 | 34 | Vector3f RandomNumberGenerator::getUniform3D() { 35 | Vector3f v; 36 | do { 37 | v = Vector3f(getDouble(-1,1),getDouble(-1,1),getDouble(-1,1)); 38 | } while (v.sqrLength()>1.0); 39 | return v; 40 | } 41 | 42 | namespace { 43 | const int UniformTableSize = 10000; // size of precalculated tables. 44 | } 45 | 46 | // Uses precalculated tables. 47 | // Initialized on first use (so init before using in multithreaded code) 48 | Vector3f RandomNumberGenerator::getUniform2DFromTable() { 49 | static QVector uniform2D; 50 | if (uniform2D.count() == 0) { 51 | for (int i = 0; i < UniformTableSize; i++) uniform2D.append(getUniform2D()); 52 | } 53 | uniformCounter2D++; 54 | if (uniformCounter2D>=uniform2D.count()) uniformCounter2D = 0; 55 | return uniform2D[uniformCounter2D]; 56 | } 57 | 58 | Vector3f RandomNumberGenerator::getUniform3DFromTable() { 59 | static QVector uniform3D; 60 | if (uniform3D.count() == 0) { 61 | for (int i = 0; i < UniformTableSize; i++) uniform3D.append(getUniform3D()); 62 | } 63 | uniformCounter3D++; 64 | if (uniformCounter3D>=uniform3D.count()) uniformCounter3D = 0; 65 | return uniform3D[uniformCounter3D]; 66 | } 67 | 68 | void RandomNumberGenerator::randomizeUniformCounter(){ 69 | uniformCounter2D = getInt(UniformTableSize); 70 | uniformCounter3D = getInt(UniformTableSize); 71 | } 72 | 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /SyntopiaCore/Math/Random.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../../ThirdPartyCode/MersenneTwister/MersenneTwister.h" 9 | #include "Vector3.h" 10 | 11 | namespace SyntopiaCore { 12 | namespace Math { 13 | 14 | /// A simple class for generating random numbers 15 | /// It is possible to have multiple independent streams, if the underlying RNG is the Mersenne Twister. 16 | /// If set to useStdLib, the CStdLib 'rand' and 'srand' functions are used - these are not independent - not even with multiple instances of this class. 17 | class RandomNumberGenerator { 18 | public: 19 | RandomNumberGenerator(bool useOldLibrary = false) : uniformCounter2D(0), uniformCounter3D(0) { if (useOldLibrary) { rng = 0; } else { rng = new MTRand(); } setSeed(0); }; 20 | ~RandomNumberGenerator() { delete rng; }; 21 | 22 | // This is only useful for backward compatibility. 23 | // The Mersenne Twister is much better since it allows multiple independent streams. 24 | void useStdLib(bool useOldLibrary) { 25 | delete rng; rng = 0; 26 | if (!useOldLibrary) { 27 | rng = new MTRand(); 28 | } 29 | setSeed(lastSeed); 30 | }; 31 | 32 | QVector getRandomIndices(int count); 33 | 34 | // Returns a vector, where the elements are ranked randomly. 35 | template 36 | QVector randomize(QVector list) { 37 | QVector indices = getRandomIndices(list.count()); 38 | QVector copy(list.count()); 39 | for (int i = 0; i < list.count(); i++) copy[i] = list[indices[i]]; 40 | return copy; 41 | } 42 | 43 | 44 | bool isUsingStdLib() { return (rng == 0); } 45 | 46 | // Returns a double in the interval [0;1] 47 | double getDouble() { 48 | if (rng) { 49 | return rng->rand(); 50 | } else { 51 | return rand()/(double)RAND_MAX; 52 | /* 53 | This one would be more correct, but the old cstdlib rand is implemented for backward compatibility: 54 | return (double)rand() / ((double)(RAND_MAX)+(double)(1)) ; // There are reasons for the multiple (double) casts, see: http://members.cox.net/srice1/random/crandom.html 55 | */ 56 | } 57 | }; 58 | 59 | // Normal distributed number with mean zero. 60 | double getNormal(double variance) { 61 | /// Note: requires MT RNG! 62 | return rng->randNorm(0,variance); 63 | } 64 | 65 | double getDouble(double min, double max) { 66 | return getDouble()*(max-min)+min; 67 | } 68 | 69 | 70 | // Returns an integer between 0 and max (both inclusive). 71 | int getInt(int max) { 72 | if (rng) { 73 | return rng->randInt(max); 74 | } else { 75 | return rand() % (max+1); // Probably not very good, use mersenne instead 76 | } 77 | } 78 | 79 | int getInt() { 80 | if (rng) { 81 | return rng->randInt(); 82 | } else { 83 | return rand(); 84 | } 85 | } 86 | 87 | void setSeed(int seed) { 88 | lastSeed = seed; 89 | if (rng) { 90 | rng->seed(seed); 91 | } else { 92 | srand(seed); 93 | } 94 | }; 95 | 96 | // Return uniform samples on either unit disc (z=0) or unit sphere 97 | // Uses Monto-carlo sampling which might be slow 98 | Vector3f getUniform2D(); 99 | Vector3f getUniform3D(); 100 | 101 | // Uses precalculated tables. 102 | // Initialized on first use (so init before using in multithreaded code) 103 | Vector3f getUniform2DFromTable(); 104 | Vector3f getUniform3DFromTable(); 105 | void randomizeUniformCounter(); // use this to avoid coherence between different rg's 106 | void setUniformCounter2D(int value) { uniformCounter2D = value; } 107 | void setUniformCounter3D(int value) { uniformCounter3D = value; } 108 | private: 109 | int lastSeed; 110 | MTRand* rng; 111 | int uniformCounter2D; 112 | int uniformCounter3D; 113 | 114 | }; 115 | 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /SyntopiaCore/Math/Vector3.cpp: -------------------------------------------------------------------------------- 1 | #include "Vector3.h" 2 | 3 | 4 | namespace SyntopiaCore { 5 | namespace Math { 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /SyntopiaCore/Math/Vector3.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | namespace SyntopiaCore { 10 | namespace Math { 11 | 12 | /// A simple class for representing three-dimensional vectors. 13 | template class Vector3 { 14 | public: 15 | Vector3() { s[0] = 0; s[1] = 0; s[2] = 0;} 16 | Vector3(scalar x, scalar y, scalar z) { s[0] = x; s[1] = y; s[2] = z; } 17 | 18 | // Constructor. Parses input such as "[1 2 3]"; 19 | Vector3(QString input, bool& succes2) { 20 | input.remove('['); 21 | input.remove(']'); 22 | 23 | QStringList sl = input.split(" "); 24 | if (sl.size() != 3) { succes2 = false; return; } 25 | 26 | bool succes = false; 27 | float f; 28 | f = sl[0].toFloat(&succes); if (!succes) { succes2 = false; return; }; s[0] = f; 29 | f = sl[1].toFloat(&succes); if (!succes) { succes2 = false; return; }; s[1] = f; 30 | f = sl[2].toFloat(&succes); if (!succes) { succes2 = false; return; }; s[2] = f; 31 | 32 | succes2 = true; 33 | } 34 | 35 | 36 | // data access 37 | scalar x() const { return s[0]; } 38 | scalar y() const { return s[1]; }; 39 | scalar z() const { return s[2]; }; 40 | scalar& x() { return s[0]; } 41 | scalar& y() { return s[1]; }; 42 | scalar& z() { return s[2]; }; 43 | scalar operator[] (int index) const { return s[index]; }; 44 | scalar& operator[] (int index) { return s[index]; }; 45 | 46 | scalar sqrLength() const { return s[0]*s[0]+s[1]*s[1]+s[2]*s[2]; } 47 | scalar length() const { return sqrt(s[0]*s[0]+s[1]*s[1]+s[2]*s[2]); } 48 | 49 | Vector3 normalized() const { scalar l = 1.0/length(); return Vector3(s[0]*l,s[1]*l,s[2]*l); } 50 | void normalize() { scalar l = 1.0/length(); s[0]*=l; s[1]*=l; s[2]*=l; } 51 | Vector3 operator- (const Vector3& rhs) const { return Vector3(s[0]-rhs.s[0], s[1]-rhs.s[1], s[2]-rhs.s[2]); } 52 | Vector3 operator+ (const Vector3& rhs) const { return Vector3(s[0]+rhs.s[0], s[1]+rhs.s[1], s[2]+rhs.s[2]); } 53 | Vector3 operator- () const { return Vector3(-s[0], -s[1], -s[2]); } 54 | bool operator== (const Vector3& rhs) const { return (s[0]==rhs.s[0] && s[1]==rhs.s[1] && s[2]==rhs.s[2]); } 55 | 56 | Vector3 operator* (scalar rhs) const { return Vector3(s[0]*rhs, s[1]*rhs, s[2]*rhs); } 57 | Vector3 operator/ (scalar rhs) const { scalar t = 1.0/rhs; return Vector3(s[0]*t, s[1]*t, s[2]*t); } 58 | 59 | 60 | QString toString() const { 61 | return QString("[%1 %2 %3]").arg(s[0]).arg(s[1]).arg(s[2]); 62 | } 63 | 64 | Vector3 cross(const Vector3 b) const { 65 | return Vector3( 66 | s[1]*b.s[2] - s[2]*b.s[1] , 67 | s[2]*b.s[0] - s[0]*b.s[2] , 68 | s[0]*b.s[1] - s[1]*b.s[0]); 69 | } 70 | 71 | static Vector3 cross(const Vector3 a, const Vector3 b) { 72 | return Vector3( 73 | a.s[1]*b.s[2] - a.s[2]*b.s[1] , 74 | a.s[2]*b.s[0] - a.s[0]*b.s[2] , 75 | a.s[0]*b.s[1] - a.s[1]*b.s[0]); 76 | } 77 | 78 | static scalar dot(const Vector3 a, const Vector3 b) { 79 | return a.s[0]*b.s[0] + a.s[1]*b.s[1] + a.s[2]*b.s[2] ; 80 | } 81 | 82 | private: 83 | scalar s[3]; 84 | }; 85 | 86 | template 87 | Vector3 operator*(T lhs, Vector3 rhs) { return Vector3(rhs[0]*lhs, rhs[1]*lhs, rhs[2]*lhs); } 88 | 89 | typedef Vector3 Vector3f ; 90 | typedef Vector3 Vector3d ; 91 | 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/ColorUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ColorUtils.h" 2 | #include "../Logging/Logging.h" 3 | 4 | using namespace SyntopiaCore::Math; 5 | using namespace SyntopiaCore::Logging; 6 | 7 | 8 | namespace SyntopiaCore { 9 | namespace Misc { 10 | 11 | SyntopiaCore::Math::Vector3f ColorUtils::HSVtoRGB(SyntopiaCore::Math::Vector3f hsv) { 12 | /// Implementation based on: http://en.wikipedia.org/wiki/HSV_color_space 13 | if (hsv[0] >= 360) hsv[0]-=360; 14 | int Hi = (int)(hsv[0] / 60) % 6; 15 | double f = (hsv[0] / 60) - Hi; 16 | double p = hsv[2]*(1-hsv[1]); 17 | double q = hsv[2]*(1-f*hsv[1]); 18 | double t = hsv[2]*(1-(1-f)*hsv[1]); 19 | if (Hi == 0) return Vector3f(hsv[2],t,p); 20 | if (Hi == 1) return Vector3f(q,hsv[2],p); 21 | if (Hi == 2) return Vector3f(p,hsv[2],t); 22 | if (Hi == 3) return Vector3f(p,q,hsv[2]); 23 | if (Hi == 4) return Vector3f(t,p,hsv[2]); 24 | if (Hi == 5) return Vector3f(hsv[2],p,q); 25 | WARNING("ColorUtils::HSVtoRGB failed"); 26 | return Vector3f(0,0,0); 27 | } 28 | 29 | 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/ColorUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include "../Math/Vector3.h" 7 | 8 | namespace SyntopiaCore { 9 | namespace Misc { 10 | 11 | 12 | class ColorUtils { 13 | public: 14 | static SyntopiaCore::Math::Vector3f HSVtoRGB(SyntopiaCore::Math::Vector3f hsv); 15 | }; 16 | 17 | 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/MiniParser.cpp: -------------------------------------------------------------------------------- 1 | #include "MiniParser.h" 2 | 3 | #include "../Logging/Logging.h" 4 | 5 | using namespace SyntopiaCore::Logging; 6 | 7 | namespace SyntopiaCore { 8 | namespace Misc { 9 | 10 | 11 | MiniParser::MiniParser( QString value, QChar separator ) : separator(separator), original(value), value(value), paramCount(0) { 12 | } 13 | 14 | MiniParser& MiniParser::getInt(int& val) { 15 | paramCount++; 16 | QString first = value.section(separator, 0,0); 17 | value = value.section(separator, 1); 18 | 19 | 20 | if (first.isEmpty()) { 21 | WARNING(QString("Expected argument number %1 for %2").arg(paramCount).arg(original)); 22 | } 23 | 24 | bool succes = false; 25 | int i = first.toInt(&succes); 26 | if (!succes) { 27 | WARNING(QString("Expected argument number %1 to be an integer. Found: %2").arg(paramCount).arg(first)); 28 | } 29 | val = i; 30 | 31 | return *this; 32 | } 33 | 34 | 35 | 36 | MiniParser& MiniParser::getBool(bool& val) { 37 | paramCount++; 38 | QString first = value.section(separator, 0,0); 39 | value = value.section(separator, 1); 40 | 41 | if (first.isEmpty()) { 42 | WARNING(QString("Expected argument number %1 for %2").arg(paramCount).arg(original)); 43 | } 44 | 45 | if (first.toLower() == "true") { 46 | val = true; 47 | } else if (first.toLower() == "false") { 48 | val = false; 49 | } else { 50 | WARNING(QString("Expected argument number %1 to be either true or false. Found: %2").arg(paramCount).arg(first)); 51 | } 52 | 53 | return *this; 54 | } 55 | 56 | MiniParser& MiniParser::getDouble(double& val) { 57 | paramCount++; 58 | QString first = value.section(separator, 0,0); 59 | value = value.section(separator, 1); 60 | 61 | if (first.isEmpty()) { 62 | WARNING(QString("Expected argument number %1 for %2").arg(paramCount).arg(original)); 63 | } 64 | 65 | bool succes = false; 66 | double d = first.toDouble(&succes); 67 | if (!succes) { 68 | WARNING(QString("Expected argument number %1 to be an double. Found: %2").arg(paramCount).arg(first)); 69 | } 70 | val = d; 71 | 72 | return *this; 73 | } 74 | 75 | MiniParser& MiniParser::getFloat(float& val) { 76 | paramCount++; 77 | QString first = value.section(separator, 0,0); 78 | value = value.section(separator, 1); 79 | 80 | if (first.isEmpty()) { 81 | WARNING(QString("Expected argument number %1 for %2").arg(paramCount).arg(original)); 82 | } 83 | 84 | bool succes = false; 85 | float d = first.toFloat(&succes); 86 | if (!succes) { 87 | WARNING(QString("Expected argument number %1 to be an float. Found: %2").arg(paramCount).arg(first)); 88 | } 89 | val = d; 90 | 91 | return *this; 92 | } 93 | 94 | 95 | 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/MiniParser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | namespace SyntopiaCore { 8 | namespace Misc { 9 | 10 | /// Small class for parsing values from simple text strings. 11 | class MiniParser { 12 | public: 13 | MiniParser( QString value, QChar separator = ','); 14 | 15 | MiniParser& getInt(int& val); 16 | MiniParser& getBool(bool& val); 17 | MiniParser& getDouble(double& val); 18 | MiniParser& getFloat(float& val); 19 | private: 20 | QChar separator; 21 | QString original; 22 | QString value; 23 | int paramCount ; 24 | }; 25 | 26 | } 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/Persistence.cpp: -------------------------------------------------------------------------------- 1 | #include "Persistence.h" 2 | 3 | #include "../Logging/Logging.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace SyntopiaCore::Logging; 14 | 15 | namespace SyntopiaCore { 16 | namespace Misc { 17 | 18 | 19 | 20 | 21 | QMap& Persistence::GetStore() { 22 | static QMap p; 23 | return p; 24 | } 25 | 26 | void Persistence::Store(QWidget* widget, QString storageName) { 27 | if (storageName.isEmpty()) storageName = widget->objectName(); 28 | if (qobject_cast(widget)) { 29 | QLineEdit* lineEdit = qobject_cast(widget); 30 | GetStore()[storageName] = QVariant(lineEdit->text()); 31 | } else if (qobject_cast(widget)) { 32 | QCheckBox* cb = qobject_cast(widget); 33 | GetStore()[storageName] = QVariant(cb->isChecked()); 34 | } else if (qobject_cast(widget)) { 35 | QSpinBox* sb = qobject_cast(widget); 36 | GetStore()[storageName] = QVariant(sb->value()); 37 | } else if (qobject_cast(widget)) { 38 | QRadioButton* rb = qobject_cast(widget); 39 | GetStore()[storageName] = QVariant(rb->isChecked()); 40 | } else if (qobject_cast(widget)) { 41 | QComboBox* cb = qobject_cast(widget); 42 | GetStore()[storageName] = QVariant(cb->currentText()); 43 | } else { 44 | WARNING("Unsupported widget: " + widget->objectName()); 45 | } 46 | } 47 | 48 | void Persistence::Restore(QWidget* widget, QString storageName) { 49 | if (storageName.isEmpty()) storageName = widget->objectName(); 50 | if (qobject_cast(widget)) { 51 | QLineEdit* lineEdit = qobject_cast(widget); 52 | if (GetStore().contains(storageName)) { 53 | lineEdit->setText(GetStore()[storageName].toString()); 54 | } 55 | 56 | } else if (qobject_cast(widget)) { 57 | QCheckBox* cb = qobject_cast(widget); 58 | if (GetStore().contains(storageName)) { 59 | cb->setChecked(GetStore()[storageName].toBool()); 60 | } 61 | 62 | } else if (qobject_cast(widget)) { 63 | QSpinBox* sb = qobject_cast(widget); 64 | if (GetStore().contains(storageName)) { 65 | sb->setValue(GetStore()[storageName].toInt()); 66 | } 67 | 68 | } else if (qobject_cast(widget)) { 69 | QRadioButton* rb = qobject_cast(widget); 70 | if (GetStore().contains(storageName)) { 71 | rb->setChecked(GetStore()[storageName].toInt()); 72 | } 73 | 74 | } else if (qobject_cast(widget)) { 75 | QComboBox* rb = qobject_cast(widget); 76 | if (GetStore().contains(storageName)) { 77 | int i = rb->findText(GetStore()[storageName].toString()); 78 | if (i!=-1) { 79 | rb->setCurrentIndex(i); 80 | } else { 81 | } 82 | } 83 | 84 | } else { 85 | WARNING("Unsupported widget: " + widget->objectName()); 86 | } 87 | } 88 | 89 | bool Persistence::Contains(QString storageName) { 90 | return GetStore().contains(storageName); 91 | } 92 | 93 | QVariant Persistence::Get(QString storageName) { 94 | return GetStore()[storageName]; 95 | } 96 | 97 | void Persistence::Put(QString storageName, QVariant value) { 98 | GetStore()[storageName] = value; 99 | } 100 | 101 | 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/Persistence.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | namespace SyntopiaCore { 9 | namespace Misc { 10 | 11 | 12 | /// Util classes for making GUI settings persistent. 13 | /// (i.e. remember the state of drop-downs, line-edits, and so on). 14 | /// 15 | /// Per default, the widget is stored under its objectName, but it possible to specify 16 | /// another name (e.g. to share widget data between dialogs). 17 | /// 18 | /// Notice that widgets must be hardcoded into the cpp-file to be supported 19 | class Persistence { 20 | public: 21 | static void Store(QWidget* widget, QString storageName = QString()); 22 | static void Restore(QWidget* widget, QString storageName = QString()); 23 | static bool Contains(QString storageName); 24 | static QVariant Get(QString storageName); 25 | static void Put(QString storageName, QVariant value); 26 | private: 27 | static QMap& GetStore(); 28 | }; 29 | 30 | 31 | } 32 | } 33 | 34 | 35 | -------------------------------------------------------------------------------- /SyntopiaCore/Misc/Version.cpp: -------------------------------------------------------------------------------- 1 | #include "Version.h" 2 | 3 | #include "../Logging/Logging.h" 4 | 5 | using namespace SyntopiaCore::Logging; 6 | 7 | namespace SyntopiaCore { 8 | namespace Misc { 9 | 10 | Version::Version() : revision(0), build(0), codename("") { 11 | this->major = 0; 12 | this->minor = 0; 13 | } 14 | 15 | Version::Version(int major, int minor, int revision, int build, QString codename) : revision(revision), build(build), codename(codename) { 16 | this->major = major; 17 | this->minor = minor; 18 | } 19 | 20 | QList Version::GetNewVersions(QString /*url*/) const { 21 | return QList(); 22 | } 23 | 24 | QString Version::toLongString() const { 25 | QString s = QString("%1.%2").arg(major).arg(minor); 26 | if (revision >= 0) s+= QString(".%3").arg(revision); 27 | if (build >= 0) s+= QString(".%4").arg(build); 28 | 29 | if (!codename.isEmpty()) s+= " " + codename; 30 | 31 | return s; 32 | } 33 | 34 | bool Version::operator<(const Version &rhs) { 35 | if (major == rhs.major) { 36 | if (minor == rhs.minor) { 37 | if (revision == rhs.revision) { 38 | return (build < rhs.build); 39 | } else { 40 | return (revision < rhs.revision); 41 | } 42 | } else { 43 | return (minor < rhs.minor); 44 | } 45 | } else { 46 | return (major < rhs.major); 47 | } 48 | 49 | } 50 | 51 | bool Version::operator>(const Version &rhs) { 52 | if ( (*this) == rhs ) return false; 53 | return !((*this) 4 | #include 5 | 6 | 7 | namespace SyntopiaCore { 8 | namespace Misc { 9 | 10 | /// For keeping track of versions 11 | /// Having a formalized version object, can 12 | /// be helpful when checking the internet for updates. 13 | class Version { 14 | public: 15 | /// Constructor. 16 | /// Settings revision or build to -1 indicates they are not in use. 17 | Version(); 18 | Version(int major, int minor, int revision = -1, int build = -1, QString codename = ""); 19 | 20 | /// Long human-readable version. 21 | QString toLongString() const; 22 | 23 | /// Returns a list of versions, newer than 'this' version, 24 | /// by reading an XML-file from the specified URL. 25 | /// 26 | /// Todo: Implement 27 | QList GetNewVersions(QString url) const; 28 | 29 | /// Comparisons 30 | bool operator<(const Version &rhs); 31 | bool operator>(const Version &rhs); 32 | bool operator==(const Version &rhs); 33 | 34 | private: 35 | int major; 36 | int minor; 37 | int revision; 38 | int build; 39 | QString codename; 40 | }; 41 | 42 | 43 | } 44 | } 45 | 46 | 47 | -------------------------------------------------------------------------------- /bugs.txt: -------------------------------------------------------------------------------- 1 | Bug List: 2 | --------- 3 | Priority 0-5, 5 is worst: 4 | 5 | - [3] Some reports of mesh showing up with broken polygons (they are quads, so I think this is because of faulty normal interpolation) 6 | - [3] Some Ubuntu user has problems with loosing the cursor in the edit view (I can not reproduce this in my VM-Ware) 7 | - [2] Triangles does not support ClassID 8 | - [2] Face Culling does not work for boxes, when coordinates are flipped. 9 | - [2] A self-refering cycle of rule retirements would crash structure synth. 10 | - [2] Parser do not allow operator names as rule names. 'rule R1 maxdepth 2 > c ' fails. 11 | - [1] Syntax Highlightning has several errors. 12 | 13 | Other TO-DO's: 14 | 15 | 16 | -------------------------------------------------------------------------------- /changelog.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/changelog.txt -------------------------------------------------------------------------------- /images/agt_internet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/agt_internet.png -------------------------------------------------------------------------------- /images/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/copy.png -------------------------------------------------------------------------------- /images/cut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/cut.png -------------------------------------------------------------------------------- /images/documentinfo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/documentinfo.png -------------------------------------------------------------------------------- /images/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/exit.png -------------------------------------------------------------------------------- /images/fileclose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileclose.png -------------------------------------------------------------------------------- /images/fileicons/Structure Synth.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/Structure Synth.icns -------------------------------------------------------------------------------- /images/fileicons/Structure Synth.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/Structure Synth.ico -------------------------------------------------------------------------------- /images/fileicons/StructureSynth-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/StructureSynth-16.png -------------------------------------------------------------------------------- /images/fileicons/StructureSynth-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/StructureSynth-256.png -------------------------------------------------------------------------------- /images/fileicons/StructureSynthDoc-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/StructureSynthDoc-256.png -------------------------------------------------------------------------------- /images/fileicons/StructureSynthDoc.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/StructureSynthDoc.icns -------------------------------------------------------------------------------- /images/fileicons/StructureSynthDoc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/StructureSynthDoc.ico -------------------------------------------------------------------------------- /images/fileicons/icon.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/icon.pdn -------------------------------------------------------------------------------- /images/fileicons/icon2.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/fileicons/icon2.pdn -------------------------------------------------------------------------------- /images/filesaveas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/filesaveas.png -------------------------------------------------------------------------------- /images/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/folder.png -------------------------------------------------------------------------------- /images/mail_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/mail_new.png -------------------------------------------------------------------------------- /images/new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/new.png -------------------------------------------------------------------------------- /images/open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/open.png -------------------------------------------------------------------------------- /images/paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/paste.png -------------------------------------------------------------------------------- /images/render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/render.png -------------------------------------------------------------------------------- /images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/save.png -------------------------------------------------------------------------------- /images/saveas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/saveas.png -------------------------------------------------------------------------------- /images/structuresynth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/images/structuresynth.png -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/seanth/Structure-Synth/dfdc230d18b1e4f669e3886151e6b2993a7fcde5/notes.txt -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | #define IDI_ICON1 1 2 | #define IDI_ICON2 2 3 | -------------------------------------------------------------------------------- /structure-synth.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Structure Synth 3 | Name[ru]=Structure Synth 4 | Comment=Creating 3D structures from a set of user specified rules 5 | Comment[ru]=Создание трехмерных структур по заданным правилам 6 | Exec=structure-synth 7 | Icon=structure-synth.png 8 | Categories=Graphics;VectorGraphics;Qt; 9 | Terminal=false 10 | Type=Application 11 | X-SuSE-translate=true 12 | -------------------------------------------------------------------------------- /structuresynth.rc: -------------------------------------------------------------------------------- 1 | #include "resource.h" 2 | 3 | IDI_ICON1 ICON "StructureSynth.ico" 4 | IDI_ICON2 ICON "StructureSynthDoc.ico" 5 | 6 | // Version 7 | 8 | VS_VERSION_INFO VERSIONINFO 9 | FILEVERSION 0,9,5,0 10 | PRODUCTVERSION 0,9,5,0 11 | FILEFLAGSMASK 0x17L 12 | #ifdef _DEBUG 13 | FILEFLAGS 0x1L 14 | #else 15 | FILEFLAGS 0x0L 16 | #endif 17 | FILEOS 0x4L 18 | FILETYPE 0x1L 19 | FILESUBTYPE 0x0L 20 | BEGIN 21 | BLOCK "StringFileInfo" 22 | BEGIN 23 | BLOCK "080004b0" 24 | BEGIN 25 | VALUE "CompanyName", "Syntopia" 26 | VALUE "FileDescription", "Structure Synth Main Executable" 27 | VALUE "FileVersion", "0, 9, 5, 0" 28 | VALUE "InternalName", "StructureSynth" 29 | VALUE "LegalCopyright", "Copyright (C) 2007-2009 Syntopia" 30 | VALUE "LegalTrademarks", "Structure Synth" 31 | VALUE "OriginalFilename", "StructureSynth.exe" 32 | VALUE "ProductName", "Structure Synth" 33 | VALUE "ProductVersion", "0, 9, 5, 0" 34 | END 35 | END 36 | BLOCK "VarFileInfo" 37 | BEGIN 38 | VALUE "Translation", 0x409, 1200 39 | END 40 | END 41 | --------------------------------------------------------------------------------