diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index a5d6735..f640ec3 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -13,7 +13,7 @@ - + Default EmberPch.h Precise - /bigobj %(AdditionalOptions) + /bigobj + %(AdditionalOptions) true false true @@ -228,7 +229,8 @@ Speed EmberPch.h true - /bigobj %(AdditionalOptions) + /bigobj + %(AdditionalOptions) Precise true false @@ -295,12 +297,12 @@ + - diff --git a/Builds/MSVC/VS2013/Ember.vcxproj.filters b/Builds/MSVC/VS2013/Ember.vcxproj.filters index 1808021..04447a9 100644 --- a/Builds/MSVC/VS2013/Ember.vcxproj.filters +++ b/Builds/MSVC/VS2013/Ember.vcxproj.filters @@ -116,8 +116,8 @@ Header Files - - Header Files + + Header Files\Variations diff --git a/Builds/MSVC/VS2013/EmberCL.vcxproj b/Builds/MSVC/VS2013/EmberCL.vcxproj index 8a306a7..0cb5041 100644 --- a/Builds/MSVC/VS2013/EmberCL.vcxproj +++ b/Builds/MSVC/VS2013/EmberCL.vcxproj @@ -298,6 +298,7 @@ + @@ -309,6 +310,7 @@ + diff --git a/Builds/MSVC/VS2013/EmberCL.vcxproj.filters b/Builds/MSVC/VS2013/EmberCL.vcxproj.filters index b1b99f1..9fb2fd9 100644 --- a/Builds/MSVC/VS2013/EmberCL.vcxproj.filters +++ b/Builds/MSVC/VS2013/EmberCL.vcxproj.filters @@ -42,6 +42,9 @@ Source Files + + Source Files + @@ -74,6 +77,9 @@ Header Files + + Header Files + diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj b/Builds/MSVC/VS2013/Fractorium.vcxproj index 021dbd0..cef44f6 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj @@ -338,7 +338,6 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" - diff --git a/Data/Variations.xlsx b/Data/Variations.xlsx index 2a0a302..e6c1ea4 100644 Binary files a/Data/Variations.xlsx and b/Data/Variations.xlsx differ diff --git a/Data/dark.qss b/Data/dark.qss index 22fc301..069ddec 100644 --- a/Data/dark.qss +++ b/Data/dark.qss @@ -1,611 +1,620 @@ -/*---Base Style--- - This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows. - It's not needed for other themes. - You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/ -QTabBar::tab { height: 5ex; }/*Do this for windows*/ -/*QTabBar::tab { height: 3ex; }*//*Do this for linux*/ - -/*This is needed to give the labels on the status bar some padding.*/ -QStatusBar QLabel { padding-left: 2px; padding-right: 2px; } - -/*Specific styles below this line*/ - -QObject -{ - background-color : rgb(53, 53, 53); - color: darkgray; - alternate-background-color: rgb(53, 53, 53); - selection-color: black; - selection-background-color: rgb(42, 130, 218); -} - -QObject:disabled -{ - color: rgb(35, 35, 35); - background-color: rgb(53, 53, 53); - border-color: rgb(35, 35, 35); -} - -QDockWidget::float-button -{ - background-color: gray; -} - -QDockWidget::title -{ - margin: 1px; - padding: 2px; - background-color: gray; -} - -QTabWidget::pane -{ - border: 1px solid gray; -} - -QPushButton -{ - margin: 1px; - padding: 4px; - border: 1px solid gray; -} - -QPushButton:pressed -{ - background-color: gray; -} - -QPushButton:focus -{ - outline: none; -} - -QTableView QPushButton -{ - border: 1px solid gray; - margin: 1px; - padding: 0px; -} - -QLineEdit, QTextEdit -{ - border: 1px solid gray; - color: darkgray; - background-color: rgb(40, 40, 50); - selection-background-color: darkgray; -} - -QToolTip -{ - background-color: darkgray; - border: 1px solid darkgray; -} - -QSpinBox, -QDoubleSpinBox -{ - padding-right: 0px; - color: darkgray; - selection-background-color: darkgray; - font: 9pt "Segoe UI";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/ -} - -QCheckBox -{ - spacing: 5px; -} - -QCheckBox::indicator, -QTableView::indicator -{ - border: none; - border-radius: 2px; - background-color: lightgray; -} - -QCheckBox::indicator:enabled:unchecked, -QTableView::indicator:enabled:unchecked -{ - background-color: lightgray; - image: url(:/Fractorium/Icons/checkbox_unchecked.png); -} - -QCheckBox::indicator:enabled:checked, -QTableView::indicator:enabled:checked -{ - background-color: lightgray; - image: url(:/Fractorium/Icons/checkbox_checked.png); -} - -QCheckBox::indicator:disabled:unchecked, -QTableView::indicator:disabled:unchecked -{ - background-color: gray; - image: none; -} - -QCheckBox::indicator:disabled:checked, -QTableView::indicator:disabled:checked -{ - background-color: gray; - image: none; -} - -QRadioButton::indicator:checked -{ - background-color: black; - border: 2px solid gray; - border-radius: 7px; - width: 8px; - height: 8px; - margin: 3px; - padding: 1px; -} - -QRadioButton::indicator:checked:disabled -{ - background-color: rgb(35, 35, 35); -} - -QRadioButton::indicator:unchecked -{ - border: 2px solid gray; - border-radius: 7px; - width: 8px; - height: 8px; - margin: 3px; - padding: 1px; -} - -QComboBox -{ - margin: 0px; - padding-left: 4px; - border: 1px solid gray; -} - -QComboBox::down-arrow:enabled -{ - border: 1px solid gray; - margin-right: 2px; - margin-top: 0px; - margin-bottom: 1px; -} - - -QComboBox::down-arrow:disabled -{ - border: 1px solid rgb(35, 35, 35); - margin-right: 2px; - margin-top: 0px; - margin-bottom: 1px; -} - -QComboBox::drop-down -{ - border: none; -} - -/*For some reason this is needed with Fusion, but not with Windows*/ -QComboBox::item:selected -{ - selection-background-color: darkgray; -} - -QComboBox QAbstractItemView -{ - border: 1px solid gray; - outline: none; - selection-background-color: darkgray; -} - -QTableView QComboBox -{ - margin: 1px; - padding: 0px; - padding-left: 3px; -} - -QGroupBox QComboBox -{ - margin: 1px; - margin-bottom: 0px; -} - -QTableView QComboBox::down-arrow -{ - margin-top: 0px; - margin-right: 1px; - margin-bottom: 0px; -} - -QProgressBar -{ - color: black; - background-color: gray; - border: 0px none gray; - border-radius: 3px; - text-align: center; -} - -QProgressBar::chunk -{ - border-radius: 3px; - background-color: lightgray; -} - -QStatusBar QProgressBar -{ - min-width: 300px; - max-width: 300px; - margin-right: 4px; -} - -QMenuBar -{ - border-bottom: 1px solid gray; -} - -QMenuBar::item -{ - background-color: rgb(53, 53, 53); -} - -QMenu::item:disabled -{ - color: rgb(35, 35, 35); - -} - -QMenu::item:enabled:selected -{ - background-color: gray; -} - -QMenu::item:disabled:selected -{ - background-color: rgb(53, 53, 53); -} - -QToolBar -{ - border: 0px none gray; -} - -QGroupBox -{ - padding-top: 3px; - border: 2px solid gray; - border-radius: 4px; - margin-top: 3ex; -} - -QGroupBox::title -{ - subcontrol-origin: border; - subcontrol-position: top left; - margin-top: -1ex; - margin-left: 0px; - padding-right: 1px; - padding-left: 2px; - top: -2ex; - left: 8px; -} - -QListView -{ - selection-color: black; - selection-background-color: darkgray; -} - -QListView::item:selected -{ - background-color: darkgray; -} - -QTreeView -{ - border: 1px solid gray; - background-color: rgb(53, 53, 53); -} - -/*Setting this gives a more consistent look, but removes the ability to gray variations that are included in the xform*/ -QTreeView::item -{ - background-color: rgb(53, 53, 53); - color: darkgray; - outline: none; -} - -QTreeView::item:selected -{ - border: 0px none black; - background-color: gray; - outline: none; -} - -QTreeView::branch:!has-children -{ - background: rgb(53, 53, 53); -} - -QTreeView::branch:has-children:closed -{ - border: 1px solid darkgray; - background: gray; - margin: 2px; -} - -QTreeView::branch:has-children:!closed -{ - border: 1px solid lightgray; - background: gray; - margin-left: 1px; - margin-right: 0px; - margin-top: 3px; - margin-bottom: 3px; -} - -QTableView -{ - border-left: 0px none gray; - border-top: 0px none gray; - border-right: 0px none gray; - border-bottom: 0px none gray; - gridline-color: gray; - color: darkgray; - selection-color: darkgray; - selection-background-color: rgb(53, 53, 53); -} - -QTableView QTableCornerButton::section:enabled -{ - background-color: darkgray; -} - -QTableView QTableCornerButton::section:disabled -{ - background-color: rgb(53, 53, 53); -} - -QTableView::indicator:disabled -{ - background-color: rgb(35, 35, 35); -} - -QTableView:disabled -{ - color: rgb(35, 35, 35); - border: none; - gridline-color: rgb(35, 35, 35); -} - -QHeaderView::section::vertical:enabled -{ - color: black; - background-color: gray; - border: none; - border-bottom: 1px solid gray; - padding: 4px; -} - -QHeaderView::section::horizontal:enabled -{ - color: black; - background-color: darkgray; - border: 0px solid darkgray; - border-right: 1px solid gray; - padding: 4px; -} - -QHeaderView::section::vertical:disabled -{ - color: rgb(35, 35, 35); - background-color: rgb(53, 53, 53); - border: 0px none darkgray; - border-bottom: 1px solid rgb(53, 53, 53); - padding: 4px; -} - -QHeaderView::section::horizontal:disabled -{ - color:rgb(35, 35, 35); - background-color: rgb(53, 53, 53); - border: 0px none darkgray; - border-right: 1px solid rgb(53, 53, 53); - padding: 4px; -} - -QScrollBar::vertical -{ - background-color: darkgray; - border: 0px solid darkgray; - width: 15px; - margin: 22px 0 22px 0; -} - -QScrollBar::handle::vertical -{ - background-color: gray; - border-top: 1px solid darkgray; - border-bottom: 1px solid darkgray; - min-height: 20px; -} - -QScrollBar::add-line::vertical -{ - border: 0px solid darkgray; - background-color: gray; - height: 22px; - subcontrol-position: bottom; - subcontrol-origin: margin; -} - -QScrollBar::sub-line::vertical -{ - border: 0px solid darkgray; - background-color: gray; - height: 22px; - subcontrol-position: top; - subcontrol-origin: margin; -} - -QScrollBar::up-arrow::vertical, QScrollBar::down-arrow::vertical -{ - border: 2px solid darkgray; - width: 5px; - height: 12px; - background-color: gray; -} - -QScrollBar::add-page::vertical, QScrollBar::sub-page::vertical, QScrollBar::add-page::horizontal, QScrollBar::sub-page::horizontal -{ - background-color: darkgray; -} - -QScrollBar::horizontal -{ - background-color: darkgray; - border: 0px solid darkgray; - height: 15px; - margin: 0px 20px 0 20px; -} - -QScrollBar::handle::horizontal -{ - background-color: gray; - border-left: 1px solid darkgray; - border-right: 1px solid darkgray; - min-width: 20px; -} - -QScrollBar::add-line::horizontal -{ - border: 0px solid darkgray; - background-color: gray; - width: 20px; - subcontrol-position: right; - subcontrol-origin: margin; -} - -QScrollBar::sub-line::horizontal -{ - border: 0px solid darkgray; - background-color: gray; - width: 20px; - subcontrol-position: left; - subcontrol-origin: margin; -} - -QScrollBar::left-arrow::horizontal, QScrollBar::right-arrow::horizontal -{ - border: 2px solid darkgray; - width: 12px; - height: 5px; - background-color: gray; -} - -QMenu::separator -{ - height: 1px; - background-color: gray; -} - -QToolBar::separator -{ - width: 1px; - margin-top: 3px; - margin-bottom: 2px; - background-color: gray; -} - -QStatusBar::item -{ - border: none; -} - -/*Specific controls*/ -QTableWidget#ColorTableHeader QHeaderView::section::horizontal, -QTableWidget#GeometryTableHeader QHeaderView::section::horizontal, -QTableWidget#FilterTableHeader QHeaderView::section::horizontal, -QTableWidget#IterationTableHeader QHeaderView::section::horizontal, -QTreeWidget#LibraryTree QHeaderView::section::horizontal -{ - border-right: none; -} - -QTableWidget#ColorTable, -QTableWidget#GeometryTable, -QTableWidget#FilterTable, -QTableWidget#IterationTable, -QTableWidget#XformWeightNameTable -{ - border-left: 1px solid gray; -} - -QTableWidget#SummaryTable, -QTableWidget#PaletteListTable -{ - border-left: 1px solid gray; -} - -QTableWidget#SummaryTable QHeaderView::section::vertical -{ - background-color: darkgray; -} - -QTableWidget#PaletteAdjustTable, -QTableWidget#PalettePreviewTable, -QTableWidget#XformColorIndexTable, -QTableWidget#XformColorValuesTable, -QTableWidget#InfoBoundsTable, -QTableWidget#OptionsXmlSavingTable, -QTableWidget#OptionsIdentityTable, -QTableWidget#FinalRenderSizeTable, -QTableWidget#FinalRenderParamsTable -{ - border-left: 1px solid gray; - border-top: 1px solid gray; -} - -QLineEdit#PaletteFilterLineEdit, -QLineEdit#VariationsFilterLineEdit -{ - height: 20px; - min-height: 20px; - max-height: 20px; -} - -QSpinBox#ThreadCountSpin, -QSpinBox#RandomCountSpin, -QSpinBox#CpuSubBatchSpin, -QSpinBox#OpenCLSubBatchSpin, -QSpinBox#FinalRenderCurrentSpin, -QSpinBox#FinalRenderThreadCountSpin -{ - padding: 2px; - border: 1px solid gray; -} - -QSpinBox#ThreadCountSpin:disabled, -QSpinBox#CpuSubBatchSpin:disabled, -QSpinBox#OpenCLSubBatchSpin:disabled, -QSpinBox#FinalRenderCurrentSpin:disabled, -QSpinBox#FinalRenderThreadCountSpin:disabled -{ - padding: 2px; - border: 1px solid rgb(35, 35, 35); -} - -QTableView#FinalRenderParamsTable QComboBox -{ - margin-top: 0px; - margin-bottom: 0px; -} - -QTableView#FinalRenderParamsTable QPushButton -{ - margin-top: 1px; - margin-bottom: 2px; - padding: 0px; -} +/*---Base Style--- + This is needed to deal with the large tabs in the fusion theme which is the default on Linux, and optional on Windows. + It's not needed for other themes. + You should keep this at the top of whatever custom style you make to ensure the tabs aren't unusually large.*/ +QTabBar::tab { height: 5ex; }/*Do this for windows*/ +/*QTabBar::tab { height: 3ex; }*//*Do this for linux*/ + +/*This is needed to give the labels on the status bar some padding.*/ +QStatusBar QLabel { padding-left: 2px; padding-right: 2px; } + +/*Specific styles below this line*/ + +QObject +{ + background-color : rgb(53, 53, 53); + color: darkgray; + alternate-background-color: rgb(53, 53, 53); + selection-color: black; + selection-background-color: rgb(42, 130, 218); +} + +QObject:disabled +{ + color: rgb(35, 35, 35); + background-color: rgb(53, 53, 53); + border-color: rgb(35, 35, 35); +} + +QDockWidget::float-button +{ + background-color: gray; +} + +QDockWidget::title +{ + margin: 1px; + padding: 2px; + background-color: gray; +} + +QTabWidget::pane +{ + border: 1px solid gray; +} + +QPushButton +{ + margin: 1px; + padding: 4px; + border: 1px solid gray; +} + +QPushButton:pressed +{ + background-color: gray; +} + +QPushButton:focus +{ + outline: none; +} + +QTableView QPushButton +{ + border: 1px solid gray; + margin: 1px; + padding: 0px; +} + +QLineEdit, QTextEdit +{ + border: 1px solid gray; + color: darkgray; + background-color: rgb(40, 40, 50); + selection-background-color: darkgray; +} + +QToolTip +{ + background-color: darkgray; + border: 1px solid darkgray; +} + +QSpinBox, +QDoubleSpinBox +{ + padding-right: 0px; + color: darkgray; + selection-background-color: darkgray; + font: 9pt "Segoe UI";/*For some reason the font changes if you set any style. Set this to whatever font is the default on your system*/ +} + +QCheckBox +{ + spacing: 5px; +} + +QCheckBox::indicator, +QTableView::indicator +{ + border: none; + border-radius: 2px; + background-color: lightgray; +} + +QCheckBox::indicator:enabled:unchecked, +QTableView::indicator:enabled:unchecked +{ + background-color: lightgray; + image: url(:/Fractorium/Icons/checkbox_unchecked.png); +} + +QCheckBox::indicator:enabled:checked, +QTableView::indicator:enabled:checked +{ + background-color: lightgray; + image: url(:/Fractorium/Icons/checkbox_checked.png); +} + +QCheckBox::indicator:disabled:unchecked, +QTableView::indicator:disabled:unchecked +{ + background-color: gray; + image: none; +} + +QCheckBox::indicator:disabled:checked, +QTableView::indicator:disabled:checked +{ + background-color: gray; + image: none; +} + +QRadioButton::indicator:checked +{ + background-color: black; + border: 2px solid gray; + border-radius: 7px; + width: 8px; + height: 8px; + margin: 3px; + padding: 1px; +} + +QRadioButton::indicator:checked:disabled +{ + background-color: rgb(35, 35, 35); +} + +QRadioButton::indicator:unchecked +{ + border: 2px solid gray; + border-radius: 7px; + width: 8px; + height: 8px; + margin: 3px; + padding: 1px; +} + +QComboBox +{ + margin: 0px; + padding-left: 4px; + border: 1px solid gray; +} + +QComboBox::down-arrow:enabled +{ + border: 1px solid gray; + margin-right: 2px; + margin-top: 0px; + margin-bottom: 1px; +} + + +QComboBox::down-arrow:disabled +{ + border: 1px solid rgb(35, 35, 35); + margin-right: 2px; + margin-top: 0px; + margin-bottom: 1px; +} + +QComboBox::drop-down +{ + border: none; +} + +/*For some reason this is needed with Fusion, but not with Windows*/ +QComboBox::item:selected +{ + selection-background-color: darkgray; +} + +QComboBox QAbstractItemView +{ + border: 1px solid gray; + outline: none; + selection-background-color: darkgray; +} + +QTableView QComboBox +{ + margin: 1px; + padding: 0px; + padding-left: 3px; +} + +QGroupBox QComboBox +{ + margin: 1px; + margin-bottom: 0px; +} + +QTableView QComboBox::down-arrow +{ + margin-top: 0px; + margin-right: 1px; + margin-bottom: 0px; +} + +QProgressBar +{ + color: black; + background-color: gray; + border: 0px none gray; + border-radius: 3px; + text-align: center; +} + +QProgressBar::chunk +{ + border-radius: 3px; + background-color: lightgray; +} + +QStatusBar QProgressBar +{ + min-width: 300px; + max-width: 300px; + margin-right: 4px; +} + +QMenuBar +{ + border-bottom: 1px solid gray; +} + +QMenuBar::item +{ + background-color: rgb(53, 53, 53); +} + +QMenu::item:disabled +{ + color: rgb(35, 35, 35); + +} + +QMenu::item:enabled:selected +{ + background-color: gray; +} + +QMenu::item:disabled:selected +{ + background-color: rgb(53, 53, 53); +} + +QToolBar +{ + border: 0px none gray; +} + +QGroupBox +{ + padding-top: 3px; + border: 2px solid gray; + border-radius: 4px; + margin-top: 3ex; +} + +QGroupBox::title +{ + subcontrol-origin: border; + subcontrol-position: top left; + margin-top: -1ex; + margin-left: 0px; + padding-right: 1px; + padding-left: 2px; + top: -2ex; + left: 8px; +} + +QListView +{ + selection-color: black; + selection-background-color: darkgray; +} + +QListView::item:selected +{ + background-color: darkgray; +} + +QTreeView +{ + border: 1px solid gray; + background-color: rgb(53, 53, 53); +} + +/*Setting this gives a more consistent look, but removes the ability to gray variations that are included in the xform*/ +QTreeView::item +{ + background-color: rgb(53, 53, 53); + color: darkgray; + outline: none; + margin-right: 1px; +} + +QTreeView::item:hover +{ + border: 0px none black; + background-color: gray; + outline: none; +} + +QTreeView::item:selected +{ + border: 0px none black; + background-color: gray; + outline: none; +} + +QTreeView::branch:!has-children +{ + background: rgb(53, 53, 53); +} + +QTreeView::branch:has-children:closed +{ + border: 1px solid darkgray; + background: gray; + margin: 2px; +} + +QTreeView::branch:has-children:!closed +{ + border: 1px solid lightgray; + background: gray; + margin-left: 1px; + margin-right: 0px; + margin-top: 3px; + margin-bottom: 3px; +} + +QTableView +{ + border-left: 0px none gray; + border-top: 0px none gray; + border-right: 0px none gray; + border-bottom: 0px none gray; + gridline-color: gray; + color: darkgray; + selection-color: darkgray; + selection-background-color: rgb(53, 53, 53); +} + +QTableView QTableCornerButton::section:enabled +{ + background-color: darkgray; +} + +QTableView QTableCornerButton::section:disabled +{ + background-color: rgb(53, 53, 53); +} + +QTableView::indicator:disabled +{ + background-color: rgb(35, 35, 35); +} + +QTableView:disabled +{ + color: rgb(35, 35, 35); + border: none; + gridline-color: rgb(35, 35, 35); +} + +QHeaderView::section::vertical:enabled +{ + color: black; + background-color: gray; + border: none; + border-bottom: 1px solid gray; + padding: 4px; +} + +QHeaderView::section::horizontal:enabled +{ + color: black; + background-color: darkgray; + border: 0px solid darkgray; + border-right: 1px solid gray; + padding: 4px; +} + +QHeaderView::section::vertical:disabled +{ + color: rgb(35, 35, 35); + background-color: rgb(53, 53, 53); + border: 0px none darkgray; + border-bottom: 1px solid rgb(53, 53, 53); + padding: 4px; +} + +QHeaderView::section::horizontal:disabled +{ + color:rgb(35, 35, 35); + background-color: rgb(53, 53, 53); + border: 0px none darkgray; + border-right: 1px solid rgb(53, 53, 53); + padding: 4px; +} + +QScrollBar::vertical +{ + background-color: darkgray; + border: 0px solid darkgray; + width: 15px; + margin: 22px 0 22px 0; +} + +QScrollBar::handle::vertical +{ + background-color: gray; + border-top: 1px solid darkgray; + border-bottom: 1px solid darkgray; + min-height: 20px; +} + +QScrollBar::add-line::vertical +{ + border: 0px solid darkgray; + background-color: gray; + height: 22px; + subcontrol-position: bottom; + subcontrol-origin: margin; +} + +QScrollBar::sub-line::vertical +{ + border: 0px solid darkgray; + background-color: gray; + height: 22px; + subcontrol-position: top; + subcontrol-origin: margin; +} + +QScrollBar::up-arrow::vertical, QScrollBar::down-arrow::vertical +{ + border: 2px solid darkgray; + width: 5px; + height: 12px; + background-color: gray; +} + +QScrollBar::add-page::vertical, QScrollBar::sub-page::vertical, QScrollBar::add-page::horizontal, QScrollBar::sub-page::horizontal +{ + background-color: darkgray; +} + +QScrollBar::horizontal +{ + background-color: darkgray; + border: 0px solid darkgray; + height: 15px; + margin: 0px 20px 0 20px; +} + +QScrollBar::handle::horizontal +{ + background-color: gray; + border-left: 1px solid darkgray; + border-right: 1px solid darkgray; + min-width: 20px; +} + +QScrollBar::add-line::horizontal +{ + border: 0px solid darkgray; + background-color: gray; + width: 20px; + subcontrol-position: right; + subcontrol-origin: margin; +} + +QScrollBar::sub-line::horizontal +{ + border: 0px solid darkgray; + background-color: gray; + width: 20px; + subcontrol-position: left; + subcontrol-origin: margin; +} + +QScrollBar::left-arrow::horizontal, QScrollBar::right-arrow::horizontal +{ + border: 2px solid darkgray; + width: 12px; + height: 5px; + background-color: gray; +} + +QMenu::separator +{ + height: 1px; + background-color: gray; +} + +QToolBar::separator +{ + width: 1px; + margin-top: 3px; + margin-bottom: 2px; + background-color: gray; +} + +QStatusBar::item +{ + border: none; +} + +/*Specific controls*/ +QTableWidget#ColorTableHeader QHeaderView::section::horizontal, +QTableWidget#GeometryTableHeader QHeaderView::section::horizontal, +QTableWidget#FilterTableHeader QHeaderView::section::horizontal, +QTableWidget#IterationTableHeader QHeaderView::section::horizontal, +QTreeWidget#LibraryTree QHeaderView::section::horizontal +{ + border-right: none; +} + +QTableWidget#ColorTable, +QTableWidget#GeometryTable, +QTableWidget#FilterTable, +QTableWidget#IterationTable, +QTableWidget#XformWeightNameTable +{ + border-left: 1px solid gray; +} + +QTableWidget#SummaryTable, +QTableWidget#PaletteListTable +{ + border-left: 1px solid gray; +} + +QTableWidget#SummaryTable QHeaderView::section::vertical +{ + background-color: darkgray; +} + +QTableWidget#PaletteAdjustTable, +QTableWidget#PalettePreviewTable, +QTableWidget#XformColorIndexTable, +QTableWidget#XformColorValuesTable, +QTableWidget#InfoBoundsTable, +QTableWidget#OptionsXmlSavingTable, +QTableWidget#OptionsIdentityTable, +QTableWidget#FinalRenderSizeTable, +QTableWidget#FinalRenderParamsTable +{ + border-left: 1px solid gray; + border-top: 1px solid gray; +} + +QLineEdit#PaletteFilterLineEdit, +QLineEdit#VariationsFilterLineEdit +{ + height: 20px; + min-height: 20px; + max-height: 20px; +} + +QSpinBox#ThreadCountSpin, +QSpinBox#RandomCountSpin, +QSpinBox#CpuSubBatchSpin, +QSpinBox#OpenCLSubBatchSpin, +QSpinBox#FinalRenderCurrentSpin, +QSpinBox#FinalRenderThreadCountSpin +{ + padding: 2px; + border: 1px solid gray; +} + +QSpinBox#ThreadCountSpin:disabled, +QSpinBox#CpuSubBatchSpin:disabled, +QSpinBox#OpenCLSubBatchSpin:disabled, +QSpinBox#FinalRenderCurrentSpin:disabled, +QSpinBox#FinalRenderThreadCountSpin:disabled +{ + padding: 2px; + border: 1px solid rgb(35, 35, 35); +} + +QTableView#FinalRenderParamsTable QComboBox +{ + margin-top: 0px; + margin-bottom: 0px; +} + +QTableView#FinalRenderParamsTable QPushButton +{ + margin-top: 1px; + margin-bottom: 2px; + padding: 0px; +} + \ No newline at end of file diff --git a/Source/Ember/DensityFilter.h b/Source/Ember/DensityFilter.h index 818c52d..166241a 100644 --- a/Source/Ember/DensityFilter.h +++ b/Source/Ember/DensityFilter.h @@ -123,7 +123,7 @@ public: // // num filters = (de_max_width / de_min_width)^(1 / estimator_curve) // - decFilterCount = pow(finalMaxRad / finalMinRad, T(1.0) / m_Curve); + decFilterCount = std::pow(finalMaxRad / finalMinRad, T(1.0) / m_Curve); if (decFilterCount > 1e7)//Too many filters. return false; @@ -133,8 +133,8 @@ public: //Condense the smaller kernels to save space. if (intFilterCount > keepThresh) { - maxIndex = static_cast(ceil(DE_THRESH + pow(T(intFilterCount - DE_THRESH), m_Curve))) + 1; - m_MaxFilteredCounts = static_cast(pow(T(maxIndex - DE_THRESH), T(1.0) / m_Curve)) + DE_THRESH; + maxIndex = static_cast(ceil(DE_THRESH + std::pow(T(intFilterCount - DE_THRESH), m_Curve))) + 1; + m_MaxFilteredCounts = static_cast(std::pow(T(maxIndex - DE_THRESH), T(1.0) / m_Curve)) + DE_THRESH; } else { @@ -163,12 +163,12 @@ public: //Calculate the filter width for this number of hits in a bin. if (filterLoop < keepThresh) { - filterHeight = (finalMaxRad / pow(T(filterLoop + 1), m_Curve)); + filterHeight = (finalMaxRad / std::pow(T(filterLoop + 1), m_Curve)); } else { - loopAdjust = pow(T(filterLoop - keepThresh), (T(1.0) / m_Curve)) + keepThresh; - filterHeight = (finalMaxRad / pow(loopAdjust + 1, m_Curve)); + loopAdjust = std::pow(T(filterLoop - keepThresh), (T(1.0) / m_Curve)) + keepThresh; + filterHeight = (finalMaxRad / std::pow(loopAdjust + 1, m_Curve)); } //Once we've reached the min radius, don't populate any more. @@ -262,7 +262,7 @@ public: T finalMaxRad = m_MaxRad * m_Supersample + 1; T finalMinRad = m_MinRad * m_Supersample + 1; - return pow(finalMaxRad / finalMinRad, T(1.0) / m_Curve) <= 1e7; + return std::pow(finalMaxRad / finalMinRad, T(1.0) / m_Curve) <= 1e7; } /// diff --git a/Source/Ember/Ember.cpp b/Source/Ember/Ember.cpp index 2bd55eb..37bb30a 100644 --- a/Source/Ember/Ember.cpp +++ b/Source/Ember/Ember.cpp @@ -5,6 +5,7 @@ namespace EmberNs { template<> unique_ptr> QTIsaac::GlobalRand = unique_ptr>(new QTIsaac()); +CriticalSection QTIsaac::m_CS; } #include "Curves.h" @@ -20,6 +21,7 @@ template<> unique_ptr> QTIsaac map>> PaletteList::m_Palettes = map>>(); \ template<> bool XmlToEmber::m_Init = false; \ template<> vector XmlToEmber::m_FlattenNames = vector(); \ - template<> vector> XmlToEmber::m_BadParamNames = vector>(); \ + template<> unordered_map XmlToEmber::m_BadParamNames = unordered_map(); \ template<> vector, vector>> XmlToEmber::m_BadVariationNames = vector, vector>>(); \ template EMBER_API class Point; \ template EMBER_API struct Color; \ @@ -350,6 +352,8 @@ uint Timing::m_ProcessorCount; EXPORTPREPOSTREGVAR(Ho, T) \ EXPORTPREPOSTREGVAR(Julia3Dq, T) \ EXPORTPREPOSTREGVAR(Line, T) \ + EXPORTPREPOSTREGVAR(Loonie2, T) \ + EXPORTPREPOSTREGVAR(Loonie3, T) \ EXPORTPREPOSTREGVAR(Loonie3D, T) \ EXPORTPREPOSTREGVAR(Mcarpet, T) \ EXPORTPREPOSTREGVAR(Waves23D, T) \ @@ -364,12 +368,21 @@ uint Timing::m_ProcessorCount; EXPORTPREPOSTREGVAR(Falloff2, T) \ EXPORTPREPOSTREGVAR(Falloff3, T) \ EXPORTPREPOSTREGVAR(Xtrb, T) \ - template EMBER_API class DCBubbleVariation; \ + EXPORTPREPOSTREGVAR(Hexaplay3D, T) \ + EXPORTPREPOSTREGVAR(Hexnix3D, T) \ + EXPORTPREPOSTREGVAR(Hexcrop, T) \ + EXPORTPREPOSTREGVAR(Hexes, T) \ + EXPORTPREPOSTREGVAR(Nblur, T) \ + EXPORTPREPOSTREGVAR(Octapol, T) \ + EXPORTPREPOSTREGVAR(Crob, T) \ + EXPORTPREPOSTREGVAR(BubbleT3D, T) \ + EXPORTPREPOSTREGVAR(Synth, T) \ + EXPORTPREPOSTREGVAR(DCBubble, T) \ EXPORTPREPOSTREGVAR(DCCarpet, T) \ EXPORTPREPOSTREGVAR(DCCube, T) \ - template EMBER_API class DCCylinderVariation; \ + EXPORTPREPOSTREGVAR(DCCylinder, T) \ EXPORTPREPOSTREGVAR(DCGridOut, T) \ - template EMBER_API class DCLinearVariation; \ + EXPORTPREPOSTREGVAR(DCLinear, T) \ EXPORTPREPOSTREGVAR(DCZTransl, T) \ EXPORTPREPOSTREGVAR(DCTriangle, T) \ template EMBER_API class VariationList; \ diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index e01f97e..345b207 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -201,7 +201,7 @@ public: m_SubBatchSize = DEFAULT_SBS; m_FuseCount = 15; m_Supersample = 1; - m_TemporalSamples = 1000; + m_TemporalSamples = 100; m_Symmetry = 0; m_Quality = 100; m_PixelsPerUnit = 240; @@ -226,7 +226,7 @@ public: m_Time = 0; m_Background.Reset(); m_Interp = EMBER_INTERP_LINEAR; - m_AffineInterp = INTERP_LOG; + m_AffineInterp = AFFINE_INTERP_LOG; //DE filter. m_MinRadDE = 0; @@ -505,15 +505,15 @@ public: } else { - m_CamMat[0][0] = cos(-m_CamYaw); - m_CamMat[1][0] = -sin(-m_CamYaw); + m_CamMat[0][0] = std::cos(-m_CamYaw); + m_CamMat[1][0] = -std::sin(-m_CamYaw); m_CamMat[2][0] = 0; - m_CamMat[0][1] = cos(m_CamPitch) * sin(-m_CamYaw); - m_CamMat[1][1] = cos(m_CamPitch) * cos(-m_CamYaw); - m_CamMat[2][1] = -sin(m_CamPitch); - m_CamMat[0][2] = sin(m_CamPitch) * sin(-m_CamYaw); - m_CamMat[1][2] = sin(m_CamPitch) * cos(-m_CamYaw); - m_CamMat[2][2] = cos(m_CamPitch); + m_CamMat[0][1] = std::cos(m_CamPitch) * std::sin(-m_CamYaw); + m_CamMat[1][1] = std::cos(m_CamPitch) * std::cos(-m_CamYaw); + m_CamMat[2][1] = -std::sin(m_CamPitch); + m_CamMat[0][2] = std::sin(m_CamPitch) * std::sin(-m_CamYaw); + m_CamMat[1][2] = std::sin(m_CamPitch) * std::cos(-m_CamYaw); + m_CamMat[2][2] = std::cos(m_CamPitch); if (projBits & PROJBITS_BLUR) { @@ -667,10 +667,10 @@ public: } /// - /// Flatten all xforms by adding a flatten variation if none is present, and if any of the - /// variations or parameters in the vector are present. + /// Flatten all xforms by adding a flatten variation if none is present, and if none of the + /// variations or parameters in the vector are not present. /// - /// Vector of variation and parameter names + /// Vector of variation and parameter names that inhibit flattening /// True if flatten was added to any of the xforms, false if it already was present or if none of the specified variations or parameters were present. bool Flatten(vector& names) { @@ -907,7 +907,7 @@ public: ClampRef(thisXform->m_ColorSpeed, -1, 1); //Interp affine and post. - if (m_AffineInterp == INTERP_LOG) + if (m_AffineInterp == AFFINE_INTERP_LOG) { vector cxMag(size); vector cxAng(size); @@ -944,7 +944,7 @@ public: Interpolater::InterpAndConvertBack(coefs, cxAng, cxMag, cxTrn, thisXform->m_Post); } } - else if (m_AffineInterp == INTERP_LINEAR) + else if (m_AffineInterp == AFFINE_INTERP_LINEAR) { //Interpolate pre and post affine using coefs. allID = true; @@ -1057,7 +1057,7 @@ public: continue; //Assume that if there are no variations, then it's a padding xform. - if (m_Xforms[i].Empty() && m_AffineInterp != INTERP_LOG) + if (m_Xforms[i].Empty() && m_AffineInterp != AFFINE_INTERP_LOG) continue; m_Xforms[i].m_Affine.Rotate(angle); @@ -1140,8 +1140,8 @@ public: m_Xforms[i].m_ColorSpeed = 0; m_Xforms[i].m_Animate = 0; m_Xforms[i].m_ColorX = m_Xforms[i].m_ColorY = (sym < 3) ? 0 : (T(k - 1) / T(sym - 2));//Added Y. - m_Xforms[i].m_Affine.A(Round6(cos(k * a))); - m_Xforms[i].m_Affine.D(Round6(sin(k * a))); + m_Xforms[i].m_Affine.A(Round6(std::cos(k * a))); + m_Xforms[i].m_Affine.D(Round6(std::sin(k * a))); m_Xforms[i].m_Affine.B(Round6(-m_Xforms[i].m_Affine.D())); m_Xforms[i].m_Affine.E(m_Xforms[i].m_Affine.A()); m_Xforms[i].m_Affine.C(0); @@ -1159,7 +1159,7 @@ public: /// Return a uint with bits set to indicate which kind of projection should be done. /// /// A uint with bits set for each kind of projection that is needed - size_t ProjBits() + size_t ProjBits() const { size_t val = 0; @@ -1410,9 +1410,9 @@ public: m_MinRadDE = 0; m_CurveDE = T(0.4); m_GammaThresh = T(0.01); - m_TemporalSamples = 1000; + m_TemporalSamples = 100; m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER; - m_AffineInterp = INTERP_LOG; + m_AffineInterp = AFFINE_INTERP_LOG; m_TemporalFilterType = BOX_TEMPORAL_FILTER; m_TemporalFilterWidth = 1; m_TemporalFilterExp = 0; @@ -1443,7 +1443,7 @@ public: m_GammaThresh = -1; m_TemporalSamples = 0; m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER; - m_AffineInterp = INTERP_LOG; + m_AffineInterp = AFFINE_INTERP_LOG; m_TemporalFilterType = BOX_TEMPORAL_FILTER; m_TemporalFilterWidth = -1; m_TemporalFilterExp = -999; diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index e937571..2df878c 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -29,15 +29,13 @@ //Wrap the sincos function for Macs and PC. #if defined(__APPLE__) || defined(_MSC_VER) - #define sincos(x, s, c) *(s)=sin(x); *(c)=cos(x); + #define sincos(x, s, c) *(s)=std::sin(x); *(c)=std::cos(x); #else - //extern void sincos(double x, double *s, double *c); - //extern void sincos(float x, float *s, float *c); - static void sincos(float x, float* s, float* c) + /*static void sincos(float x, float* s, float* c) { - *s = sin(x); - *c = cos(x); - } + *s = std::sin(x); + *c = std::cos(x); + }*/ #endif namespace EmberNs @@ -92,6 +90,15 @@ static inline size_t NowMs() #define DO_DOUBLE 1//Comment this out for shorter build times during development. Always uncomment for release. //#define ISAAC_FLAM3_DEBUG 1//This is almost never needed, but is very useful when troubleshooting difficult bugs. Enable it to do a side by side comparison with flam3. +//These two must always match. +#ifdef WIN32 +#define ALIGN __declspec(align(16)) +#else +#define ALIGN __attribute__ ((aligned (16))) +#endif + +#define ALIGN_CL "((aligned (16)))"//The extra parens are necessary. + #if GLM_VERSION >= 96 #define v2T glm::tvec2 #define v3T glm::tvec3 @@ -113,7 +120,7 @@ static inline size_t NowMs() #endif enum eInterp : uint { EMBER_INTERP_LINEAR = 0, EMBER_INTERP_SMOOTH = 1 }; -enum eAffineInterp : uint { INTERP_LINEAR = 0, INTERP_LOG = 1, INTERP_COMPAT = 2, INTERP_OLDER = 3 }; +enum eAffineInterp : uint { AFFINE_INTERP_LINEAR = 0, AFFINE_INTERP_LOG = 1, AFFINE_INTERP_COMPAT = 2, AFFINE_INTERP_OLDER = 3 }; enum ePaletteMode : uint { PALETTE_STEP = 0, PALETTE_LINEAR = 1 }; enum ePaletteInterp : uint { INTERP_HSV = 0, INTERP_SWEEP = 1 }; enum eMotion : uint { MOTION_SIN = 1, MOTION_TRIANGLE = 2, MOTION_HILL = 3, MOTION_SAW = 4 }; diff --git a/Source/Ember/EmberPch.h b/Source/Ember/EmberPch.h index 3952f53..e57b407 100644 --- a/Source/Ember/EmberPch.h +++ b/Source/Ember/EmberPch.h @@ -53,6 +53,7 @@ #include #include #include +#include //Third party headers. #ifdef _WIN32 diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index 97c7611..a7ea972 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -64,6 +64,8 @@ public: bool Save(const string& filename, vector>& embers, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false) { bool b = false; + bool hasTimes = false; + T t = 0; string temp; ofstream f; @@ -76,6 +78,21 @@ public: if (f.is_open()) { + //Check to see if there are valid times by checking if any differed. + //If so, assume they were intentionally entered times. + for (size_t i = 1; i < embers.size(); i++) + { + if (embers[i].m_Time != embers[i - 1].m_Time) + { + hasTimes = true; + break; + } + } + + if (!hasTimes) + for (auto& ember : embers) + ember.m_Time = t++; + if ((append && start) || !append) { temp = "\n"; @@ -170,7 +187,6 @@ public: os << " gamma=\"" << ember.m_Gamma << "\""; os << " highlight_power=\"" << ember.m_HighlightPower << "\""; os << " vibrancy=\"" << ember.m_Vibrancy << "\""; - //os << " hue=\"" << ember.m_Hue << "\"";//Oddly enough, flam3 never wrote this value out.//ORIG os << " estimator_radius=\"" << ember.m_MaxRadDE << "\""; os << " estimator_minimum=\"" << ember.m_MinRadDE << "\""; os << " estimator_curve=\"" << ember.m_CurveDE << "\""; @@ -186,16 +202,18 @@ public: else if (ember.m_PaletteMode == PALETTE_LINEAR) os << " palette_mode=\"linear\""; - if (ember.m_Interp == EMBER_INTERP_SMOOTH) + if (ember.m_Interp == EMBER_INTERP_LINEAR) + os << " interpolation=\"linear\""; + else if (ember.m_Interp == EMBER_INTERP_SMOOTH) os << " interpolation=\"smooth\""; - if (ember.m_AffineInterp == INTERP_LINEAR) + if (ember.m_AffineInterp == AFFINE_INTERP_LINEAR) os << " interpolation_type=\"linear\""; - else if (ember.m_AffineInterp == INTERP_LOG) + else if (ember.m_AffineInterp == AFFINE_INTERP_LOG) os << " interpolation_type=\"log\""; - else if (ember.m_AffineInterp == INTERP_COMPAT) + else if (ember.m_AffineInterp == AFFINE_INTERP_COMPAT) os << " interpolation_type=\"old\""; - else if (ember.m_AffineInterp == INTERP_OLDER) + else if (ember.m_AffineInterp == AFFINE_INTERP_OLDER) os << " interpolation_type=\"older\""; if (ember.m_PaletteInterp == INTERP_SWEEP) diff --git a/Source/Ember/Interpolate.h b/Source/Ember/Interpolate.h index 98b0df3..1ad0c9b 100644 --- a/Source/Ember/Interpolate.h +++ b/Source/Ember/Interpolate.h @@ -110,8 +110,8 @@ public: destXform->DeleteVariationById(VAR_LINEAR); //Only do the next substitution for log interpolation. - if ((i == 0 && destEmbers[i].m_AffineInterp == INTERP_LOG) || - (i > 0 && destEmbers[i - 1].m_AffineInterp == INTERP_LOG)) + if ((i == 0 && destEmbers[i].m_AffineInterp == AFFINE_INTERP_LOG) || + (i > 0 && destEmbers[i - 1].m_AffineInterp == AFFINE_INTERP_LOG)) { for (ii = -1; ii <= 1; ii += 2) { @@ -790,7 +790,7 @@ public: accang[col] += coefs[i] * cxAng[i][col]; if (accmode[col] == 0) - accmag[col] += coefs[i] * log(cxMag[i][col]); + accmag[col] += coefs[i] * std::log(cxMag[i][col]); else accmag[col] += coefs[i] * (cxMag[i][col]); @@ -803,12 +803,12 @@ public: for (col = 0; col < 2; col++) { if (accmode[col] == 0) - expmag = exp(accmag[col]); + expmag = std::exp(accmag[col]); else expmag = accmag[col]; - store.m_Mat[0][col] = expmag * cos(accang[col]); - store.m_Mat[1][col] = expmag * sin(accang[col]); + store.m_Mat[0][col] = expmag * std::cos(accang[col]); + store.m_Mat[1][col] = expmag * std::sin(accang[col]); } } @@ -865,7 +865,7 @@ public: //abs peak values should be not be greater than 1. if (funcNum == MOTION_SIN) { - return sin(T(2.0) * T(M_PI) * timeVal); + return std::sin(T(2.0) * T(M_PI) * timeVal); } else if (funcNum == MOTION_TRIANGLE) { @@ -885,7 +885,7 @@ public: } else if (funcNum == MOTION_HILL) { - return ((1 - cos(T(2.0) * T(M_PI) * timeVal)) * T(0.5)); + return ((1 - std::cos(T(2.0) * T(M_PI) * timeVal)) * T(0.5)); } else //MOTION_SAW { diff --git a/Source/Ember/Isaac.h b/Source/Ember/Isaac.h index 9da06ee..708f700 100644 --- a/Source/Ember/Isaac.h +++ b/Source/Ember/Isaac.h @@ -1,6 +1,6 @@ #pragma once -#include "EmberDefines.h" +#include "Timing.h" /// /// C++ TEMPLATE VERSION OF Robert J. Jenkins Jr.'s @@ -65,6 +65,8 @@ public: /// static unique_ptr > GlobalRand; + static CriticalSection m_CS; + /// /// The structure which holds all of the random information. /// @@ -116,6 +118,18 @@ public: return ret; } + /// + /// Locked version of RandByte(). + /// + /// The next random integer in the range of 0-255 + static inline T LockedRandByte() + { + m_CS.Enter(); + T t = GlobalRand->RandByte(); + m_CS.Leave(); + return t; + } + /// /// Return the next random integer. /// @@ -129,6 +143,18 @@ public: #endif } + /// + /// Locked version of Rand(). + /// + /// The next random integer + static inline T LockedRand() + { + m_CS.Enter(); + T t = GlobalRand->Rand(); + m_CS.Leave(); + return t; + } + /// /// Return the next random integer between 0 and the value passed in minus 1. /// @@ -139,6 +165,19 @@ public: return (upper == 0) ? Rand() : Rand() % upper; } + /// + /// Locked version of Rand(). + /// + /// A value one greater than the maximum value that will be returned + /// A value between 0 and the value passed in minus 1 + static inline T LockedRand(T upper) + { + m_CS.Enter(); + T t = GlobalRand->Rand(upper); + m_CS.Leave(); + return t; + } + /// /// Returns a random floating point value between the specified minimum and maximum. /// Template argument expected to be float or double. @@ -153,6 +192,21 @@ public: return fMin + (f * (fMax - fMin)); } + /// + /// Locked version of Frand(). + /// + /// The minimum value allowed, inclusive. + /// The maximum value allowed, inclusive. + /// A new random floating point value within the specified range, inclusive. + template + static inline floatType LockedFrand(floatType fMin, floatType fMax) + { + m_CS.Enter(); + floatType t = GlobalRand->Frand(fMin, fMax); + m_CS.Leave(); + return t; + } + /// /// Thin wrapper around a call to Frand() with a range of 0-1. /// Template argument expected to be float or double. @@ -168,6 +222,19 @@ public: #endif } + /// + /// Locked version of Frand01(). + /// + /// A new random number in the range of 0-1, inclusive. + template + static inline floatType LockedFrand01() + { + m_CS.Enter(); + floatType t = GlobalRand->Frand01(); + m_CS.Leave(); + return t; + } + /// /// Thin wrapper around a call to Frand() with a range of -1-1. /// Template argument expected to be float or double. @@ -183,6 +250,19 @@ public: #endif } + /// + /// Locked version of Frand11(). + /// + /// A new random number in the range of -1-1, inclusive. + template + static inline floatType LockedFrand11() + { + m_CS.Enter(); + floatType t = GlobalRand->Frand11(); + m_CS.Leave(); + return t; + } + /// /// Not sure what this does. /// @@ -193,6 +273,19 @@ public: return RandBit() ? floatType(0.38196) : floatType(0.61804); } + /// + /// Locked version of GoldenBit(). + /// + /// Something that is golden + template + static inline floatType LockedGoldenBit() + { + m_CS.Enter(); + floatType t = GlobalRand->GoldenBit(); + m_CS.Leave(); + return t; + } + /// /// Returns a random 0 or 1. /// @@ -202,6 +295,18 @@ public: return RandByte() & 1; } + /// + /// Locked version of RandBit(). + /// + /// A random 0 or 1 + static inline uint LockedRandBit() + { + m_CS.Enter(); + uint t = GlobalRand->RandBit(); + m_CS.Leave(); + return t; + } + /// /// A different way of getting a floating point rand in the range -1-1. /// Flam3 used this but it seems unnecessary now, keep around if it's ever needed. diff --git a/Source/Ember/Iterator.h b/Source/Ember/Iterator.h index 4decbf4..c277d4f 100644 --- a/Source/Ember/Iterator.h +++ b/Source/Ember/Iterator.h @@ -108,12 +108,12 @@ public: for (size_t distrib = 0; distrib < distribCount; distrib++) { - T totalDensity = 0; + double totalDensity = 0; //First find the total densities of all xforms. for (i = 0; i < ember.XformCount(); i++) { - T d = xforms[i].m_Weight; + double d = xforms[i].m_Weight; if (distrib > 0) d *= xforms[distrib - 1].Xaos(i); @@ -127,14 +127,15 @@ public: //Calculate how much of a fraction of a the total density each element represents. size_t j = 0; - T tempDensity = 0, currentDensityLimit = 0, densityPerElement = totalDensity / CHOOSE_XFORM_GRAIN; + //These must be double, else roundoff error will prevent the last element of m_XformDistributions from being set. + double tempDensity = 0, currentDensityLimit = 0, densityPerElement = totalDensity / CHOOSE_XFORM_GRAIN; //Assign xform indices in order to each element of m_XformDistributions. //The number of elements assigned a given index is proportional to that xform's //density relative to the sum of all densities. for (i = 0; i < ember.XformCount(); i++) { - T temp = xforms[i].m_Weight; + double temp = xforms[i].m_Weight; if (distrib > 0) temp *= xforms[distrib - 1].Xaos(i); @@ -145,6 +146,11 @@ public: //Also check that j is within the bounds of the distribution array just to be safe in the case of a rounding error. while (tempDensity < currentDensityLimit && j < CHOOSE_XFORM_GRAIN) { +#ifdef _DEBUG + //Ensure distribution contains no out of bounds indices. + if (byte(i) >= ember.XformCount()) + throw "Out of bounds xform index in selection distribution."; +#endif //printf("offset = %d, xform = %d, running sum = %f\n", j, i, tempDensity); m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + j] = byte(i); tempDensity += densityPerElement; @@ -152,6 +158,11 @@ public: } } +#ifdef _DEBUG + //Ensure every element of the distribution was populated. + if (j < CHOOSE_XFORM_GRAIN) + throw "Not all distribution elements set, undefined behavior."; +#endif //Flam3 did this, which gives the same result. //T t = xforms[0].m_Weight; // diff --git a/Source/Ember/Palette.h b/Source/Ember/Palette.h index 713ca3e..8346213 100644 --- a/Source/Ember/Palette.h +++ b/Source/Ember/Palette.h @@ -492,17 +492,17 @@ public: static T CalcAlpha(T density, T gamma, T linrange) { T frac, alpha; - T funcval = pow(linrange, gamma); + T funcval = std::pow(linrange, gamma); if (density > 0) { if (density < linrange) { frac = density / linrange; - alpha = (T(1.0) - frac) * density * (funcval / linrange) + frac * pow(density, gamma); + alpha = (T(1.0) - frac) * density * (funcval / linrange) + frac * std::pow(density, gamma); } else - alpha = pow(density, gamma); + alpha = std::pow(density, gamma); } else alpha = 0; @@ -545,7 +545,7 @@ public: if (maxa > 255 && highPow >= 0) { newls = T(255.0) / maxc; - lsratio = pow(newls / ls, highPow); + lsratio = std::pow(newls / ls, highPow); //Calculate the max-value color (ranged 0 - 1). for (rgbi = 0; rgbi < 3; rgbi++) diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index 47e6fd9..330e879 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -113,7 +113,7 @@ void Renderer::ComputeBounds() template void Renderer::ComputeQuality() { - m_Scale = pow(T(2.0), Zoom()); + m_Scale = std::pow(T(2.0), Zoom()); m_ScaledQuality = Quality() * m_Scale * m_Scale; } @@ -470,7 +470,7 @@ eRenderStatus Renderer::Run(vector& finalImage, double time, s goto Finish; } - //Don't need to do this every time through for a single image. + //Do this every iteration for an animation, or else do it once for a single image. if (TemporalSamples() > 1 || !resume) { ComputeQuality(); @@ -573,7 +573,7 @@ FilterAndAccum: //Apply appropriate filter if iterating is complete. if (filterAndAccumOnly || temporalSample >= TemporalSamples()) { - fullRun = m_DensityFilter.get() ? GaussianDensityFilter() : LogScaleDensityFilter(); + fullRun = m_DensityFilter.get() ? GaussianDensityFilter() : LogScaleDensityFilter(forceOutput); } else { @@ -581,7 +581,7 @@ FilterAndAccum: if (m_DensityFilter.get() && m_InteractiveFilter == FILTER_DE) fullRun = GaussianDensityFilter(); else if (!m_DensityFilter.get() || m_InteractiveFilter == FILTER_LOG) - fullRun = LogScaleDensityFilter(); + fullRun = LogScaleDensityFilter(forceOutput); } //Only update state if iterating and filtering finished completely (didn't arrive here via forceOutput). @@ -801,14 +801,42 @@ bool Renderer::ResetBuckets(bool resetHist, bool resetAccum) return resetHist || resetAccum; } +/// +/// Log scales a single row with a specially structured loop that will be vectorized by the compiler. +/// Note this adds an epsilon to the denomiator used to compute the logScale +/// value because the conditional check for zero would have prevented the loop from +/// being vectorized. +/// +/// The absolute element index in the histogram this row starts on +/// The absolute element index in the histogram this row ends on +template +void Renderer::VectorizedLogScale(size_t row, size_t rowEnd) +{ + float k1 = float(m_K1);//All types must be float. + float k2 = float(m_K2); + auto* __restrict hist = m_HistBuckets.data();//Vectorizer can't tell these point to different locations. + auto* __restrict acc = m_AccumulatorBuckets.data(); + + for (size_t i = row; i < rowEnd; i++) + { + float logScale = (k1 * std::log(1.0f + hist[i].a * k2)) / (hist[i].a + std::numeric_limits::epsilon()); + + acc[i].r = hist[i].r * logScale;//Must break these out individually. Vectorizer can't reason about vec4's overloaded * operator. + acc[i].g = hist[i].g * logScale; + acc[i].b = hist[i].b * logScale; + acc[i].a = hist[i].a * logScale; + } +} + /// /// Perform log scale density filtering. /// Base case for simple log scale density estimation as discussed (mostly) in the paper /// in section 4, p. 6-9. /// +/// Whether this output was forced due to an interactive render /// True if not prematurely aborted, else false. template -eRenderStatus Renderer::LogScaleDensityFilter() +eRenderStatus Renderer::LogScaleDensityFilter(bool forceOutput) { size_t startRow = 0; size_t endRow = m_SuperRasH; @@ -816,30 +844,46 @@ eRenderStatus Renderer::LogScaleDensityFilter() size_t endCol = m_SuperRasW; //Timing t(4); - //Original didn't parallelize this, doing so gives a 50-75% speedup. - //The value can be directly assigned, which is quicker than summing. - parallel_for(startRow, endRow, [&] (size_t j) + //if (forceOutput)//Assume interactive render, so speed up at the expense of slight quality. + //{ + // parallel_for(startRow, endRow, [&](size_t j) + // { + // if (!m_Abort) + // { + // size_t row = j * m_SuperRasW; + // size_t rowEnd = row + endCol; + + // VectorizedLogScale(row, rowEnd); + // } + // }); + //} + //else { - size_t row = j * m_SuperRasW; - //__m128 logm128;//Figure out SSE at some point. - //__m128 bucketm128; - //__m128 scaledBucket128; - - for (size_t i = startCol; (i < endCol) && !m_Abort; i++) + //Original didn't parallelize this, doing so gives a 50-75% speedup. + //The value can be directly assigned, which is quicker than summing. + parallel_for(startRow, endRow, [&](size_t j) { - size_t index = row + i; + size_t row = j * m_SuperRasW; + size_t rowEnd = row + endCol; - //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. - if (m_HistBuckets[index].a != 0) + if (!m_Abort) { - bucketT logScale = (m_K1 * log(1 + m_HistBuckets[index].a * m_K2)) / m_HistBuckets[index].a; + for (size_t i = row; i < rowEnd; i++) + { + //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. + if (m_HistBuckets[i].a != 0) + { + bucketT logScale = (m_K1 * std::log(1 + m_HistBuckets[i].a * m_K2)) / m_HistBuckets[i].a; - //Original did a temporary assignment, then *= logScale, then passed the result to bump_no_overflow(). - //Combine here into one operation for a slight speedup. - m_AccumulatorBuckets[index] = m_HistBuckets[index] * logScale; + //Original did a temporary assignment, then *= logScale, then passed the result to bump_no_overflow(). + //Combine here into one operation for a slight speedup. + m_AccumulatorBuckets[i] = m_HistBuckets[i] * logScale; + } + } } - } - }); + }); + } + //t.Toc(__FUNCTION__); return m_Abort ? RENDER_ABORT : RENDER_OK; @@ -858,7 +902,7 @@ eRenderStatus Renderer::GaussianDensityFilter() Timing totalTime, localTime; bool scf = !(Supersample() & 1); intmax_t ss = Floor(Supersample() / T(2)); - T scfact = pow(Supersample() / (Supersample() + T(1)), T(2)); + T scfact = std::pow(Supersample() / (Supersample() + T(1)), T(2)); size_t threads = m_ThreadsToUse; size_t startRow = Supersample() - 1; @@ -896,7 +940,7 @@ eRenderStatus Renderer::GaussianDensityFilter() if (bucket->a == 0) continue; - bucketT cacheLog = (m_K1 * log(1 + bucket->a * m_K2)) / bucket->a;//Caching this calculation gives a 30% speedup. + bucketT cacheLog = (m_K1 * std::log(1 + bucket->a * m_K2)) / bucket->a;//Caching this calculation gives a 30% speedup. if (ss == 0) { @@ -928,7 +972,7 @@ eRenderStatus Renderer::GaussianDensityFilter() else if (filterSelect <= DE_THRESH) filterSelectInt = size_t(ceil(filterSelect)) - 1; else - filterSelectInt = DE_THRESH + size_t(Floor(pow(filterSelect - DE_THRESH, m_DensityFilter->Curve()))); + filterSelectInt = DE_THRESH + size_t(Floor(std::pow(filterSelect - DE_THRESH, m_DensityFilter->Curve()))); //If the filter selected below the min specified clamp it to the min. if (filterSelectInt > m_DensityFilter->MaxFilterIndex()) @@ -1214,6 +1258,13 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t temporalSample double percent, etaMs; EmberStats stats; + //Do this every iteration for an animation, or else do it once for a single image. CPU only. + if (!m_LastIter) + { + m_ThreadEmbers.clear(); + m_ThreadEmbers.insert(m_ThreadEmbers.begin(), m_ThreadsToUse, m_Ember); + } + #ifdef TG size_t threadIndex; @@ -1261,7 +1312,8 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t temporalSample //Finally, iterate. //t.Tic(); //Iterating, loop 3. - m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, params, m_Samples[threadIndex].data(), m_Rand[threadIndex]); + m_BadVals[threadIndex] += m_Iterator->Iterate(m_ThreadEmbers[threadIndex], params, m_Samples[threadIndex].data(), m_Rand[threadIndex]); + //m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, params, m_Samples[threadIndex].data(), m_Rand[threadIndex]); //iterationTime += t.Toc(); if (m_LockAccum) @@ -1459,9 +1511,7 @@ void Renderer::Accumulate(QTIsaac& rand, Poin size_t histIndex, intColorIndex, histSize = m_HistBuckets.size(); bucketT colorIndex, colorIndexFrac; auto dmap = palette->m_Entries.data(); - //T oneColDiv2 = m_CarToRas.OneCol() / 2; - //T oneRowDiv2 = m_CarToRas.OneRow() / 2; - + //It's critical to understand what's going on here as it's one of the most important parts of the algorithm. //A color value gets retrieved from the palette and //its RGB values are added to the existing RGB values in the histogram bucket. @@ -1484,17 +1534,6 @@ void Renderer::Accumulate(QTIsaac& rand, Poin p.m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY; } - //T angle = rand.Frand01() * M_2PI; - //T r = exp(T(0.5) * sqrt(-log(rand.Frand01()))) - 1; - - //T r = (rand.Frand01() + rand.Frand01() - 1); - //T r = (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); - - //p.m_X += (r * oneColDiv2) * cos(angle); - //p.m_Y += (r * oneRowDiv2) * sin(angle); - //p.m_X += r * cos(angle); - //p.m_Y += r * sin(angle); - //Checking this first before converting gives better performance than converting and checking a single value, which the original did. //Second, an interesting optimization observation is that when keeping the bounds vars within m_CarToRas and calling its InBounds() member function, //rather than here as members, about a 7% speedup is achieved. This is possibly due to the fact that data from m_CarToRas is accessed @@ -1610,7 +1649,7 @@ void Renderer::GammaCorrection(tvec4& bucket for (glm::length_t rgbi = 0; rgbi < 3; rgbi++) { - a = newRgb[rgbi] + ((1 - vibrancy) * 255 * pow(bucket[rgbi], g)); + a = newRgb[rgbi] + ((1 - vibrancy) * 255 * std::pow(bucket[rgbi], g)); if (NumChannels() <= 3 || !Transparency()) { diff --git a/Source/Ember/Renderer.h b/Source/Ember/Renderer.h index 6c33fb8..5a1fec7 100644 --- a/Source/Ember/Renderer.h +++ b/Source/Ember/Renderer.h @@ -70,7 +70,7 @@ protected: virtual void MakeDmap(T colorScalar); virtual bool Alloc(bool histOnly = false); virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true); - virtual eRenderStatus LogScaleDensityFilter(); + virtual eRenderStatus LogScaleDensityFilter(bool forceOutput = false); virtual eRenderStatus GaussianDensityFilter(); virtual eRenderStatus AccumulatorToFinalImage(vector& pixels, size_t finalOffset); virtual eRenderStatus AccumulatorToFinalImage(byte* pixels, size_t finalOffset); @@ -152,6 +152,7 @@ protected: /*inline*/ void AddToAccum(const tvec4& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj); template void GammaCorrection(tvec4& bucket, Color& background, bucketT g, bucketT linRange, bucketT vibrancy, bool doAlpha, bool scale, accumT* correctedChannels); void CurveAdjust(bucketT& a, const glm::length_t& index); + void VectorizedLogScale(size_t row, size_t rowEnd); protected: T m_Scale; @@ -173,6 +174,7 @@ protected: Ember m_TempEmber; Ember m_LastEmber; vector> m_Embers; + vector> m_ThreadEmbers; CarToRas m_CarToRas; Iterator* m_Iterator; unique_ptr> m_StandardIterator; diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h index 490aaa3..d649907 100644 --- a/Source/Ember/SheepTools.h +++ b/Source/Ember/SheepTools.h @@ -185,8 +185,9 @@ public: /// The variations to use if the mutation mode is random /// The type of symmetry to add if random specified. If 0, it will be added randomly. /// The speed to multiply the pre affine transforms by if the mutate mode is MUTATE_ALL_COEFS, else ignored. + /// The maximum number of variations to allow in any single xform in the ember. /// A string describing what was done - string Mutate(Ember& ember, eMutateMode mode, vector& useVars, intmax_t sym, T speed) + string Mutate(Ember& ember, eMutateMode mode, vector& useVars, intmax_t sym, T speed, size_t maxVars) { bool done = false; size_t modXform; @@ -224,7 +225,7 @@ public: do { //Create a random flame, and use the variations to replace those in the original. - Random(mutation, useVars, sym, ember.TotalXformCount()); + Random(mutation, useVars, sym, ember.TotalXformCount(), maxVars); for (size_t i = 0; i < ember.TotalXformCount(); i++) { @@ -255,7 +256,7 @@ public: else if (mode == MUTATE_ONE_XFORM_COEFS) { //Generate a 2-xform random. - Random(mutation, useVars, sym, 2); + Random(mutation, useVars, sym, 2, maxVars); //Which xform to mutate? modXform = m_Rand.Rand() % ember.TotalXformCount(); @@ -305,10 +306,10 @@ public: T f = T(M_PI) * m_Rand.Frand11(); T ra, rb, rd, re; - ra = (xform->m_Affine.A() * cos(f) + xform->m_Affine.B() * -sin(f)); - rd = (xform->m_Affine.A() * sin(f) + xform->m_Affine.D() * cos(f)); - rb = (xform->m_Affine.B() * cos(f) + xform->m_Affine.E() * -sin(f)); - re = (xform->m_Affine.B() * sin(f) + xform->m_Affine.E() * cos(f)); + ra = (xform->m_Affine.A() * std::cos(f) + xform->m_Affine.B() * -std::sin(f)); + rd = (xform->m_Affine.A() * std::sin(f) + xform->m_Affine.D() * std::cos(f)); + rb = (xform->m_Affine.B() * std::cos(f) + xform->m_Affine.E() * -std::sin(f)); + re = (xform->m_Affine.B() * std::sin(f) + xform->m_Affine.E() * std::cos(f)); xform->m_Affine.A(ra); xform->m_Affine.B(rb); @@ -317,10 +318,10 @@ public: f *= -1; - ra = (xform->m_Post.A() * cos(f) + xform->m_Post.B() * -sin(f)); - rd = (xform->m_Post.A() * sin(f) + xform->m_Post.D() * cos(f)); - rb = (xform->m_Post.B() * cos(f) + xform->m_Post.E() * -sin(f)); - re = (xform->m_Post.B() * sin(f) + xform->m_Post.E() * cos(f)); + ra = (xform->m_Post.A() * std::cos(f) + xform->m_Post.B() * -std::sin(f)); + rd = (xform->m_Post.A() * std::sin(f) + xform->m_Post.D() * std::cos(f)); + rb = (xform->m_Post.B() * std::cos(f) + xform->m_Post.E() * -std::sin(f)); + re = (xform->m_Post.B() * std::sin(f) + xform->m_Post.E() * std::cos(f)); xform->m_Post.A(ra); xform->m_Post.B(rb); @@ -408,7 +409,7 @@ public: else if (mode == MUTATE_ALL_COEFS) { os << "mutate all coefs"; - Random(mutation, useVars, sym, ember.TotalXformCount()); + Random(mutation, useVars, sym, ember.TotalXformCount(), maxVars); //Change all the coefs by a fraction of the random. for (size_t x = 0; x < ember.TotalXformCount(); x++) @@ -599,11 +600,12 @@ public: /// Thin wrapper around Random() that passes an empty vector for useVars, a random value for symmetry and 0 for max xforms. /// /// The newly created random ember - void Random(Ember& ember) + /// The maximum number of variations to allow in any single xform in the ember. + void Random(Ember& ember, size_t maxVars) { vector useVars; - Random(ember, useVars, static_cast(m_Rand.Frand(-2, 2)), 0); + Random(ember, useVars, static_cast(m_Rand.Frand(-2, 2)), 0, maxVars); } /// @@ -613,7 +615,8 @@ public: /// A list of variations to use. If empty, any variation can be used. /// The symmetry type to use from -2 to 2 /// The number of xforms to use. If 0, a quasi random count is used. - void Random(Ember& ember, vector& useVars, intmax_t sym, size_t specXforms) + /// The maximum number of variations to allow in any single xform in the ember. + void Random(Ember& ember, vector& useVars, intmax_t sym, size_t specXforms, size_t maxVars) { bool postid, addfinal = false; int var, samed, multid, samepost; @@ -705,11 +708,13 @@ public: if (var > -1) { - xform->AddVariation(m_VariationList.GetVariation(var)->Copy());//Use only one variation specified for all xforms. + if (xform->TotalVariationCount() < maxVars) + xform->AddVariation(m_VariationList.GetVariation(var)->Copy());//Use only one variation specified for all xforms. } else if (multid && var == -1) { - xform->AddVariation(m_VariationList.GetVariation(m_Rand.Rand() % varCount)->Copy());//Choose a random var for this xform. + if (xform->TotalVariationCount() < maxVars) + xform->AddVariation(m_VariationList.GetVariation(m_Rand.Rand() % varCount)->Copy());//Choose a random var for this xform. } else { @@ -719,7 +724,8 @@ public: Xform* prevXform = ember.GetXform(i - 1); for (j = 0; j < prevXform->TotalVariationCount(); j++) - xform->AddVariation(prevXform->GetVariation(j)->Copy()); + if (xform->TotalVariationCount() < maxVars) + xform->AddVariation(prevXform->GetVariation(j)->Copy()); } else { @@ -735,21 +741,24 @@ public: //the probability that multiple vars are used. for (j = 0; j < n; j++) { - if (var != -2) + if (xform->TotalVariationCount() < maxVars) { - //Pick a random variation and use a random weight from 0-1. - Variation* v = m_VariationList.GetVariationCopy(static_cast(m_Rand.Rand() % varCount), m_Rand.Frand(T(0.001), 1)); + if (var != -2) + { + //Pick a random variation and use a random weight from 0-1. + Variation* v = m_VariationList.GetVariationCopy(static_cast(m_Rand.Rand() % varCount), m_Rand.Frand(T(0.001), 1)); - if (v && !xform->AddVariation(v)) - delete v;//It already existed and therefore was not added. - } - else - { - //Pick a random variation from the suppled IDs and use a random weight from 0-1. - Variation* v = m_VariationList.GetVariationCopy(useVars[m_Rand.Rand() % useVars.size()], m_Rand.Frand(T(0.001), 1)); + if (v && !xform->AddVariation(v)) + delete v;//It already existed and therefore was not added. + } + else + { + //Pick a random variation from the suppled IDs and use a random weight from 0-1. + Variation* v = m_VariationList.GetVariationCopy(useVars[m_Rand.Rand() % useVars.size()], m_Rand.Frand(T(0.001), 1)); - if (v && !xform->AddVariation(v)) - delete v; + if (v && !xform->AddVariation(v)) + delete v; + } } } @@ -770,15 +779,18 @@ public: //the probability that multiple vars are used. for (j = 0; j < n; j++) { - if (var != -2) + if (xform->TotalVariationCount() < maxVars) { - //Pick a random variation and use a random weight from 0-1. - xform->AddVariation(m_VariationList.GetVariationCopy(static_cast(m_Rand.Rand() % varCount), m_Rand.Frand(T(0.001), 1))); - } - else - { - //Pick a random variation from the suppled IDs and use a random weight from 0-1. - xform->AddVariation(m_VariationList.GetVariationCopy(useVars[m_Rand.Rand() % useVars.size()], m_Rand.Frand(T(0.001), 1))); + if (var != -2) + { + //Pick a random variation and use a random weight from 0-1. + xform->AddVariation(m_VariationList.GetVariationCopy(static_cast(m_Rand.Rand() % varCount), m_Rand.Frand(T(0.001), 1))); + } + else + { + //Pick a random variation from the suppled IDs and use a random weight from 0-1. + xform->AddVariation(m_VariationList.GetVariationCopy(useVars[m_Rand.Rand() % useVars.size()], m_Rand.Frand(T(0.001), 1))); + } } } @@ -1240,8 +1252,8 @@ public: { T r[2]; T th = by * 2 * T(M_PI) / 360; - T c = cos(th); - T s = -sin(th); + T c = std::cos(th); + T s = -std::sin(th); newCenterX -= oldCenterX; newCenterY -= oldCenterY; diff --git a/Source/Ember/SpatialFilter.h b/Source/Ember/SpatialFilter.h index 94f32b6..8445614 100644 --- a/Source/Ember/SpatialFilter.h +++ b/Source/Ember/SpatialFilter.h @@ -207,7 +207,7 @@ protected: x *= T(M_PI); if (x != 0) - return sin(x) / x; + return std::sin(x) / x; return 1.0; } @@ -269,7 +269,7 @@ public: /// The filtered value virtual T Filter(T t) const { - return exp(-2 * t * t) * std::sqrt(2 / T(M_PI)); + return std::exp(-2 * t * t) * std::sqrt(2 / T(M_PI)); } }; @@ -604,7 +604,7 @@ public: /// The filtered value virtual T Filter(T t) const { - return (T(0.42) + T(0.5) * cos(T(M_PI) * t) + T(0.08) * cos(2 * T(M_PI) * t)); + return (T(0.42) + T(0.5) * std::cos(T(M_PI) * t) + T(0.08) * std::cos(2 * T(M_PI) * t)); } }; @@ -675,7 +675,7 @@ public: /// The filtered value virtual T Filter(T t) const { - return T(0.54) + T(0.46) * cos(T(M_PI) * t); + return T(0.54) + T(0.46) * std::cos(T(M_PI) * t); } }; @@ -703,7 +703,7 @@ public: /// The filtered value virtual T Filter(T t) const { - return T(0.5) + T(0.5) * cos(T(M_PI) * t); + return T(0.5) + T(0.5) * std::cos(T(M_PI) * t); } }; diff --git a/Source/Ember/TemporalFilter.h b/Source/Ember/TemporalFilter.h index 4931d1c..305d24c 100644 --- a/Source/Ember/TemporalFilter.h +++ b/Source/Ember/TemporalFilter.h @@ -207,7 +207,7 @@ public: slpx = T(Size() - i) / Size(); //Scale the color based on these values. - m_Filter[i] = pow(slpx, fabs(filterExp)); + m_Filter[i] = std::pow(slpx, fabs(filterExp)); //Keep the max. if (m_Filter[i] > maxFilt) diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index 8634d8f..cca9184 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -41,6 +41,18 @@ static inline bool FindIf(c& container, pr pred) return std::find_if(container.begin(), container.end(), pred) != container.end(); } +/// +/// Thin wrapper around std::find_if() determine if a value exists at least once. +/// +/// The container to call find_if() on +/// The value to search for +/// True if the value was contained at least once, else false. +template +static inline bool Contains(c& container, const T& val) +{ + return std::find_if(container.begin(), container.end(), [&](const T& t) -> bool { return t == val; }) != container.end(); +} + /// /// Thin wrapper around computing the total size of a vector. /// @@ -574,7 +586,7 @@ static #endif float SafeTan(float x) { - return tan(Clamp(x, FLOAT_MIN_TAN, FLOAT_MAX_TAN)); + return std::tan(Clamp(x, FLOAT_MIN_TAN, FLOAT_MAX_TAN)); } template <> @@ -583,7 +595,7 @@ static #endif double SafeTan(double x) { - return tan(x); + return std::tan(x); } /// @@ -632,7 +644,7 @@ static inline T Spread(T x, T y) template static inline T Powq4(T x, T y) { - return pow(fabs(x), y) * SignNz(x); + return std::pow(std::fabs(x), y) * SignNz(x); } /// @@ -696,7 +708,7 @@ static inline T Fabsmod(T v) template static inline T Fosc(T p, T amp, T ph) { - return T(0.5) - cos(p * amp + ph) * T(0.5); + return T(0.5) - std::cos(p * amp + ph) * T(0.5); } /// @@ -708,7 +720,7 @@ static inline T Fosc(T p, T amp, T ph) template static inline T Foscn(T p, T ph) { - return T(0.5) - cos(p + ph) * T(0.5); + return T(0.5) - std::cos(p + ph) * T(0.5); } /// @@ -719,7 +731,7 @@ static inline T Foscn(T p, T ph) template static inline T LogScale(T x) { - return x == 0 ? 0 : log((fabs(x) + 1) * T(M_E)) * SignNz(x) / T(M_E); + return x == 0 ? 0 : std::log((fabs(x) + 1) * T(M_E)) * SignNz(x) / T(M_E); } /// @@ -730,7 +742,7 @@ static inline T LogScale(T x) template static inline T LogMap(T x) { - return x == 0 ? 0 : (T(M_E) + log(x * T(M_E))) * T(0.25) * SignNz(x); + return x == 0 ? 0 : (T(M_E) + std::log(x * T(M_E))) * T(0.25) * SignNz(x); } /// diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h index 8886324..2287a1d 100644 --- a/Source/Ember/Variation.h +++ b/Source/Ember/Variation.h @@ -73,6 +73,7 @@ enum eVariationId VAR_BTRANSFORM , VAR_BUBBLE , VAR_BUBBLE2 , + VAR_BUBBLET3D , VAR_BUTTERFLY , VAR_BWRAPS , VAR_CARDIOID , @@ -101,6 +102,7 @@ enum eVariationId VAR_CPOW , VAR_CPOW2 , VAR_CRESCENTS , + VAR_CROB , VAR_CROP , VAR_CROPN , VAR_CROSS , @@ -173,6 +175,10 @@ enum eVariationId VAR_HEART , VAR_HEAT , VAR_HEMISPHERE , + VAR_HEXAPLAY3D , + VAR_HEXCROP , + VAR_HEXES , + VAR_HEXNIX3D , VAR_HO , VAR_HOLE , VAR_HORSESHOE , @@ -210,6 +216,8 @@ enum eVariationId VAR_LOG , VAR_LOQ , VAR_LOONIE , + VAR_LOONIE2 , + VAR_LOONIE3 , VAR_LOONIE3D , VAR_MASK , VAR_MCARPET , @@ -223,10 +231,12 @@ enum eVariationId VAR_MODULUS , VAR_MURL , VAR_MURL2 , + VAR_NBLUR , VAR_NGON , VAR_NOISE , VAR_NPOLAR , VAR_OCTAGON , + VAR_OCTAPOL , VAR_ORTHO , VAR_OSCILLOSCOPE , VAR_OVOID , @@ -284,6 +294,7 @@ enum eVariationId VAR_SINUS_GRID , VAR_SINUSOIDAL , VAR_SINUSOIDAL3D , + //VAR_SMARTCROP , VAR_SPHERICAL , VAR_SPHERICAL3D , VAR_SPHERICALN , @@ -308,6 +319,7 @@ enum eVariationId VAR_SUPER_SHAPE3D , VAR_SVF , VAR_SWIRL , + VAR_SYNTH , VAR_TAN , VAR_TANCOS , VAR_TANGENT , @@ -369,6 +381,7 @@ enum eVariationId VAR_PRE_BTRANSFORM, VAR_PRE_BUBBLE, VAR_PRE_BUBBLE2, + VAR_PRE_BUBBLET3D, VAR_PRE_BUTTERFLY, VAR_PRE_BWRAPS, VAR_PRE_CARDIOID, @@ -397,6 +410,7 @@ enum eVariationId VAR_PRE_CPOW, VAR_PRE_CPOW2, VAR_PRE_CRESCENTS, + VAR_PRE_CROB, VAR_PRE_CROP, VAR_PRE_CROPN, VAR_PRE_CROSS, @@ -469,6 +483,10 @@ enum eVariationId VAR_PRE_HEART, VAR_PRE_HEAT, VAR_PRE_HEMISPHERE, + VAR_PRE_HEXAPLAY3D, + VAR_PRE_HEXCROP, + VAR_PRE_HEXES, + VAR_PRE_HEXNIX3D, VAR_PRE_HO, VAR_PRE_HOLE, VAR_PRE_HORSESHOE, @@ -506,6 +524,8 @@ enum eVariationId VAR_PRE_LOG, VAR_PRE_LOQ, VAR_PRE_LOONIE, + VAR_PRE_LOONIE2, + VAR_PRE_LOONIE3, VAR_PRE_LOONIE3D, VAR_PRE_MASK, VAR_PRE_MCARPET, @@ -519,10 +539,12 @@ enum eVariationId VAR_PRE_MODULUS, VAR_PRE_MURL, VAR_PRE_MURL2, + VAR_PRE_NBLUR, VAR_PRE_NGON, VAR_PRE_NOISE, VAR_PRE_NPOLAR, VAR_PRE_OCTAGON, + VAR_PRE_OCTAPOL, VAR_PRE_ORTHO, VAR_PRE_OSCILLOSCOPE, VAR_PRE_OVOID, @@ -580,6 +602,7 @@ enum eVariationId VAR_PRE_SINUS_GRID, VAR_PRE_SINUSOIDAL, VAR_PRE_SINUSOIDAL3D, + //VAR_PRE_SMARTCROP, VAR_PRE_SPHERICAL, VAR_PRE_SPHERICAL3D, VAR_PRE_SPHERICALN, @@ -604,6 +627,7 @@ enum eVariationId VAR_PRE_SUPER_SHAPE3D, VAR_PRE_SVF, VAR_PRE_SWIRL, + VAR_PRE_SYNTH, VAR_PRE_TAN, VAR_PRE_TANCOS, VAR_PRE_TANGENT, @@ -665,6 +689,7 @@ enum eVariationId VAR_POST_BTRANSFORM, VAR_POST_BUBBLE, VAR_POST_BUBBLE2, + VAR_POST_BUBBLET3D, VAR_POST_BUTTERFLY, VAR_POST_BWRAPS, VAR_POST_CARDIOID, @@ -693,6 +718,7 @@ enum eVariationId VAR_POST_CPOW, VAR_POST_CPOW2, VAR_POST_CRESCENTS, + VAR_POST_CROB, VAR_POST_CROP, VAR_POST_CROPN, VAR_POST_CROSS, @@ -765,6 +791,10 @@ enum eVariationId VAR_POST_HEART, VAR_POST_HEAT, VAR_POST_HEMISPHERE, + VAR_POST_HEXAPLAY3D, + VAR_POST_HEXCROP, + VAR_POST_HEXES, + VAR_POST_HEXNIX3D, VAR_POST_HO, VAR_POST_HOLE, VAR_POST_HORSESHOE, @@ -802,6 +832,8 @@ enum eVariationId VAR_POST_LOG, VAR_POST_LOQ, VAR_POST_LOONIE, + VAR_POST_LOONIE2, + VAR_POST_LOONIE3, VAR_POST_LOONIE3D, VAR_POST_MASK, VAR_POST_MCARPET, @@ -815,10 +847,12 @@ enum eVariationId VAR_POST_MODULUS, VAR_POST_MURL, VAR_POST_MURL2, + VAR_POST_NBLUR, VAR_POST_NGON, VAR_POST_NOISE, VAR_POST_NPOLAR, VAR_POST_OCTAGON, + VAR_POST_OCTAPOL, VAR_POST_ORTHO, VAR_POST_OSCILLOSCOPE, VAR_POST_OVOID, @@ -876,6 +910,7 @@ enum eVariationId VAR_POST_SINUS_GRID, VAR_POST_SINUSOIDAL, VAR_POST_SINUSOIDAL3D, + //VAR_POST_SMARTCROP, VAR_POST_SPHERICAL, VAR_POST_SPHERICAL3D, VAR_POST_SPHERICALN, @@ -900,6 +935,7 @@ enum eVariationId VAR_POST_SUPER_SHAPE3D, VAR_POST_SVF, VAR_POST_SWIRL, + VAR_POST_SYNTH, VAR_POST_TAN, VAR_POST_TANCOS, VAR_POST_TANGENT, @@ -931,7 +967,7 @@ enum eVariationId VAR_POST_ZSCALE, VAR_POST_ZTRANSLATE, - //Direct color are special and only some have pre/post counterparts. + //Direct color variations are special. VAR_DC_BUBBLE, VAR_DC_CARPET, VAR_DC_CUBE, @@ -941,15 +977,21 @@ enum eVariationId VAR_DC_TRIANGLE, VAR_DC_ZTRANSL, + VAR_PRE_DC_BUBBLE, VAR_PRE_DC_CARPET, VAR_PRE_DC_CUBE, + VAR_PRE_DC_CYLINDER, VAR_PRE_DC_GRIDOUT, + VAR_PRE_DC_LINEAR, VAR_PRE_DC_TRIANGLE, VAR_PRE_DC_ZTRANSL, + VAR_POST_DC_BUBBLE, VAR_POST_DC_CARPET, VAR_POST_DC_CUBE, + VAR_POST_DC_CYLINDER, VAR_POST_DC_GRIDOUT, + VAR_POST_DC_LINEAR, VAR_POST_DC_TRIANGLE, VAR_POST_DC_ZTRANSL, @@ -1215,6 +1257,30 @@ public: return ss.str(); } + /// + /// Returns an OpenCL string for the fields in this variation + /// that change during iterations. + /// Note these are different than regular variation parameters, + /// and thus require a completely different solution. + /// + /// + virtual string StateOpenCLString() const + { + return ""; + } + + /// + /// Returns an OpenCL string for the initialization of the fields in this variation + /// that change during iterations. + /// Note these are different than regular variation parameters, + /// and thus require a completely different solution. + /// + /// + virtual string StateInitOpenCLString() const + { + return ""; + } + /// /// Return the name and weight of the variation as a string. /// @@ -1274,6 +1340,12 @@ public: /// The OpenCL string to perform the equivalent calculation on the GPU in OpenCL virtual string OpenCLString() const { return ""; } + /// + /// If the OpenCL string depends on any global functions specific to this variation, return their names. + /// + /// The names for global OpenCL functions specific to this variation + virtual vector OpenCLGlobalFuncNames() const { return vector(); } + /// /// If the OpenCL string depends on any functions specific to this variation, return them. /// @@ -1389,6 +1461,7 @@ template class ParametricVariation; /// Each of these takes the form of a name string and a pointer to a value. /// Also, some of them can be considered precalculated values, rather than /// formal parameters. +/// Further, some can change state between iterations. /// This class encapsulates a single parameter. /// Template argument expected to be float or double. /// @@ -1409,7 +1482,7 @@ public: /// /// Constructor for a precalc param that takes arguments. /// - /// Whether the parameter is actually a precalculated value. Default: false. + /// Whether the parameter is actually a precalculated value. Always true. /// A pointer to the parameter /// The name of the parameter ParamWithName(bool isPrecalc, @@ -1419,6 +1492,21 @@ public: Init(param, name, 0, REAL, TLOW, TMAX, true); } + /// + /// Constructor for a state param that takes arguments. + /// + /// Whether the parameter is actually a precalculated value. Always true. + /// Whether the parameter changes state between iterations. Always true. + /// A pointer to the parameter + /// The name of the parameter + ParamWithName(bool isPrecalc, + bool isState, + T* param, + string name) + { + Init(param, name, 0, REAL, TLOW, TMAX, true, true); + } + /// /// Constructor for a non-precalc param that takes arguments. /// @@ -1466,6 +1554,7 @@ public: m_Type = paramWithName.m_Type; m_Name = paramWithName.m_Name; m_IsPrecalc = paramWithName.m_IsPrecalc; + m_IsState = paramWithName.m_IsState; } return *this; @@ -1481,7 +1570,8 @@ public: /// The minimum value the parameter can be /// The maximum value the parameter can be /// Whether the parameter is actually a precalculated value. Default: false. - void Init(T* param, const string& name, T def = 0, eParamType type = REAL, T min = TLOW, T max = TMAX, bool isPrecalc = false) + /// Whether the parameter changes state between iterations. Default: false. + void Init(T* param, const string& name, T def = 0, eParamType type = REAL, T min = TLOW, T max = TMAX, bool isPrecalc = false, bool isState = false) { m_Param = param; m_Def = def; @@ -1490,6 +1580,7 @@ public: m_Type = type; m_Name = name; m_IsPrecalc = isPrecalc; + m_IsState = isState; Set(m_Def);//Initial value. } @@ -1569,7 +1660,8 @@ public: << "Param Min: " << m_Min << endl << "Param Max: " << m_Max << endl << "Param Type: " << m_Type << endl - << "Is Precalc: " << m_IsPrecalc << endl; + << "Is Precalc: " << m_IsPrecalc << endl + << "Is State: " << m_IsState << endl; return ss.str(); } @@ -1585,6 +1677,7 @@ public: eParamType Type() const { return m_Type; } string Name() const { return m_Name; } bool IsPrecalc() const { return m_IsPrecalc; } + bool IsState() const { return m_IsState; } private: T* m_Param;//Pointer to the parameter value. @@ -1594,6 +1687,7 @@ private: eParamType m_Type;//The type of the parameter. string m_Name;//Name of the parameter. bool m_IsPrecalc;//Whether the parameter is actually a precalculated value. + bool m_IsState;//Whether the parameter changes state between iterations. This is also considered precalc. }; /// @@ -1694,7 +1788,7 @@ public: /// Get a pointer to a parameter value with the specified name. /// /// The name to search for - /// A pointer to the parameter value if the name matched, else false. + /// A pointer to the parameter value if the name matched, else null. T* GetParam(const char* name) const { for (auto& param : m_Params) @@ -1808,11 +1902,35 @@ public: return vec; } + /// + /// Returns an OpenCL string for the fields in this variation + /// that change during iterations. + /// Note these are different than regular variation parameters, + /// and thus require a completely different solution. + /// + /// + virtual string StateOpenCLString() const override + { + ostringstream os, os2; + os2 << "_" << XformIndexInEmber() << ";"; + string index = os2.str(); + + for (auto& param : m_Params) + { + if (param.IsState()) + { + os << "\n\treal_t " << param.Name() << index; + } + } + + return os.str(); + } + /// /// Return the name, weight and parameters of the variation as a string. /// /// The name, weight and parameters of the variation - virtual string ToString() const + virtual string ToString() const override { ostringstream ss; @@ -1849,6 +1967,20 @@ protected: } } + /// + /// Get a pointer to the underlying ParamWithName object with the specified name. + /// + /// The name to search for + /// A pointer to the underlying ParamWithName object if the name matched, else null. + const ParamWithName* GetUnderlyingParam(const char* name) const + { + for (auto& param : m_Params) + if (!_stricmp(param.Name().c_str(), name)) + return ¶m; + + return nullptr; + } + vector> m_Params;//The params pointer vector which stores pointer to parameter members of derived classes. }; diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h index 6abd57c..a63a925 100644 --- a/Source/Ember/VariationList.h +++ b/Source/Ember/VariationList.h @@ -5,6 +5,7 @@ #include "Variations03.h" #include "Variations04.h" #include "Variations05.h" +#include "Variations06.h" #include "VariationsDC.h" /// @@ -35,7 +36,7 @@ public: /// VariationList() { - m_Variations.reserve(900);//Change this as the list grows. + m_Variations.reserve(eVariationId::LAST_VAR); ADDPREPOSTREGVAR(Linear) ADDPREPOSTREGVAR(Sinusoidal) ADDPREPOSTREGVAR(Spherical) @@ -315,6 +316,8 @@ public: ADDPREPOSTREGVAR(Ho) ADDPREPOSTREGVAR(Julia3Dq) ADDPREPOSTREGVAR(Line) + ADDPREPOSTREGVAR(Loonie2) + ADDPREPOSTREGVAR(Loonie3) ADDPREPOSTREGVAR(Loonie3D) ADDPREPOSTREGVAR(Mcarpet) ADDPREPOSTREGVAR(Waves23D) @@ -329,16 +332,25 @@ public: ADDPREPOSTREGVAR(Falloff2) ADDPREPOSTREGVAR(Falloff3) ADDPREPOSTREGVAR(Xtrb) + ADDPREPOSTREGVAR(Hexaplay3D) + ADDPREPOSTREGVAR(Hexnix3D) + ADDPREPOSTREGVAR(Hexcrop) + ADDPREPOSTREGVAR(Hexes) + ADDPREPOSTREGVAR(Nblur) + ADDPREPOSTREGVAR(Octapol) + ADDPREPOSTREGVAR(Crob) + ADDPREPOSTREGVAR(BubbleT3D) + ADDPREPOSTREGVAR(Synth) //ADDPREPOSTREGVAR(LinearXZ) //ADDPREPOSTREGVAR(LinearYZ) //DC are special. - m_Variations.push_back(new DCBubbleVariation()); + ADDPREPOSTREGVAR(DCBubble) ADDPREPOSTREGVAR(DCCarpet) ADDPREPOSTREGVAR(DCCube) - m_Variations.push_back(new DCCylinderVariation()); + ADDPREPOSTREGVAR(DCCylinder) ADDPREPOSTREGVAR(DCGridOut) - m_Variations.push_back(new DCLinearVariation()); + ADDPREPOSTREGVAR(DCLinear) ADDPREPOSTREGVAR(DCTriangle) ADDPREPOSTREGVAR(DCZTransl) @@ -348,6 +360,7 @@ public: m_RegVariations.reserve(m_Variations.size() / 3); m_PreVariations.reserve(m_Variations.size() / 3); m_PostVariations.reserve(m_Variations.size() / 3); + m_ParametricVariations.reserve(size_t(m_Variations.size() * .90));//This is a rough guess at how many are parametric. for (auto var : m_Variations) if (var->VarType() == VARTYPE_REG) m_RegVariations.push_back(var); for (auto var : m_Variations) if (var->VarType() == VARTYPE_PRE) m_PreVariations.push_back(var); diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h index 10720b7..c7af86f 100644 --- a/Source/Ember/Variations01.h +++ b/Source/Ember/Variations01.h @@ -58,8 +58,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * sin(helper.In.x); - helper.Out.y = m_Weight * sin(helper.In.y); + helper.Out.x = m_Weight * std::sin(helper.In.x); + helper.Out.y = m_Weight * std::sin(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } @@ -118,6 +118,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -208,6 +213,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -264,8 +274,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * helper.m_PrecalcSqrtSumSquares * sin(helper.m_PrecalcAtanxy + helper.m_PrecalcSqrtSumSquares); - helper.Out.y = m_Weight * helper.m_PrecalcSqrtSumSquares * cos(helper.m_PrecalcAtanxy - helper.m_PrecalcSqrtSumSquares); + helper.Out.x = m_Weight * helper.m_PrecalcSqrtSumSquares * std::sin(helper.m_PrecalcAtanxy + helper.m_PrecalcSqrtSumSquares); + helper.Out.y = m_Weight * helper.m_PrecalcSqrtSumSquares * std::cos(helper.m_PrecalcAtanxy - helper.m_PrecalcSqrtSumSquares); helper.Out.z = m_Weight * helper.In.z; } @@ -305,8 +315,8 @@ public: T a = helper.m_PrecalcSqrtSumSquares * helper.m_PrecalcAtanxy; T r = m_Weight * helper.m_PrecalcSqrtSumSquares; - helper.Out.x = r * sin(a); - helper.Out.y = (-r) * cos(a); + helper.Out.x = r * std::sin(a); + helper.Out.y = (-r) * std::cos(a); helper.Out.z = m_Weight * helper.In.z; } @@ -353,8 +363,8 @@ public: T val = T(M_PI) * helper.m_PrecalcSqrtSumSquares; T r = m_WeightByPI * helper.m_PrecalcAtanxy; - helper.Out.x = sin(val) * r; - helper.Out.y = cos(val) * r; + helper.Out.x = std::sin(val) * r; + helper.Out.y = std::cos(val) * r; helper.Out.z = m_Weight * helper.In.z; } @@ -416,8 +426,8 @@ public: T r = Zeps(helper.m_PrecalcSqrtSumSquares); T r1 = m_Weight / r; - helper.Out.x = r1 * (helper.m_PrecalcCosa + sin(r)); - helper.Out.y = r1 * (helper.m_PrecalcSina - cos(r)); + helper.Out.x = r1 * (helper.m_PrecalcCosa + std::sin(r)); + helper.Out.y = r1 * (helper.m_PrecalcSina - std::cos(r)); helper.Out.z = m_Weight * helper.In.z; } @@ -437,6 +447,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -478,6 +493,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -497,8 +517,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * helper.m_PrecalcSina * cos(helper.m_PrecalcSqrtSumSquares); - helper.Out.y = m_Weight * helper.m_PrecalcCosa * sin(helper.m_PrecalcSqrtSumSquares); + helper.Out.x = m_Weight * helper.m_PrecalcSina * std::cos(helper.m_PrecalcSqrtSumSquares); + helper.Out.y = m_Weight * helper.m_PrecalcCosa * std::sin(helper.m_PrecalcSqrtSumSquares); helper.Out.z = m_Weight * helper.In.z; } @@ -540,8 +560,8 @@ public: { T a = helper.m_PrecalcAtanxy; T r = helper.m_PrecalcSqrtSumSquares; - T n0 = sin(a + r); - T n1 = cos(a - r); + T n0 = std::sin(a + r); + T n1 = std::cos(a - r); T m0 = n0 * n0 * n0 * r; T m1 = n1 * n1 * n1 * r; @@ -598,8 +618,8 @@ public: if (rand.RandBit()) a += T(M_PI); - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -694,8 +714,8 @@ public: { T c10 = m_Xform->m_Affine.B(); T c11 = m_Xform->m_Affine.E(); - T nx = helper.In.x + c10 * sin(helper.In.y * m_Dx2); - T ny = helper.In.y + c11 * sin(helper.In.x * m_Dy2); + T nx = helper.In.x + c10 * std::sin(helper.In.y * m_Dx2); + T ny = helper.In.y + c11 * std::sin(helper.In.x * m_Dy2); helper.Out.x = m_Weight * nx; helper.Out.y = m_Weight * ny; @@ -817,8 +837,8 @@ public: { T dx = SafeTan(3 * helper.In.y); T dy = SafeTan(3 * helper.In.x); - T nx = helper.In.x + m_Xform->m_Affine.C() * sin(dx); - T ny = helper.In.y + m_Xform->m_Affine.F() * sin(dy); + T nx = helper.In.x + m_Xform->m_Affine.C() * std::sin(dx); + T ny = helper.In.y + m_Xform->m_Affine.F() * std::sin(dy); helper.Out.x = m_Weight * nx; helper.Out.y = m_Weight * ny; @@ -864,11 +884,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T dx = m_Weight * exp(helper.In.x - 1); + T dx = m_Weight * std::exp(helper.In.x - 1); T dy = T(M_PI) * helper.In.y; - helper.Out.x = dx * cos(dy); - helper.Out.y = dx * sin(dy); + helper.Out.x = dx * std::cos(dy); + helper.Out.y = dx * std::sin(dy); helper.Out.z = m_Weight * helper.In.z; } @@ -911,7 +931,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = m_Weight * pow(helper.m_PrecalcSqrtSumSquares, helper.m_PrecalcSina); + T r = m_Weight * std::pow(helper.m_PrecalcSqrtSumSquares, helper.m_PrecalcSina); helper.Out.x = r * helper.m_PrecalcCosa; helper.Out.y = r * helper.m_PrecalcSina; @@ -953,8 +973,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.In.x * T(M_PI); - T nx = cos(a) * cosh(helper.In.y); - T ny = -sin(a) * sinh(helper.In.y); + T nx = std::cos(a) * std::cosh(helper.In.y); + T ny = -std::sin(a) * std::sinh(helper.In.y); helper.Out.x = m_Weight * nx; helper.Out.y = m_Weight * ny; @@ -1028,6 +1048,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -1061,8 +1086,8 @@ public: T r = m_Weight * helper.m_PrecalcSqrtSumSquares; a += (fmod(a + dy, dx) > dx2) ? -dx2 : dx2; - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -1085,6 +1110,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -1111,7 +1141,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = helper.m_PrecalcSqrtSumSquares * (m_BlobLow + m_BlobDiff * (T(0.5) + T(0.5) * sin(m_BlobWaves * helper.m_PrecalcAtanxy))); + T r = helper.m_PrecalcSqrtSumSquares * (m_BlobLow + m_BlobDiff * (T(0.5) + T(0.5) * std::sin(m_BlobWaves * helper.m_PrecalcAtanxy))); helper.Out.x = m_Weight * helper.m_PrecalcSina * r; helper.Out.y = m_Weight * helper.m_PrecalcCosa * r; @@ -1194,10 +1224,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T nx1 = cos(m_PdjB * helper.In.x); - T nx2 = sin(m_PdjC * helper.In.x); - T ny1 = sin(m_PdjA * helper.In.y); - T ny2 = cos(m_PdjD * helper.In.y); + T nx1 = std::cos(m_PdjB * helper.In.x); + T nx2 = std::sin(m_PdjC * helper.In.x); + T ny1 = std::sin(m_PdjA * helper.In.y); + T ny2 = std::cos(m_PdjD * helper.In.y); helper.Out.x = m_Weight * (ny1 - nx1); helper.Out.y = m_Weight * (nx2 - ny2); @@ -1300,8 +1330,8 @@ public: else a = a + m_Fan2Dx2; - helper.Out.x = r * sin(a); - helper.Out.y = r * cos(a); + helper.Out.x = r * std::sin(a); + helper.Out.y = r * std::cos(a); helper.Out.z = m_Weight * helper.In.z; } @@ -1534,9 +1564,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * sin(helper.In.x); + helper.Out.x = m_Weight * std::sin(helper.In.x); helper.Out.y = m_Weight * helper.In.y; - helper.Out.z = m_Weight * cos(helper.In.x); + helper.Out.z = m_Weight * std::cos(helper.In.x); } virtual string OpenCLString() const override @@ -1601,12 +1631,17 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { T angle = m_Angle * T(M_PI) / 2; - m_Vsin = sin(angle); - m_VfCos = m_Dist * cos(angle); + m_Vsin = std::sin(angle); + m_VfCos = m_Dist * std::cos(angle); } virtual void Random(QTIsaac& rand) override @@ -1650,8 +1685,8 @@ public: T tempr = rand.Frand01() * M_2PI; T r = m_Weight * rand.Frand01(); - helper.Out.x = helper.In.x * r * cos(tempr); - helper.Out.y = helper.In.y * r * sin(tempr); + helper.Out.x = helper.In.x * r * std::cos(tempr); + helper.Out.y = helper.In.y * r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; } @@ -1690,10 +1725,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T tempr = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand(ISAAC_INT(m_Rn))) / m_Power; - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); - helper.Out.x = r * cos(tempr); - helper.Out.y = r * sin(tempr); + helper.Out.x = r * std::cos(tempr); + helper.Out.y = r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; } @@ -1770,15 +1805,15 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { int rnd = int(m_Rn * rand.Frand01()); - T tempr, r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); + T tempr, r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); if ((rnd & 1) == 0) tempr = (M_2PI * rnd + helper.m_PrecalcAtanyx) / m_Power; else tempr = (M_2PI * rnd - helper.m_PrecalcAtanyx) / m_Power; - helper.Out.x = r * cos(tempr); - helper.Out.y = r * sin(tempr); + helper.Out.x = r * std::cos(tempr); + helper.Out.y = r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; //int rnd = (int)(m_Rn * rand.Frand01()); @@ -1892,8 +1927,8 @@ public: T tempr = rand.Frand01() * M_2PI; T r = m_Weight * rand.Frand01(); - helper.Out.x = r * cos(tempr); - helper.Out.y = r * sin(tempr); + helper.Out.x = r * std::cos(tempr); + helper.Out.y = r * std::sin(tempr); helper.Out.z = m_Weight * helper.In.z; } @@ -1931,8 +1966,8 @@ public: T angle = rand.Frand01() * M_2PI; T r = m_Weight * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); - helper.Out.x = r * cos(angle); - helper.Out.y = r * sin(angle); + helper.Out.x = r * std::cos(angle); + helper.Out.y = r * std::sin(angle); helper.Out.z = m_Weight * helper.In.z; } @@ -1979,8 +2014,8 @@ public: T tempa = helper.m_PrecalcAtanyx + m_Spin * rndG; T rz = m_Zoom * rndG - 1; - helper.Out.x = ra * cos(tempa) + rz * helper.In.x; - helper.Out.y = ra * sin(tempa) + rz * helper.In.y; + helper.Out.x = ra * std::cos(tempa) + rz * helper.In.x; + helper.Out.y = ra * std::sin(tempa) + rz * helper.In.y; helper.Out.z = m_Weight * helper.In.z; } @@ -2055,8 +2090,8 @@ public: T a = m_Rotation + M_2PI * (sl + rand.Frand01() * m_Thickness) / m_Slices; T r = m_Weight * rand.Frand01(); - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); } virtual string OpenCLString() const override @@ -2127,14 +2162,14 @@ public: if ((helper.In.x == 0) && (helper.In.y == 0)) rFactor = 0; else - rFactor = pow(helper.m_PrecalcSumSquares, m_CPower); + rFactor = std::pow(helper.m_PrecalcSumSquares, m_CPower); T phi = helper.m_PrecalcAtanyx - m_CSides * Floor(helper.m_PrecalcAtanyx * m_CSidesInv); if (phi > T(0.5) * m_CSides) phi -= m_CSides; - T amp = (m_Corners * (1 / cos(phi) - 1) + m_Circle) * m_Weight * rFactor; + T amp = (m_Corners * (1 / std::cos(phi) - 1) + m_Circle) * m_Weight * rFactor; helper.Out.x = amp * helper.In.x; helper.Out.y = amp * helper.In.y; @@ -2269,6 +2304,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { m_C22 = 2 * m_C2; @@ -2427,7 +2467,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * sin(helper.In.x) / cos(helper.In.y); + helper.Out.x = m_Weight * std::sin(helper.In.x) / std::cos(helper.In.y); helper.Out.y = m_Weight * SafeTan(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } @@ -2497,8 +2537,8 @@ public: T r = m_Weight / Zeps(helper.m_PrecalcSumSquares); T tanr = m_Weight * SafeTan(ang) * r; - helper.Out.x = tanr * cos(helper.In.x); - helper.Out.y = tanr * sin(helper.In.y); + helper.Out.x = tanr * std::cos(helper.In.x); + helper.Out.y = tanr * std::sin(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } @@ -2519,6 +2559,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -2576,7 +2621,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T r = m_Weight * helper.m_PrecalcSqrtSumSquares; - T cr = cos(r); + T cr = std::cos(r); T icr = 1 / cr; helper.Out.x = m_Weight * helper.In.x; @@ -2630,7 +2675,7 @@ public: T sinr, cosr, diff; sincos(r, &sinr, &cosr); - diff = log10(sinr * sinr) + cosr; + diff = std::log10(sinr * sinr) + cosr; if (BadVal(diff)) diff = -30.0; @@ -2698,6 +2743,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -2820,14 +2870,14 @@ public: { T theta = m_Pm4 * helper.m_PrecalcAtanyx + T(M_PI_4); - T t1 = fabs(cos(theta)); - t1 = pow(t1, m_N2); + T t1 = fabs(std::cos(theta)); + t1 = std::pow(t1, m_N2); - T t2 = fabs(sin(theta)); - t2 = pow(t2, m_N3); + T t2 = fabs(std::sin(theta)); + t2 = std::pow(t2, m_N3); T r = m_Weight * ((m_Rnd * rand.Frand01() + (1 - m_Rnd) * helper.m_PrecalcSqrtSumSquares) - m_Holes) - * pow(t1 + t2, m_PNeg1N1) / helper.m_PrecalcSqrtSumSquares; + * std::pow(t1 + t2, m_PNeg1N1) / helper.m_PrecalcSqrtSumSquares; helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; @@ -2925,7 +2975,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T theta = helper.m_PrecalcAtanyx; - T r = m_Weight * (rand.Frand01() - m_Holes) * cos(m_Petals * theta) / helper.m_PrecalcSqrtSumSquares; + T r = m_Weight * (rand.Frand01() - m_Holes) * std::cos(m_Petals * theta) / helper.m_PrecalcSqrtSumSquares; helper.Out.x = r * helper.In.x; helper.Out.y = r * helper.In.y; @@ -3241,7 +3291,7 @@ public: } else { - helper.Out.x = m_V4 * log((t + x2) / (t - x2)); + helper.Out.x = m_V4 * std::log((t + x2) / (t - x2)); helper.Out.y = m_V * y; helper.Out.z = m_Weight * helper.In.z; } @@ -3497,6 +3547,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -3651,12 +3706,12 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.m_PrecalcAtanyx; - T lnr = T(0.5) * log(helper.m_PrecalcSumSquares); + T lnr = T(0.5) * std::log(helper.m_PrecalcSumSquares); T angle = m_C * a + m_D * lnr + m_Ang * Floor(m_Power * rand.Frand01()); - T m = m_Weight * exp(m_C * lnr - m_D * a); + T m = m_Weight * std::exp(m_C * lnr - m_D * a); - helper.Out.x = m * cos(angle); - helper.Out.y = m * sin(angle); + helper.Out.x = m * std::cos(angle); + helper.Out.y = m * std::sin(angle); helper.Out.z = m_Weight * helper.In.z; } @@ -3740,8 +3795,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * helper.In.x + m_XAmpV * exp(-helper.In.y * helper.In.y * m_XLengthV); - helper.Out.y = m_Weight * helper.In.y + m_YAmpV * exp(-helper.In.x * helper.In.x * m_YLengthV); + helper.Out.x = m_Weight * helper.In.x + m_XAmpV * std::exp(-helper.In.y * helper.In.y * m_XLengthV); + helper.Out.y = m_Weight * helper.In.y + m_YAmpV * std::exp(-helper.In.x * helper.In.x * m_YLengthV); helper.Out.z = m_Weight * helper.In.z; } @@ -3830,8 +3885,8 @@ public: T r1 = std::sqrt(tmp + tmp2); T r2 = std::sqrt(tmp - tmp2); T xmax = (r1 + r2) * T(0.5); - T a1 = log(xmax + std::sqrt(xmax - 1)); - T a2 = -acos(Clamp(helper.In.x / xmax, -1, 1)); + T a1 = std::log(xmax + std::sqrt(xmax - 1)); + T a2 = -std::acos(Clamp(helper.In.x / xmax, -1, 1)); T w = m_Weight / T(11.57034632);//This is an interesting magic number. T snv, csv, snhu, cshu; @@ -3860,7 +3915,7 @@ public: << "\t\treal_t r2 = sqrt(tmp - tmp2);\n" << "\t\treal_t xmax = (r1 + r2) * (real_t)(0.5);\n" << "\t\treal_t a1 = log(xmax + sqrt(xmax - (real_t)(1.0)));\n" - << "\t\treal_t a2 = -acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t a2 = -acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\t\treal_t w = xform->m_VariationWeights[" << varIndex << "] / (real_t)(11.57034632);\n" << "\t\treal_t snv = sin(a1);\n" << "\t\treal_t csv = cos(a1);\n" @@ -3916,9 +3971,9 @@ public: helper.Out.x = w * atan2(a, b); if (helper.In.y > 0) - helper.Out.y = w * log(xmax + ssx); + helper.Out.y = w * std::log(xmax + ssx); else - helper.Out.y = -(w * log(xmax + ssx)); + helper.Out.y = -(w * std::log(xmax + ssx)); helper.Out.z = m_Weight * helper.In.z; } @@ -3998,12 +4053,12 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.m_PrecalcAtanyx; - T lnr = T(0.5) * log(helper.m_PrecalcSumSquares); - T m = m_Weight * exp(m_C * lnr - m_D * a); + T lnr = T(0.5) * std::log(helper.m_PrecalcSumSquares); + T m = m_Weight * std::exp(m_C * lnr - m_D * a); T n = m_C * a + m_D * lnr; - helper.Out.x = m * cos(n); - helper.Out.y = m * sin(n); + helper.Out.x = m * std::cos(n); + helper.Out.y = m * std::sin(n); helper.Out.z = m_Weight * helper.In.z; } @@ -4085,7 +4140,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T expx = exp(helper.In.x) * T(0.5); + T expx = std::exp(helper.In.x) * T(0.5); T expnx = T(0.25) / expx; T sn, cn, tmp; @@ -4119,6 +4174,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -4145,8 +4205,8 @@ public: { T a = atan2(y, x) + m_Spin + m_Twist * (m_Weight - r); - helper.Out.x = m_Weight * (r * cos(a) + m_X);//Fix to make it colapse to 0 when weight is 0.//SMOULDER - helper.Out.y = m_Weight * (r * sin(a) - m_Y); + helper.Out.x = m_Weight * (r * std::cos(a) + m_X);//Fix to make it colapse to 0 when weight is 0.//SMOULDER + helper.Out.y = m_Weight * (r * std::sin(a) - m_Y); } else { @@ -4197,6 +4257,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual bool SetParamVal(const char* name, T val) override { if (!_stricmp(name, "lazysusan_spin")) @@ -4431,9 +4496,9 @@ public: T t; if (m_Damping == 0.0) - t = m_Amplitude * cos(m_2PiFreq * helper.In.x) + m_Separation; + t = m_Amplitude * std::cos(m_2PiFreq * helper.In.x) + m_Separation; else - t = m_Amplitude * exp(-fabs(helper.In.x) * m_Damping) * cos(m_2PiFreq * helper.In.x) + m_Separation; + t = m_Amplitude * std::exp(-fabs(helper.In.x) * m_Damping) * std::cos(m_2PiFreq * helper.In.x) + m_Separation; if (fabs(helper.In.y) <= t) { @@ -4537,7 +4602,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { helper.Out.x = m_Vvar * helper.m_PrecalcAtanxy; - helper.Out.y = m_Vvar2 * log(helper.m_PrecalcSumSquares); + helper.Out.y = m_Vvar2 * std::log(helper.m_PrecalcSumSquares); helper.Out.z = m_Weight * helper.In.z; } @@ -4596,8 +4661,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * (helper.In.x + m_X * sin(SafeTan(helper.In.y * m_C))); - helper.Out.y = m_Weight * (helper.In.y + m_Y * sin(SafeTan(helper.In.x * m_C))); + helper.Out.x = m_Weight * (helper.In.x + m_X * std::sin(SafeTan(helper.In.y * m_C))); + helper.Out.y = m_Weight * (helper.In.y + m_Y * std::sin(SafeTan(helper.In.x * m_C))); helper.Out.z = m_Weight * helper.In.z; } @@ -4691,6 +4756,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { m_InvWeight = 1 / Zeps(m_Weight); @@ -5057,8 +5127,8 @@ public: a = a * m_CompFac + c * m_Angle; r = m_Weight * (r + m_Hole); - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -5139,14 +5209,14 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); int tRand = int(m_Rn * rand.Frand01()); T a = (helper.m_PrecalcAtanyx + M_2PI * tRand) / m_Power; T c = T(Floor((m_Count * a + T(M_PI)) * T(M_1_PI) * T(0.5))); a = a * m_Cf + c * m_Angle; - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -5242,8 +5312,8 @@ public: a = a * compFac + c * m_Angle; r = m_Weight * (r + m_Hole); - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -5274,6 +5344,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Random(QTIsaac& rand) override { m_Angle = T(M_PI) * rand.Frand01(); @@ -5324,8 +5399,8 @@ public: else a = helper.m_PrecalcAtanyx + m_Outside / (m_Weight - r); - helper.Out.x = m_Weight * r * cos(a); - helper.Out.y = m_Weight * r * sin(a); + helper.Out.x = m_Weight * r * std::cos(a); + helper.Out.y = m_Weight * r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -5392,9 +5467,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * (helper.In.x + m_ScaleX * sin(helper.In.y * m_FreqX)); - helper.Out.y = m_Weight * (helper.In.y + m_ScaleY * sin(helper.In.x * m_FreqY)); - helper.Out.z = m_Weight * (helper.In.z + m_ScaleZ * sin(helper.m_PrecalcSqrtSumSquares * m_FreqZ)); + helper.Out.x = m_Weight * (helper.In.x + m_ScaleX * std::sin(helper.In.y * m_FreqX)); + helper.Out.y = m_Weight * (helper.In.y + m_ScaleY * std::sin(helper.In.x * m_FreqY)); + helper.Out.z = m_Weight * (helper.In.z + m_ScaleZ * std::sin(helper.m_PrecalcSqrtSumSquares * m_FreqZ)); } virtual string OpenCLString() const override @@ -5465,10 +5540,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T expe = m_Weight * exp(helper.In.x); + T expe = m_Weight * std::exp(helper.In.x); - helper.Out.x = expe * cos(helper.In.y); - helper.Out.y = expe * sin(helper.In.y); + helper.Out.x = expe * std::cos(helper.In.y); + helper.Out.y = expe * std::sin(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } @@ -5505,7 +5580,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * log(helper.m_PrecalcSumSquares) * m_Denom; + helper.Out.x = m_Weight * std::log(helper.m_PrecalcSumSquares) * m_Denom; helper.Out.y = m_Weight * helper.m_PrecalcAtanyx; helper.Out.z = m_Weight * helper.In.z; } @@ -5530,7 +5605,7 @@ public: virtual void Precalc() override { - m_Denom = T(0.5) / log(m_Base); + m_Denom = T(0.5) / std::log(m_Base); } protected: @@ -5561,8 +5636,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * sin(helper.In.x) * cosh(helper.In.y); - helper.Out.y = m_Weight * cos(helper.In.x) * sinh(helper.In.y); + helper.Out.x = m_Weight * std::sin(helper.In.x) * cosh(helper.In.y); + helper.Out.y = m_Weight * std::cos(helper.In.x) * sinh(helper.In.y); helper.Out.z = m_Weight * helper.In.z; } @@ -5595,8 +5670,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { //clamp fabs x and y to 7.104760e+002 for cosh, and |x| 7.104760e+002 for sinh - helper.Out.x = m_Weight * cos(helper.In.x) * cosh(helper.In.y); - helper.Out.y = -(m_Weight * sin(helper.In.x) * sinh(helper.In.y)); + helper.Out.x = m_Weight * std::cos(helper.In.x) * cosh(helper.In.y); + helper.Out.y = -(m_Weight * std::sin(helper.In.x) * sinh(helper.In.y)); helper.Out.z = m_Weight * helper.In.z; } @@ -5721,9 +5796,9 @@ public: T cscsin, csccos, cscsinh, csccosh, cscden; sincos(helper.In.x, &cscsin, &csccos); - cscsinh = sinh(helper.In.y); - csccosh = cosh(helper.In.y); - cscden = 2 / (cosh(2 * helper.In.y) - cos(2 * helper.In.x)); + cscsinh = std::sinh(helper.In.y); + csccosh = std::cosh(helper.In.y); + cscden = 2 / (std::cosh(2 * helper.In.y) - std::cos(2 * helper.In.x)); helper.Out.x = m_Weight * cscden * cscsin * csccosh; helper.Out.y = -(m_Weight * cscden * csccos * cscsinh); helper.Out.z = m_Weight * helper.In.z; @@ -5987,9 +6062,9 @@ public: T cschsin, cschcos, cschsinh, cschcosh, cschden; sincos(helper.In.y, &cschsin, &cschcos); - cschsinh = sinh(helper.In.x); - cschcosh = cosh(helper.In.x); - cschden = 2 / (cosh(2 * helper.In.x) - cos(2 * helper.In.y)); + cschsinh = std::sinh(helper.In.x); + cschcosh = std::cosh(helper.In.x); + cschden = 2 / (std::cosh(2 * helper.In.x) - std::cos(2 * helper.In.y)); helper.Out.x = m_Weight * cschden * cschsinh * cschcos; helper.Out.y = -(m_Weight * cschden * cschcosh * cschsin); helper.Out.z = m_Weight * helper.In.z; @@ -6077,8 +6152,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T s = sin(m_Freq * helper.In.x); - T t = sin(m_Freq * helper.In.y); + T s = std::sin(m_Freq * helper.In.x); + T t = std::sin(m_Freq * helper.In.y); T dy = helper.In.y + m_AugerWeight * (m_Scale * s / 2 + fabs(helper.In.y) * s); T dx = helper.In.x + m_AugerWeight * (m_Scale * t / 2 + fabs(helper.In.x) * t); @@ -6166,10 +6241,9 @@ public: T avgr = m_Weight * (m_Spr * std::sqrt(std::sqrt(yy + SQR(xpw)) / frac)); T avga = (atan2(helper.In.y, xmw) - atan2(helper.In.y, xpw)) * T(0.5); - helper.Out.x = avgr * cos(avga); - helper.Out.y = avgr * sin(avga); + helper.Out.x = avgr * std::cos(avga); + helper.Out.y = avgr * std::sin(avga); helper.Out.z = helper.In.z; - //helper.Out.z = m_Weight * helper.In.z; } virtual string OpenCLString() const override diff --git a/Source/Ember/Variations02.h b/Source/Ember/Variations02.h index 52f45a5..b84bf43 100644 --- a/Source/Ember/Variations02.h +++ b/Source/Ember/Variations02.h @@ -58,12 +58,12 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T theta = helper.m_PrecalcAtanyx; - T t = (rand.Frand01() * m_Thickness) * (1 / cos(m_N * theta)) - m_Holes; + T t = (rand.Frand01() * m_Thickness) * (1 / std::cos(m_N * theta)) - m_Holes; if (fabs(t) != 0) { - helper.Out.x = m_Weight * t * cos(theta); - helper.Out.y = m_Weight * t * sin(theta); + helper.Out.x = m_Weight * t * std::cos(theta); + helper.Out.y = m_Weight * t * std::sin(theta); helper.Out.z = 0; } else @@ -170,8 +170,8 @@ public: r = (SQR(lx) + SQR(ly)) / m_R2; T theta = m_BwrapsInnerTwist * (1 - r) + m_BwrapsOuterTwist * r; - T s = sin(theta); - T c = cos(theta); + T s = std::sin(theta); + T c = std::cos(theta); vx = cx + c * lx + s * ly; vy = cy - s * lx + c * ly; @@ -336,8 +336,8 @@ public: T r = m_Weight * side; T val = T(M_PI_4) * perimeter / side - T(M_PI_4); - T sina = sin(val); - T cosa = cos(val); + T sina = std::sin(val); + T cosa = std::cos(val); helper.Out.x = r * cosa; helper.Out.y = r * sina; @@ -716,10 +716,10 @@ public: { if (m_Bcbw != 0) { - T ang = atan2(y, x); + T ang = std::atan2(y, x); T omega = (T(0.2) * m_Bcbw * rand.Frand01()) + 1; - T px = omega * cos(ang); - T py = omega * sin(ang); + T px = omega * std::cos(ang); + T py = omega * std::sin(ang); helper.Out.x = m_Weight * px; helper.Out.y = m_Weight * py; } @@ -1134,10 +1134,10 @@ public: T angle = rand.Frand01() * M_2PI; T r = m_Weight * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); T angle2 = rand.Frand01() * T(M_PI); - T sina = sin(angle); - T cosa = cos(angle); - T sinb = sin(angle2); - T cosb = cos(angle2); + T sina = std::sin(angle); + T cosa = std::cos(angle); + T sinb = std::sin(angle2); + T cosb = std::cos(angle2); helper.Out.x = r * sinb * cosa; helper.Out.y = r * sinb * sina; @@ -1202,6 +1202,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -1254,6 +1259,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { m_C2x = 2 * m_Cx; @@ -1305,13 +1315,13 @@ public: { T r = helper.m_PrecalcSqrtSumSquares; T temp = r * m_Pi; - T sr = sin(temp); - T cr = cos(temp); + T sr = std::sin(temp); + T cr = std::cos(temp); T vv = m_Weight * helper.m_PrecalcAtanxy / Zeps(m_Pi); helper.Out.x = vv * sr; helper.Out.y = vv * cr; - helper.Out.z = vv * (r * cos(helper.In.z)); + helper.Out.z = vv * (r * std::cos(helper.In.z)); } virtual string OpenCLString() const override @@ -1337,6 +1347,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -1519,7 +1534,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = m_Weight * std::sqrt(helper.m_PrecalcSumSquares + sin(helper.m_PrecalcAtanyx * m_A) + 1); + T r = m_Weight * std::sqrt(helper.m_PrecalcSumSquares + std::sin(helper.m_PrecalcAtanyx * m_A) + 1); helper.Out.x = r * helper.m_PrecalcCosa; helper.Out.y = r * helper.m_PrecalcSina; @@ -1580,7 +1595,7 @@ public: int isXY = int(LRint(helper.In.x * m_Cs) + LRint(helper.In.y * m_Cs)); - if (isXY % 2) + if (isXY & 1) { dx = m_Ncx + rnx; dy = m_Ncy; @@ -1619,7 +1634,7 @@ public: << "\n" << "\t\tint isXY = (int)(LRint(vIn.x * " << cs << ") + LRint(vIn.y * " << cs << "));\n" << "\n" - << "\t\tif (isXY % 2)\n" + << "\t\tif (isXY & 1)\n" << "\t\t{\n" << "\t\t dx = " << ncx << " + rnx;\n" << "\t\t dy = " << ncy << ";\n" @@ -1638,6 +1653,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "LRint" }; + } + virtual void Precalc() override { m_Cs = 1 / Zeps(m_Size); @@ -1719,8 +1739,8 @@ public: r = m_Vvar4Pi * side + m_Hole; val = T(M_PI_4) * perimeter / side - T(M_PI_4); - helper.Out.x = r * cos(val); - helper.Out.y = r * sin(val); + helper.Out.x = r * std::cos(val); + helper.Out.y = r * std::sin(val); helper.Out.z = m_Weight * helper.In.z; } @@ -1832,8 +1852,8 @@ public: T r = m_Weight * (side + m_Hole); T val = T(M_PI_4) * perimeter / side - T(M_PI_4); - helper.Out.x = r * cos(val); - helper.Out.y = r * sin(val); + helper.Out.x = r * std::cos(val); + helper.Out.y = r * std::sin(val); helper.Out.z = m_Weight * helper.In.z; } @@ -1956,6 +1976,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Fabsmod", "Fosc", "Foscn", "Lerp" }; + } + virtual void Precalc() override { m_Ax = M_2PI * fabs(m_AmountX); @@ -2061,10 +2086,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T expor = exp(helper.In.x * m_K - helper.In.y * m_T); + T expor = std::exp(helper.In.x * m_K - helper.In.y * m_T); T temp = helper.In.x * m_T + helper.In.y * m_K; - T snv = sin(temp); - T csv = cos(temp); + T snv = std::sin(temp); + T csv = std::cos(temp); helper.Out.x = m_Weight * expor * csv; helper.Out.y = m_Weight * expor * snv; @@ -2098,7 +2123,7 @@ public: virtual void Precalc() override { - m_K = T(0.5) * log(Zeps(SQR(m_Real) + SQR(m_Imag)));//Original used 1e-300, which isn't representable with a float. + m_K = T(0.5) * std::log(Zeps(SQR(m_Real) + SQR(m_Imag)));//Original used 1e-300, which isn't representable with a float. m_T = atan2(m_Imag, m_Real); } @@ -2272,8 +2297,8 @@ public: temp = (helper.In.x * T(M_PI) + helper.In.y * m_NatLog) * -1; sincos(temp, &snum2, &cnum2); - T eradius1 = exp(helper.In.x * m_NatLog); - T eradius2 = exp((helper.In.x * m_NatLog - helper.In.y * T(M_PI)) * -1); + T eradius1 = std::exp(helper.In.x * m_NatLog); + T eradius2 = std::exp((helper.In.x * m_NatLog - helper.In.y * T(M_PI)) * -1); helper.Out.x = m_Weight * (eradius1 * cnum1 - eradius2 * cnum2) * m_Five; helper.Out.y = m_Weight * (eradius1 * snum1 - eradius2 * snum2) * m_Five; @@ -2310,7 +2335,7 @@ public: virtual void Precalc() override { m_Five = 1 / SQRT5; - m_NatLog = log(M_PHI); + m_NatLog = std::log(M_PHI); } protected: @@ -2351,8 +2376,8 @@ public: temp = (helper.In.x * T(M_PI) + helper.In.y * m_NatLog) * -1; sincos(temp, &snum2, &cnum2); - T eradius1 = m_Sc * exp(m_Sc2 * (helper.In.x * m_NatLog)); - T eradius2 = m_Sc * exp(m_Sc2 * ((helper.In.x * m_NatLog - helper.In.y * T(M_PI)) * -1)); + T eradius1 = m_Sc * std::exp(m_Sc2 * (helper.In.x * m_NatLog)); + T eradius2 = m_Sc * std::exp(m_Sc2 * ((helper.In.x * m_NatLog - helper.In.y * T(M_PI)) * -1)); helper.Out.x = m_Weight * (eradius1 * cnum1 - eradius2 * cnum2) * m_Five; helper.Out.y = m_Weight * (eradius1 * snum1 - eradius2 * snum2) * m_Five; @@ -2391,7 +2416,7 @@ public: virtual void Precalc() override { m_Five = 1 / SQRT5; - m_NatLog = log(M_PHI); + m_NatLog = std::log(M_PHI); } protected: @@ -2686,6 +2711,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "LRint" }; + } }; /// @@ -2704,7 +2734,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r, delta = pow(helper.m_PrecalcAtanyx / T(M_PI) + 1, m_A); + T r, delta = std::pow(helper.m_PrecalcAtanyx / T(M_PI) + 1, m_A); if (m_Inside != 0) r = m_Weight * delta / (helper.m_PrecalcSqrtSumSquares + delta); @@ -2814,7 +2844,7 @@ public: { T pa = 2 * T(M_PI) / m_P; T qa = 2 * T(M_PI) / m_Q; - T r = (1 - cos(pa)) / (cos(pa) + cos(qa)) + 1; + T r = (1 - std::cos(pa)) / (std::cos(pa) + std::cos(qa)) + 1; T a = m_N * pa; if (r > 0) @@ -2822,8 +2852,8 @@ public: else r = 1; - m_Real = r * cos(a); - m_Imag = r * sin(a); + m_Real = r * std::cos(a); + m_Imag = r * std::sin(a); } protected: @@ -2864,8 +2894,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T temp = rand.Rand() * m_Pa; - T sina = sin(temp); - T cosa = cos(temp); + T sina = std::sin(temp); + T cosa = std::cos(temp); T re = m_R * cosa; T im = m_R * sina; T a = helper.In.x + re; @@ -2912,8 +2942,8 @@ public: virtual void Precalc() override { - T r2 = 1 - (cos(2 * T(M_PI) / m_P) - 1) / - (cos(2 * T(M_PI) / m_P) + cos(2 * T(M_PI) / m_Q)); + T r2 = 1 - (std::cos(2 * T(M_PI) / m_P) - 1) / + (std::cos(2 * T(M_PI) / m_P) + std::cos(2 * T(M_PI) / m_Q)); if (r2 > 0) m_R = 1 / std::sqrt(r2); @@ -2966,8 +2996,8 @@ public: T y = (b * c - a * d); T vr = m_Weight / (SQR(c) + SQR(d)); T temp = rand.Rand() * m_Pa; - T sina = sin(temp); - T cosa = cos(temp); + T sina = std::sin(temp); + T cosa = std::cos(temp); helper.Out.x = vr * (x * cosa + y * sina); helper.Out.y = vr * (y * cosa - x * sina); @@ -3007,8 +3037,8 @@ public: virtual void Precalc() override { - T r2 = 1 - (cos(2 * T(M_PI) / m_P) - 1) / - (cos(2 * T(M_PI) / m_P) + cos(2 * T(M_PI) / m_Q)); + T r2 = 1 - (std::cos(2 * T(M_PI) / m_P) - 1) / + (std::cos(2 * T(M_PI) / m_P) + std::cos(2 * T(M_PI) / m_Q)); if (r2 > 0) m_R = 1 / std::sqrt(r2); @@ -3101,7 +3131,7 @@ public: { T pa = 2 * T(M_PI) / m_P; T qa = 2 * T(M_PI) / m_Q; - T r = -(cos(pa) - 1) / (cos(pa) + cos(qa)); + T r = -(std::cos(pa) - 1) / (std::cos(pa) + std::cos(qa)); T na = m_N * pa; if (r > 0) @@ -3109,8 +3139,8 @@ public: else r = 1; - m_Cx = r * cos(na); - m_Cy = r * sin(na); + m_Cx = r * std::cos(na); + m_Cy = r * std::sin(na); m_C2 = SQR(m_Cx) + SQR(m_Cy); m_C2x = 2 * m_Cx; m_C2y = 2 * m_Cy; @@ -3173,8 +3203,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T temp = rand.Rand() * m_Pa; - T cx = m_R * cos(temp); - T cy = m_R * sin(temp); + T cx = m_R * std::cos(temp); + T cy = m_R * std::sin(temp); T s2x = 1 + SQR(cx) - SQR(cy); T s2y = 1 + SQR(cy) - SQR(cx); T r2 = helper.m_PrecalcSumSquares + SQR(helper.In.z); @@ -3223,7 +3253,7 @@ public: { T pa = M_2PI / m_P; T qa = M_2PI / m_Q; - T r = -(cos(pa) - 1) / (cos(pa) + cos(qa)); + T r = -(std::cos(pa) - 1) / (std::cos(pa) + std::cos(qa)); if (r > 0) r = 1 / std::sqrt(1 + r); @@ -3281,8 +3311,8 @@ public: T y = helper.In.y * m_S2y; T vr = m_Weight / (m_C2 * r2 + x2cx + 1); T temp = rand.Rand() * m_Pa; - T sina = sin(temp); - T cosa = cos(temp); + T sina = std::sin(temp); + T cosa = std::cos(temp); helper.Out.x = vr * (x * cosa + y * sina); helper.Out.y = vr * (y * cosa - x * sina); @@ -3327,7 +3357,7 @@ public: { T pa = M_2PI / m_P; T qa = M_2PI / m_Q; - T r = -(cos(pa) - 1) / (cos(pa) + cos(qa)); + T r = -(std::cos(pa) - 1) / (std::cos(pa) + std::cos(qa)); if (r > 0) r = 1 / std::sqrt(1 + r); @@ -3389,8 +3419,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = T(M_PI) / (helper.m_PrecalcSqrtSumSquares + 1); - T s = sin(a); - T c = cos(a); + T s = std::sin(a); + T c = std::cos(a); T r = helper.m_PrecalcAtanyx * m_V; helper.Out.x = r * c; @@ -3457,9 +3487,9 @@ public: T x = m_A * helper.In.x + m_B * helper.In.y + m_E; T y = m_C * helper.In.x + m_D * helper.In.y + m_F; T angle = (atan2(y, x) + M_2PI * rand.Rand(int(m_AbsN))) / m_Power; - T sina = sin(angle); - T cosa = cos(angle); - T r = m_Weight * pow(SQR(x) + SQR(y), m_Cn); + T sina = std::sin(angle); + T cosa = std::cos(angle); + T r = m_Weight * std::pow(SQR(x) + SQR(y), m_Cn); helper.Out.x = r * cosa; helper.Out.y = r * sina; @@ -3556,9 +3586,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.m_PrecalcAtanyx * m_InvPower + rand.Rand() * m_InvPower2pi; - T sina = sin(a); - T cosa = cos(a); - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_HalfInvPower); + T sina = std::sin(a); + T cosa = std::cos(a); + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_HalfInvPower); helper.Out.x = r * cosa; helper.Out.y = r * sina; @@ -3636,9 +3666,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T angle = helper.m_PrecalcAtanyx * m_Power; - T sina = sin(angle); - T cosa = cos(angle); - T r = m_Cp * pow(helper.m_PrecalcSumSquares, m_P2); + T sina = std::sin(angle); + T cosa = std::cos(angle); + T r = m_Cp * std::pow(helper.m_PrecalcSumSquares, m_P2); T re = r * cosa + 1; T im = r * sina; T r1 = m_Vp / (SQR(re) + SQR(im)); @@ -3726,16 +3756,16 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T angle = helper.m_PrecalcAtanyx * m_Power; - T sina = sin(angle); - T cosa = cos(angle); - T r = m_C * pow(helper.m_PrecalcSumSquares, m_P2); + T sina = std::sin(angle); + T cosa = std::cos(angle); + T r = m_C * std::pow(helper.m_PrecalcSumSquares, m_P2); T re = r * cosa + 1; T im = r * sina; - r = pow(SQR(re) + SQR(im), m_InvP); - angle = atan2(im, re) * m_InvP2; - sina = sin(angle); - cosa = cos(angle); + r = std::pow(SQR(re) + SQR(im), m_InvP); + angle = std::atan2(im, re) * m_InvP2; + sina = std::sin(angle); + cosa = std::cos(angle); re = r * cosa; im = r * sina; @@ -3793,7 +3823,7 @@ public: if (m_C == -1) m_Vp = 0; else - m_Vp = m_Weight * pow(m_C + 1, 2 / m_Power); + m_Vp = m_Weight * std::pow(m_C + 1, 2 / m_Power); } protected: @@ -3836,14 +3866,14 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T x = (m_IsOdd != 0) ? helper.In.x : m_Vvar * helper.m_PrecalcAtanxy; - T y = (m_IsOdd != 0) ? helper.In.y : m_Vvar2 * log(helper.m_PrecalcSumSquares); - T angle = (atan2(y, x) + M_2PI * rand.Rand(int(m_AbsN))) / m_Nnz; - T r = m_Weight * pow(SQR(x) + SQR(y), m_Cn) * ((m_IsOdd == 0) ? 1 : m_Parity); - T sina = sin(angle) * r; - T cosa = cos(angle) * r; + T y = (m_IsOdd != 0) ? helper.In.y : m_Vvar2 * std::log(helper.m_PrecalcSumSquares); + T angle = (std::atan2(y, x) + M_2PI * rand.Rand(int(m_AbsN))) / m_Nnz; + T r = m_Weight * std::pow(SQR(x) + SQR(y), m_Cn) * ((m_IsOdd == 0) ? 1 : m_Parity); + T sina = std::sin(angle) * r; + T cosa = std::cos(angle) * r; - x = (m_IsOdd != 0) ? cosa : (m_Vvar2 * log(SQR(cosa) + SQR(sina))); - y = (m_IsOdd != 0) ? sina : (m_Vvar * atan2(cosa, sina)); + x = (m_IsOdd != 0) ? cosa : (m_Vvar2 * std::log(SQR(cosa) + SQR(sina))); + y = (m_IsOdd != 0) ? sina : (m_Vvar * std::atan2(cosa, sina)); helper.Out.x = x; helper.Out.y = y; helper.Out.z = m_Weight * helper.In.z; @@ -3889,7 +3919,7 @@ public: m_Vvar2 = m_Vvar * T(0.5); m_AbsN = abs(m_Nnz); m_Cn = 1 / m_Nnz / 2; - m_IsOdd = T(abs(int(m_Parity)) % 2); + m_IsOdd = T(abs(int(m_Parity)) & 1); } protected: @@ -3972,8 +4002,8 @@ public: else { r = 1 / std::sqrt(r); - ts = sin(helper.m_PrecalcAtanyx); - tc = cos(helper.m_PrecalcAtanyx); + ts = std::sin(helper.m_PrecalcAtanyx); + tc = std::cos(helper.m_PrecalcAtanyx); x = r * tc; y = r * ts; @@ -3981,13 +4011,13 @@ public: { xo = (SQR(x) + SQR(y) + 1) / (2 * x); ro = std::sqrt(SQR(x - xo) + SQR(y)); - theta = atan2(T(1), ro); + theta = std::atan2(T(1), ro); a = fmod(m_Out * theta + atan2(y, xo - x) + theta, 2 * theta) - theta; sincos(a, &s, &c); x = (xo - c * ro); y = s * ro; - theta = atan2(y, x); + theta = std::atan2(y, x); sincos(theta, &ts, &tc); r = 1 / std::sqrt(SQR(x) + SQR(y)); @@ -3998,13 +4028,13 @@ public: { xo = - (SQR(x) + SQR(y) + 1) / (2 * x); ro = std::sqrt(SQR(-x - xo) + SQR(y)); - theta = atan2(T(1), ro); - a = fmod(m_Out * theta + atan2(y, xo + x) + theta, 2 * theta) - theta; + theta = std::atan2(T(1), ro); + a = fmod(m_Out * theta + std::atan2(y, xo + x) + theta, 2 * theta) - theta; sincos(a, &s, &c); x = (xo - c * ro); y = s * ro; - theta = atan2(y, x); + theta = std::atan2(y, x); sincos(theta, &ts, &tc); r = 1 / std::sqrt(SQR(x) + SQR(y)); @@ -4189,10 +4219,10 @@ public: m_C1d = std::sqrt(1 + SQR(m_C1r)); m_C2d = std::sqrt(1 + SQR(m_C2r)); - m_C1x = m_C1d * cos(fmod(m_C1a, T(M_PI))); - m_C1y = m_C1d * sin(fmod(m_C1a, T(M_PI))); - m_C2x = m_C2d * cos(fmod(m_C2a, T(M_PI))); - m_C2y = m_C2d * sin(fmod(m_C2a, T(M_PI))); + m_C1x = m_C1d * std::cos(fmod(m_C1a, T(M_PI))); + m_C1y = m_C1d * std::sin(fmod(m_C1a, T(M_PI))); + m_C2x = m_C2d * std::cos(fmod(m_C2a, T(M_PI))); + m_C2y = m_C2d * std::sin(fmod(m_C2a, T(M_PI))); } protected: @@ -4290,11 +4320,16 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { - m_Cx = -m_R * cos(m_A * T(M_PI_2)) * cos(m_B * T(M_PI_2)); - m_Cy = m_R * sin(m_A * T(M_PI_2)) * cos(m_B * T(M_PI_2)); - m_Cz = -m_R * sin(m_B * T(M_PI_2)); + m_Cx = -m_R * std::cos(m_A * T(M_PI_2)) * std::cos(m_B * T(M_PI_2)); + m_Cy = m_R * std::sin(m_A * T(M_PI_2)) * std::cos(m_B * T(M_PI_2)); + m_Cz = -m_R * std::sin(m_B * T(M_PI_2)); m_C2 = SQR(m_Cx) + SQR(m_Cy) + SQR(m_Cz); @@ -4360,8 +4395,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T xp = pow(fabs(m_Weight) * fabs(helper.In.x), m_Powx);//Original did not fabs. - T yp = pow(fabs(m_Weight) * fabs(helper.In.y), m_Powy); + T xp = std::pow(fabs(m_Weight) * fabs(helper.In.x), m_Powx);//Original did not fabs. + T yp = std::pow(fabs(m_Weight) * fabs(helper.In.y), m_Powy); helper.Out.x = xp * Sign(helper.In.x) + m_Lcx * helper.In.x + m_Scx; helper.Out.y = yp * Sign(helper.In.y) + m_Lcy * helper.In.y + m_Scy; @@ -4408,6 +4443,11 @@ protected: m_Params.push_back(ParamWithName(&m_Scy, prefix + "polynomial_scy")); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sign" }; + } + private: T m_Powx; T m_Powy; @@ -4618,7 +4658,7 @@ public: //Calculate cosine wave with given frequency, velocity //and phase based on the distance to center. - T wave = cos(m_F * d - m_Vxp); + T wave = std::cos(m_F * d - m_Vxp); //Calculate the wave offsets T d1 = wave * m_Pxa + d; @@ -4686,6 +4726,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Lerp" }; + } + virtual void Precalc() override { m_F = m_Frequency * 5; @@ -4757,8 +4802,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T c0 = m_Ax / (1 + exp(m_Sx * helper.In.x)); - T c1 = m_Ay / (1 + exp(m_Sy * helper.In.y)); + T c0 = m_Ax / (1 + std::exp(m_Sx * helper.In.x)); + T c1 = m_Ay / (1 + std::exp(m_Sy * helper.In.y)); T x = (2 * (c0 - T(0.5))); T y = (2 * (c1 - T(0.5))); @@ -4879,8 +4924,8 @@ public: { T x = helper.In.x; T y = helper.In.y; - T sx = -1 * cos(x * m_Fx); - T sy = -1 * cos(y * m_Fy); + T sx = -1 * std::cos(x * m_Fx); + T sy = -1 * std::cos(y * m_Fy); T tx = Lerp(helper.In.x, sx, m_Ax); T ty = Lerp(helper.In.y, sy, m_Ay); @@ -4921,6 +4966,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Lerp" }; + } + virtual void Precalc() override { m_Ax = m_AmpX; @@ -4980,7 +5030,7 @@ public: T xPlusy = x + y; T x2Minusy2 = x2 - y2; T x2Plusy2 = x2 + y2; - T result = x2Minusy2 * sin(M_2PI * m_Distort * xPlusy); + T result = x2Minusy2 * std::sin(M_2PI * m_Distort * xPlusy); T divident = 1; if (x2Plusy2 != 0) @@ -5097,9 +5147,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = exp(helper.In.y); - T s = sin(helper.In.x); - T c = cos(helper.In.x); + T r = std::exp(helper.In.y); + T s = std::sin(helper.In.x); + T c = std::cos(helper.In.x); helper.Out.x = m_Vvar2 * r * s; helper.Out.y = m_Vvar2 * r * c; @@ -5162,13 +5212,13 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T angle = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand(int(m_AbsN))) / m_Power; - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); - T sina = sin(angle); - T cosa = cos(angle); + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); + T sina = std::sin(angle); + T cosa = std::cos(angle); T xn = r * cosa; T yn = r * sina; - T siny = sin(m_FreqX * yn); - T sinx = sin(m_FreqY * xn); + T siny = std::sin(m_FreqX * yn); + T sinx = std::sin(m_FreqY * xn); T dx = xn + T(0.5) * (m_ScaleX * siny + fabs(xn) * m_IncX * siny); T dy = yn + T(0.5) * (m_ScaleY * sinx + fabs(yn) * m_IncY * sinx); @@ -5432,6 +5482,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sign" }; + } + protected: void Init() { @@ -5467,8 +5522,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight01 / SafeTan(helper.In.x) * cos(helper.In.y); - helper.Out.y = m_Weight01 / sin(helper.In.x) * (-helper.In.y); + helper.Out.x = m_Weight01 / SafeTan(helper.In.x) * std::cos(helper.In.y); + helper.Out.y = m_Weight01 / std::sin(helper.In.x) * (-helper.In.y); helper.Out.z = m_Weight * helper.In.z; } @@ -5520,8 +5575,13 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * sin(helper.In.x) * (cosh(helper.In.y) + 1) * Sqr(sin(helper.In.x)); - helper.Out.y = m_Weight * cos(helper.In.x) * (cosh(helper.In.y) + 1) * Sqr(sin(helper.In.x)); + T sinx = std::sin(helper.In.x); + T sinx2 = SQR(sinx); + T cosx = std::cos(helper.In.x); + T coshy1 = std::cosh(helper.In.y) + 1; + + helper.Out.x = m_Weight * sinx * coshy1 * sinx2; + helper.Out.y = m_Weight * cosx * coshy1 * sinx2; helper.Out.z = m_Weight * helper.In.z; } @@ -5531,13 +5591,23 @@ public: intmax_t varIndex = IndexInXform(); ss << "\t{\n" - << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) * (cosh(vIn.y) + (real_t)(1.0)) * Sqr(sin(vIn.x));\n" - << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * cos(vIn.x) * (cosh(vIn.y) + (real_t)(1.0)) * Sqr(sin(vIn.x));\n" + << "\t\treal_t sinx = sin(vIn.x);\n" + << "\t\treal_t sinx2 = SQR(sinx);\n" + << "\t\treal_t cosx = cos(vIn.x);\n" + << "\t\treal_t coshy1 = cosh(vIn.y) + 1.0;\n" + << "\n" + << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sinx * coshy1 * sinx2;\n" + << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * cosx * coshy1 * sinx2;\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } }; /// @@ -5554,9 +5624,13 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T d = m_Weight / helper.m_PrecalcSumSquares; + T sinx = std::sin(helper.In.x); + T sinx2 = SQR(sinx); + T cosx = std::cos(helper.In.x); + T coshy1 = std::cosh(helper.In.y) + 1; - helper.Out.x = d * sin(helper.In.x) * (cosh(helper.In.y) + 1) * Sqr(sin(helper.In.x)); - helper.Out.y = d * cos(helper.In.x) * (cosh(helper.In.y) + 1) * Sqr(sin(helper.In.x)); + helper.Out.x = d * sinx * coshy1 * sinx2; + helper.Out.y = d * cosx * coshy1 * sinx2; helper.Out.z = m_Weight * helper.In.z; } @@ -5567,14 +5641,23 @@ public: ss << "\t{\n" << "\t\treal_t d = xform->m_VariationWeights[" << varIndex << "] / precalcSumSquares;\n" + << "\t\treal_t sinx = sin(vIn.x);\n" + << "\t\treal_t sinx2 = SQR(sinx);\n" + << "\t\treal_t cosx = cos(vIn.x);\n" + << "\t\treal_t coshy1 = cosh(vIn.y) + 1.0;\n" << "\n" - << "\t\tvOut.x = d * sin(vIn.x) * (cosh(vIn.y) + (real_t)(1.0)) * Sqr(sin(vIn.x));\n" - << "\t\tvOut.y = d * cos(vIn.x) * (cosh(vIn.y) + (real_t)(1.0)) * Sqr(sin(vIn.x));\n" + << "\t\tvOut.x = d * sinx * coshy1 * sinx2;\n" + << "\t\tvOut.y = d * cosx * coshy1 * sinx2;\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\t}\n"; return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } }; /// @@ -5601,15 +5684,15 @@ public: a += M_2PI * n; - if (cos(a * m_InvSpread) < rand.Rand() * 2 / 0xFFFFFFFF - 1)//Rand max. + if (std::cos(a * m_InvSpread) < rand.Rand() * 2 / 0xFFFFFFFF - 1)//Rand max. a -= m_FullSpread; - T lnr2 = log(helper.m_PrecalcSumSquares); - T r = m_Weight * exp(m_HalfC * lnr2 - m_D * a); + T lnr2 = std::log(helper.m_PrecalcSumSquares); + T r = m_Weight * std::exp(m_HalfC * lnr2 - m_D * a); T temp = m_C * a + m_HalfD * lnr2 + m_Ang * rand.Rand(); - helper.Out.x = r * cos(temp); - helper.Out.y = r * sin(temp); + helper.Out.x = r * std::cos(temp); + helper.Out.y = r * std::sin(temp); helper.Out.z = m_Weight * helper.In.z; } @@ -5658,8 +5741,8 @@ public: virtual void Precalc() override { m_Ang = M_2PI / m_Divisor; - m_C = m_R * cos(T(M_PI) / 2 * m_A) / m_Divisor; - m_D = m_R * sin(T(M_PI) / 2 * m_A) / m_Divisor; + m_C = m_R * std::cos(T(M_PI) / 2 * m_A) / m_Divisor; + m_D = m_R * std::sin(T(M_PI) / 2 * m_A) / m_Divisor; m_HalfC = m_C / 2; m_HalfD = m_D / 2; m_InvSpread = T(0.5) / m_Spread; diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h index 99ba5a7..97e2767 100644 --- a/Source/Ember/Variations03.h +++ b/Source/Ember/Variations03.h @@ -46,6 +46,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -108,11 +113,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r2 = pow(helper.m_PrecalcSumSquares, m_Power * T(0.5)) * m_Weight; + T r2 = std::pow(helper.m_PrecalcSumSquares, m_Power * T(0.5)) * m_Weight; T ran = (helper.m_PrecalcAtanyx / Zeps(m_Denominator) + (m_Root * M_2PI * Floor(rand.Frand01() * m_Denominator) / Zeps(m_Denominator))) * m_Numerator; - helper.Out.x = r2 * cos(ran); - helper.Out.y = r2 * sin(ran); + helper.Out.x = r2 * std::cos(ran); + helper.Out.y = r2 * std::sin(ran); helper.Out.z = m_Weight * helper.In.z; } @@ -141,6 +146,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { m_Power = m_Numerator / Zeps(m_Denominator * m_Correctn * (1 / m_Correctd)); @@ -187,8 +197,8 @@ public: { T u = std::sqrt(ClampGte0(Zeps(m_A) * SQR(helper.In.x) + Zeps(m_B) * SQR(helper.In.y)));//Original did not clamp. - helper.Out.x = cos(u) * SafeTan(helper.In.x) * m_Weight; - helper.Out.y = sin(u) * SafeTan(helper.In.y) * m_Weight; + helper.Out.x = std::cos(u) * SafeTan(helper.In.x) * m_Weight; + helper.Out.y = std::sin(u) * SafeTan(helper.In.y) * m_Weight; helper.Out.z = m_Weight * helper.In.z; } @@ -212,6 +222,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "ClampGte", "Zeps" }; + } + protected: void Init() { @@ -276,11 +291,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = Zeps(pow(helper.m_PrecalcSqrtSumSquares, m_Dist)); + T r = Zeps(std::pow(helper.m_PrecalcSqrtSumSquares, m_Dist)); intmax_t n = Floor(m_Power * rand.Frand01()); T alpha = helper.m_PrecalcAtanyx + n * M_2PI / Zeps(T(Floor(m_Power))); - T sina = sin(alpha); - T cosa = cos(alpha); + T sina = std::sin(alpha); + T cosa = std::cos(alpha); helper.Out.x = m_Weight * cosa / r; helper.Out.y = m_Weight * sina / r; @@ -311,6 +326,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -342,8 +362,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T sin45 = sin(45 * DEG_2_RAD_T);//Was 45 radians? They probably meant to convert this from degrees. - T cos45 = cos(45 * DEG_2_RAD_T); + T sin45 = std::sin(45 * DEG_2_RAD_T);//Was 45 radians? They probably meant to convert this from degrees. + T cos45 = std::cos(45 * DEG_2_RAD_T); helper.Out.x = ((m_Rotate * helper.In.x) * cos45 - helper.In.y * sin45 + m_LineUp) + m_X; @@ -434,7 +454,7 @@ public: { T alpha = fabs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));//Original did not fabs(). - if (rand.Frand01() > m_Contrast * pow(alpha, m_Pow)) + if (rand.Frand01() > m_Contrast * std::pow(alpha, m_Pow)) { x = helper.In.x; y = helper.In.y; @@ -523,7 +543,12 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr", "Zeps" }; + } + + virtual string OpenCLFuncsString() const override { return "void GlynnSim1Circle(__constant real_t* radius1, __constant real_t* thickness, __constant real_t* x1, __constant real_t* y1, uint2* mwc, real_t* x, real_t* y)\n" @@ -542,8 +567,8 @@ public: virtual void Precalc() override { T val = DEG_2_RAD_T * m_Phi1; - T sinPhi1 = sin(val); - T cosPhi1 = cos(val); + T sinPhi1 = std::sin(val); + T cosPhi1 = std::cos(val); m_Pow = fabs(m_Pow); m_X1 = m_Radius * cosPhi1; @@ -571,8 +596,8 @@ private: { T r = m_Radius1 * (m_Thickness + (1 - m_Thickness) * rand.Frand01()); T phi = M_2PI * rand.Frand01(); - T sinPhi = sin(phi); - T cosPhi = cos(phi); + T sinPhi = std::sin(phi); + T cosPhi = std::cos(phi); *x = r * cosPhi + m_X1; *y = r * sinPhi + m_Y1; @@ -616,7 +641,7 @@ public: { T alpha = fabs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));//Original did not fabs(). - if (rand.Frand01() > m_Contrast * pow(alpha, m_Pow)) + if (rand.Frand01() > m_Contrast * std::pow(alpha, m_Pow)) { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; @@ -679,7 +704,12 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + + virtual string OpenCLFuncsString() const override { return "void GlynnSim2Circle(__constant real_t* radius, __constant real_t* thickness, __constant real_t* phi10, __constant real_t* delta, __constant real_t* gamma, uint2* mwc, real_t* x, real_t* y)\n" @@ -727,8 +757,8 @@ private: { T r = m_Radius + m_Thickness - m_Gamma * rand.Frand01(); T phi = m_Phi10 + m_Delta * rand.Frand01(); - T sinPhi = sin(phi); - T cosPhi = cos(phi); + T sinPhi = std::sin(phi); + T cosPhi = std::cos(phi); *x = r * cosPhi; *y = r * sinPhi; @@ -774,7 +804,7 @@ public: { T alpha = fabs(m_Radius / Zeps(helper.m_PrecalcSqrtSumSquares));//Original did not fabs(). - if (rand.Frand01() > m_Contrast * pow(alpha, m_Pow)) + if (rand.Frand01() > m_Contrast * std::pow(alpha, m_Pow)) { helper.Out.x = m_Weight * helper.In.x; helper.Out.y = m_Weight * helper.In.y; @@ -835,7 +865,12 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + + virtual string OpenCLFuncsString() const override { return "void GlynnSim3Circle(__constant real_t* radius, __constant real_t* radius1, __constant real_t* radius2, __constant real_t* thickness, __constant real_t* gamma, uint2* mwc, real_t* x, real_t* y)\n" @@ -884,8 +919,8 @@ private: { T r = m_Radius + m_Thickness - m_Gamma * rand.Frand01(); T phi = M_2PI * rand.Frand01(); - T sinPhi = sin(phi); - T cosPhi = cos(phi); + T sinPhi = std::sin(phi); + T cosPhi = std::cos(phi); if (rand.Frand01() < m_Gamma) r = m_Radius1; @@ -928,19 +963,19 @@ public: f -= angle; T x = f * m_Length; - T z = std::sqrt(1 + SQR(x) - 2 * x * cos(m_Alpha)); + T z = std::sqrt(1 + SQR(x) - 2 * x * std::cos(m_Alpha)); - if (int(angle) % 2) - angle = M_2PI / m_Power * (int(angle) / 2) + asin(sin(m_Alpha) * x / z); + if (int(angle) & 1) + angle = M_2PI / m_Power * (int(angle) / 2) + std::asin(std::sin(m_Alpha) * x / z); else - angle = M_2PI / m_Power * (int(angle) / 2) - asin(sin(m_Alpha) * x / z); + angle = M_2PI / m_Power * (int(angle) / 2) - std::asin(std::sin(m_Alpha) * x / z); z *= std::sqrt(rand.Frand01()); T temp = angle - T(M_PI_2); - helper.Out.x = m_Weight * z * cos(temp); - helper.Out.y = m_Weight * z * sin(temp); + helper.Out.x = m_Weight * z * std::cos(temp); + helper.Out.y = m_Weight * z * std::sin(temp); helper.Out.z = m_Weight * helper.In.z; } @@ -964,7 +999,7 @@ public: << "\t\treal_t x = f * " << length << ";\n" << "\t\treal_t z = sqrt(1 + SQR(x) - 2 * x * cos(" << alpha << "));\n" << "\n" - << "\t\tif (((int)angle) % 2)\n" + << "\t\tif (((int)angle) & 1)\n" << "\t\t angle = M_2PI / " << power << " * (((int)angle) / 2) + asin(sin(" << alpha << ") * x / z);\n" << "\t\telse\n" << "\t\t angle = M_2PI / " << power << " * (((int)angle) / 2) - asin(sin(" << alpha << ") * x / z);\n" @@ -984,8 +1019,8 @@ public: virtual void Precalc() override { m_Alpha = T(M_PI) / m_Power; - m_Length = std::sqrt(1 + SQR(m_Range) - 2 * m_Range * cos(m_Alpha)); - m_Alpha = asin(sin(m_Alpha) * m_Range / m_Length); + m_Length = std::sqrt(1 + SQR(m_Range) - 2 * m_Range * std::cos(m_Alpha)); + m_Alpha = std::asin(std::sin(m_Alpha) * m_Range / m_Length); } protected: @@ -1024,9 +1059,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T ang = rand.Frand01() * M_2PI; - T s = sin(ang); - T c = cos(ang); - T r = m_Weight * (m_Power == 1 ? acos(rand.Frand01() * 2 - 1) / T(M_PI) : acos(exp(log(rand.Frand01()) * m_Power) * 2 - 1) / T(M_PI)); + T s = std::sin(ang); + T c = std::cos(ang); + T r = m_Weight * (m_Power == 1 ? std::acos(rand.Frand01() * 2 - 1) / T(M_PI) : std::acos(std::exp(std::log(rand.Frand01()) * m_Power) * 2 - 1) / T(M_PI)); helper.Out.x = r * c; helper.Out.y = r * s; @@ -1084,8 +1119,8 @@ public: T rad = std::sqrt(rand.Frand01()); T temp = rand.Frand01() * M_2PI; - helper.Out.x = m_Weight * cos(temp) * rad; - helper.Out.y = m_Weight * sin(temp) * rad; + helper.Out.x = m_Weight * std::cos(temp) * rad; + helper.Out.y = m_Weight * std::sin(temp) * rad; helper.Out.z = m_Weight * helper.In.z; } @@ -1126,7 +1161,7 @@ public: T coeff = fabs(helper.In.z); if (coeff != 0 && m_Power != 1) - coeff = exp(log(coeff) * m_Power); + coeff = std::exp(log(coeff) * m_Power); helper.Out.x = m_Weight * (helper.m_TransX + helper.In.x * coeff); helper.Out.y = m_Weight * (helper.m_TransY + helper.In.y * coeff); @@ -1187,7 +1222,7 @@ public: T xang = (helper.m_PrecalcAtanyx + T(M_PI)) / m_Alpha; xang = (xang - int(xang)) * m_Alpha; - xang = cos((xang < m_Alpha / 2) ? xang : m_Alpha - xang); + xang = std::cos((xang < m_Alpha / 2) ? xang : m_Alpha - xang); T xr = xang > 0 ? m_Radius / xang : 1; @@ -1201,8 +1236,8 @@ public: { T rdc = xr + (rand.Frand01() * T(0.5) * m_ScatterDist); - helper.Out.x = m_Weight * rdc * cos(helper.m_PrecalcAtanyx); - helper.Out.y = m_Weight * rdc * sin(helper.m_PrecalcAtanyx); + helper.Out.x = m_Weight * rdc * std::cos(helper.m_PrecalcAtanyx); + helper.Out.y = m_Weight * rdc * std::sin(helper.m_PrecalcAtanyx); } } else @@ -1312,8 +1347,8 @@ public: T xang = (helper.m_PrecalcAtanyx + M_3PI + m_Alpha / 2) / m_Alpha; T zang = ((xang - int(xang)) * m_Width + int(xang)) * m_Alpha - T(M_PI) - m_Alpha / 2 * m_Width; - helper.Out.x = m_Weight * helper.m_PrecalcSqrtSumSquares * cos(zang); - helper.Out.y = m_Weight * helper.m_PrecalcSqrtSumSquares * sin(zang); + helper.Out.x = m_Weight * helper.m_PrecalcSqrtSumSquares * std::cos(zang); + helper.Out.y = m_Weight * helper.m_PrecalcSqrtSumSquares * std::sin(zang); helper.Out.z = m_Weight * helper.In.z; } @@ -1384,18 +1419,18 @@ public: } else { - T delta = (sin(helper.m_PrecalcAtanyx * m_N) + m_Symmetry) / m_DeltaHelp; + T delta = (std::sin(helper.m_PrecalcAtanyx * m_N) + m_Symmetry) / m_DeltaHelp; T positive = 1 - T(delta < 0 ? 1 : 0) * 2; if (m_Mode != 0) - delta = exp(m_Prescale * log(delta * positive)) * m_Postscale * m_Mode; + delta = std::exp(m_Prescale * std::log(delta * positive)) * m_Postscale * m_Mode; else - delta = exp(m_Prescale * log(delta * positive)) * m_Postscale * positive; + delta = std::exp(m_Prescale * std::log(delta * positive)) * m_Postscale * positive; T rad = m_Radius + (helper.m_PrecalcSqrtSumSquares - m_Radius) * delta; - helper.Out.x = m_Weight * rad * cos(helper.m_PrecalcAtanyx); - helper.Out.y = m_Weight * rad * sin(helper.m_PrecalcAtanyx); + helper.Out.x = m_Weight * rad * std::cos(helper.m_PrecalcAtanyx); + helper.Out.y = m_Weight * rad * std::sin(helper.m_PrecalcAtanyx); helper.Out.z = m_Weight * helper.In.z; //helper.m_TransZ += m_Weight * outPoint.m_Z;//Original had this which is probably wrong. } @@ -1493,12 +1528,12 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T z = helper.In.z / m_AbsN; - T r = m_Weight * pow(helper.m_PrecalcSumSquares + SQR(z), m_Cn); + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares + SQR(z), m_Cn); T tmp = r * helper.m_PrecalcSqrtSumSquares; T ang = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand(uint(m_AbsN))) / m_N; - helper.Out.x = tmp * cos(ang); - helper.Out.y = tmp * sin(ang); + helper.Out.x = tmp * std::cos(ang); + helper.Out.y = tmp * std::sin(ang); helper.Out.z = r * z; } @@ -1573,11 +1608,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); T temp = (helper.m_PrecalcAtanyx + M_2PI * rand.Rand(uint(m_AbsN))) / m_N; - helper.Out.x = r * cos(temp); - helper.Out.y = r * sin(temp); + helper.Out.x = r * std::cos(temp); + helper.Out.y = r * std::sin(temp); helper.Out.z = r * helper.In.z / (helper.m_PrecalcSqrtSumSquares * m_AbsN); } @@ -1650,8 +1685,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = SignNz(helper.In.x) * pow(fabs(helper.In.x), m_PowX) * m_Weight; - helper.Out.y = SignNz(helper.In.y) * pow(fabs(helper.In.y), m_PowY) * m_Weight; + helper.Out.x = SignNz(helper.In.x) * std::pow(fabs(helper.In.x), m_PowX) * m_Weight; + helper.Out.y = SignNz(helper.In.y) * std::pow(fabs(helper.In.y), m_PowY) * m_Weight; helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } @@ -1673,6 +1708,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SignNz" }; + } + protected: void Init() { @@ -1704,9 +1744,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = T(helper.In.x < 0 ? -1 : 1) * pow(fabs(helper.In.x), m_PowX) * m_Weight; - helper.Out.y = T(helper.In.y < 0 ? -1 : 1) * pow(fabs(helper.In.y), m_PowY) * m_Weight; - helper.Out.z = T(helper.In.z < 0 ? -1 : 1) * pow(fabs(helper.In.z), m_PowZ) * m_Weight; + helper.Out.x = T(helper.In.x < 0 ? -1 : 1) * std::pow(fabs(helper.In.x), m_PowX) * m_Weight; + helper.Out.y = T(helper.In.y < 0 ? -1 : 1) * std::pow(fabs(helper.In.y), m_PowY) * m_Weight; + helper.Out.z = T(helper.In.z < 0 ? -1 : 1) * std::pow(fabs(helper.In.z), m_PowZ) * m_Weight; } virtual string OpenCLString() const override @@ -1788,6 +1828,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -1847,6 +1892,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -1882,11 +1932,11 @@ public: { T t = (m_TMax - m_TMin) * rand.Frand01() + m_TMin; T y = (m_YMax - m_YMin) * rand.Frand01() + m_YMin; - T x1 = (m_A + m_B) * cos(t) - m_C1 * cos((m_A + m_B) / m_B * t); - T y1 = (m_A + m_B) * sin(t) - m_C2 * sin((m_A + m_B) / m_B * t); + T x1 = (m_A + m_B) * std::cos(t) - m_C1 * std::cos((m_A + m_B) / m_B * t); + T y1 = (m_A + m_B) * std::sin(t) - m_C2 * std::sin((m_A + m_B) / m_B * t); - helper.Out.x = m_Weight * (x1 + m_D * cos(t) + y); - helper.Out.y = m_Weight * (y1 + m_D * sin(t) + y); + helper.Out.x = m_Weight * (x1 + m_D * std::cos(t) + y); + helper.Out.y = m_Weight * (y1 + m_D * std::sin(t) + y); helper.Out.z = m_Weight * helper.In.z; } @@ -1962,11 +2012,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T sinX = sin(helper.In.x); - T cosX = cos(helper.In.x); - T cosY = cos(helper.In.y); - T bx = Cube(cosX*cosY); - T by = Cube(sinX*cosY); + T sinX = std::sin(helper.In.x); + T cosX = std::cos(helper.In.x); + T cosY = std::cos(helper.In.y); + T bx = Cube(cosX * cosY); + T by = Cube(sinX * cosY); helper.Out.x = m_Weight * cosX * bx; helper.Out.y = m_Weight * cosX * by; @@ -1993,6 +2043,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Cube" }; + } }; /// @@ -2054,13 +2109,13 @@ public: otherZ = outPoint.m_Z; if (inZ == 0) - tempTz = cos(helper.m_PrecalcSqrtSumSquares); + tempTz = std::cos(helper.m_PrecalcSqrtSumSquares); else tempTz = helper.In.z; if (otherZ == 0) { - tempPz = cos(helper.m_PrecalcSqrtSumSquares); + tempPz = std::cos(helper.m_PrecalcSqrtSumSquares); if (m_VarType == VARTYPE_PRE) helper.m_TransZ = 0; @@ -2170,8 +2225,8 @@ public: T c1 = Zeps(SQR(helper.In.x)); T c2 = Zeps(SQR(helper.In.y)); - helper.Out.x = m_Weight * ((1 / d) * cos(c1) * sin(c2)); - helper.Out.y = m_Weight * ((1 / d) * sin(c1) * sin(c2)); + helper.Out.x = m_Weight * ((1 / d) * std::cos(c1) * std::sin(c2)); + helper.Out.y = m_Weight * ((1 / d) * std::sin(c1) * std::sin(c2)); helper.Out.z = m_Weight * helper.In.z; } @@ -2192,6 +2247,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -2308,7 +2368,7 @@ public: T dx, dy, r = m_Weight / (helper.m_PrecalcSumSquares + EPS); int isXY = int(LRint(helper.In.x * m_InvSize) + LRint(helper.In.y * m_InvSize)); - if (isXY % 2) + if (isXY & 1) { dx = -m_X + m_Rand * rand.Frand01(); dy = -m_Y; @@ -2319,8 +2379,8 @@ public: dy = m_Y + m_Rand * rand.Frand01(); } - helper.Out.x = m_Weight * (sin(helper.In.x) * r + dx); - helper.Out.y = m_Weight * (sin(helper.In.y) * r + dy); + helper.Out.x = m_Weight * (std::sin(helper.In.x) * r + dx); + helper.Out.y = m_Weight * (std::sin(helper.In.y) * r + dy); helper.Out.z = m_Weight * helper.In.z; } @@ -2340,7 +2400,7 @@ public: << "\t\treal_t dx, dy, r = xform->m_VariationWeights[" << varIndex << "] / (precalcSumSquares + EPS);\n" << "\t\tint isXY = LRint(vIn.x * " << invSize << ") + LRint(vIn.y * " << invSize << ");\n" << "\n" - << "\t\tif (isXY % 2)\n" + << "\t\tif (isXY & 1)\n" << "\t\t{\n" << "\t\t dx = -" << x << " + " << rand << " * MwcNext01(mwc);\n" << "\t\t dy = -" << y << ";\n" @@ -2359,6 +2419,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "LRint" }; + } + virtual void Precalc() override { m_InvSize = 1 / (m_Size + EPS); @@ -2403,11 +2468,11 @@ public: { T preX = helper.In.x * (m_XDistort + 1); T preY = helper.In.y * (m_YDistort + 1); - T temp = atan2(preY, preX) * m_InvN + rand.Rand() * m_Inv2PiN; - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn); + T temp = std::atan2(preY, preX) * m_InvN + rand.Rand() * m_Inv2PiN; + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn); - helper.Out.x = r * cos(temp); - helper.Out.y = r * sin(temp); + helper.Out.x = r * std::cos(temp); + helper.Out.y = r * std::sin(temp); helper.Out.z = m_Weight * helper.In.z; } @@ -2528,6 +2593,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -2574,10 +2644,10 @@ public: intmax_t n; T z = 4 * m_Dist / m_Power; - T r = pow(helper.m_PrecalcSqrtSumSquares, z); + T r = std::pow(helper.m_PrecalcSqrtSumSquares, z); T alpha = helper.m_PrecalcAtanyx * m_Power; - T x = r * cos(alpha); - T y = r * sin(alpha); + T x = r * std::cos(alpha); + T y = r * std::sin(alpha); T reU = m_Re_A * x - m_Im_A * y + m_Re_B; T imU = m_Re_A * y + m_Im_A * x + m_Im_B; T reV = m_Re_C * x - m_Im_C * y + m_Re_D; @@ -2588,12 +2658,12 @@ public: y = (imU * reV - reU * imV) / radV; z = 1 / z; - r = pow(std::sqrt(SQR(x) + SQR(y)), z); + r = std::pow(std::sqrt(SQR(x) + SQR(y)), z); n = Floor(m_Power * rand.Frand01()); - alpha = (atan2(y, x) + n * M_2PI) / Floor(m_Power); + alpha = (std::atan2(y, x) + n * M_2PI) / Floor(m_Power); - helper.Out.x = m_Weight * r * cos(alpha); - helper.Out.y = m_Weight * r * sin(alpha); + helper.Out.x = m_Weight * r * std::cos(alpha); + helper.Out.y = m_Weight * r * std::sin(alpha); helper.Out.z = m_Weight * helper.In.z; } @@ -2731,8 +2801,8 @@ public: } //Initial "object" co-ordinates. - mx = (m_Radius + s * cos(t / 2)) * cos(t); - my = (m_Radius + s * cos(t / 2)) * sin(t); + mx = (m_Radius + s * std::cos(t / 2)) * std::cos(t); + my = (m_Radius + s * std::cos(t / 2)) * std::sin(t); mz = s * sin(t / 2); //Rotate around X axis (change y & z) and store temporarily in R variables. @@ -2820,10 +2890,10 @@ public: virtual void Precalc() override { - m_RotxSin = sin(m_RotateX * M_2PI); - m_RotxCos = cos(m_RotateX * M_2PI); - m_RotySin = sin(m_RotateY * M_2PI); - m_RotyCos = cos(m_RotateY * M_2PI); + m_RotxSin = std::sin(m_RotateX * M_2PI); + m_RotxCos = std::cos(m_RotateX * M_2PI); + m_RotySin = std::sin(m_RotateY * M_2PI); + m_RotyCos = std::cos(m_RotateY * M_2PI); } protected: @@ -2952,11 +3022,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T cn = cos(m_N * helper.In.y); - T sx = sin(helper.In.x); - T cx = cos(helper.In.x); - T sy = sin(helper.In.y); - T cy = cos(helper.In.y); + T cn = std::cos(m_N * helper.In.y); + T sx = std::sin(helper.In.x); + T cx = std::cos(helper.In.x); + T sy = std::sin(helper.In.y); + T cy = std::cos(helper.In.y); helper.Out.x = m_Weight * (cy * (cn * cx)); helper.Out.y = m_Weight * (cy * (cn * sx)); @@ -3016,7 +3086,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T a = helper.m_PrecalcAtanyx; - T t = log(helper.m_PrecalcSqrtSumSquares); + T t = std::log(helper.m_PrecalcSqrtSumSquares); if (t < 0) t -= m_SizeDiv2; @@ -3028,8 +3098,8 @@ public: else a += m_Odd; - helper.Out.x = helper.m_PrecalcSqrtSumSquares * cos(a); - helper.Out.y = helper.m_PrecalcSqrtSumSquares * sin(a); + helper.Out.x = helper.m_PrecalcSqrtSumSquares * std::cos(a); + helper.Out.y = helper.m_PrecalcSqrtSumSquares * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -3106,11 +3176,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T sx = sin(helper.In.x); - T cx = cos(helper.In.x); - T sy = sin(helper.In.y); - T cy = cos(helper.In.y); - T ir = m_InvTimesR + (m_1MinusInv * (m_R * cos(m_N * helper.In.x))); + T sx = std::sin(helper.In.x); + T cx = std::cos(helper.In.x); + T sy = std::sin(helper.In.y); + T cy = std::cos(helper.In.y); + T ir = m_InvTimesR + (m_1MinusInv * (m_R * std::cos(m_N * helper.In.x))); helper.Out.x = m_Weight * (cx * (ir + sy)); helper.Out.y = m_Weight * (sx * (ir + sy)); @@ -3202,7 +3272,7 @@ public: { alt = int(a * m_KnPi); - if (alt % 2 == 0) + if ((alt & 1) == 0) a = alt * m_PiKn + fmod(m_KaKn + a, m_PiKn); else a = alt * m_PiKn + fmod(-m_KaKn + a, m_PiKn); @@ -3211,14 +3281,14 @@ public: { alt = int(-a * m_KnPi); - if (alt % 2 == 1) + if ((alt & 1) == 1) a = -(alt * m_PiKn + fmod(-m_KaKn - a, m_PiKn)); else a = -(alt * m_PiKn + fmod(m_KaKn - a, m_PiKn)); } - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); helper.Out.z = m_Weight * helper.In.z; } @@ -3244,7 +3314,7 @@ public: << "\t\t{\n" << "\t\t alt = (int)(a * " << knpi << ");\n" << "\n" - << "\t\t if (alt % 2 == 0)\n" + << "\t\t if ((alt & 1) == 0)\n" << "\t\t a = alt * " << pikn << " + fmod(" << kakn << " + a, " << pikn << ");\n" << "\t\t else\n" << "\t\t a = alt * " << pikn << " + fmod(-" << kakn << " + a, " << pikn << ");\n" @@ -3253,7 +3323,7 @@ public: << "\t\t{\n" << "\t\t alt = (int)(-a * " << knpi << ");\n" << "\n" - << "\t\t if (alt % 2 == 1)\n" + << "\t\t if ((alt & 1) == 1)\n" << "\t\t a = -(alt * " << pikn << " + fmod(-" << kakn << " - a, " << pikn << "));\n" << "\t\t else\n" << "\t\t a = -(alt * " << pikn << " + fmod(" << kakn << " - a, " << pikn << "));\n" @@ -3315,16 +3385,16 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T tau = T(0.5) * (log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); - T sigma = T(M_PI) - atan2(helper.In.y, helper.In.x + 1) - atan2(helper.In.y, 1 - helper.In.x); + T tau = T(0.5) * (std::log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - std::log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); + T sigma = T(M_PI) - std::atan2(helper.In.y, helper.In.x + 1) - std::atan2(helper.In.y, 1 - helper.In.x); if (tau < m_Radius && -tau < m_Radius) tau = fmod(tau + m_Radius + m_Distance * m_Radius, 2 * m_Radius) - m_Radius; - T temp = cosh(tau) - cos(sigma); + T temp = std::cosh(tau) - std::cos(sigma); - helper.Out.x = m_Weight * sinh(tau) / temp; - helper.Out.y = m_Weight * sin(sigma) / temp; + helper.Out.x = m_Weight * std::sinh(tau) / temp; + helper.Out.y = m_Weight * std::sin(sigma) / temp; helper.Out.z = m_Weight * helper.In.z; } @@ -3354,6 +3424,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + protected: void Init() { @@ -3385,15 +3460,15 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T tau = T(0.5) * (log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); - T sigma = T(M_PI) - atan2(helper.In.y, helper.In.x + 1) - atan2(helper.In.y, 1 - helper.In.x); + T tau = T(0.5) * (std::log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - std::log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); + T sigma = T(M_PI) - std::atan2(helper.In.y, helper.In.x + 1) - std::atan2(helper.In.y, 1 - helper.In.x); sigma = sigma + tau * m_Out + m_In / tau; - T temp = cosh(tau) - cos(sigma); + T temp = std::cosh(tau) - std::cos(sigma); - helper.Out.x = m_Weight * sinh(tau) / temp; - helper.Out.y = m_Weight * sin(sigma) / temp; + helper.Out.x = m_Weight * std::sinh(tau) / temp; + helper.Out.y = m_Weight * std::sin(sigma) / temp; helper.Out.z = m_Weight * helper.In.z; } @@ -3422,6 +3497,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + protected: void Init() { @@ -3453,8 +3533,8 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T tau = T(0.5) * (log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - log(Sqr(helper.In.x - 1) + SQR(helper.In.y))) / m_Power + m_Move; - T sigma = T(M_PI) - atan2(helper.In.y, helper.In.x + 1) - atan2(helper.In.y, 1 - helper.In.x) + m_Rotate; + T tau = T(0.5) * (std::log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - std::log(Sqr(helper.In.x - 1) + SQR(helper.In.y))) / m_Power + m_Move; + T sigma = T(M_PI) - std::atan2(helper.In.y, helper.In.x + 1) - std::atan2(helper.In.y, 1 - helper.In.x) + m_Rotate; sigma = sigma / m_Power + M_2PI / m_Power * Floor(rand.Frand01() * m_Power); @@ -3463,10 +3543,10 @@ public: else tau -= m_Split; - T temp = cosh(tau) - cos(sigma); + T temp = std::cosh(tau) - std::cos(sigma); - helper.Out.x = m_Weight * sinh(tau) / temp; - helper.Out.y = m_Weight * sin(sigma) / temp; + helper.Out.x = m_Weight * std::sinh(tau) / temp; + helper.Out.y = m_Weight * std::sin(sigma) / temp; helper.Out.z = m_Weight * helper.In.z; } @@ -3502,6 +3582,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + protected: void Init() { @@ -3537,16 +3622,16 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T tau = T(0.5) * (log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); - T sigma = T(M_PI) - atan2(helper.In.y, helper.In.x + 1) - atan2(helper.In.y, 1 - helper.In.x); + T tau = T(0.5) * (std::log(Sqr(helper.In.x + 1) + SQR(helper.In.y)) - std::log(Sqr(helper.In.x - 1) + SQR(helper.In.y))); + T sigma = T(M_PI) - std::atan2(helper.In.y, helper.In.x + 1) - std::atan2(helper.In.y, 1 - helper.In.x); int alt = int(sigma * m_CnPi); - if (alt % 2 == 0) + if ((alt & 1) == 0) sigma = alt * m_PiCn + fmod(sigma + m_CaCn, m_PiCn); else sigma = alt * m_PiCn + fmod(sigma - m_CaCn, m_PiCn); - T temp = cosh(tau) - cos(sigma); + T temp = std::cosh(tau) - std::cos(sigma); helper.Out.x = m_Weight * sinh(tau) / temp; helper.Out.y = m_Weight * sin(sigma) / temp; @@ -3571,7 +3656,7 @@ public: << "\t\treal_t sigma = M_PI - atan2(vIn.y, vIn.x + (real_t)(1.0)) - atan2(vIn.y, (real_t)(1.0) - vIn.x);\n" << "\t\tint alt = (int)(sigma * " << cnPi << ");\n" << "\n" - << "\t\tif (alt % 2 == 0)\n" + << "\t\tif ((alt & 1) == 0)\n" << "\t\t sigma = alt * " << piCn << " + fmod(sigma + " << caCn << ", " << piCn << ");\n" << "\t\telse\n" << "\t\t sigma = alt * " << piCn << " + fmod(sigma - " << caCn << ", " << piCn << ");\n" @@ -3586,6 +3671,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + virtual void Precalc() override { m_CnPi = m_Num * T(M_1_PI); @@ -3853,13 +3943,13 @@ public: if (xmax < 1) xmax = 1; - T nu = acos(Clamp(helper.In.x / xmax, -1, 1)); // -Pi < nu < Pi + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1)); // -Pi < nu < Pi if (helper.In.y > 0) { alt = int(nu * m_CnPi); - if (alt % 2 == 0) + if ((alt & 1) == 0) nu = alt * m_PiCn + fmod(nu + m_CaCn, m_PiCn); else nu = alt * m_PiCn + fmod(nu - m_CaCn, m_PiCn); @@ -3868,7 +3958,7 @@ public: { alt = int(nu * m_CnPi); - if (alt % 2 == 0) + if ((alt & 1) == 0) nu = alt * m_PiCn + fmod(nu + m_CaCn, m_PiCn); else nu = alt * m_PiCn + fmod(nu - m_CaCn, m_PiCn); @@ -3876,7 +3966,7 @@ public: nu *= -1; } - helper.Out.x = m_Weight * xmax * cos(nu); + helper.Out.x = m_Weight * xmax * std::cos(nu); helper.Out.y = m_Weight * std::sqrt(xmax - 1) * std::sqrt(xmax + 1) * sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -3903,13 +3993,13 @@ public: << "\t\tif (xmax < 1)\n" << "\t\t xmax = 1;\n" << "\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y > 0)\n" << "\t\t{\n" << "\t\t alt = (int)(nu * " << cnPi << ");\n" << "\n" - << "\t\t if (alt % 2 == 0)\n" + << "\t\t if ((alt & 1) == 0)\n" << "\t\t nu = alt * " << piCn << " + fmod(nu + " << caCn << ", " << piCn << ");\n" << "\t\t else\n" << "\t\t nu = alt * " << piCn << " + fmod(nu - " << caCn << ", " << piCn << ");\n" @@ -3918,7 +4008,7 @@ public: << "\t\t{\n" << "\t\t alt = (int)(nu * " << cnPi << ");\n" << "\n" - << "\t\t if (alt % 2 == 0)\n" + << "\t\t if ((alt & 1) == 0)\n" << "\t\t nu = alt * " << piCn << " + fmod(nu + " << caCn << ", " << piCn << ");\n" << "\t\t else\n" << "\t\t nu = alt * " << piCn << " + fmod(nu - " << caCn << ", " << piCn << ");\n" @@ -3934,6 +4024,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + virtual void Precalc() override { m_CnPi = m_Num * T(M_1_PI); @@ -3999,8 +4094,8 @@ public: ClampGteRef(xmax, 1); - T mu = acosh(xmax); - T nu = acos(Clamp(x / xmax, -1, 1));//-Pi < nu < Pi. + T mu = std::acosh(xmax); + T nu = std::acos(Clamp(x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; @@ -4008,8 +4103,8 @@ public: nu = nu / m_Power + M_2PI / m_Power * Floor(rand.Frand01() * m_Power); mu /= m_Power; - helper.Out.x = m_Weight * cosh(mu) * cos(nu); - helper.Out.y = m_Weight * sinh(mu) * sin(nu); + helper.Out.x = m_Weight * std::cosh(mu) * std::cos(nu); + helper.Out.y = m_Weight * std::sinh(mu) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -4043,7 +4138,7 @@ public: << "\t\t xmax = 1;\n" << "\n" << "\t\treal_t mu = acosh(xmax);\n" - << "\t\treal_t nu = acos(Clamp(x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -4059,6 +4154,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + virtual void Precalc() override { m_Sign = 1; @@ -4104,8 +4204,8 @@ public: ClampGteRef(xmax, 1); - T mu = acosh(xmax); - T nu = acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. + T mu = std::acosh(xmax); + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; @@ -4118,8 +4218,8 @@ public: mu = fmod(mu - m_Radius - m_Distance * m_Radius, 2 * m_Radius) + m_Radius; } - helper.Out.x = m_Weight * cosh(mu) * cos(nu); - helper.Out.y = m_Weight * sinh(mu) * sin(nu); + helper.Out.x = m_Weight * std::cosh(mu) * std::cos(nu); + helper.Out.y = m_Weight * std::sinh(mu) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -4141,7 +4241,7 @@ public: << "\t\t xmax = 1;\n" << "\n" << "\t\treal_t mu = acosh(xmax);\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -4162,6 +4262,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + protected: void Init() { @@ -4199,8 +4304,8 @@ public: ClampGteRef(xmax, 1); - T mu = acosh(xmax); - T nu = acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. + T mu = std::acosh(xmax); + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; @@ -4218,8 +4323,8 @@ public: nu += m_Rotate; - helper.Out.x = m_Weight * cosh(mu) * cos(nu); - helper.Out.y = m_Weight * sinh(mu) * sin(nu); + helper.Out.x = m_Weight * std::cosh(mu) * std::cos(nu); + helper.Out.y = m_Weight * std::sinh(mu) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -4241,7 +4346,7 @@ public: << "\t\t xmax = 1;\n" << "\n" << "\t\treal_t mu = acosh(xmax);\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -4267,6 +4372,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + protected: void Init() { @@ -4304,8 +4414,8 @@ public: ClampGteRef(xmax, 1); - T mu = acosh(xmax); - T nu = acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. + T mu = std::acosh(xmax); + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; @@ -4314,8 +4424,8 @@ public: mu *= m_Dist; mu += m_Push; - helper.Out.x = m_Weight * cosh(mu) * cos(nu); - helper.Out.y = m_Weight * sinh(mu) * sin(nu); + helper.Out.x = m_Weight * std::cosh(mu) * std::cos(nu); + helper.Out.y = m_Weight * std::sinh(mu) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -4338,7 +4448,7 @@ public: << "\t\t xmax = 1;\n" << "\n" << "\t\treal_t mu = acosh(xmax);\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -4355,6 +4465,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + protected: void Init() { @@ -4395,15 +4510,15 @@ public: if (xmax < 1) xmax = 1; - T nu = acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; nu = fmod(nu + m_Rotate + T(M_PI), M_2PI) - T(M_PI); - helper.Out.x = m_Weight * xmax * cos(nu); - helper.Out.y = m_Weight * std::sqrt(xmax - 1) * std::sqrt(xmax + 1) * sin(nu); + helper.Out.x = m_Weight * xmax * std::cos(nu); + helper.Out.y = m_Weight * std::sqrt(xmax - 1) * std::sqrt(xmax + 1) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -4423,7 +4538,7 @@ public: << "\t\tif (xmax < 1)\n" << "\t\t xmax = 1;\n" << "\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -4438,6 +4553,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + protected: void Init() { @@ -4473,8 +4593,8 @@ public: ClampGteRef(xmax, 1); - T mu = acosh(xmax); - T nu = acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. + T mu = std::acosh(xmax); + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; @@ -4488,8 +4608,8 @@ public: if (nu < -T(M_PI)) nu += M_2PI; - helper.Out.x = m_Weight * cosh(mu) * cos(nu); - helper.Out.y = m_Weight * sinh(mu) * sin(nu); + helper.Out.x = m_Weight * std::cosh(mu) * std::cos(nu); + helper.Out.y = m_Weight * std::sinh(mu) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -4511,7 +4631,7 @@ public: << "\t\t xmax = 1;\n" << "\n" << "\t\treal_t mu = acosh(xmax);\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -4533,6 +4653,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + protected: void Init() { diff --git a/Source/Ember/Variations04.h b/Source/Ember/Variations04.h index 43faed3..dbef1a2 100644 --- a/Source/Ember/Variations04.h +++ b/Source/Ember/Variations04.h @@ -26,16 +26,16 @@ public: ClampGteRef(xmax, -1); - T mu = acosh(xmax); - T nu = acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. + T mu = std::acosh(xmax); + T nu = std::acos(Clamp(helper.In.x / xmax, -1, 1));//-Pi < nu < Pi. if (helper.In.y < 0) nu *= -1; nu = nu + mu * m_Out + m_In / mu; - helper.Out.x = m_Weight * cosh(mu) * cos(nu); - helper.Out.y = m_Weight * sinh(mu) * sin(nu); + helper.Out.x = m_Weight * std::cosh(mu) * std::cos(nu); + helper.Out.y = m_Weight * std::sinh(mu) * std::sin(nu); helper.Out.z = m_Weight * helper.In.z; } @@ -57,7 +57,7 @@ public: << "\t\t xmax = 1;\n" << "\n" << "\t\treal_t mu = acosh(xmax);\n" - << "\t\treal_t nu = acos(Clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\treal_t nu = acos(clamp(vIn.x / xmax, -(real_t)(1.0), (real_t)(1.0)));\n" << "\n" << "\t\tif (vIn.y < 0)\n" << "\t\t nu *= -1;\n" @@ -72,6 +72,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt" }; + } + protected: void Init() { @@ -623,6 +628,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -660,6 +670,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -683,8 +698,8 @@ public: if (m_VarType == VARTYPE_REG) { - helper.Out.x = 0; - outPoint.m_X = helper.In.x; + helper.Out.x = helper.In.x; + outPoint.m_X = 0; } else { @@ -729,8 +744,8 @@ public: virtual void Precalc() override { - m_RxSin = sin(m_Weight * T(M_PI_2)); - m_RxCos = cos(m_Weight * T(M_PI_2)); + m_RxSin = std::sin(m_Weight * T(M_PI_2)); + m_RxCos = std::cos(m_Weight * T(M_PI_2)); } protected: @@ -812,8 +827,8 @@ public: virtual void Precalc() override { - m_RySin = sin(m_Weight * T(M_PI_2)); - m_RyCos = cos(m_Weight * T(M_PI_2)); + m_RySin = std::sin(m_Weight * T(M_PI_2)); + m_RyCos = std::cos(m_Weight * T(M_PI_2)); } protected: @@ -853,8 +868,8 @@ public: if (m_VarType == VARTYPE_REG) { - helper.Out.z = 0; - outPoint.m_Z = helper.In.z; + helper.Out.z = helper.In.z; + outPoint.m_Z = 0; } else { @@ -894,8 +909,8 @@ public: virtual void Precalc() override { - m_RzSin = sin(m_Weight * T(M_PI_2)); - m_RzCos = cos(m_Weight * T(M_PI_2)); + m_RzSin = std::sin(m_Weight * T(M_PI_2)); + m_RzCos = std::cos(m_Weight * T(M_PI_2)); } protected: @@ -1181,7 +1196,7 @@ public: << "\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x + (MwcNext01(mwc) - (real_t)(0.5)) * r);\n" << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (vIn.y + (MwcNext01(mwc) - (real_t)(0.5)) * r);\n" - << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n"//WHY IS THIS DIFFERENT THAN THE CPU ONE?//TODO << "\t}\n"; return ss.str(); @@ -1231,11 +1246,11 @@ public: { T jun = Zeps(fabs(m_N)); - T a = (atan2(helper.In.y, pow(fabs(helper.In.x), m_Sep)) + M_2PI * Floor(rand.Frand01() * m_AbsN)) / jun; - T r = m_Weight * pow(helper.m_PrecalcSumSquares, m_Cn * m_A); + T a = (std::atan2(helper.In.y, std::pow(fabs(helper.In.x), m_Sep)) + M_2PI * Floor(rand.Frand01() * m_AbsN)) / jun; + T r = m_Weight * std::pow(helper.m_PrecalcSumSquares, m_Cn * m_A); - helper.Out.x = r * cos(a) + m_B; - helper.Out.y = r * sin(a) + m_B; + helper.Out.x = r * std::cos(a) + m_B; + helper.Out.y = r * std::sin(a) + m_B; helper.Out.z = m_Weight * helper.In.z;//Original did not multiply by weight. Do it here to be consistent with others. } @@ -1266,6 +1281,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { T jun = Zeps(fabs(m_N)); @@ -1317,8 +1337,8 @@ public: T sqY = SQR(helper.In.y); T v = (sqX + sqY) * m_W;//Do not use precalcSumSquares here because its components are needed below. - helper.Out.x = m_Weight * sin(helper.In.x) * (sqX + m_W - v); - helper.Out.y = m_Weight * sin(helper.In.y) * (sqY + m_W - v); + helper.Out.x = m_Weight * std::sin(helper.In.x) * (sqX + m_W - v); + helper.Out.y = m_Weight * std::sin(helper.In.y) * (sqY + m_W - v); helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } @@ -1467,7 +1487,7 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual string OpenCLFuncsString() const override { return "real_t VoronDiscreteNoise(int x)\n" @@ -1611,8 +1631,8 @@ public: virtual void Precalc() override { - m_SinR = sin(m_Rotation); - m_CosR = cos(m_Rotation); + m_SinR = std::sin(m_Rotation); + m_CosR = std::cos(m_Rotation); } protected: @@ -1695,24 +1715,24 @@ public: if (rand.RandBit()) phi1 = -phi1; - sinr = sin(rho1); - cosr = cos(rho1); + sinr = std::sin(rho1); + cosr = std::cos(rho1); - sinp = sin(phi1); - cosp = cos(phi1); + sinp = std::sin(phi1); + cosp = std::cos(phi1); temp = m_M4_1 * rho1; - msinr = sin(temp); - mcosr = cos(temp); + msinr = std::sin(temp); + mcosr = std::cos(temp); temp = m_M4_2 * phi1; - msinp = sin(temp); - mcosp = cos(temp); + msinp = std::sin(temp); + mcosp = std::cos(temp); - pr1 = m_An2_1 * pow(fabs(mcosr), m_N2_1) + m_Bn3_1 * pow(fabs(msinr), m_N3_1); - pr2 = m_An2_2 * pow(fabs(mcosp), m_N2_2) + m_Bn3_2 * pow(fabs(msinp), m_N3_2); - r1 = pow(fabs(pr1), m_N1_1) + m_Spiral * rho1; - r2 = pow(fabs(pr2), m_N1_2); + pr1 = m_An2_1 * std::pow(fabs(mcosr), m_N2_1) + m_Bn3_1 * std::pow(fabs(msinr), m_N3_1); + pr2 = m_An2_2 * std::pow(fabs(mcosp), m_N2_2) + m_Bn3_2 * std::pow(fabs(msinp), m_N3_2); + r1 = std::pow(fabs(pr1), m_N1_1) + m_Spiral * rho1; + r2 = std::pow(fabs(pr2), m_N1_2); if (int(m_Toroidmap) == 1) { @@ -1810,10 +1830,10 @@ public: { m_N1n_1 = (-1 / m_N1_1); m_N1n_2 = (-1 / m_N1_2); - m_An2_1 = pow(fabs(1 / m_A1), m_N2_1); - m_An2_2 = pow(fabs(1 / m_A2), m_N2_2); - m_Bn3_1 = pow(fabs(1 / m_B1), m_N3_1); - m_Bn3_2 = pow(fabs(1 / m_B2), m_N3_2); + m_An2_1 = std::pow(fabs(1 / m_A1), m_N2_1); + m_An2_2 = std::pow(fabs(1 / m_A2), m_N2_2); + m_Bn3_1 = std::pow(fabs(1 / m_B1), m_N3_1); + m_Bn3_2 = std::pow(fabs(1 / m_B2), m_N3_2); m_M4_1 = m_M1 / 4; m_M4_2 = m_M2 / 4; m_Rho2Pi = m_Rho * T(M_2_PI); @@ -1902,8 +1922,8 @@ public: T t, rX, rY, rZ; t = Zeps(helper.m_PrecalcSumSquares + SQR(helper.In.z)); - rX = m_Weight / pow(t, m_StretchX); - rY = m_Weight / pow(t, m_StretchY); + rX = m_Weight / std::pow(t, m_StretchX); + rY = m_Weight / std::pow(t, m_StretchY); helper.Out.x = helper.In.x * rX; helper.Out.y = helper.In.y * rY; @@ -1911,7 +1931,7 @@ public: //Optional 3D calculation. if (int(m_ZOn) == 1) { - rZ = m_Weight / pow(t, m_StretchZ); + rZ = m_Weight / std::pow(t, m_StretchZ); helper.Out.z = helper.In.z * rZ; } } @@ -1948,6 +1968,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -1987,10 +2012,10 @@ public: T yi = helper.In.y - m_Y; const T rad = std::sqrt(SQR(xi) + SQR(yi)); - const T ang = atan2(yi, xi); + const T ang = std::atan2(yi, xi); const T rdc = m_Radius + (rand.Frand01() * T(0.5) * m_Ca); - const T s = sin(ang); - const T c = cos(ang); + const T s = std::sin(ang); + const T c = std::cos(ang); const int esc = rad > m_Radius; const int cr0 = int(m_Zero); @@ -2131,15 +2156,15 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const T z = helper.In.z / m_AbsN; - const T radiusOut = m_Weight * pow(helper.m_PrecalcSumSquares + z * z, m_Cn); + const T radiusOut = m_Weight * std::pow(helper.m_PrecalcSumSquares + z * z, m_Cn); const T x = m_A * helper.In.x + m_B * helper.In.y + m_E; const T y = m_C * helper.In.x + m_D * helper.In.y + m_F; const T tempRand = T(int(rand.Frand01() * m_AbsN)); - const T alpha = (atan2(y, x) + M_2PI * tempRand) / m_Power; + const T alpha = (std::atan2(y, x) + M_2PI * tempRand) / m_Power; const T gamma = radiusOut * helper.m_PrecalcSqrtSumSquares; - helper.Out.x = gamma * cos(alpha); - helper.Out.y = gamma * sin(alpha); + helper.Out.x = gamma * std::cos(alpha); + helper.Out.y = gamma * std::sin(alpha); helper.Out.z = radiusOut * z; } @@ -2234,8 +2259,8 @@ public: { T r = 1 / helper.m_PrecalcSqrtSumSquares; - helper.Out.x = m_Weight * r * cos(helper.m_PrecalcAtanyx); - helper.Out.y = m_Weight * r * sin(helper.m_PrecalcAtanyx); + helper.Out.x = m_Weight * r * std::cos(helper.m_PrecalcAtanyx); + helper.Out.y = m_Weight * r * std::sin(helper.m_PrecalcAtanyx); } else if (helper.In.x > 0 && helper.In.y < 0)//Quadrant I: loonie. { @@ -2262,11 +2287,11 @@ public: if (r < m_Weight) { - T a = atan2(y, x) + m_Spin + m_Twist * (m_Weight - r); + T a = std::atan2(y, x) + m_Spin + m_Twist * (m_Weight - r); r *= m_Weight; - helper.Out.x = r * cos(a) + m_X; - helper.Out.y = r * sin(a) - m_Y; + helper.Out.x = r * std::cos(a) + m_X; + helper.Out.y = r * std::sin(a) - m_Y; } else { @@ -2355,6 +2380,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + virtual void Precalc() override { m_SqrWeight = SQR(m_Weight); @@ -2556,12 +2586,12 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { const T zr = Hypot(helper.In.z, helper.m_PrecalcSqrtSumSquares); - const T phi = acos(Clamp(helper.In.z / zr, -1, 1)); - const T ps = sin(phi); - const T pc = cos(phi); + const T phi = std::acos(Clamp(helper.In.z / zr, -1, 1)); + const T ps = std::sin(phi); + const T pc = std::cos(phi); - helper.Out.x = m_Weight * cos(helper.m_PrecalcAtanyx) * ps * (zr + m_Radius); - helper.Out.y = m_Weight * sin(helper.m_PrecalcAtanyx) * ps * (zr + m_Radius); + helper.Out.x = m_Weight * std::cos(helper.m_PrecalcAtanyx) * ps * (zr + m_Radius); + helper.Out.y = m_Weight * std::sin(helper.m_PrecalcAtanyx) * ps * (zr + m_Radius); helper.Out.z = m_Weight * pc * (zr + m_Radius); } @@ -2575,7 +2605,7 @@ public: ss << "\t{\n" << "\t\tconst real_t zr = Hypot(vIn.z, precalcSqrtSumSquares);\n" - << "\t\tconst real_t phi = acos(Clamp(vIn.z / zr, -(real_t)(1.0), (real_t)(1.0)));\n" + << "\t\tconst real_t phi = acos(clamp(vIn.z / zr, -(real_t)(1.0), (real_t)(1.0)));\n" << "\t\tconst real_t ps = sin(phi);\n" << "\t\tconst real_t pc = cos(phi);\n" << "\n" @@ -2587,6 +2617,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } + protected: void Init() { @@ -2621,11 +2656,11 @@ public: Sqr(helper.In.z - m_ZOrigin)) * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); T u = rand.Frand01() * M_2PI; - T su = sin(u); - T cu = cos(u); + T su = std::sin(u); + T cu = std::cos(u); T v = rand.Frand01() * M_2PI; - T sv = sin(v); - T cv = cos(v); + T sv = std::sin(v); + T cv = std::cos(v); helper.Out.x = m_X * r * sv * cu; helper.Out.y = m_Y * r * sv * su; @@ -2665,6 +2700,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + protected: void Init() { @@ -2749,12 +2789,17 @@ public: << "\t\tvOut.x = (x * re + y * im) * r;\n" << "\t\tvOut.y = (y * re - x * im) * r;\n" << "\t\tvOut.z = (z * xform->m_VariationWeights[" << varIndex << "]) / c;\n" - << "\t\toutPoint->m_ColorX = Clamp(outPoint->m_ColorX + " << dcAdjust << " * c, (real_t)(0.0), (real_t)(1.0));\n" + << "\t\toutPoint->m_ColorX = clamp(outPoint->m_ColorX + " << dcAdjust << " * c, (real_t)(0.0), (real_t)(1.0));\n" << "\t}\n"; return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot", "Spread", "SignNz", "Powq4", "Powq4c", "Zeps" }; + } + virtual void Precalc() override { m_C2x2 = 2 * m_C2; @@ -2810,19 +2855,19 @@ public: { T r = std::sqrt(fabs(helper.m_PrecalcSumSquares + helper.In.z)); - r += m_Ar * sin(fma(m_Br, r, m_Cr)); + r += m_Ar * std::sin(fma(m_Br, r, m_Cr)); if (r == 0) r = EPS; - T temp = fma(m_At, sin(fma(m_Bt, r, m_Ct)), helper.m_PrecalcAtanyx); - T st = sin(temp); - T ct = cos(temp); + T temp = fma(m_At, std::sin(fma(m_Bt, r, m_Ct)), helper.m_PrecalcAtanyx); + T st = std::sin(temp); + T ct = std::cos(temp); - temp = fma(m_Ap, sin(fma(m_Bp, r, m_Cp)), acos(Clamp(helper.In.z / r, -1, 1))); + temp = fma(m_Ap, std::sin(fma(m_Bp, r, m_Cp)), std::acos(Clamp(helper.In.z / r, -1, 1))); - T sp = sin(temp); - T cp = cos(temp); + T sp = std::sin(temp); + T cp = std::cos(temp); helper.Out.x = r * ct * sp; helper.Out.y = r * st * sp; @@ -2866,7 +2911,7 @@ public: << "\t\treal_t st = sin(temp);\n" << "\t\treal_t ct = cos(temp);\n" << "\n" - << "\t\ttemp = fma(" << ap << ", sin(fma(" << bp << ", r, " << cp << ")), acos(Clamp(vIn.z / r, -(real_t)(1.0), (real_t)(1.0))));\n" + << "\t\ttemp = fma(" << ap << ", sin(fma(" << bp << ", r, " << cp << ")), acos(clamp(vIn.z / r, -(real_t)(1.0), (real_t)(1.0))));\n" << "\n" << "\t\treal_t sp = sin(temp);\n" << "\t\treal_t cp = cos(temp);\n" @@ -3080,7 +3125,7 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual string OpenCLFuncsString() const override { return "real_t Interference2Sine(real_t a, real_t b, real_t c, real_t p, real_t x)\n" @@ -3121,17 +3166,17 @@ protected: private: inline static T Sine(T a, T b, T c, T p, T x) { - return a * pow(fabs(sin(b * x + c)), p);//Original did not fabs(). + return a * std::pow(std::fabs(std::sin(b * x + c)), p);//Original did not fabs(). } inline static T Tri(T a, T b, T c, T p, T x) { - return a * 2 * pow(fabs(asin(cos(b * x + c - T(M_PI_2)))) * T(M_1_PI), p);//Original did not fabs(). + return a * 2 * std::pow(std::fabs(std::asin(std::cos(b * x + c - T(M_PI_2)))) * T(M_1_PI), p);//Original did not fabs(). } inline static T Squ(T a, T b, T c, T p, T x) { - return a * pow(sin(b * x + c) < 0 ? EPS : T(1), p);//Original passed -1 to pow if sin() was < 0. Doing so will return NaN, so EPS is passed instead. + return a * std::pow(std::sin(b * x + c) < 0 ? EPS : T(1), p);//Original passed -1 to pow if sin() was < 0. Doing so will return NaN, so EPS is passed instead. } T m_A1; @@ -3160,10 +3205,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T absV = Hypot(helper.In.y, helper.In.z); - T s = sin(helper.In.x); - T c = cos(helper.In.x); - T sh = sinh(absV); - T ch = cosh(absV); + T s = std::sin(helper.In.x); + T c = std::cos(helper.In.x); + T sh = std::sinh(absV); + T ch = std::cosh(absV); T d = m_Weight * c * sh / absV; helper.Out.x = m_Weight * s * ch; @@ -3191,6 +3236,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3207,10 +3257,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T absV = Hypot(helper.In.y, helper.In.z); - T s = sin(absV); - T c = cos(absV); - T sh = sinh(helper.In.x); - T ch = cosh(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); + T sh = std::sinh(helper.In.x); + T ch = std::cosh(helper.In.x); T d = m_Weight * ch * s / absV; helper.Out.x = m_Weight * sh * c; @@ -3238,6 +3288,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3255,10 +3310,10 @@ public: { T absV = Hypot(helper.In.y, helper.In.z); T ni = m_Weight / (helper.m_PrecalcSumSquares + SQR(helper.In.z)); - T s = sin(-helper.In.x); - T c = cos(-helper.In.x); - T sh = sinh(absV); - T ch = cosh(absV); + T s = std::sin(-helper.In.x); + T c = std::cos(-helper.In.x); + T sh = std::sinh(absV); + T ch = std::cosh(absV); T d = ni * s * sh / absV; helper.Out.x = c * ch * ni; @@ -3287,6 +3342,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3304,10 +3364,10 @@ public: { T absV = Hypot(helper.In.y, helper.In.z); T ni = m_Weight / (helper.m_PrecalcSumSquares + SQR(helper.In.z)); - T s = sin(absV); - T c = cos(absV); - T sh = sinh(helper.In.x); - T ch = cosh(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); + T sh = std::sinh(helper.In.x); + T ch = std::cosh(helper.In.x); T d = ni * sh * s / absV; helper.Out.x = ch * c * ni; @@ -3336,6 +3396,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3354,10 +3419,10 @@ public: T sysz = SQR(helper.In.y) + SQR(helper.In.z); T absV = std::sqrt(sysz); T ni = m_Weight / (SQR(helper.In.x) + sysz); - T s = sin(helper.In.x); - T c = cos(helper.In.x); - T sh = sinh(absV); - T ch = cosh(absV); + T s = std::sin(helper.In.x); + T c = std::cos(helper.In.x); + T sh = std::sinh(absV); + T ch = std::cosh(absV); T d = c * sh / absV; T b = -s * sh / absV; T stcv = s * ch; @@ -3413,10 +3478,10 @@ public: T sysz = SQR(helper.In.y) + SQR(helper.In.z); T absV = std::sqrt(sysz); T ni = m_Weight / (SQR(helper.In.x) + sysz); - T s = sin(absV); - T c = cos(absV); - T sh = sinh(helper.In.x); - T ch = cosh(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); + T sh = std::sinh(helper.In.x); + T ch = std::cosh(helper.In.x); T d = ch * s / absV; T b = sh * s / absV; T stcv = sh * c; @@ -3470,10 +3535,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T absV = Hypot(helper.In.y, helper.In.z); - T s = sin(helper.In.x); - T c = cos(helper.In.x); - T sh = sinh(absV); - T ch = cosh(absV); + T s = std::sin(helper.In.x); + T c = std::cos(helper.In.x); + T sh = std::sinh(absV); + T ch = std::cosh(absV); T d = -m_Weight * s * sh / absV; helper.Out.x = m_Weight * c * ch; @@ -3501,6 +3566,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3517,10 +3587,10 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T absV = Hypot(helper.In.y, helper.In.z); - T s = sin(absV); - T c = cos(absV); - T sh = sinh(helper.In.x); - T ch = cosh(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); + T sh = std::sinh(helper.In.x); + T ch = std::cosh(helper.In.x); T d = -m_Weight * sh * s / absV; helper.Out.x = m_Weight * c * ch; @@ -3548,6 +3618,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3566,10 +3641,10 @@ public: T sysz = SQR(helper.In.y) + SQR(helper.In.z); T absV = std::sqrt(sysz); T ni = m_Weight / (SQR(helper.In.x) + sysz); - T s = sin(helper.In.x); - T c = cos(helper.In.x); - T sh = sinh(absV); - T ch = cosh(absV); + T s = std::sin(helper.In.x); + T c = std::cos(helper.In.x); + T sh = std::sinh(absV); + T ch = std::cosh(absV); T d = c * sh / absV; T b = -s * sh / absV; T stcv = s * ch; @@ -3625,10 +3700,10 @@ public: T sysz = SQR(helper.In.y) + SQR(helper.In.z); T absV = std::sqrt(sysz); T ni = m_Weight / (SQR(helper.In.x) + sysz); - T s = sin(absV); - T c = cos(absV); - T sh = sinh(helper.In.x); - T ch = cosh(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); + T sh = std::sinh(helper.In.x); + T ch = std::cosh(helper.In.x); T d = ch * s / absV; T b = sh * s / absV; T stcv = sh * c; @@ -3683,10 +3758,10 @@ public: { T absV = Hypot(helper.In.y, helper.In.z); T ni = m_Weight / (helper.m_PrecalcSumSquares + SQR(helper.In.z)); - T s = sin(helper.In.x); - T c = cos(helper.In.x); - T sh = sinh(absV); - T ch = cosh(absV); + T s = std::sin(helper.In.x); + T c = std::cos(helper.In.x); + T sh = std::sinh(absV); + T ch = std::cosh(absV); T d = ni * c * sh / absV; helper.Out.x = s * ch * ni; @@ -3715,6 +3790,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3732,10 +3812,10 @@ public: { T absV = Hypot(helper.In.y, helper.In.z); T ni = m_Weight / (helper.m_PrecalcSumSquares + SQR(helper.In.z)); - T s = sin(absV); - T c = cos(absV); - T sh = sinh(helper.In.x); - T ch = cosh(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); + T sh = std::sinh(helper.In.x); + T ch = std::cosh(helper.In.x); T d = ni * ch * s / absV; helper.Out.x = sh * c * ni; @@ -3764,6 +3844,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3780,9 +3865,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T absV = Hypot(helper.In.y, helper.In.z); - T e = exp(helper.In.x); - T s = sin(absV); - T c = cos(absV); + T e = std::exp(helper.In.x); + T s = std::sin(absV); + T c = std::cos(absV); T a = e * s / absV; helper.Out.x = m_Weight * e * c; @@ -3809,6 +3894,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } }; /// @@ -3828,9 +3918,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T absV = Hypot(helper.In.y, helper.In.z); - T c = m_Weight * atan2(absV, helper.In.x) / absV; + T c = m_Weight * std::atan2(absV, helper.In.x) / absV; - helper.Out.x = log(SQR(helper.In.x) + SQR(absV)) * m_Denom; + helper.Out.x = std::log(SQR(helper.In.x) + SQR(absV)) * m_Denom; helper.Out.y = c * helper.In.y; helper.Out.z = c * helper.In.z; } @@ -3855,10 +3945,15 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } virtual void Precalc() override { - m_Denom = T(0.5) / log(m_Base); + m_Denom = T(0.5) / std::log(m_Base); } protected: @@ -3907,6 +4002,11 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } }; /// @@ -4024,7 +4124,7 @@ public: T xx = (rand.Frand01() - T(0.5)) * 2; T yy = (rand.Frand01() - T(0.5)) * 2; T k = SignNz(yy); - T yymax = ((m_A * pow(fabs(xx), m_P) + k * m_B * std::sqrt(fabs(1 - SQR(xx)))) - m_A); + T yymax = ((m_A * std::pow(fabs(xx), m_P) + k * m_B * std::sqrt(fabs(1 - SQR(xx)))) - m_A); //The function must be in a range 0-1 to work properly. yymax /= Zeps(fabs(m_A) + fabs(m_B)); @@ -4083,6 +4183,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SignNz", "Zeps" }; + } + protected: void Init() { @@ -4190,26 +4295,26 @@ public: { if (tileType < 1) { - r0 = pow((pow(fabs(x ), m_Exponent) + pow(fabs(y ), m_Exponent)), m_OneOverEx); - r1 = pow((pow(fabs(x - 1), m_Exponent) + pow(fabs(y - 1), m_Exponent)), m_OneOverEx); + r0 = std::pow((pow(fabs(x ), m_Exponent) + std::pow(fabs(y ), m_Exponent)), m_OneOverEx); + r1 = std::pow((pow(fabs(x - 1), m_Exponent) + std::pow(fabs(y - 1), m_Exponent)), m_OneOverEx); } else { - r0 = pow((pow(fabs(x - 1), m_Exponent) + pow(fabs(y ), m_Exponent)), m_OneOverEx); - r1 = pow((pow(fabs(x ), m_Exponent) + pow(fabs(y - 1), m_Exponent)), m_OneOverEx); + r0 = std::pow((pow(fabs(x - 1), m_Exponent) + std::pow(fabs(y ), m_Exponent)), m_OneOverEx); + r1 = std::pow((pow(fabs(x ), m_Exponent) + std::pow(fabs(y - 1), m_Exponent)), m_OneOverEx); } } else//Slow drawmode { if (tileType == 1) { - r0 = pow((pow(fabs(x ), m_Exponent) + pow(fabs(y ), m_Exponent)), m_OneOverEx); - r1 = pow((pow(fabs(x - 1), m_Exponent) + pow(fabs(y - 1), m_Exponent)), m_OneOverEx); + r0 = std::pow((std::pow(fabs(x ), m_Exponent) + std::pow(fabs(y ), m_Exponent)), m_OneOverEx); + r1 = std::pow((std::pow(fabs(x - 1), m_Exponent) + std::pow(fabs(y - 1), m_Exponent)), m_OneOverEx); } else { - r0 = pow((pow(fabs(x - 1), m_Exponent) + pow(fabs(y ), m_Exponent)), m_OneOverEx); - r1 = pow((pow(fabs(x ), m_Exponent) + pow(fabs(y - 1), m_Exponent)), m_OneOverEx); + r0 = std::pow((std::pow(fabs(x - 1), m_Exponent) + std::pow(fabs(y ), m_Exponent)), m_OneOverEx); + r1 = std::pow((std::pow(fabs(x ), m_Exponent) + std::pow(fabs(y - 1), m_Exponent)), m_OneOverEx); } } @@ -4378,13 +4483,18 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Round" }; + } + virtual void Precalc() override { m_OneOverEx = 1 / m_Exponent; m_AbsSeed = fabs(m_Seed); m_Seed2 = std::sqrt(Zeps(m_AbsSeed + (m_AbsSeed / 2))) / Zeps((m_AbsSeed * T(0.5))) * T(0.25); - m_OneOverRmax = 1 / (T(0.5) * (pow(T(2), 1 / m_Exponent) - 1) * m_ArcWidth); - m_Scale = (cos(-m_Rotation) - sin(-m_Rotation)) / m_Weight; + m_OneOverRmax = 1 / (T(0.5) * (std::pow(T(2), 1 / m_Exponent) - 1) * m_ArcWidth); + m_Scale = (std::cos(-m_Rotation) - std::sin(-m_Rotation)) / m_Weight; } protected: @@ -4508,7 +4618,7 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual string OpenCLFuncsString() const override { return "inline real_t GdoffsFcip(real_t a) { return (real_t)((a < 0) ? -((int)(fabs(a)) + 1) : 0) + ((a > 1) ? ((int)(a)) : 0); }\n" @@ -4561,7 +4671,7 @@ private: static inline T GdoffsFcip(T a) { return T((a < 0) ? -(int(fabs(a)) + 1) : 0) + ((a > 1) ? (int(a)) : 0); } static inline T GdoffsFclp(T a) { return ((a < 0) ? -(fmod(fabs(a), T(1))) : fmod(fabs(a), T(1))); } static inline T GdoffsFscl(T a) { return GdoffsFclp((a + 1) / 2); } - static inline T GdoffsFosc(T p, T a) { return GdoffsFscl(-1 * cos(p * a * M_2PI)); } + static inline T GdoffsFosc(T p, T a) { return GdoffsFscl(-1 * std::cos(p * a * M_2PI)); } static inline T GdoffsFlip(T a, T b, T c) { return (c * (b - a) + a); } T m_DeltaX;//Params. @@ -4703,6 +4813,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + protected: void Init() { @@ -4748,8 +4863,8 @@ public: r *= m_R2 / m_R1; temp = atan2(helper.In.y, c1mx); - helper.Out.x = m_Weight * (r * cos(temp) - m_C2); - helper.Out.y = m_Weight * r * sin(temp); + helper.Out.x = m_Weight * (r * std::cos(temp) - m_C2); + helper.Out.y = m_Weight * r * std::sin(temp); } else { @@ -4767,8 +4882,8 @@ public: r *= m_R1 / m_R2; temp = atan2(helper.In.y, c1mx); - helper.Out.x = m_Weight * (r * cos(temp) + m_C1); - helper.Out.y = m_Weight * r * sin(temp); + helper.Out.x = m_Weight * (r * std::cos(temp) + m_C1); + helper.Out.y = m_Weight * r * std::sin(temp); } else { @@ -4887,12 +5002,12 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T arg = helper.m_PrecalcAtanyx + fmod(T(rand.Rand()), T(1 / m_ReInv)) * M_2PI; - T lnmod = m_Dist * T(0.5) * log(helper.m_PrecalcSumSquares); + T lnmod = m_Dist * T(0.5) * std::log(helper.m_PrecalcSumSquares); T temp = arg * m_ReInv + lnmod * m_Im100; - T mod2 = exp(lnmod * m_ReInv - arg * m_Im100); + T mod2 = std::exp(lnmod * m_ReInv - arg * m_Im100); - helper.Out.x = m_Weight * mod2 * cos(temp); - helper.Out.y = m_Weight * mod2 * sin(temp); + helper.Out.x = m_Weight * mod2 * std::cos(temp); + helper.Out.y = m_Weight * mod2 * std::sin(temp); helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } @@ -5006,11 +5121,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T r = helper.m_PrecalcSqrtSumSquares * (m_BlobLow + m_BlobDiff * (T(0.5) + T(0.5) * sin(m_BlobWaves * helper.m_PrecalcAtanxy))); + T r = helper.m_PrecalcSqrtSumSquares * (m_BlobLow + m_BlobDiff * (T(0.5) + T(0.5) * std::sin(m_BlobWaves * helper.m_PrecalcAtanxy))); helper.Out.x = m_Weight * helper.m_PrecalcSina * r; helper.Out.y = m_Weight * helper.m_PrecalcCosa * r; - helper.Out.z = m_Weight * sin(m_BlobWaves * helper.m_PrecalcAtanxy) * r; + helper.Out.z = m_Weight * std::sin(m_BlobWaves * helper.m_PrecalcAtanxy) * r; } virtual string OpenCLString() const override @@ -5082,7 +5197,7 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T t = Zeps((cos(helper.In.x) + cos(helper.In.y)) / m_Mp + 1); + T t = Zeps((std::cos(helper.In.x) + std::cos(helper.In.y)) / m_Mp + 1); T r = m_Weight / t; T tmp = helper.m_PrecalcSumSquares + 1; T x2 = 2 * helper.In.x; @@ -5137,6 +5252,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SafeSqrt", "Zeps" }; + } + virtual void Precalc() override { m_V = m_Weight / T(M_PI_2); diff --git a/Source/Ember/Variations05.h b/Source/Ember/Variations05.h index 0f59d9c..672307f 100644 --- a/Source/Ember/Variations05.h +++ b/Source/Ember/Variations05.h @@ -208,7 +208,12 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot", "Zeps" }; + } + + virtual string OpenCLFuncsString() const override { return "real_t CircleLinearDiscreteNoise2(int x, int y)\n" @@ -339,7 +344,12 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } + + virtual string OpenCLFuncsString() const override { return "real_t CircleRandDiscreteNoise2(int x, int y)\n" @@ -470,7 +480,7 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual string OpenCLFuncsString() const override { return "real_t CircleTrans1DiscreteNoise2(int x, int y)\n" @@ -516,6 +526,11 @@ public: "\n"; } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Hypot" }; + } + protected: void Init() { @@ -559,8 +574,8 @@ private: n = Floor(T(0.5) * y / m_Sc); alpha = M_2PI * rand.Frand01(); u = T(0.3) + T(0.7) * DiscreteNoise2(int(m + 10), int(n + 3)); - x = u * cos(alpha); - y = u * sin(alpha); + x = u * std::cos(alpha); + y = u * std::sin(alpha); if (++iters > 10) break; @@ -599,8 +614,8 @@ public: T lattd = m_Weight * T(0.5); T px, py, pz; - exnze = 1 - (m_SmoothStyle * (1 - (cos(atan2(helper.In.x, helper.In.z))))); - wynze = 1 - (m_SmoothStyle * (1 - (sin(atan2(helper.In.y, helper.In.z))))); + exnze = 1 - (m_SmoothStyle * (1 - (std::cos(std::atan2(helper.In.x, helper.In.z))))); + wynze = 1 - (m_SmoothStyle * (1 - (std::sin(std::atan2(helper.In.y, helper.In.z))))); if (m_SmoothStyle > 1) znxy = 1 - (m_SmoothStyle * (1 - ((exnze + wynze) / 2 * m_SmoothStyle))); @@ -823,8 +838,8 @@ public: if (m_Style == 2) { - exnze = cos(atan2(helper.In.x, helper.In.z)); - wynze = sin(atan2(helper.In.y, helper.In.z)); + exnze = std::cos(std::atan2(helper.In.x, helper.In.z)); + wynze = std::sin(std::atan2(helper.In.y, helper.In.z)); znxy = (exnze + wynze) * T(0.5); } else @@ -1029,14 +1044,14 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - T expx = exp(helper.In.x) * T(0.5); + T expx = std::exp(helper.In.x) * T(0.5); T expnx = T(0.25) / expx; T boot = helper.In.z == 0 ? helper.m_PrecalcAtanyx : helper.In.z; - T tmp = m_Weight / (expx + expnx - (cos(helper.In.y) * cos(boot))); + T tmp = m_Weight / (expx + expnx - (std::cos(helper.In.y) * std::cos(boot))); helper.Out.x = (expx - expnx) * tmp; - helper.Out.y = sin(helper.In.y) * tmp; - helper.Out.z = sin(boot) * tmp; + helper.Out.y = std::sin(helper.In.y) * tmp; + helper.Out.z = std::sin(boot) * tmp; } virtual string OpenCLString() const override @@ -1080,15 +1095,15 @@ public: T ww = SQR(helper.In.z); T atOmegaX = atan2(vv, ww); T atOmegaY = atan2(uu, ww); - T su = sin(helper.In.x); - T cu = cos(helper.In.x); - T sv = sin(helper.In.y); - T cv = cos(helper.In.y); + T su = std::sin(helper.In.x); + T cu = std::cos(helper.In.x); + T sv = std::sin(helper.In.y); + T cv = std::cos(helper.In.y); T cucv = cu * cv; T sucv = su * cv; - T x = pow(fabs(cucv), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must fabs first argument to pow, because negative values will return NaN. - T y = pow(fabs(sucv), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values. - T z = pow(fabs(sv), m_ZPow) + sv * m_ZPow; + T x = std::pow(fabs(cucv), m_XPow) + (cucv * m_XPow) + (T(0.25) * atOmegaX);//Must fabs first argument to pow, because negative values will return NaN. + T y = std::pow(fabs(sucv), m_YPow) + (sucv * m_YPow) + (T(0.25) * atOmegaY);//Original did not do this and would frequently return bad values. + T z = std::pow(fabs(sv), m_ZPow) + sv * m_ZPow; helper.Out.x = m_Weight * x; helper.Out.y = m_Weight * y; @@ -1163,11 +1178,11 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T temp = helper.m_PrecalcAtanyx * m_InvPower + rand.Rand() * m_InvPower2pi; - T sina = sin(temp); - T cosa = cos(temp); + T sina = std::sin(temp); + T cosa = std::cos(temp); T z = helper.In.z * m_AbsInvPower; T r2d = helper.m_PrecalcSumSquares; - T r = m_Weight * pow(r2d + SQR(z), m_HalfInvPower); + T r = m_Weight * std::pow(r2d + SQR(z), m_HalfInvPower); T rsss = r * helper.m_PrecalcSqrtSumSquares; helper.Out.x = rsss * cosa; @@ -1285,9 +1300,9 @@ public: virtual void Precalc() override { //Unit vector of the line. - m_Ux = cos(m_Delta * T(M_PI)) * cos(m_Phi * T(M_PI)); - m_Uy = sin(m_Delta * T(M_PI)) * cos(m_Phi * T(M_PI)); - m_Uz = sin(m_Phi * T(M_PI)); + m_Ux = std::cos(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI)); + m_Uy = std::sin(m_Delta * T(M_PI)) * std::cos(m_Phi * T(M_PI)); + m_Uz = std::sin(m_Phi * T(M_PI)); T r = std::sqrt(SQR(m_Ux) + SQR(m_Uy) + SQR(m_Uz)); @@ -1318,6 +1333,266 @@ private: T m_Uz; }; +/// +/// Loonie2. +/// +template +class EMBER_API Loonie2Variation : public ParametricVariation +{ +public: + Loonie2Variation(T weight = 1.0) : ParametricVariation("loonie2", VAR_LOONIE2, weight, true, true) + { + Init(); + } + + PARVARCOPY(Loonie2Variation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + int i; + T xrt = helper.In.x, yrt = helper.In.y, swp; + T r2 = xrt * m_Coss + fabs(yrt) * m_Sins; + T circle = helper.m_PrecalcSqrtSumSquares; + + for (i = 0; i < m_Sides - 1; i++) + { + swp = xrt * m_Cosa - yrt * m_Sina; + yrt = xrt * m_Sina + yrt * m_Cosa; + xrt = swp; + + r2 = std::max(r2, xrt * m_Coss + fabs(yrt) * m_Sins); + } + + r2 = r2 * m_Cosc + circle * m_Sinc; + + if (i > 1) + r2 = SQR(r2); + else + r2 = fabs(r2) * r2; + + if (r2 > 0 && (r2 < m_W2)) + { + T r = m_Weight * std::sqrt(fabs(m_W2 / r2 - 1)); + + helper.Out.x = r * helper.In.x; + helper.Out.y = r * helper.In.y; + } + else if (r2 < 0) + { + T r = m_Weight / std::sqrt(fabs(m_W2 / r2) - 1); + + helper.Out.x = r * helper.In.x; + helper.Out.y = r * helper.In.y; + } + else + { + helper.Out.x = m_Weight * helper.In.x; + helper.Out.y = m_Weight * helper.In.y; + } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string star = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string circle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sins = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string coss = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sinc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string cosc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + << "\t\tint i;\n" + << "\t\treal_t xrt = vIn.x, yrt = vIn.y, swp;\n" + << "\t\treal_t r2 = xrt * " << coss << " + fabs(yrt) * " << sins << ";\n" + << "\t\treal_t circle = precalcSqrtSumSquares;\n" + << "\n" + << "\t\tfor (i = 0; i < " << sides << " - 1; i++)\n" + << "\t\t{\n" + << "\t\t swp = xrt * " << cosa << " - yrt * " << sina << ";\n" + << "\t\t yrt = xrt * " << sina << " + yrt * " << cosa << ";\n" + << "\t\t xrt = swp;\n" + << "\n" + << "\t\t r2 = max(r2, xrt * " << coss << " + fabs(yrt) * " << sins << ");\n" + << "\t\t}\n" + << "\n" + << "\t\tr2 = r2 * " << cosc << " + circle * " << sinc << ";\n" + << "\n" + << "\t\tif (i > 1)\n" + << "\t\t r2 = SQR(r2);\n" + << "\t\telse\n" + << "\t\t r2 = fabs(r2) * r2;\n" + << "\n" + << "\t\tif (r2 > 0 && (r2 < " << w2 << "))\n" + << "\t\t{\n" + << "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(fabs(" << w2 << " / r2 - 1));\n" + << "\n" + << "\t\t vOut.x = r * vIn.x;\n" + << "\t\t vOut.y = r * vIn.y;\n" + << "\t\t}\n" + << "\t\telse if (r2 < 0)\n" + << "\t\t{\n" + << "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] / sqrt(fabs(" << w2 << " / r2) - 1);\n" + << "\n" + << "\t\t vOut.x = r * vIn.x;\n" + << "\t\t vOut.y = r * vIn.y;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" + << "\t\t}\n" + << "\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" + << "\t}\n"; + + return ss.str(); + } + + virtual void Precalc() override + { + auto a = M_2PI / m_Sides; + auto s = T(-M_PI_2) * m_Star; + auto c = T(M_PI_2) * m_Circle; + + m_W2 = SQR(m_Weight); + sincos(a, &m_Sina, &m_Cosa); + sincos(s, &m_Sins, &m_Coss); + sincos(c, &m_Sinc, &m_Cosc); + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.push_back(ParamWithName(&m_Sides, prefix + "loonie2_sides", 4, INTEGER, 1, 50)); + m_Params.push_back(ParamWithName(&m_Star, prefix + "loonie2_star", 0, REAL, -1, 1)); + m_Params.push_back(ParamWithName(&m_Circle, prefix + "loonie2_circle", 0, REAL, -1, 1)); + m_Params.push_back(ParamWithName(true, &m_W2, prefix + "loonie2_w2"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_Sina, prefix + "loonie2_sina")); + m_Params.push_back(ParamWithName(true, &m_Cosa, prefix + "loonie2_cosa")); + m_Params.push_back(ParamWithName(true, &m_Sins, prefix + "loonie2_sins")); + m_Params.push_back(ParamWithName(true, &m_Coss, prefix + "loonie2_coss")); + m_Params.push_back(ParamWithName(true, &m_Sinc, prefix + "loonie2_sinc")); + m_Params.push_back(ParamWithName(true, &m_Cosc, prefix + "loonie2_cosc")); + } + +private: + T m_Sides; + T m_Star; + T m_Circle; + T m_W2;//Precalc. + T m_Sina; + T m_Cosa; + T m_Sins; + T m_Coss; + T m_Sinc; + T m_Cosc; +}; + +/// +/// Loonie3. +/// +template +class EMBER_API Loonie3Variation : public ParametricVariation +{ +public: + Loonie3Variation(T weight = 1.0) : ParametricVariation("loonie3", VAR_LOONIE3, weight, true) + { + Init(); + } + + PARVARCOPY(Loonie3Variation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + T r2; + + if (helper.In.x > EPS) + r2 = SQR(helper.m_PrecalcSumSquares / helper.In.x); + else + r2 = 2 * m_W2; + + if (r2 < m_W2) + { + T r = m_Weight * std::sqrt(m_W2 / r2 - 1); + + helper.Out.x = r * helper.In.x; + helper.Out.y = r * helper.In.y; + } + else + { + helper.Out.x = m_Weight * helper.In.x; + helper.Out.y = m_Weight * helper.In.y; + } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + << "\t\treal_t r2;\n" + << "\n" + << "\t\tif (vIn.x > EPS)\n" + << "\t\t r2 = SQR(precalcSumSquares / vIn.x);\n" + << "\t\telse\n" + << "\t\t r2 = 2 * " << w2 << ";\n" + << "\n" + << "\t\tif (r2 < " << w2 << ")\n" + << "\t\t{\n" + << "\t\t real_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(" << w2 << " / r2 - 1);\n" + << "\n" + << "\t\t vOut.x = r * vIn.x;\n" + << "\t\t vOut.y = r * vIn.y;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" + << "\t\t}\n" + << "\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" + << "\t}\n"; + + return ss.str(); + } + + virtual void Precalc() override + { + m_W2 = SQR(m_Weight); + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.push_back(ParamWithName(true, &m_W2, prefix + "loonie3_w2"));//Precalc. + } + +private: + T m_W2;//Precalc. +}; + /// /// loonie_3D. /// @@ -1495,9 +1770,9 @@ public: { T avgxy = (helper.In.x + helper.In.y) * T(0.5); - helper.Out.x = m_Weight * (helper.In.x + m_Scale * sin(helper.In.y * m_Freq)); - helper.Out.y = m_Weight * (helper.In.y + m_Scale * sin(helper.In.x * m_Freq)); - helper.Out.z = m_Weight * (helper.In.z + m_Scale * sin(avgxy * m_Freq));//Averages the XY to get Z. + helper.Out.x = m_Weight * (helper.In.x + m_Scale * std::sin(helper.In.y * m_Freq)); + helper.Out.y = m_Weight * (helper.In.y + m_Scale * std::sin(helper.In.x * m_Freq)); + helper.Out.z = m_Weight * (helper.In.z + m_Scale * std::sin(avgxy * m_Freq));//Averages the XY to get Z. } virtual string OpenCLString() const override @@ -1555,9 +1830,9 @@ public: T a = m_Rotation + M_2PI * (sl + rand.Frand01() * m_Thickness) / m_Slices; T r = m_Weight * rand.Frand01(); - helper.Out.x = r * cos(a); - helper.Out.y = r * sin(a); - helper.Out.z = m_Weight * sin(r); + helper.Out.x = r * std::cos(a); + helper.Out.y = r * std::sin(a); + helper.Out.z = m_Weight * std::sin(r); } virtual string OpenCLString() const override @@ -1634,8 +1909,8 @@ public: if (otherZ == 0) tempPZ = m_Vv * m_SinTanC * helper.m_PrecalcAtanyx; - helper.Out.x = m_HalfWeight * (helper.In.x + m_X * sin(SafeTan(m_C * helper.In.y))); - helper.Out.y = m_HalfWeight * (helper.In.y + m_Y * sin(SafeTan(m_C * helper.In.x))); + helper.Out.x = m_HalfWeight * (helper.In.x + m_X * std::sin(SafeTan(m_C * helper.In.y))); + helper.Out.y = m_HalfWeight * (helper.In.y + m_Y * std::sin(SafeTan(m_C * helper.In.x))); helper.Out.z = tempPZ + m_Vv * (m_Z * m_SinTanC * tempTZ); } @@ -1673,9 +1948,14 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + virtual void Precalc() override { - m_SinTanC = sin(SafeTan(m_C)); + m_SinTanC = std::sin(SafeTan(m_C)); m_HalfWeight = m_Weight * T(0.5); if (fabs(m_Weight) <= 1) @@ -1730,9 +2010,9 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { - helper.Out.x = m_Weight * sin(helper.In.x); - helper.Out.y = m_Weight * sin(helper.In.y); - helper.Out.z = m_Weight * (atan2(SQR(helper.In.x), SQR(helper.In.y)) * cos(helper.In.z)); + helper.Out.x = m_Weight * std::sin(helper.In.x); + helper.Out.y = m_Weight * std::sin(helper.In.y); + helper.Out.z = m_Weight * (std::atan2(SQR(helper.In.x), SQR(helper.In.y)) * std::cos(helper.In.z)); } virtual string OpenCLString() const override @@ -1838,8 +2118,6 @@ public: helper.Out.x = m_Xw * ((xrng - int(xrng)) * m_XWidth + int(xrng) + (T(0.5) - xpos) * m_1mX); helper.Out.y = m_Yw * ((yrng - int(yrng)) * m_YWidth + int(yrng) + (T(0.5) - ypos) * m_1mY); helper.Out.z = m_Weight * helper.In.z; - //outPoint.m_X = 0; - //outPoint.m_Y = 0; } virtual string OpenCLString() const override @@ -2073,8 +2351,8 @@ public: if (r > 0) a = T(M_PI) - a; - helper.Out.x = m_Weight * r * cos(a); - helper.Out.y = m_Weight * r * sin(a); + helper.Out.x = m_Weight * r * std::cos(a); + helper.Out.y = m_Weight * r * std::sin(a); helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; } @@ -2133,14 +2411,14 @@ public: helper.Out.z = m_Weight * (helper.In.z + m_MulZ * az * rs); break; case 1://Radial. - sigma = asin(r == 0 ? 0 : helper.In.z / r) + m_MulZ * az * rs; + sigma = std::asin(r == 0 ? 0 : helper.In.z / r) + m_MulZ * az * rs; phi = helper.m_PrecalcAtanyx + m_MulY * ay * rs; rad = r + m_MulX * ax * rs; - sigmas = sin(sigma); - sigmac = cos(sigma); - phis = sin(phi); - phic = cos(phi); + sigmas = std::sin(sigma); + sigmac = std::cos(sigma); + phis = std::sin(phi); + phic = std::cos(phi); helper.Out.x = m_Weight * (rad * sigmac * phic); helper.Out.y = m_Weight * (rad * sigmac * phis); @@ -2150,9 +2428,9 @@ public: default: scale = Clamp(rs, 0, T(0.9)) + T(0.1); denom = 1 / scale; - helper.Out.x = m_Weight * Lerp(helper.In.x, floor(helper.In.x * denom) + scale * ax, m_MulX * rs) + m_MulX * pow(ax, m_BoxPow) * rs * denom;//m_BoxPow should be an integer value held in T, - helper.Out.y = m_Weight * Lerp(helper.In.y, floor(helper.In.y * denom) + scale * ay, m_MulY * rs) + m_MulY * pow(ay, m_BoxPow) * rs * denom;//so fabs() shouldn't be necessary. - helper.Out.z = m_Weight * Lerp(helper.In.z, floor(helper.In.z * denom) + scale * az, m_MulZ * rs) + m_MulZ * pow(az, m_BoxPow) * rs * denom; + helper.Out.x = m_Weight * Lerp(helper.In.x, floor(helper.In.x * denom) + scale * ax, m_MulX * rs) + m_MulX * std::pow(ax, m_BoxPow) * rs * denom;//m_BoxPow should be an integer value held in T, + helper.Out.y = m_Weight * Lerp(helper.In.y, floor(helper.In.y * denom) + scale * ay, m_MulY * rs) + m_MulY * std::pow(ay, m_BoxPow) * rs * denom;//so fabs() shouldn't be necessary. + helper.Out.z = m_Weight * Lerp(helper.In.z, floor(helper.In.z * denom) + scale * az, m_MulZ * rs) + m_MulZ * std::pow(az, m_BoxPow) * rs * denom; break; } } @@ -2209,7 +2487,7 @@ public: << "\t\t vOut.z = xform->m_VariationWeights[" << varIndex << "] * (rad * sigmas);\n" << "\t\t break;\n" << "\t\t case 2:\n" - << "\t\t scale = Clamp(rs, 0, (real_t)(0.9)) + (real_t)(0.1);\n" + << "\t\t scale = clamp(rs, (real_t)(0.0), (real_t)(0.9)) + (real_t)(0.1);\n" << "\t\t denom = 1 / scale;\n" << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * Lerp(vIn.x, floor(vIn.x * denom) + scale * ax, " << mulX << " * rs) + " << mulX << " * pow(ax, " << boxPow << ") * rs * denom;\n" << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * Lerp(vIn.y, floor(vIn.y * denom) + scale * ay, " << mulY << " * rs) + " << mulY << " * pow(ay, " << boxPow << ") * rs * denom;\n" @@ -2221,6 +2499,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr", "Lerp" }; + } + virtual void Precalc() override { m_InternalScatter = T(0.04) * m_Scatter; @@ -2302,13 +2585,13 @@ public: else { const T rIn = std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z)); - const T sigma = asin(helper.In.z / rIn) + m_MulZ * random.z * dist; + const T sigma = std::asin(helper.In.z / rIn) + m_MulZ * random.z * dist; const T phi = helper.m_PrecalcAtanyx + m_MulY * random.y * dist; const T r = rIn + m_MulX * random.x * dist; - const T sigmas = sin(sigma); - const T sigmac = cos(sigma); - const T phis = sin(phi); - const T phic = cos(phi); + const T sigmas = std::sin(sigma); + const T sigmac = std::cos(sigma); + const T phis = std::sin(phi); + const T phic = std::cos(phi); helper.Out.x = r * sigmac * phic; helper.Out.y = r * sigmac * phis; @@ -2322,10 +2605,10 @@ public: const T sigma = dist * random.y * M_2PI; const T phi = dist * random.z * T(M_PI); const T rad = dist * random.x; - const T sigmas = sin(sigma); - const T sigmac = cos(sigma); - const T phis = sin(phi); - const T phic = cos(phi); + const T sigmas = std::sin(sigma); + const T sigmac = std::cos(sigma); + const T phis = std::sin(phi); + const T phic = std::cos(phi); helper.Out.x = helper.In.x + m_MulX * rad * sigmac * phic; helper.Out.y = helper.In.y + m_MulY * rad * sigmac * phis; @@ -2418,6 +2701,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + virtual void Precalc() override { m_RMax = T(0.04) * m_Scatter; @@ -2497,10 +2785,10 @@ public: const T sigma = dist * random.y * M_2PI; const T phi = dist * random.z * T(M_PI); const T rad = dist * random.x; - const T sigmas = sin(sigma); - const T sigmac = cos(sigma); - const T phis = sin(phi); - const T phic = cos(phi); + const T sigmas = std::sin(sigma); + const T sigmac = std::cos(sigma); + const T phis = std::sin(phi); + const T phic = std::cos(phi); helper.Out.x = helper.In.x + m_MulX * rad * sigmac * phic; helper.Out.y = helper.In.y + m_MulY * rad * sigmac * phis; @@ -2518,13 +2806,13 @@ public: else { const T rIn = std::sqrt(helper.m_PrecalcSumSquares + SQR(helper.In.z)); - const T sigma = asin(helper.In.z / rIn) + m_MulZ * random.z * dist; + const T sigma = std::asin(helper.In.z / rIn) + m_MulZ * random.z * dist; const T phi = helper.m_PrecalcAtanyx + m_MulY * random.y * dist; const T r = rIn + m_MulX * random.x * dist; - const T sigmas = sin(sigma); - const T sigmac = cos(sigma); - const T phis = sin(phi); - const T phic = cos(phi); + const T sigmas = std::sin(sigma); + const T sigmac = std::cos(sigma); + const T phis = std::sin(phi); + const T phic = std::cos(phi); helper.Out.x = r * sigmac * phic; helper.Out.y = r * sigmac * phis; @@ -2644,6 +2932,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "SignNz", "LogMap", "LogScale", "Sqr" }; + } + virtual void Precalc() override { m_RMax = T(0.04) * m_BlurStrength; @@ -2864,7 +3157,7 @@ public: return ss.str(); } - virtual string OpenCLFuncsString() const + virtual string OpenCLFuncsString() const override { return "\n" @@ -3093,10 +3386,10 @@ private: T inx = (be - m_Radius + (al - m_Radius) * m_CosC) / m_SinC; T iny = al - m_Radius; T angle = (atan2(iny, inx) + M_2PI * (rand.Rand(int(m_AbsN)))) / m_Power; - T r = m_Weight * pow(SQR(inx) + SQR(iny), m_Cn); + T r = m_Weight * std::pow(SQR(inx) + SQR(iny), m_Cn); - x = r * cos(angle); - y = r * sin(angle); + x = r * std::cos(angle); + y = r * std::sin(angle); } void Hex(T al, T be, T ga, T& al1, T& be1, QTIsaac& rand) @@ -3237,6 +3530,875 @@ private: T m_Cn; }; +/// +/// hexaplay3D. +/// This uses state and the OpenCL version looks different and better than the CPU. +/// +template +class EMBER_API Hexaplay3DVariation : public ParametricVariation +{ +public: + Hexaplay3DVariation(T weight = 1.0) : ParametricVariation("hexaplay3D", VAR_HEXAPLAY3D, weight) + { + Init(); + } + + PARVARCOPY(Hexaplay3DVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + if (m_FCycle > 5) + { + m_FCycle = 0; + m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. + } + + if (m_BCycle > 2) + { + m_BCycle = 0; + m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. + } + + int posNeg = 1; + int loc; + T tempx, tempy; + T lrmaj = m_Weight;//Sets hexagon length radius - major plane. + T boost;//Boost is the separation distance between the two planes. + T sumX, sumY; + + if (m_VarType == VARTYPE_PRE) + { + sumX = helper.In.x; + sumY = helper.In.y; + } + else + { + sumX = outPoint.m_X; + sumY = outPoint.m_Y; + outPoint.m_X = 0; + outPoint.m_Y = 0; + } + + if (rand.Frand01() < T(0.5)) + posNeg = -1; + + //Determine whether one or two major planes. + int majplane = 1; + T abmajp = fabs(m_MajP); + + if (abmajp <= 1) + { + majplane = 1;//Want either 1 or 2. + } + else + { + majplane = 2; + boost = (abmajp - 1) * T(0.5);//Distance above and below XY plane. + } + + //Creating Z factors relative to the planes. These will be added, whereas x and y will be assigned. + if (majplane == 2) + helper.Out.z = helper.In.z * T(0.5) * m_ZLift + (posNeg * boost); + else + helper.Out.z = helper.In.z * T(0.5) * m_ZLift; + + //Work out the segments and hexagonal nodes. + if (m_RSwtch <= 1)//Occasion to build using 60 degree segments. + { + loc = int(m_FCycle);//Sequential nodes selection. + tempx = m_Seg60[loc].x; + tempy = m_Seg60[loc].y; + m_FCycle++; + } + else//Occasion to build on 120 degree segments. + { + loc = int(m_BCycle);//Sequential nodes selection. + tempx = m_Seg120[loc].x; + tempy = m_Seg120[loc].y; + m_BCycle++; + } + + helper.Out.x = ((sumX + helper.In.x) * m_HalfScale) + (lrmaj * tempx); + helper.Out.y = ((sumY + helper.In.y) * m_HalfScale) + (lrmaj * tempy); + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber(); + string index = ss2.str() + "]"; + string stateIndex = ss2.str(); + string majp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string zlift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string seg60xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc. + string seg60yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6; + string seg120xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; + string seg120yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; + string halfScale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string rswtch = "varState->" + m_Params[i++].Name() + stateIndex;//State. + string fcycle = "varState->" + m_Params[i++].Name() + stateIndex; + string bcycle = "varState->" + m_Params[i++].Name() + stateIndex; + + ss << "\t{\n" + << "\t\tif (" << fcycle << " > 5)\n" + << "\t\t{\n" + << "\t\t " << fcycle << " = 0;\n" + << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" + << "\t\t}\n" + << "\n" + << "\t\tif (" << bcycle << " > 2)\n" + << "\t\t{\n" + << "\t\t " << bcycle << " = 0;\n" + << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" + << "\t\t}\n" + << "\t\t\n" + << "\t\tint posNeg = 1;\n" + << "\t\tint loc;\n" + << "\t\treal_t tempx, tempy;\n" + << "\t\treal_t lrmaj = xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\treal_t boost;\n" + << "\t\treal_t sumX, sumY;\n\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\tsumX = vIn.x;\n" + << "\t\tsumY = vIn.y;\n"; + } + else + { + ss + << "\t\tsumX = outPoint->m_X;\n" + << "\t\tsumY = outPoint->m_Y;\n" + << "\t\toutPoint->m_X = 0;\n" + << "\t\toutPoint->m_Y = 0;\n"; + } + + ss + << "\t\t\n" + << "\t\tif (MwcNext01(mwc) < 0.5)\n" + << "\t\t posNeg = -1;\n" + << "\n" + << "\t\tint majplane = 1;\n" + << "\t\treal_t abmajp = fabs(" << majp << ");\n" + << "\n" + << "\t\tif (abmajp <= 1)\n" + << "\t\t{\n" + << "\t\t majplane = 1;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t majplane = 2;\n" + << "\t\t boost = (abmajp - 1) * 0.5;\n" + << "\t\t}\n" + << "\n" + << "\t\tif (majplane == 2)\n" + << "\t\t vOut.z = vIn.z * 0.5 * " << zlift << " + (posNeg * boost);\n" + << "\t\telse\n" + << "\t\t vOut.z = vIn.z * 0.5 * " << zlift << ";\n" + << "\n" + << "\t\tif (" << rswtch << " <= 1)\n" + << "\t\t{\n" + << "\t\t loc = (int)" << fcycle << ";\n" + << "\t\t tempx = parVars[" << seg60xStartIndex << " + loc];\n" + << "\t\t tempy = parVars[" << seg60yStartIndex << " + loc];\n" + << "\t\t " << fcycle << " = " << fcycle << " + 1;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t loc = (int)" << bcycle << ";\n" + << "\t\t tempx = parVars[" << seg120xStartIndex << " + loc];\n" + << "\t\t tempy = parVars[" << seg120yStartIndex << " + loc];\n" + << "\t\t " << bcycle << " = " << bcycle << " + 1;\n" + << "\t\t}\n" + << "\n" + << "\t\tvOut.x = ((sumX + vIn.x) * " << halfScale << ") + (lrmaj * tempx);\n" + << "\t\tvOut.y = ((sumY + vIn.y) * " << halfScale << ") + (lrmaj * tempy);\n" + << "\t}\n"; + + return ss.str(); + } + + virtual string StateInitOpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0; + ss2 << "_" << XformIndexInEmber(); + string stateIndex = ss2.str(); + string prefix = Prefix(); + + //CPU sets fycle and bcycle to 0 at the beginning in Precalc(). + //Set to random in OpenCL since a value can't be set once and kept between kernel launches without writing it back to an OpenCL buffer. + ss << "\n\t\tvarState." << prefix << "hexaplay3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);"; + ss << "\n\t\tvarState." << prefix << "hexaplay3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);"; + ss << "\n\t\tvarState." << prefix << "hexaplay3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);"; + + return ss.str(); + } + + virtual void Precalc() override + { + T hlift = std::sin(T(M_PI) / 3); + + m_RSwtch = std::trunc(QTIsaac::LockedFrand01() * 3);//Chooses 6 or 3 nodes. + m_FCycle = 0; + m_BCycle = 0; + m_Seg60[0].x = 1; + m_Seg60[1].x = T(0.5); + m_Seg60[2].x = T(-0.5); + m_Seg60[3].x = -1; + m_Seg60[4].x = T(-0.5); + m_Seg60[5].x = T(0.5); + + m_Seg60[0].y = 0; + m_Seg60[1].y = hlift; + m_Seg60[2].y = hlift; + m_Seg60[3].y = 0; + m_Seg60[4].y = -hlift; + m_Seg60[5].y = -hlift; + + m_Seg120[0].x = 1; + m_Seg120[1].x = T(-0.5); + m_Seg120[2].x = T(-0.5); + + m_Seg120[0].y = 0; + m_Seg120[1].y = hlift; + m_Seg120[2].y = -hlift; + m_HalfScale = m_Scale * T(0.5); + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.reserve(25); + m_Params.push_back(ParamWithName(&m_MajP, prefix + "hexaplay3D_majp", 1, REAL)); + m_Params.push_back(ParamWithName(&m_Scale, prefix + "hexaplay3D_scale", T(0.25), REAL)); + m_Params.push_back(ParamWithName(&m_ZLift, prefix + "hexaplay3D_zlift", T(0.25), REAL)); + m_Params.push_back(ParamWithName(true, &m_Seg60[0].x, prefix + "hexaplay3D_seg60x0"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_Seg60[1].x, prefix + "hexaplay3D_seg60x1")); + m_Params.push_back(ParamWithName(true, &m_Seg60[2].x, prefix + "hexaplay3D_seg60x2")); + m_Params.push_back(ParamWithName(true, &m_Seg60[3].x, prefix + "hexaplay3D_seg60x3")); + m_Params.push_back(ParamWithName(true, &m_Seg60[4].x, prefix + "hexaplay3D_seg60x4")); + m_Params.push_back(ParamWithName(true, &m_Seg60[5].x, prefix + "hexaplay3D_seg60x5")); + m_Params.push_back(ParamWithName(true, &m_Seg60[0].y, prefix + "hexaplay3D_seg60y0")); + m_Params.push_back(ParamWithName(true, &m_Seg60[1].y, prefix + "hexaplay3D_seg60y1")); + m_Params.push_back(ParamWithName(true, &m_Seg60[2].y, prefix + "hexaplay3D_seg60y2")); + m_Params.push_back(ParamWithName(true, &m_Seg60[3].y, prefix + "hexaplay3D_seg60y3")); + m_Params.push_back(ParamWithName(true, &m_Seg60[4].y, prefix + "hexaplay3D_seg60y4")); + m_Params.push_back(ParamWithName(true, &m_Seg60[5].y, prefix + "hexaplay3D_seg60y5")); + m_Params.push_back(ParamWithName(true, &m_Seg120[0].x, prefix + "hexaplay3D_seg120x0")); + m_Params.push_back(ParamWithName(true, &m_Seg120[1].x, prefix + "hexaplay3D_seg120x1")); + m_Params.push_back(ParamWithName(true, &m_Seg120[2].x, prefix + "hexaplay3D_seg120x2")); + m_Params.push_back(ParamWithName(true, &m_Seg120[0].y, prefix + "hexaplay3D_seg120y0")); + m_Params.push_back(ParamWithName(true, &m_Seg120[1].y, prefix + "hexaplay3D_seg120y1")); + m_Params.push_back(ParamWithName(true, &m_Seg120[2].y, prefix + "hexaplay3D_seg120y2")); + m_Params.push_back(ParamWithName(true, &m_HalfScale, prefix + "hexaplay3D_halfscale")); + m_Params.push_back(ParamWithName(true, true, &m_RSwtch, prefix + "hexaplay3D_rswtch"));//State. + m_Params.push_back(ParamWithName(true, true, &m_FCycle, prefix + "hexaplay3D_fcycle")); + m_Params.push_back(ParamWithName(true, true, &m_BCycle, prefix + "hexaplay3D_bcycle")); + } + +private: + T m_MajP; + T m_Scale; + T m_ZLift; + v2T m_Seg60[6];//Precalc. + v2T m_Seg120[3]; + T m_HalfScale; + T m_RSwtch;//State. + T m_FCycle; + T m_BCycle; +}; + +/// +/// hexnix3D. +/// This uses state and the OpenCL version looks different and better than the CPU. +/// It takes care of doing either a sum or produce of the output variables internally, +/// rather than relying on the calling code of Xform::Apply() to do it. +/// This is because different paths do different things to helper.Out.z +/// +template +class EMBER_API Hexnix3DVariation : public ParametricVariation +{ +public: + Hexnix3DVariation(T weight = 1.0) : ParametricVariation("hexnix3D", VAR_HEXNIX3D, weight) + { + Init(); + } + + PARVARCOPY(Hexnix3DVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + if (m_FCycle > 5) + { + m_FCycle = 0; + m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. + } + + if (m_BCycle > 2) + { + m_BCycle = 0; + m_RSwtch = std::trunc(rand.Frand01() * 3);//Chooses 6 or 3 nodes. + } + + T lrmaj = m_Weight; + T smooth = 1; + T smRotxFP = 0; + T smRotyFP = 0; + T smRotxFT = 0; + T smRotyFT = 0; + T gentleZ = 0; + T sumX, sumY, sumZ; + + if (m_VarType == VARTYPE_PRE) + { + sumX = helper.In.x; + sumY = helper.In.y; + sumZ = helper.In.z; + } + else + { + sumX = outPoint.m_X; + sumY = outPoint.m_Y; + sumZ = outPoint.m_Z; + outPoint.m_X = 0; + outPoint.m_Y = 0; + } + + if (fabs(m_Weight) <= 0.5) + { + smooth = m_Weight * 2; + } + else + { + smooth = 1; + } + + int posNeg = 1; + int loc; + T boost = 0; + T scale = m_Scale; + T scale3; + T tempx, tempy; + + if (rand.Frand01() < T(0.5)) + { + posNeg = -1; + } + + int majplane = 0; + T abmajp = fabs(m_MajP); + + if (abmajp <= 1) + { + majplane = 0; + boost = 0; + } + else if (abmajp > 1 && abmajp < 2) + { + majplane = 1; + boost = 0; + } + else + { + majplane = 2; + boost = (abmajp - 2) * T(0.5); + } + + if (majplane == 0) + { + helper.Out.z = smooth * helper.In.z * scale * m_ZLift; + } + else if (majplane == 1 && m_MajP < 0) + { + if (m_MajP < -1 && m_MajP >= -2) + { + gentleZ = (abmajp - 1); + } + else + { + gentleZ = 1; + } + + if (posNeg < 0) + { + helper.Out.z = -2 * (sumZ * gentleZ); + } + } + + if (majplane == 2 && m_MajP < 0) + { + if (posNeg > 0) + { + helper.Out.z = (smooth * (helper.In.z * scale * m_ZLift + boost)); + } + else//For this case when non-pre assign and zero out, for all others, sum as usual. + { + helper.Out.z = (sumZ - (2 * smooth * sumZ)) + (smooth * posNeg * (helper.In.z * scale * m_ZLift + boost)); + + if (m_VarType != VARTYPE_PRE) + outPoint.m_Z = 0; + } + } + else + { + helper.Out.z = smooth * (helper.In.z * scale * m_ZLift + (posNeg * boost)); + } + + if (m_RSwtch <= 1) + { + loc = int(rand.Frand01() * 6); + tempx = m_Seg60[loc].x; + tempy = m_Seg60[loc].y; + scale3 = 1; + m_FCycle++; + } + else + { + loc = int(rand.Frand01() * 3); + tempx = m_Seg120[loc].x; + tempy = m_Seg120[loc].y; + scale3 = m_3side; + m_BCycle++; + } + + smRotxFP = (smooth * scale * sumX * tempx) - (smooth * scale * sumY * tempy); + smRotyFP = (smooth * scale * sumY * tempx) + (smooth * scale * sumX * tempy); + smRotxFT = (helper.In.x * smooth * scale * tempx) - (helper.In.y * smooth * scale * tempy); + smRotyFT = (helper.In.y * smooth * scale * tempx) + (helper.In.x * smooth * scale * tempy); + + helper.Out.x = sumX * (1 - smooth) + smRotxFP + smRotxFT + smooth * lrmaj * scale3 * tempx; + helper.Out.y = sumY * (1 - smooth) + smRotyFP + smRotyFT + smooth * lrmaj * scale3 * tempy; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber(); + string index = ss2.str() + "]"; + string stateIndex = ss2.str(); + + string majp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string zlift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string side3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string seg60xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc. + string seg60yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6; + string seg120xStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; + string seg120yStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 3; + string rswtch = "varState->" + m_Params[i++].Name() + stateIndex;//State. + string fcycle = "varState->" + m_Params[i++].Name() + stateIndex; + string bcycle = "varState->" + m_Params[i++].Name() + stateIndex; + + ss << "\t{\n" + << "\t\tif (" << fcycle << " > 5)\n" + << "\t\t{\n" + << "\t\t " << fcycle << " = 0;\n" + << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" + << "\t\t}\n" + << "\n" + << "\t\tif (" << bcycle << " > 2)\n" + << "\t\t{\n" + << "\t\t " << bcycle << " = 0;\n" + << "\t\t " << rswtch << " = trunc(MwcNext01(mwc) * 3.0);\n" + << "\t\t}\n" + << "\n" + << "\t\treal_t lrmaj = xform->m_VariationWeights[" << varIndex << "];\n" + << "\t\treal_t smooth = 1;\n" + << "\t\treal_t smRotxFP = 0;\n" + << "\t\treal_t smRotyFP = 0;\n" + << "\t\treal_t smRotxFT = 0;\n" + << "\t\treal_t smRotyFT = 0;\n" + << "\t\treal_t gentleZ = 0;\n" + << "\t\treal_t sumX, sumY, sumZ;\n\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\tsumX = vIn.x;\n" + << "\t\tsumY = vIn.y;\n" + << "\t\tsumZ = vIn.z;\n"; + } + else + { + ss + << "\t\tsumX = outPoint->m_X;\n" + << "\t\tsumY = outPoint->m_Y;\n" + << "\t\tsumZ = outPoint->m_Z;\n" + << "\t\toutPoint->m_X = 0;\n" + << "\t\toutPoint->m_Y = 0;\n"; + } + + ss + << "\n" + << "\t\tif (fabs(lrmaj) <= 0.5)\n" + << "\t\t{\n" + << "\t\t smooth = lrmaj * 2;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t smooth = 1;\n" + << "\t\t}\n" + << "\n" + << "\t\tint posNeg = 1;\n" + << "\t\tint loc;\n" + << "\t\treal_t boost = 0;\n" + << "\t\treal_t scale = " << scale << ";\n"//Temp will be used from here on. + << "\t\treal_t scale3;\n" + << "\t\treal_t tempx, tempy;\n" + << "\n" + << "\t\tif (MwcNext01(mwc) < 0.5)\n" + << "\t\t{\n" + << "\t\t posNeg = -1;\n" + << "\t\t}\n" + << "\n" + << "\t\tint majplane = 0;\n" + << "\t\treal_t abmajp = fabs(" << majp << ");\n" + << "\n" + << "\t\tif (abmajp <= 1)\n" + << "\t\t{\n" + << "\t\t majplane = 0;\n" + << "\t\t boost = 0;\n" + << "\t\t}\n" + << "\t\telse if (abmajp > 1 && abmajp < 2)\n" + << "\t\t{\n" + << "\t\t majplane = 1;\n" + << "\t\t boost = 0;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t majplane = 2;\n" + << "\t\t boost = (abmajp - 2) * 0.5;\n" + << "\t\t}\n" + << "\n" + << "\t\tif (majplane == 0)\n" + << "\t\t{\n" + << "\t\t vOut.z = smooth * vIn.z * scale * " << zlift << ";\n" + << "\t\t}\n" + << "\t\telse if (majplane == 1 && " << majp << " < 0)\n" + << "\t\t{\n" + << "\t\t if (" << majp << " < -1 && " << majp << " >= -2)\n" + << "\t\t {\n" + << "\t\t gentleZ = (abmajp - 1);\n" + << "\t\t }\n" + << "\t\t else\n" + << "\t\t {\n" + << "\t\t gentleZ = 1;\n" + << "\t\t }\n" + << "\n" + << "\t\t if (posNeg < 0)\n" + << "\t\t {\n" + << "\t\t vOut.z = -2 * (sumZ * gentleZ);\n" + << "\t\t }\n" + << "\t\t}\n" + << "\n" + << "\t\tif (majplane == 2 && " << majp << " < 0)\n" + << "\t\t{\n" + << "\t\t if (posNeg > 0)\n" + << "\t\t {\n" + << "\t\t vOut.z = (smooth * (vIn.z * scale * " << zlift << " + boost));\n" + << "\t\t }\n" + << "\t\t else\n" + << "\t\t {\n" + << "\t\t vOut.z = (sumZ - (2 * smooth * sumZ)) + (smooth * posNeg * (vIn.z * scale * " << zlift << " + boost));\n"; + + if (m_VarType != VARTYPE_PRE) + ss << "\t\t outPoint->m_Z = 0;\n"; + + ss + << "\t\t }\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t vOut.z = smooth * (vIn.z * scale * " << zlift << " + (posNeg * boost));\n" + << "\t\t}\n" + << "\n" + << "\t\tif (" << rswtch << " <= 1)\n" + << "\t\t{\n" + << "\t\t loc = (int)(MwcNext01(mwc) * 6);\n" + << "\t\t tempx = parVars[" << seg60xStartIndex << " + loc];\n" + << "\t\t tempy = parVars[" << seg60yStartIndex << " + loc];\n" + << "\t\t scale3 = 1;\n" + << "\t\t " << fcycle << " = " << fcycle << " + 1;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t loc = (int)(MwcNext01(mwc) * 3);\n" + << "\t\t tempx = parVars[" << seg120xStartIndex << " + loc];\n" + << "\t\t tempy = parVars[" << seg120yStartIndex << " + loc];\n" + << "\t\t scale3 = " << side3 << ";\n" + << "\t\t " << bcycle << " = " << bcycle << " + 1;\n" + << "\t\t}\n" + << "\n" + << "\t\tsmRotxFP = (smooth * scale * sumX * tempx) - (smooth * scale * sumY * tempy);\n" + << "\t\tsmRotyFP = (smooth * scale * sumY * tempx) + (smooth * scale * sumX * tempy);\n" + << "\t\tsmRotxFT = (vIn.x * smooth * scale * tempx) - (vIn.y * smooth * scale * tempy);\n" + << "\t\tsmRotyFT = (vIn.y * smooth * scale * tempx) + (vIn.x * smooth * scale * tempy);\n" + << "\t\tvOut.x = sumX * (1 - smooth) + smRotxFP + smRotxFT + smooth * lrmaj * scale3 * tempx;\n" + << "\t\tvOut.y = sumY * (1 - smooth) + smRotyFP + smRotyFT + smooth * lrmaj * scale3 * tempy;\n" + << "\t}\n"; + + return ss.str(); + } + + virtual string StateInitOpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0; + ss2 << "_" << XformIndexInEmber(); + string stateIndex = ss2.str(); + string prefix = Prefix(); + + //CPU sets fycle and bcycle to 0 at the beginning in Precalc(). + //Set to random in OpenCL since a value can't be set once and kept between kernel launches without writing it back to an OpenCL buffer. + ss << "\n\t\tvarState." << prefix << "hexnix3D_rswtch" << stateIndex << " = trunc(MwcNext01(&mwc) * 3.0);"; + ss << "\n\t\tvarState." << prefix << "hexnix3D_fcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 5.0);"; + ss << "\n\t\tvarState." << prefix << "hexnix3D_bcycle" << stateIndex << " = trunc(MwcNext01(&mwc) * 2.0);"; + + return ss.str(); + } + + virtual void Precalc() override + { + T hlift = std::sin(T(M_PI) / 3); + + m_RSwtch = std::trunc(QTIsaac::LockedFrand01() * 3);//Chooses 6 or 3 nodes. + m_FCycle = 0; + m_BCycle = 0; + m_Seg60[0].x = 1; + m_Seg60[1].x = T(0.5); + m_Seg60[2].x = T(-0.5); + m_Seg60[3].x = -1; + m_Seg60[4].x = T(-0.5); + m_Seg60[5].x = T(0.5); + + m_Seg60[0].y = 0; + m_Seg60[1].y = -hlift; + m_Seg60[2].y = -hlift; + m_Seg60[3].y = 0; + m_Seg60[4].y = hlift; + m_Seg60[5].y = hlift; + + m_Seg120[0].x = 0; + m_Seg120[1].x = std::cos(7 * T(M_PI) / 6); + m_Seg120[2].x = std::cos(11 * T(M_PI) / 6); + + m_Seg120[0].y = -1; + m_Seg120[1].y = T(0.5); + m_Seg120[2].y = T(0.5); + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.reserve(25); + m_Params.push_back(ParamWithName(&m_MajP, prefix + "hexnix3D_majp", 1, REAL)); + m_Params.push_back(ParamWithName(&m_Scale, prefix + "hexnix3D_scale", T(0.25), REAL)); + m_Params.push_back(ParamWithName(&m_ZLift, prefix + "hexnix3D_zlift")); + m_Params.push_back(ParamWithName(&m_3side, prefix + "hexnix3D_3side", T(0.667), REAL)); + m_Params.push_back(ParamWithName(true, &m_Seg60[0].x, prefix + "hexnix3D_seg60x0"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_Seg60[1].x, prefix + "hexnix3D_seg60x1")); + m_Params.push_back(ParamWithName(true, &m_Seg60[2].x, prefix + "hexnix3D_seg60x2")); + m_Params.push_back(ParamWithName(true, &m_Seg60[3].x, prefix + "hexnix3D_seg60x3")); + m_Params.push_back(ParamWithName(true, &m_Seg60[4].x, prefix + "hexnix3D_seg60x4")); + m_Params.push_back(ParamWithName(true, &m_Seg60[5].x, prefix + "hexnix3D_seg60x5")); + m_Params.push_back(ParamWithName(true, &m_Seg60[0].y, prefix + "hexnix3D_seg60y0")); + m_Params.push_back(ParamWithName(true, &m_Seg60[1].y, prefix + "hexnix3D_seg60y1")); + m_Params.push_back(ParamWithName(true, &m_Seg60[2].y, prefix + "hexnix3D_seg60y2")); + m_Params.push_back(ParamWithName(true, &m_Seg60[3].y, prefix + "hexnix3D_seg60y3")); + m_Params.push_back(ParamWithName(true, &m_Seg60[4].y, prefix + "hexnix3D_seg60y4")); + m_Params.push_back(ParamWithName(true, &m_Seg60[5].y, prefix + "hexnix3D_seg60y5")); + m_Params.push_back(ParamWithName(true, &m_Seg120[0].x, prefix + "hexnix3D_seg120x0")); + m_Params.push_back(ParamWithName(true, &m_Seg120[1].x, prefix + "hexnix3D_seg120x1")); + m_Params.push_back(ParamWithName(true, &m_Seg120[2].x, prefix + "hexnix3D_seg120x2")); + m_Params.push_back(ParamWithName(true, &m_Seg120[0].y, prefix + "hexnix3D_seg120y0")); + m_Params.push_back(ParamWithName(true, &m_Seg120[1].y, prefix + "hexnix3D_seg120y1")); + m_Params.push_back(ParamWithName(true, &m_Seg120[2].y, prefix + "hexnix3D_seg120y2")); + m_Params.push_back(ParamWithName(true, true, &m_RSwtch, prefix + "hexnix3D_rswtch"));//State. + m_Params.push_back(ParamWithName(true, true, &m_FCycle, prefix + "hexnix3D_fcycle")); + m_Params.push_back(ParamWithName(true, true, &m_BCycle, prefix + "hexnix3D_bcycle")); + } + +private: + T m_MajP; + T m_Scale; + T m_ZLift; + T m_3side; + v2T m_Seg60[6];//Precalc. + v2T m_Seg120[3]; + T m_RSwtch;//State. + T m_FCycle; + T m_BCycle; +}; + +/// +/// hexcrop. +/// +template +class EMBER_API HexcropVariation : public ParametricVariation +{ +public: + HexcropVariation(T weight = 1.0) : ParametricVariation("hexcrop", VAR_HEXCROP, weight) + { + Init(); + } + + PARVARCOPY(HexcropVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + v2T i; + int c = 0, n = -1, j = 5; + + i.x = helper.In.x + m_CenterX; + i.y = helper.In.y + m_CenterY; + + while (++n < 6) + { + if ((m_P[n].y <= i.y && i.y < m_P[j].y) || (m_P[j].y <= i.y && i.y < m_P[n].y)) + if (i.x < (m_P[j].x - m_P[n].x) * (i.y - m_P[n].y) / (m_P[j].y - m_P[n].y) + m_P[n].x) + c ^= 1; + + j = n; + } + + if (m_VarType == VARTYPE_REG) + { + helper.Out.x = c != 0 ? outPoint.m_X + i.x * m_Weight : m_Dropoff; + helper.Out.y = c != 0 ? outPoint.m_Y + i.y * m_Weight : m_Dropoff; + outPoint.m_X = 0; + outPoint.m_Y = 0; + } + else + { + helper.Out.x = c != 0 ? i.x * m_Weight : m_Dropoff; + helper.Out.y = c != 0 ? i.y * m_Weight : m_Dropoff; + } + + helper.Out.z = m_Weight * helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber(); + string index = ss2.str() + "]"; + string stateIndex = ss2.str(); + + string scalex = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string scaley = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string centerx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string centery = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string dropoff = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string pxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 6;//Precalc. + string pyStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; + + ss << "\t{\n" + << "\t\treal2 i;\n" + << "\t\tint c = 0, n = -1, j = 5;\n" + << "\n" + << "\t\ti.x = vIn.x + " << centerx << ";\n" + << "\t\ti.y = vIn.y + " << centery << ";\n" + << "\n" + << "\t\twhile (++n < 6)\n" + << "\t\t{\n" + << "\t\t int xjoff = " << pxStartIndex << " + j;\n" + << "\t\t int xnoff = " << pxStartIndex << " + n;\n" + << "\t\t int yjoff = " << pyStartIndex << " + j;\n" + << "\t\t int ynoff = " << pyStartIndex << " + n;\n" + << "\n" + << "\t\t if ((parVars[ynoff] <= i.y && i.y < parVars[yjoff]) || (parVars[yjoff] <= i.y && i.y < parVars[ynoff]))\n" + << "\t\t if (i.x < (parVars[xjoff] - parVars[xnoff]) * (i.y - parVars[ynoff]) / (parVars[yjoff] - parVars[ynoff]) + parVars[xnoff])\n" + << "\t\t c ^= 1;\n" + << "\n" + << "\t\t j = n;\n" + << "\t\t}\n" + << "\n"; + + if (m_VarType == VARTYPE_REG) + { + ss + << "\t\tvOut.x = c != 0 ? outPoint->m_X + i.x * xform->m_VariationWeights[" << varIndex << "] : " << dropoff << ";\n" + << "\t\tvOut.y = c != 0 ? outPoint->m_Y + i.y * xform->m_VariationWeights[" << varIndex << "] : " << dropoff << ";\n" + << "\t\toutPoint->m_X = 0;\n" + << "\t\toutPoint->m_Y = 0;\n"; + } + else + { + ss + << "\t\tvOut.x = c != 0 ? i.x * xform->m_VariationWeights[" << varIndex << "] : " << dropoff << ";\n" + << "\t\tvOut.y = c != 0 ? i.y * xform->m_VariationWeights[" << varIndex << "] : " << dropoff << ";\n"; + } + + ss + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" + << "\t}\n"; + + return ss.str(); + } + + virtual void Precalc() override + { + m_P[0].x = T(-0.5000000000000000000000000000000) * m_ScaleX; + m_P[0].y = T(1.0606601717798212866012665431573) * m_ScaleY; + m_P[1].x = T(0.5000000000000000000000000000000) * m_ScaleX; + m_P[1].y = T(1.0606601717798212866012665431573) * m_ScaleY; + m_P[2].x = T(1.4142135623730950488016887242097) * m_ScaleX; + m_P[2].y = T(0.0000000000000000000000000000000) * m_ScaleY; + m_P[3].x = T(0.5000000000000000000000000000000) * m_ScaleX; + m_P[3].y = T(-1.0606601717798212866012665431573) * m_ScaleY; + m_P[4].x = T(-0.5000000000000000000000000000000) * m_ScaleX; + m_P[4].y = T(-1.0606601717798212866012665431573) * m_ScaleY; + m_P[5].x = T(-1.4142135623730950488016887242097) * m_ScaleX; + m_P[5].y = T(0.0000000000000000000000000000000) * m_ScaleY; + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.reserve(17); + m_Params.push_back(ParamWithName(&m_ScaleX, prefix + "hexcrop_scale_x", 1)); + m_Params.push_back(ParamWithName(&m_ScaleY, prefix + "hexcrop_scale_y", 1)); + m_Params.push_back(ParamWithName(&m_CenterX, prefix + "hexcrop_center_x")); + m_Params.push_back(ParamWithName(&m_CenterY, prefix + "hexcrop_center_y")); + m_Params.push_back(ParamWithName(&m_Dropoff, prefix + "hexcrop_dropoff", T(1E10))); + m_Params.push_back(ParamWithName(true, &m_P[0].x, prefix + "hexcrop_px0"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_P[1].x, prefix + "hexcrop_px1")); + m_Params.push_back(ParamWithName(true, &m_P[2].x, prefix + "hexcrop_px2")); + m_Params.push_back(ParamWithName(true, &m_P[3].x, prefix + "hexcrop_px3")); + m_Params.push_back(ParamWithName(true, &m_P[4].x, prefix + "hexcrop_px4")); + m_Params.push_back(ParamWithName(true, &m_P[5].x, prefix + "hexcrop_px5")); + m_Params.push_back(ParamWithName(true, &m_P[0].y, prefix + "hexcrop_py0")); + m_Params.push_back(ParamWithName(true, &m_P[1].y, prefix + "hexcrop_py1")); + m_Params.push_back(ParamWithName(true, &m_P[2].y, prefix + "hexcrop_py2")); + m_Params.push_back(ParamWithName(true, &m_P[3].y, prefix + "hexcrop_py3")); + m_Params.push_back(ParamWithName(true, &m_P[4].y, prefix + "hexcrop_py4")); + m_Params.push_back(ParamWithName(true, &m_P[5].y, prefix + "hexcrop_py5")); + } + +private: + T m_ScaleX; + T m_ScaleY; + T m_CenterX; + T m_CenterY; + T m_Dropoff; + v2T m_P[6];//Precalc. +}; + MAKEPREPOSTPARVAR(Bubble2, bubble2, BUBBLE2) MAKEPREPOSTPARVAR(CircleLinear, CircleLinear, CIRCLELINEAR) MAKEPREPOSTPARVARASSIGN(CircleRand, CircleRand, CIRCLERAND, ASSIGNTYPE_SUM) @@ -3247,6 +4409,8 @@ MAKEPREPOSTVAR(Foci3D, foci_3D, FOCI3D) MAKEPREPOSTPARVAR(Ho, ho, HO) MAKEPREPOSTPARVAR(Julia3Dq, julia3Dq, JULIA3DQ) MAKEPREPOSTPARVARASSIGN(Line, line, LINE, ASSIGNTYPE_SUM) +MAKEPREPOSTPARVAR(Loonie2, loonie2, LOONIE2) +MAKEPREPOSTPARVAR(Loonie3, loonie3, LOONIE3) MAKEPREPOSTPARVAR(Loonie3D, loonie_3D, LOONIE3D) MAKEPREPOSTPARVAR(Mcarpet, mcarpet, MCARPET) MAKEPREPOSTPARVAR(Waves23D, waves2_3D, WAVES23D) @@ -3261,4 +4425,7 @@ MAKEPREPOSTPARVAR(Falloff, falloff, FALLOFF) MAKEPREPOSTPARVAR(Falloff2, falloff2, FALLOFF2) MAKEPREPOSTPARVAR(Falloff3, falloff3, FALLOFF3) MAKEPREPOSTPARVAR(Xtrb, xtrb, XTRB) +MAKEPREPOSTPARVAR(Hexaplay3D, hexaplay3D, HEXAPLAY3D) +MAKEPREPOSTPARVAR(Hexnix3D, hexnix3D, HEXNIX3D) +MAKEPREPOSTPARVAR(Hexcrop, hexcrop, HEXCROP) } diff --git a/Source/Ember/Variations06.h b/Source/Ember/Variations06.h new file mode 100644 index 0000000..a3bc4f6 --- /dev/null +++ b/Source/Ember/Variations06.h @@ -0,0 +1,3832 @@ +#pragma once + +#include "Variation.h" + +namespace EmberNs +{ +/// +/// hexes. +/// +template +class EMBER_API HexesVariation : public ParametricVariation +{ +public: + HexesVariation(T weight = 1.0) : ParametricVariation("hexes", VAR_HEXES, weight) + { + Init(); + } + + PARVARCOPY(HexesVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + // Xh = (Xo + sqrt(3) * Yo) / (3 * l) + static const T AXhXo = T(1.0 / 3.0); + static const T AXhYo = T(1.7320508075688772935 / 3.0); + // Now: Xh = ( AXhXo * Xo + AXhYo * Yo ) / l; + + // Yh = (-Xo + sqrt(3) * Yo) / (3 * l) + static const T AYhXo = T(-1.0 / 3.0); + static const T AYhYo = T(1.7320508075688772935 / 3.0); + // Now: Yh = ( AYhXo * Xo + AYhYo * Yo ) / l; + + // Xo = 3/2 * l * (Xh - Yh) + static const T AXoXh = T(1.5); + static const T AXoYh = T(-1.5); + // Now: Xo = ( AXoXh * Xh + AXoYh * Yh ) * l; + + // Yo = sqrt(3)/2 * l * (Xh + Yh) + static const T AYoXh = T(1.7320508075688772935 / 2.0); + static const T AYoYh = T(1.7320508075688772935 / 2.0); + static const v2T offset[4] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } }; + + int i = 0; + T di, dj; + T XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL, Vx, Vy; + v2T U; + v2T P[7]; + + //For speed/convenience. + s = m_Cellsize; + + //Infinite number of small cells? No effect . . . + if (s == 0) + return; + + //Get co-ordinates, and convert to hex co-ordinates. + U.x = helper.In.x; + U.y = helper.In.y; + + XCh = T(Floor((AXhXo * U.x + AXhYo * U.y) / s)); + YCh = T(Floor((AYhXo * U.x + AYhYo * U.y) / s)); + + // Get a set of 4 hex center points, based around the one above + for (di = XCh; di < XCh + T(1.1); di += 1) + { + for (dj = YCh; dj < YCh + T(1.1); dj += 1) + { + P[i].x = (AXoXh * di + AXoYh * dj) * s; + P[i].y = (AYoXh * di + AYoYh * dj) * s; + i++; + } + } + + int q = Closest(&P[0], 4, U); + + //Remake list starting from chosen hex, ensure it is completely surrounded (total 7 points). + + //First adjust centers according to which one was found to be closest. + XCh += offset[q].x; + YCh += offset[q].y; + + //First point is central/closest. + XCo = (AXoXh * XCh + AXoYh * YCh) * s; + YCo = (AYoXh * XCh + AYoYh * YCh) * s; + P[0].x = XCo; + P[0].y = YCo; + + //Next six points are based on hex graph (6 hexes around center). As long as + //center points are not too distorted from simple hex, this defines all possible edges. + + //In hex co-ords, offsets are: (0,1) (1,1) (1,0) (0,-1) (-1,-1) (-1, 0). + P[1].x = XCo + (AXoYh)* s; + P[1].y = YCo + (AYoYh)* s; + P[2].x = XCo + (AXoXh + AXoYh) * s; + P[2].y = YCo + (AYoXh + AYoYh) * s; + P[3].x = XCo + (AXoXh)* s; + P[3].y = YCo + (AYoXh)* s; + P[4].x = XCo - AXoYh * s; + P[4].y = YCo - AYoYh * s; + P[5].x = XCo - (AXoXh + AXoYh) * s; + P[5].y = YCo - (AYoXh + AYoYh) * s; + P[6].x = XCo - AXoXh * s; + P[6].y = YCo - AYoXh * s; + + L1 = Voronoi(&P[0], 7, 0, U); + + //Delta vector from center of hex. + DXo = U.x - P[0].x; + DYo = U.y - P[0].y; + + //Apply "interesting bit" to cell's DXo and DYo co-ordinates. + + //trgL is the defined value of l, independent of any rotation. + trgL = std::pow(Zeps(L1), m_Power) * m_Scale;//Original added 1e-100, use Zeps to be more precise. + + //Rotate. + Vx = DXo * m_RotCos + DYo * m_RotSin; + Vy = -DXo * m_RotSin + DYo * m_RotCos; + + //Measure voronoi distance again. + U.x = Vx + P[0].x; + U.y = Vy + P[0].y; + L2 = Voronoi(&P[0], 7, 0, U); + + //Scale to meet target size . . . adjust according to how close + //we are to the edge. + + //Code here attempts to remove the "rosette" effect caused by + //scaling between. + + //L is maximum of L1 or L2 . . . + //When L = 0.8 or higher . . . match trgL/L2 exactly. + //When L = T(0.5) or less . . . match trgL/L1 exactly. + L = (L1 > L2) ? L1 : L2; + + if (L < T(0.5)) + { + R = trgL / L1; + } + else + { + if (L > T(0.8)) + R = trgL / L2; + else + R = ((trgL / L1) * (T(0.8) - L) + (trgL / L2) * (L - T(0.5))) / T(0.3); + } + + Vx *= R; + Vy *= R; + + //Add cell center co-ordinates back in. + Vx += P[0].x; + Vy += P[0].y; + + //Finally add values in. + helper.Out.x = m_Weight * Vx; + helper.Out.y = m_Weight * Vy; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string cellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string rotate = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string rotsin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string rotcos = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + << "\t\tint i = 0;\n" + << "\t\treal_t di, dj;\n" + << "\t\treal_t XCh, YCh, XCo, YCo, DXo, DYo, L, L1, L2, R, s, trgL, Vx, Vy;\n" + << "\t\treal2 U;\n" + << "\t\treal2 P[7];\n" + << "\n" + << "\t\ts = " << cellsize << ";\n" + << "\n" + << "\t\tif (s == 0)\n" + << "\t\t return;\n" + << "\n" + << "\t\tU.x = vIn.x;\n" + << "\t\tU.y = vIn.y;\n" + << "\n" + << "\t\tXCh = floor((AXhXo * U.x + AXhYo * U.y) / s);\n" + << "\t\tYCh = floor((AYhXo * U.x + AYhYo * U.y) / s);\n" + << "\n" + << "\t\tfor (di = XCh; di < XCh + 1.1; di += 1)\n" + << "\t\t{\n" + << "\t\t for (dj = YCh; dj < YCh + 1.1; dj += 1)\n" + << "\t\t {\n" + << "\t\t P[i].x = (AXoXh * di + AXoYh * dj) * s;\n" + << "\t\t P[i].y = (AYoXh * di + AYoYh * dj) * s;\n" + << "\t\t i++;\n" + << "\t\t }\n" + << "\t\t}\n" + << "\n" + << "\t\tint q = Closest(&P[0], 4, &U);\n" + << "\n" + << "\t\tXCh += offset[q].x;\n" + << "\t\tYCh += offset[q].y;\n" + << "\n" + << "\t\tXCo = (AXoXh * XCh + AXoYh * YCh) * s;\n" + << "\t\tYCo = (AYoXh * XCh + AYoYh * YCh) * s;\n" + << "\t\tP[0].x = XCo;\n" + << "\t\tP[0].y = YCo;\n" + << "\n" + << "\t\tP[1].x = XCo + (AXoYh)* s;\n" + << "\t\tP[1].y = YCo + (AYoYh)* s;\n" + << "\t\tP[2].x = XCo + (AXoXh + AXoYh) * s;\n" + << "\t\tP[2].y = YCo + (AYoXh + AYoYh) * s;\n" + << "\t\tP[3].x = XCo + (AXoXh)* s;\n" + << "\t\tP[3].y = YCo + (AYoXh)* s;\n" + << "\t\tP[4].x = XCo - AXoYh * s;\n" + << "\t\tP[4].y = YCo - AYoYh * s;\n" + << "\t\tP[5].x = XCo - (AXoXh + AXoYh) * s;\n" + << "\t\tP[5].y = YCo - (AYoXh + AYoYh) * s;\n" + << "\t\tP[6].x = XCo - AXoXh * s;\n" + << "\t\tP[6].y = YCo - AYoXh * s;\n" + << "\n" + << "\t\tL1 = Voronoi(&P[0], 7, 0, &U);\n" + << "\n" + << "\t\tDXo = U.x - P[0].x;\n" + << "\t\tDYo = U.y - P[0].y;\n" + << "\n" + << "\t\ttrgL = pow(Zeps(L1), " << power << ") * " << scale << ";\n" + << "\n" + << "\t\tVx = DXo * " << rotcos << " + DYo * " << rotsin << ";\n" + << "\t\tVy = -DXo * " << rotsin << " + DYo * " << rotcos << ";\n" + << "\n" + << "\t\tU.x = Vx + P[0].x;\n" + << "\t\tU.y = Vy + P[0].y;\n" + << "\t\tL2 = Voronoi(&P[0], 7, 0, &U);\n" + << "\n" + << "\t\tL = (L1 > L2) ? L1 : L2;\n" + << "\n" + << "\t\tif (L < 0.5)\n" + << "\t\t{\n" + << "\t\t R = trgL / L1;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t{\n" + << "\t\t if (L > 0.8)\n" + << "\t\t R = trgL / L2;\n" + << "\t\t else\n" + << "\t\t R = ((trgL / L1) * (0.8 - L) + (trgL / L2) * (L - 0.5)) / 0.3;\n" + << "\t\t}\n" + << "\n" + << "\t\tVx *= R;\n" + << "\t\tVy *= R;\n" + << "\n" + << "\t\tVx += P[0].x;\n" + << "\t\tVy += P[0].y;\n" + << "\n" + << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * Vx;\n" + << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * Vy;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" + << "\t}\n"; + + return ss.str(); + } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + + virtual string OpenCLFuncsString() const override + { + return + "constant real_t AXhXo = (real_t)(1.0 / 3.0);\n" + "constant real_t AXhYo = (real_t)(1.7320508075688772935 / 3.0);\n" + "constant real_t AYhXo = (real_t)(-1.0 / 3.0);\n" + "constant real_t AYhYo = (real_t)(1.7320508075688772935 / 3.0);\n" + "constant real_t AXoXh = (real_t)(1.5);\n" + "constant real_t AXoYh = (real_t)(-1.5);\n" + "constant real_t AYoXh = (real_t)(1.7320508075688772935 / 2.0);\n" + "constant real_t AYoYh = (real_t)(1.7320508075688772935 / 2.0);\n" + "constant real2 offset[4] = { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 } };\n" + "\n" + "real_t Vratio(real2* p, real2* q, real2* u)\n" + "{\n" + " real_t pmQx, pmQy;\n" + "\n" + " pmQx = (*p).x - (*q).x;\n" + " pmQy = (*p).y - (*q).y;\n" + "\n" + " if (pmQx == 0 && pmQy == 0)\n" + " return 1.0;\n" + "\n" + " return 2 * (((*u).x - (*q).x) * pmQx + ((*u).y - (*q).y) * pmQy) / (pmQx * pmQx + pmQy * pmQy);\n" + "}\n" + "\n" + "int Closest(real2* p, int n, real2* u)\n" + "{\n" + " real_t d2;\n" + " real_t d2min = TMAX;\n" + " int i, j;\n" + "\n" + " for (i = 0; i < n; i++)\n" + " {\n" + " d2 = (p[i].x - (*u).x) * (p[i].x - (*u).x) + (p[i].y - (*u).y) * (p[i].y - (*u).y);\n" + "\n" + " if (d2 < d2min)\n" + " {\n" + " d2min = d2;\n" + " j = i;\n" + " }\n" + " }\n" + "\n" + " return j;\n" + "}\n" + "\n" + "real_t Voronoi(real2* p, int n, int q, real2* u)\n" + "{\n" + " real_t ratio;\n" + " real_t ratiomax = TLOW;\n" + " int i;\n" + "\n" + " for (i = 0; i < n; i++)\n" + " {\n" + " if (i != q)\n" + " {\n" + " ratio = Vratio(&p[i], &p[q], u);\n" + "\n" + " if (ratio > ratiomax)\n" + " ratiomax = ratio;\n" + " }\n" + " }\n" + "\n" + " return ratiomax;\n" + "}\n" + ; + } + + virtual void Precalc() override + { + m_RotSin = std::sin(m_Rotate * M_2PI); + m_RotCos = std::cos(m_Rotate * M_2PI); + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.push_back(ParamWithName(&m_Cellsize, prefix + "hexes_cellsize", 1)); + m_Params.push_back(ParamWithName(&m_Power, prefix + "hexes_power", 1)); + m_Params.push_back(ParamWithName(&m_Rotate, prefix + "hexes_rotate", T(0.166))); + m_Params.push_back(ParamWithName(&m_Scale, prefix + "hexes_scale", 1)); + m_Params.push_back(ParamWithName(true, &m_RotSin, prefix + "hexes_rotsin"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_RotCos, prefix + "hexes_rotcos")); + } + +private: + static T Vratio(v2T& p, v2T& q, v2T& u) + { + T pmQx, pmQy; + + pmQx = p.x - q.x; + pmQy = p.y - q.y; + + if (pmQx == 0 && pmQy == 0) + return 1.0; + + return 2 * ((u.x - q.x) * pmQx + (u.y - q.y) * pmQy) / (pmQx * pmQx + pmQy * pmQy); + } + + static int Closest(v2T* p, int n, v2T& u) + { + T d2; + T d2min = TMAX; + int i, j; + + for (i = 0; i < n; i++) + { + d2 = (p[i].x - u.x) * (p[i].x - u.x) + (p[i].y - u.y) * (p[i].y - u.y); + + if (d2 < d2min) + { + d2min = d2; + j = i; + } + } + + return j; + } + + static T Voronoi(v2T* p, int n, int q, v2T& u) + { + T ratio; + T ratiomax = TLOW; + int i; + + for (i = 0; i < n; i++) + { + if (i != q) + { + ratio = Vratio(p[i], p[q], u); + + if (ratio > ratiomax) + ratiomax = ratio; + } + } + + return ratiomax; + } + + T m_Cellsize; + T m_Power; + T m_Rotate; + T m_Scale; + T m_RotSin;//Precalc. + T m_RotCos; +}; + +/// +/// nBlur. +/// +template +class EMBER_API NblurVariation : public ParametricVariation +{ + struct RandXyParams + { + T NumEdges; + T RatioHole; + T CircumCircle; + T EqualBlur; + T ExactCalc; + T MidAngle; + T AngStart; + T AngStripes; + T HasStripes; + T NegStripes; + T MaxStripes; + T Tan90M2; + T ArcTan1; + T ArcTan2; + T RatioStripes; + T RatioComplement; + T SpeedCalc1; + T SpeedCalc2; + T LenInnerEdges; + T LenOuterEdges; + T X; + T Y; + T LenXY; + }; + +public: + NblurVariation(T weight = 1.0) : ParametricVariation("nBlur", VAR_NBLUR, weight) + { + Init(); + } + + PARVARCOPY(NblurVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + T xTmp, yTmp; + RandXyParams params; + + params.NumEdges = m_NumEdges; + params.RatioHole = m_RatioHole; + params.CircumCircle = m_CircumCircle; + params.EqualBlur = m_EqualBlur; + params.ExactCalc = m_ExactCalc; + params.MidAngle = m_MidAngle; + params.AngStart = m_AngStart; + params.AngStripes = m_AngStripes; + params.HasStripes = m_HasStripes; + params.NegStripes = m_NegStripes; + params.MaxStripes = m_MaxStripes; + params.Tan90M2 = m_Tan90M2; + params.ArcTan1 = m_ArcTan1; + params.ArcTan2 = m_ArcTan2; + params.RatioStripes = m_RatioStripes; + params.RatioComplement = m_RatioComplement; + params.SpeedCalc1 = m_SpeedCalc1; + params.SpeedCalc2 = m_SpeedCalc2; + + RandXY(params, rand); + + if ((m_ExactCalc == 1) && (m_CircumCircle == 0)) + while ((params.LenXY < params.LenInnerEdges) || (params.LenXY > params.LenOuterEdges)) + RandXY(params, rand); + + if ((m_ExactCalc == 1) && (m_CircumCircle == 1)) + while (params.LenXY < params.LenInnerEdges) + RandXY(params, rand); + + xTmp = params.X; + yTmp = params.Y; + + params.X = m_Cosa * xTmp - m_Sina * yTmp; + params.Y = m_Sina * xTmp + m_Cosa * yTmp; + + helper.Out.x = m_AdjustedWeight * params.X; + helper.Out.y = m_AdjustedWeight * params.Y; + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string numEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string numStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string ratioStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string ratioHole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string circumCircle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string adjustToLinear = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string equalBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string exactCalc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string highlightEdges = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string ratioComplement = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalc. + string midAngle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angStart = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string hasStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string negStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string maxStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string absStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string sina = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string cosa = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string tan90M2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string arcTan1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string arcTan2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string speedCalc1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string speedCalc2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string adjustedWeight = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + << "\t\treal_t xTmp, yTmp;\n" + << "\t\tRandXyParams params;\n" + << "\n" + << "\t\tparams.NumEdges = " << numEdges << ";\n" + << "\t\tparams.RatioHole = " << ratioHole << ";\n" + << "\t\tparams.CircumCircle = " << circumCircle << ";\n" + << "\t\tparams.EqualBlur = " << equalBlur << ";\n" + << "\t\tparams.ExactCalc = " << exactCalc << ";\n" + << "\t\tparams.MidAngle = " << midAngle << ";\n" + << "\t\tparams.AngStart = " << angStart << ";\n" + << "\t\tparams.AngStripes = " << angStripes << ";\n" + << "\t\tparams.HasStripes = " << hasStripes << ";\n" + << "\t\tparams.NegStripes = " << negStripes << ";\n" + << "\t\tparams.MaxStripes = " << maxStripes << ";\n" + << "\t\tparams.Tan90M2 = " << tan90M2 << ";\n" + << "\t\tparams.ArcTan1 = " << arcTan1 << ";\n" + << "\t\tparams.ArcTan2 = " << arcTan2 << ";\n" + << "\t\tparams.RatioStripes = " << ratioStripes << ";\n" + << "\t\tparams.RatioComplement = " << ratioComplement << ";\n" + << "\t\tparams.SpeedCalc1 = " << speedCalc1 << ";\n" + << "\t\tparams.SpeedCalc2 = " << speedCalc2 << ";\n" + << "\n" + << "\t\tRandXY(¶ms, mwc);\n" + << "\n" + << "\t\tif ((" << exactCalc << " == 1) && (" << circumCircle << " == 0))\n" + << "\t\t while ((params.LenXY < params.LenInnerEdges) || (params.LenXY > params.LenOuterEdges))\n" + << "\t\t RandXY(¶ms, mwc);\n" + << "\n" + << "\t\tif ((" << exactCalc << " == 1) && (" << circumCircle << " == 1))\n" + << "\t\t while (params.LenXY < params.LenInnerEdges)\n" + << "\t\t RandXY(¶ms, mwc);\n" + << "\n" + << "\t\txTmp = params.X;\n" + << "\t\tyTmp = params.Y;\n" + << "\n" + << "\t\tparams.X = " << cosa << " * xTmp - " << sina << " * yTmp;\n" + << "\t\tparams.Y = " << sina << " * xTmp + " << cosa << " * yTmp;\n" + << "\n" + << "\t\tvOut.x = " << adjustedWeight << " * params.X;\n" + << "\t\tvOut.y = " << adjustedWeight << " * params.Y;\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" + << "\t}\n"; + + return ss.str(); + } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Swap" }; + } + + virtual string OpenCLFuncsString() const override + { + return + "typedef struct __attribute__ " ALIGN_CL " _RandXyParams\n" + "{\n" + " real_t NumEdges;\n" + " real_t RatioHole;\n" + " real_t CircumCircle;\n" + " real_t EqualBlur;\n" + " real_t ExactCalc;\n" + " real_t MidAngle;\n" + " real_t AngStart;\n" + " real_t AngStripes;\n" + " real_t HasStripes;\n" + " real_t NegStripes;\n" + " real_t MaxStripes;\n" + " real_t Tan90M2;\n" + " real_t ArcTan1;\n" + " real_t ArcTan2;\n" + " real_t RatioStripes;\n" + " real_t RatioComplement;\n" + " real_t SpeedCalc1;\n" + " real_t SpeedCalc2;\n" + " real_t LenInnerEdges;\n" + " real_t LenOuterEdges;\n" + " real_t X;\n" + " real_t Y;\n" + " real_t LenXY;\n" + "} RandXyParams;\n" + "\n" + "static void RandXY(RandXyParams* params, uint2* mwc)\n" + "{\n" + " real_t angXY, angMem, angTmp;\n" + " real_t ratioTmp, ratioTmpNum, ratioTmpDen;\n" + " real_t xTmp, yTmp;\n" + " real_t ranTmp;\n" + " int count;\n" + "\n" + " if (params->ExactCalc == 1)\n" + " angXY = MwcNext01(mwc) * M_2PI;\n" + " else\n" + " angXY = (atan(params->ArcTan1 * (MwcNext01(mwc) - 0.5)) / params->ArcTan2 + 0.5 + (real_t)(MwcNextRange(mwc, (uint)params->NumEdges))) * params->MidAngle;\n" + "\n" + " params->X = sincos(angXY, ¶ms->Y);\n" + " angMem = angXY;\n" + "\n" + " while (angXY > params->MidAngle)\n" + " angXY -= params->MidAngle;\n" + "\n" + " if (params->HasStripes == 1)\n" + " {\n" + " count = 0;\n" + " angTmp = params->AngStart;\n" + "\n" + " while (angXY > angTmp)\n" + " {\n" + " angTmp += params->AngStripes;\n" + "\n" + " if (angTmp > params->MidAngle)\n" + " angTmp = params->MidAngle;\n" + "\n" + " count++;\n" + " }\n" + "\n" + " if (angTmp != params->MidAngle)\n" + " angTmp -= params->AngStart;\n" + "\n" + " if (params->NegStripes == 0)\n" + " {\n" + " if ((count & 1) == 1)\n" + " {\n" + " if (angXY > angTmp)\n" + " {\n" + " angXY = angXY + params->AngStart;\n" + " angMem = angMem + params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " angTmp += params->AngStripes;\n" + " count++;\n" + " }\n" + " else\n" + " {\n" + " angXY = angXY - params->AngStart;\n" + " angMem = angMem - params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " angTmp -= params->AngStripes;\n" + " count--;\n" + " }\n" + " }\n" + "\n" + " if (((count & 1) == 0) && (params->RatioStripes > 1))\n" + " {\n" + " if ((angXY > angTmp) && (count != params->MaxStripes))\n" + " {\n" + " angMem = angMem - angXY + angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " }\n" + " else\n" + " {\n" + " angMem = angMem - angXY + angTmp - (angTmp - angXY) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " }\n" + " }\n" + "\n" + " if (((count & 1) == 0) && (params->RatioStripes < 1))\n" + " {\n" + " if ((fabs(angXY - angTmp) > params->SpeedCalc2) && (count != params->MaxStripes))\n" + " {\n" + " if ((angXY - angTmp) > params->SpeedCalc2)\n" + " {\n" + " ratioTmpNum = (angXY - (angTmp + params->SpeedCalc2)) * params->SpeedCalc2;\n" + " ratioTmpDen = params->AngStart - params->SpeedCalc2;\n" + " ratioTmp = ratioTmpNum / ratioTmpDen;\n" + " params->X = sincos((angMem - angXY + angTmp + ratioTmp), ¶ms->Y);\n" + " angXY = angTmp + ratioTmp;\n" + " }\n" + "\n" + " if ((angTmp - angXY) > params->SpeedCalc2)\n" + " {\n" + " ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n" + " ratioTmpDen = params->AngStart - params->SpeedCalc2;\n" + " ratioTmp = ratioTmpNum / ratioTmpDen;\n" + " params->X = sincos((angMem - angXY + angTmp - ratioTmp), ¶ms->Y);\n" + " angXY = angTmp - ratioTmp;\n" + " }\n" + " }\n" + "\n" + " if (count == params->MaxStripes)\n" + " {\n" + " if ((angTmp - angXY) > params->SpeedCalc2)\n" + " {\n" + " ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n" + " ratioTmpDen = params->AngStart - params->SpeedCalc2;\n" + " ratioTmp = ratioTmpNum / ratioTmpDen;\n" + " params->X = sincos((angMem - angXY + angTmp - ratioTmp), ¶ms->Y);\n" + " angXY = angTmp - ratioTmp;\n" + " }\n" + " }\n" + " }\n" + " }\n" + " else\n" + " {\n" + " Swap(¶ms->RatioStripes, ¶ms->RatioComplement);\n" + " Swap(¶ms->SpeedCalc1, ¶ms->SpeedCalc2);\n" + "\n" + " if ((count & 1) == 0)\n" + " {\n" + " if ((angXY > angTmp) && (count != params->MaxStripes))\n" + " {\n" + " angXY = angXY + params->AngStart;\n" + " angMem = angMem + params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " angTmp += params->AngStripes;\n" + " count++;\n" + " }\n" + " else\n" + " {\n" + " angXY = angXY - params->AngStart;\n" + " angMem = angMem - params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " angTmp -= params->AngStripes;\n" + " count--;\n" + " }\n" + " }\n" + "\n" + " if (((count & 1) == 1) && (params->RatioStripes > 1))\n" + " {\n" + " if ((angXY > angTmp) && (count != params->MaxStripes))\n" + " {\n" + " angMem = angMem - angXY + angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " }\n" + " else\n" + " {\n" + " angMem = angMem - angXY + angTmp - (angTmp - angXY) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " angXY = angTmp + (angXY - angTmp) / params->AngStart * params->RatioStripes * params->AngStart;\n" + " params->X = sincos(angMem, ¶ms->Y);\n" + " }\n" + " }\n" + "\n" + " if (((count & 1) == 1) && (params->RatioStripes < 1))\n" + " {\n" + " if ((fabs(angXY - angTmp) > params->SpeedCalc2) && (count != params->MaxStripes))\n" + " {\n" + " if ((angXY - angTmp) > params->SpeedCalc2)\n" + " {\n" + " ratioTmpNum = (angXY - (angTmp + params->SpeedCalc2)) * params->SpeedCalc2;\n" + " ratioTmpDen = params->AngStart - params->SpeedCalc2;\n" + " ratioTmp = ratioTmpNum / ratioTmpDen;\n" + " params->X = sincos((angMem - angXY + angTmp + ratioTmp), ¶ms->Y);\n" + " angXY = angTmp + ratioTmp;\n" + " }\n" + "\n" + " if ((angTmp - angXY) > params->SpeedCalc2)\n" + " {\n" + " ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n" + " ratioTmpDen = params->AngStart - params->SpeedCalc2;\n" + " ratioTmp = ratioTmpNum / ratioTmpDen;\n" + " params->X = sincos((angMem - angXY + angTmp - ratioTmp), ¶ms->Y);\n" + " angXY = angTmp - ratioTmp;\n" + " }\n" + " }\n" + "\n" + " if (count == params->MaxStripes)\n" + " {\n" + " angTmp = params->MidAngle;\n" + "\n" + " if ((angTmp - angXY) > params->SpeedCalc2)\n" + " {\n" + " ratioTmpNum = (angTmp - params->SpeedCalc2 - angXY) * params->SpeedCalc2;\n" + " ratioTmpDen = params->AngStart - params->SpeedCalc2;\n" + " ratioTmp = ratioTmpNum / ratioTmpDen;\n" + " params->X = sincos((angMem - angXY + angTmp - ratioTmp), ¶ms->Y);\n" + " angXY = angTmp - ratioTmp;\n" + " }\n" + " }\n" + " }\n" + "\n" + " Swap(¶ms->RatioStripes, ¶ms->RatioComplement);\n" + " Swap(¶ms->SpeedCalc1, ¶ms->SpeedCalc2);\n" + " }\n" + " }\n" + "\n" + " xTmp = params->Tan90M2 / (params->Tan90M2 - tan(angXY));\n" + " yTmp = xTmp * tan(angXY);\n" + " params->LenOuterEdges = sqrt(SQR(xTmp) + SQR(yTmp));\n" + "\n" + " if (params->ExactCalc == 1)\n" + " {\n" + " if (params->EqualBlur == 1)\n" + " ranTmp = sqrt(MwcNext01(mwc));\n" + " else\n" + " ranTmp = MwcNext01(mwc);\n" + " }\n" + " else\n" + " {\n" + " if (params->CircumCircle == 1)\n" + " {\n" + " if (params->EqualBlur == 1)\n" + " ranTmp = sqrt(MwcNext01(mwc));\n" + " else\n" + " ranTmp = MwcNext01(mwc);\n" + " }\n" + " else\n" + " {\n" + " if (params->EqualBlur == 1)\n" + " ranTmp = sqrt(MwcNext01(mwc)) * params->LenOuterEdges;\n" + " else\n" + " ranTmp = MwcNext01(mwc) * params->LenOuterEdges;\n" + " }\n" + " }\n" + "\n" + " params->LenInnerEdges = params->RatioHole * params->LenOuterEdges;\n" + "\n" + " if (params->ExactCalc == 0)\n" + " {\n" + " if (ranTmp < params->LenInnerEdges)\n" + " {\n" + " if (params->CircumCircle == 1)\n" + " {\n" + " if (params->EqualBlur == 1)\n" + " ranTmp = params->LenInnerEdges + sqrt(MwcNext01(mwc)) * (1 - params->LenInnerEdges + EPS);\n" + " else\n" + " ranTmp = params->LenInnerEdges + MwcNext01(mwc) * (1 - params->LenInnerEdges + EPS);\n" + " }\n" + " else\n" + " {\n" + " if (params->EqualBlur == 1)\n" + " ranTmp = params->LenInnerEdges + sqrt(MwcNext01(mwc)) * (params->LenOuterEdges - params->LenInnerEdges);\n" + " else\n" + " ranTmp = params->LenInnerEdges + MwcNext01(mwc) * (params->LenOuterEdges - params->LenInnerEdges);\n" + " }\n" + " }\n" + " }\n" + "\n" + " params->X *= ranTmp;\n" + " params->Y *= ranTmp;\n" + " params->LenXY = sqrt(SQR(params->X) + SQR(params->Y));\n" + "}\n\n" + ; + } + + virtual void Precalc() override + { + if (m_NumEdges < 3) + m_NumEdges = 3; + + if (m_NumStripes != 0) + { + m_HasStripes = 1; + + if (m_NumStripes < 0) + { + m_NegStripes = 1; + //m_NumStripes *= -1; + } + else + m_NegStripes = 0; + } + else + { + m_HasStripes = 0; + m_NegStripes = 0; + } + + m_AbsStripes = std::fabs(m_NumStripes); + m_MidAngle = M_2PI / m_NumEdges; + + if (m_HasStripes == 1) + { + m_AngStripes = m_MidAngle / (2 * m_AbsStripes); + m_AngStart = m_AngStripes / 2; + m_RatioComplement = 2 - m_RatioStripes; + } + + if ((m_RatioHole > T(0.95)) && (m_ExactCalc == 1) && (m_CircumCircle == 0)) + m_RatioHole = T(0.95); + + m_Tan90M2 = std::tan(T(M_PI_2) + m_MidAngle / 2); + sincos((m_MidAngle / 2), &m_Sina, &m_Cosa); + + if (m_HighlightEdges <= 0.1) + m_HighlightEdges = T(0.1); + + if (m_AdjustToLinear == 1) + { + if (int(m_NumEdges) % 4 == 0) + { + m_AdjustedWeight = m_Weight / (std::sqrt(2 - 2 * std::cos(m_MidAngle * (m_NumEdges / 2 - 1))) / 2); + } + else + { + m_AdjustedWeight = m_Weight / (std::sqrt(2 - 2 * std::cos(m_MidAngle * std::floor((m_NumEdges / 2)))) / 2); + } + } + else + { + m_AdjustedWeight = m_Weight; + } + + if (m_CircumCircle == 1) + { + m_ExactCalc = 0; + m_HighlightEdges = T(0.1); + } + + m_SpeedCalc1 = m_RatioComplement * m_AngStart; + m_SpeedCalc2 = m_RatioStripes * m_AngStart; + m_MaxStripes = 2 * m_AbsStripes; + + if (m_NegStripes == 0) + { + m_ArcTan1 = (13 / std::pow(m_NumEdges, T(1.3))) * m_HighlightEdges; + m_ArcTan2 = (2 * std::atan(m_ArcTan1 / -2)); + } + else + { + m_ArcTan1 = (T(7.5) / std::pow(m_NumEdges, T(1.3))) * m_HighlightEdges; + m_ArcTan2 = 2 * std::atan(m_ArcTan1 / -2); + } + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.reserve(25); + m_Params.push_back(ParamWithName(&m_NumEdges, prefix + "nBlur_numEdges", 3, INTEGER)); + m_Params.push_back(ParamWithName(&m_NumStripes, prefix + "nBlur_numStripes", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_RatioStripes, prefix + "nBlur_ratioStripes", 1, REAL, 0, 2)); + m_Params.push_back(ParamWithName(&m_RatioHole, prefix + "nBlur_ratioHole", 0, REAL, 0, 1)); + m_Params.push_back(ParamWithName(&m_CircumCircle, prefix + "nBlur_circumCircle", 0, INTEGER, 0, 1)); + m_Params.push_back(ParamWithName(&m_AdjustToLinear, prefix + "nBlur_adjustToLinear", 1, INTEGER, 0, 1)); + m_Params.push_back(ParamWithName(&m_EqualBlur, prefix + "nBlur_equalBlur", 1, INTEGER, 0, 1)); + m_Params.push_back(ParamWithName(&m_ExactCalc, prefix + "nBlur_exactCalc", 0, INTEGER, 0, 1)); + m_Params.push_back(ParamWithName(&m_HighlightEdges, prefix + "nBlur_highlightEdges", 1)); + m_Params.push_back(ParamWithName(true, &m_RatioComplement, prefix + "nBlur_ratioComplement"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_MidAngle, prefix + "nBlur_midAngle")); + m_Params.push_back(ParamWithName(true, &m_AngStart, prefix + "nBlur_angStart")); + m_Params.push_back(ParamWithName(true, &m_AngStripes, prefix + "nBlur_angStripes")); + m_Params.push_back(ParamWithName(true, &m_HasStripes, prefix + "nBlur_hasStripes")); + m_Params.push_back(ParamWithName(true, &m_NegStripes, prefix + "nBlur_negStripes")); + m_Params.push_back(ParamWithName(true, &m_MaxStripes, prefix + "nBlur_maxStripes")); + m_Params.push_back(ParamWithName(true, &m_AbsStripes, prefix + "nBlur_absStripes")); + m_Params.push_back(ParamWithName(true, &m_Sina, prefix + "nBlur_sina")); + m_Params.push_back(ParamWithName(true, &m_Cosa, prefix + "nBlur_cosa")); + m_Params.push_back(ParamWithName(true, &m_Tan90M2, prefix + "nBlur_tan90m2")); + m_Params.push_back(ParamWithName(true, &m_ArcTan1, prefix + "nBlur_arcTan1")); + m_Params.push_back(ParamWithName(true, &m_ArcTan2, prefix + "nBlur_arcTan2")); + m_Params.push_back(ParamWithName(true, &m_SpeedCalc1, prefix + "nBlur_speedCalc1")); + m_Params.push_back(ParamWithName(true, &m_SpeedCalc2, prefix + "nBlur_speedCalc2")); + m_Params.push_back(ParamWithName(true, &m_AdjustedWeight, prefix + "nBlur_adjustedWeight")); + } + +private: + static void RandXY(RandXyParams& params, QTIsaac& rand) + { + T angXY, angMem, angTmp; + T ratioTmp, ratioTmpNum, ratioTmpDen; + T xTmp, yTmp; + T ranTmp; + int count; + + if (params.ExactCalc == 1) + angXY = rand.Frand01() * M_2PI; + else + angXY = (std::atan(params.ArcTan1 * (rand.Frand01() - T(0.5))) / params.ArcTan2 + T(0.5) + T(rand.Rand() % glm::uint(params.NumEdges))) * params.MidAngle; + + sincos(angXY, ¶ms.X, ¶ms.Y); + angMem = angXY; + + while (angXY > params.MidAngle) + angXY -= params.MidAngle; + + if (params.HasStripes == 1) + { + count = 0; + angTmp = params.AngStart; + + while (angXY > angTmp) + { + angTmp += params.AngStripes; + + if (angTmp > params.MidAngle) + angTmp = params.MidAngle; + + count++; + } + + if (angTmp != params.MidAngle) + angTmp -= params.AngStart; + + if (params.NegStripes == 0) + { + if ((count & 1) == 1) + { + if (angXY > angTmp) + { + angXY = angXY + params.AngStart; + angMem = angMem + params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + angTmp += params.AngStripes; + count++; + } + else + { + angXY = angXY - params.AngStart; + angMem = angMem - params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + angTmp -= params.AngStripes; + count--; + } + } + + if (((count & 1) == 0) && (params.RatioStripes > 1)) + { + if ((angXY > angTmp) && (count != params.MaxStripes)) + { + angMem = angMem - angXY + angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart; + angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + } + else + { + angMem = angMem - angXY + angTmp - (angTmp - angXY) / params.AngStart * params.RatioStripes * params.AngStart; + angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + } + } + + if (((count & 1) == 0) && (params.RatioStripes < 1)) + { + if ((std::fabs(angXY - angTmp) > params.SpeedCalc2) && (count != params.MaxStripes)) + { + if ((angXY - angTmp) > params.SpeedCalc2) + { + ratioTmpNum = (angXY - (angTmp + params.SpeedCalc2)) * params.SpeedCalc2; + ratioTmpDen = params.AngStart - params.SpeedCalc2; + ratioTmp = ratioTmpNum / ratioTmpDen; + sincos((angMem - angXY + angTmp + ratioTmp), ¶ms.X, ¶ms.Y); + angXY = angTmp + ratioTmp; + } + + if ((angTmp - angXY) > params.SpeedCalc2) + { + ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2; + ratioTmpDen = params.AngStart - params.SpeedCalc2; + ratioTmp = ratioTmpNum / ratioTmpDen; + sincos((angMem - angXY + angTmp - ratioTmp), ¶ms.X, ¶ms.Y); + angXY = angTmp - ratioTmp; + } + } + + if (count == params.MaxStripes) + { + if ((angTmp - angXY) > params.SpeedCalc2) + { + ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2; + ratioTmpDen = params.AngStart - params.SpeedCalc2; + ratioTmp = ratioTmpNum / ratioTmpDen; + sincos((angMem - angXY + angTmp - ratioTmp), ¶ms.X, ¶ms.Y); + angXY = angTmp - ratioTmp; + } + } + } + } + else + { + std::swap(params.RatioStripes, params.RatioComplement); + std::swap(params.SpeedCalc1, params.SpeedCalc2); + + if ((count & 1) == 0) + { + if ((angXY > angTmp) && (count != params.MaxStripes)) + { + angXY = angXY + params.AngStart; + angMem = angMem + params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + angTmp += params.AngStripes; + count++; + } + else + { + angXY = angXY - params.AngStart; + angMem = angMem - params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + angTmp -= params.AngStripes; + count--; + } + } + + if (((count & 1) == 1) && (params.RatioStripes > 1)) + { + if ((angXY > angTmp) && (count != params.MaxStripes)) + { + angMem = angMem - angXY + angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart; + angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + } + else + { + angMem = angMem - angXY + angTmp - (angTmp - angXY) / params.AngStart * params.RatioStripes * params.AngStart; + angXY = angTmp + (angXY - angTmp) / params.AngStart * params.RatioStripes * params.AngStart; + sincos(angMem, ¶ms.X, ¶ms.Y); + } + } + + if (((count & 1) == 1) && (params.RatioStripes < 1)) + { + if ((std::fabs(angXY - angTmp) > params.SpeedCalc2) && (count != params.MaxStripes)) + { + if ((angXY - angTmp) > params.SpeedCalc2) + { + ratioTmpNum = (angXY - (angTmp + params.SpeedCalc2)) * params.SpeedCalc2; + ratioTmpDen = params.AngStart - params.SpeedCalc2; + ratioTmp = ratioTmpNum / ratioTmpDen; + sincos((angMem - angXY + angTmp + ratioTmp), ¶ms.X, ¶ms.Y); + angXY = angTmp + ratioTmp; + } + + if ((angTmp - angXY) > params.SpeedCalc2) + { + ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2; + ratioTmpDen = params.AngStart - params.SpeedCalc2; + ratioTmp = ratioTmpNum / ratioTmpDen; + sincos((angMem - angXY + angTmp - ratioTmp), ¶ms.X, ¶ms.Y); + angXY = angTmp - ratioTmp; + } + } + + if (count == params.MaxStripes) + { + angTmp = params.MidAngle; + + if ((angTmp - angXY) > params.SpeedCalc2) + { + ratioTmpNum = (angTmp - params.SpeedCalc2 - angXY) * params.SpeedCalc2; + ratioTmpDen = params.AngStart - params.SpeedCalc2; + ratioTmp = ratioTmpNum / ratioTmpDen; + sincos((angMem - angXY + angTmp - ratioTmp), ¶ms.X, ¶ms.Y); + angXY = angTmp - ratioTmp; + } + } + } + + std::swap(params.RatioStripes, params.RatioComplement); + std::swap(params.SpeedCalc1, params.SpeedCalc2); + } + } + + xTmp = params.Tan90M2 / (params.Tan90M2 - std::tan(angXY)); + yTmp = xTmp * std::tan(angXY); + params.LenOuterEdges = std::sqrt(SQR(xTmp) + SQR(yTmp)); + + if (params.ExactCalc == 1) + { + if (params.EqualBlur == 1) + ranTmp = std::sqrt(rand.Frand01()); + else + ranTmp = rand.Frand01(); + } + else + { + if (params.CircumCircle == 1) + { + if (params.EqualBlur == 1) + ranTmp = std::sqrt(rand.Frand01()); + else + ranTmp = rand.Frand01(); + } + else + { + if (params.EqualBlur == 1) + ranTmp = std::sqrt(rand.Frand01()) * params.LenOuterEdges; + else + ranTmp = rand.Frand01() * params.LenOuterEdges; + } + } + + params.LenInnerEdges = params.RatioHole * params.LenOuterEdges; + + if (params.ExactCalc == 0) + { + if (ranTmp < params.LenInnerEdges) + { + if (params.CircumCircle == 1) + { + if (params.EqualBlur == 1) + ranTmp = params.LenInnerEdges + std::sqrt(rand.Frand01()) * (1 - params.LenInnerEdges + EPS); + else + ranTmp = params.LenInnerEdges + rand.Frand01() * (1 - params.LenInnerEdges + EPS); + } + else + { + if (params.EqualBlur == 1) + ranTmp = params.LenInnerEdges + std::sqrt(rand.Frand01()) * (params.LenOuterEdges - params.LenInnerEdges); + else + ranTmp = params.LenInnerEdges + rand.Frand01() * (params.LenOuterEdges - params.LenInnerEdges); + } + } + } + + params.X *= ranTmp; + params.Y *= ranTmp; + params.LenXY = std::sqrt(SQR(params.X) + SQR(params.Y)); + } + + T m_NumEdges; + T m_NumStripes; + T m_RatioStripes; + T m_RatioHole; + T m_CircumCircle; + T m_AdjustToLinear; + T m_EqualBlur; + T m_ExactCalc; + T m_HighlightEdges; + T m_RatioComplement;//Precalc. + T m_MidAngle; + T m_AngStart; + T m_AngStripes; + T m_HasStripes; + T m_NegStripes; + T m_MaxStripes; + T m_AbsStripes; + T m_Sina; + T m_Cosa; + T m_Tan90M2; + T m_ArcTan1; + T m_ArcTan2; + T m_SpeedCalc1; + T m_SpeedCalc2; + T m_AdjustedWeight; +}; + +/// +/// octapol. +/// +template +class EMBER_API OctapolVariation : public ParametricVariation +{ +public: + OctapolVariation(T weight = 1.0) : ParametricVariation("octapol", VAR_OCTAPOL, weight) + { + Init(); + } + + PARVARCOPY(OctapolVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + bool clear = false; + T x = helper.In.x * T(0.15), y = helper.In.y * T(0.15), z = helper.In.z, r = 0, u = 0, v = 0; + v2T xy = { x, y }; + v2T tempOut = { 0, 0 }; + + if ((m_TempRad > 0) && HitsCircleAroundOrigin(m_TempRad, xy, r)) + { + T rd = std::log(Sqr(r / m_TempRad)); + T phi = std::atan2(y, x); + + tempOut.x = m_Weight * Lerp(x, phi, rd * m_Polarweight); + tempOut.y = m_Weight * Lerp(y, r, rd * m_Polarweight); + } + else if (HitsSquareAroundOrigin(m_St, xy)) + { + if (HitsRect(m_H, m_K, xy) || HitsRect(m_J, m_D, xy) || + HitsRect(m_A, m_J, xy) || HitsRect(m_K, m_E, xy) || + HitsTriangle(m_I, m_A, m_H, xy, u, v) || + HitsTriangle(m_J, m_B, m_C, xy, u, v) || + HitsTriangle(m_L, m_D, m_E, xy, u, v) || + HitsTriangle(m_K, m_F, m_G, xy, u, v)) + { + tempOut.x = m_Weight * x; + tempOut.y = m_Weight * y; + } + else + clear = true; + } + else + clear = true; + + if (clear) + { + if (m_VarType == VARTYPE_PRE) + { + helper.m_TransX = 0; + helper.m_TransY = 0; + } + else + { + outPoint.m_X = 0; + outPoint.m_Y = 0; + } + } + + helper.Out.x = tempOut.x + (m_Weight * x); + helper.Out.y = tempOut.y + (m_Weight * y); + helper.Out.z = m_Weight * z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber(); + string index = ss2.str() + "]"; + string stateIndex = ss2.str(); + string polarweight = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string s = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string t = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string tempRad = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string abss = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string abst = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string st = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string axStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string bxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string cxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string dxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string exStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string fxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string gxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string hxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string ixStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string jxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string kxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; i += 2; + string lxStartIndex = ToUpper(m_Params[i].Name()) + stateIndex; + + ss << "\t{\n" + << "\t\tbool clear = false;\n" + << "\t\treal_t x = vIn.x * 0.15, y = vIn.y * 0.15, z = vIn.z, r = 0, u = 0, v = 0, x2 = 0, y2 = 0;\n" + << "\t\treal2 xy = { x, y };\n" + << "\t\treal2 tempOut = { 0, 0 };\n" + << "\t\treal2 A = { parVars[" << axStartIndex << "], parVars[" << axStartIndex << " + 1] };\n" + << "\t\treal2 B = { parVars[" << bxStartIndex << "], parVars[" << bxStartIndex << " + 1] };\n" + << "\t\treal2 C = { parVars[" << cxStartIndex << "], parVars[" << cxStartIndex << " + 1] };\n" + << "\t\treal2 D = { parVars[" << dxStartIndex << "], parVars[" << dxStartIndex << " + 1] };\n" + << "\t\treal2 E = { parVars[" << exStartIndex << "], parVars[" << exStartIndex << " + 1] };\n" + << "\t\treal2 F = { parVars[" << fxStartIndex << "], parVars[" << fxStartIndex << " + 1] };\n" + << "\t\treal2 G = { parVars[" << gxStartIndex << "], parVars[" << gxStartIndex << " + 1] };\n" + << "\t\treal2 H = { parVars[" << hxStartIndex << "], parVars[" << hxStartIndex << " + 1] };\n" + << "\t\treal2 I = { parVars[" << ixStartIndex << "], parVars[" << ixStartIndex << " + 1] };\n" + << "\t\treal2 J = { parVars[" << jxStartIndex << "], parVars[" << jxStartIndex << " + 1] };\n" + << "\t\treal2 K = { parVars[" << kxStartIndex << "], parVars[" << kxStartIndex << " + 1] };\n" + << "\t\treal2 L = { parVars[" << lxStartIndex << "], parVars[" << lxStartIndex << " + 1] };\n" + << "\n" + << "\t\tif ((" << tempRad << " > 0) && HitsCircleAroundOrigin(" << tempRad << ", &xy, &r))\n" + << "\t\t{\n" + << "\t\t real_t rd = log(Sqr(r / " << tempRad << "));\n" + << "\t\t real_t phi = atan2(y, x);\n" + << "\n" + << "\t\t tempOut.x = xform->m_VariationWeights[" << varIndex << "] * Lerp(x, phi, rd * " << polarweight << ");\n" + << "\t\t tempOut.y = xform->m_VariationWeights[" << varIndex << "] * Lerp(y, r, rd * " << polarweight << ");\n" + << "\t\t}\n" + << "\t\telse if (HitsSquareAroundOrigin(" << st << ", &xy))\n" + << "\t\t{\n" + << "\t\t if (HitsRect(&H, &K, &xy) || HitsRect(&J, &D, &xy) ||\n" + << "\t\t HitsRect(&A, &J, &xy) || HitsRect(&K, &E, &xy) ||\n" + << "\t\t HitsTriangle(&I, &A, &H, &xy, &u, &v) ||\n" + << "\t\t HitsTriangle(&J, &B, &C, &xy, &u, &v) ||\n" + << "\t\t HitsTriangle(&L, &D, &E, &xy, &u, &v) ||\n" + << "\t\t HitsTriangle(&K, &F, &G, &xy, &u, &v))\n" + << "\t\t {\n" + << "\t\t tempOut.x = xform->m_VariationWeights[" << varIndex << "] * x;\n" + << "\t\t tempOut.y = xform->m_VariationWeights[" << varIndex << "] * y;\n" + << "\t\t }\n" + << "\t\t else\n" + << "\t\t clear = true;\n" + << "\t\t}\n" + << "\t\telse\n" + << "\t\t clear = true;\n" + << "\n" + << "\t\tif (clear)\n" + << "\t\t{\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\t transX = 0;\n" + << "\t\t transY = 0;\n"; + } + else + { + ss + << "\t\t outPoint->m_X = 0;\n" + << "\t\t outPoint->m_Y = 0;\n"; + } + + ss + << "\t\t}\n" + << "\n" + << "\t\tvOut.x = tempOut.x + (xform->m_VariationWeights[" << varIndex << "] * x);\n" + << "\t\tvOut.y = tempOut.y + (xform->m_VariationWeights[" << varIndex << "] * y);\n" + << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * z;\n" + << "\t}\n"; + + return ss.str(); + } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Lerp", "Sqr" }; + } + + virtual string OpenCLFuncsString() const override + { + return + "static int HitsRect(real2* tl, real2* br, real2* p)\n" + "{\n" + " return ((*p).x >= (*tl).x && (*p).y >= (*tl).y && (*p).x <= (*br).x && (*p).y <= (*br).y);\n" + "}\n" + "\n" + "static int HitsSquareAroundOrigin(real_t a, real2* p)\n" + "{\n" + " return (fabs((*p).x) <= a && fabs((*p).y) <= a);\n" + "}\n" + "\n" + "static int HitsCircleAroundOrigin(real_t radius, real2* p, real_t* r)\n" + "{\n" + " if (radius == 0)\n" + " return 1;\n" + "\n" + " *r = sqrt(SQR((*p).x) + SQR((*p).y));\n" + " return (*r <= radius);\n" + "}\n" + "\n" + "static int HitsTriangle(real2* a, real2* b, real2* c, real2* p, real_t* u, real_t* v)\n" + "{\n" + " real2 v0 = { (*c).x - (*a).x, (*c).y - (*a).y };\n" + " real2 v1 = { (*b).x - (*a).x, (*b).y - (*a).y };\n" + " real2 v2 = { (*p).x - (*a).x, (*p).y - (*a).y };\n" + " real_t d00 = dot(v0, v0);\n" + " real_t d01 = dot(v0, v1);\n" + " real_t d02 = dot(v0, v2);\n" + " real_t d11 = dot(v1, v1);\n" + " real_t d12 = dot(v1, v2);\n" + " real_t denom = (d00 * d11 - d01 * d01);\n" + "\n" + " if (denom != 0)\n" + " {\n" + " *u = (d11 * d02 - d01 * d12) / denom;\n" + " *v = (d00 * d12 - d01 * d02) / denom;\n" + " }\n" + " else\n" + " *u = *v = 0;\n" + "\n" + " return ((*u + *v) < 1) && (*u > 0) && (*v > 0);\n" + "}\n\n"; + } + + virtual void Precalc() override + { + static const T DENOM_SQRT2 = T(0.707106781); + + m_AbsS = std::fabs(m_S); + m_AbsT = std::fabs(m_T); + m_St = m_AbsS * T(0.5) + m_AbsT; + m_TempRad = DENOM_SQRT2 * m_AbsS * std::fabs(m_Radius); + + m_A = { -T(0.5) * m_AbsS, T(0.5) * m_AbsS + m_AbsT }; + m_B = { T(0.5) * m_AbsS, T(0.5) * m_AbsS + m_AbsT }; + m_C = { m_AbsT, T(0.5) * m_AbsS }; + m_D = { m_AbsT, -T(0.5) * m_AbsS }; + m_E = { T(0.5) * m_AbsS, -T(0.5) * m_AbsS - m_AbsT }; + m_F = { -T(0.5) * m_AbsS, -T(0.5) * m_AbsS - m_AbsT }; + m_G = { -m_AbsT, -T(0.5) * m_AbsS }; + m_H = { -m_AbsT, T(0.5) * m_AbsS }; + m_I = { -T(0.5) * m_AbsS, T(0.5) * m_AbsS }; + m_J = { T(0.5) * m_AbsS, T(0.5) * m_AbsS }; + m_K = { -T(0.5) * m_AbsS, -T(0.5) * m_AbsS }; + m_L = { T(0.5) * m_AbsS, -T(0.5) * m_AbsS }; + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.push_back(ParamWithName(&m_Polarweight, prefix + "octapol_polarweight")); + m_Params.push_back(ParamWithName(&m_Radius, prefix + "octapol_radius", 1)); + m_Params.push_back(ParamWithName(&m_S, prefix + "octapol_s", T(0.5))); + m_Params.push_back(ParamWithName(&m_T, prefix + "octapol_t", T(0.5))); + m_Params.push_back(ParamWithName(true, &m_TempRad, prefix + "octapol_rad"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_AbsS, prefix + "octapol_abss")); + m_Params.push_back(ParamWithName(true, &m_AbsT, prefix + "octapol_abst")); + m_Params.push_back(ParamWithName(true, &m_St, prefix + "octapol_absst")); + m_Params.push_back(ParamWithName(true, &m_A.x, prefix + "octapol_ax")); + m_Params.push_back(ParamWithName(true, &m_A.y, prefix + "octapol_ay")); + m_Params.push_back(ParamWithName(true, &m_B.x, prefix + "octapol_bx")); + m_Params.push_back(ParamWithName(true, &m_B.y, prefix + "octapol_by")); + m_Params.push_back(ParamWithName(true, &m_C.x, prefix + "octapol_cx")); + m_Params.push_back(ParamWithName(true, &m_C.y, prefix + "octapol_cy")); + m_Params.push_back(ParamWithName(true, &m_D.x, prefix + "octapol_dx")); + m_Params.push_back(ParamWithName(true, &m_D.y, prefix + "octapol_dy")); + m_Params.push_back(ParamWithName(true, &m_E.x, prefix + "octapol_ex")); + m_Params.push_back(ParamWithName(true, &m_E.y, prefix + "octapol_ey")); + m_Params.push_back(ParamWithName(true, &m_F.x, prefix + "octapol_fx")); + m_Params.push_back(ParamWithName(true, &m_F.y, prefix + "octapol_fy")); + m_Params.push_back(ParamWithName(true, &m_G.x, prefix + "octapol_gx")); + m_Params.push_back(ParamWithName(true, &m_G.y, prefix + "octapol_gy")); + m_Params.push_back(ParamWithName(true, &m_H.x, prefix + "octapol_hx")); + m_Params.push_back(ParamWithName(true, &m_H.y, prefix + "octapol_hy")); + m_Params.push_back(ParamWithName(true, &m_I.x, prefix + "octapol_ix")); + m_Params.push_back(ParamWithName(true, &m_I.y, prefix + "octapol_iy")); + m_Params.push_back(ParamWithName(true, &m_J.x, prefix + "octapol_jx")); + m_Params.push_back(ParamWithName(true, &m_J.y, prefix + "octapol_jy")); + m_Params.push_back(ParamWithName(true, &m_K.x, prefix + "octapol_kx")); + m_Params.push_back(ParamWithName(true, &m_K.y, prefix + "octapol_ky")); + m_Params.push_back(ParamWithName(true, &m_L.x, prefix + "octapol_lx")); + m_Params.push_back(ParamWithName(true, &m_L.y, prefix + "octapol_ly")); + } + +private: + int HitsRect(v2T& tl, v2T& br, v2T& p) + { + return (p.x >= tl.x && p.y >= tl.y && p.x <= br.x && p.y <= br.y); + } + + int HitsSquareAroundOrigin(T a, v2T& p) + { + return (std::fabs(p.x) <= a && std::fabs(p.y) <= a); + } + + int HitsCircleAroundOrigin(T radius, v2T& p, T& r) + { + if (radius == 0) + return 1; + + r = sqrt(SQR(p.x) + SQR(p.y)); + return (r <= radius); + } + + int HitsTriangle(v2T& a, v2T& b, v2T& c, v2T& p, T& u, T& v) + { + v2T v0 = { c.x - a.x, c.y - a.y }; + v2T v1 = { b.x - a.x, b.y - a.y }; + v2T v2 = { p.x - a.x, p.y - a.y }; + T d00 = glm::dot(v0, v0); + T d01 = glm::dot(v0, v1); + T d02 = glm::dot(v0, v2); + T d11 = glm::dot(v1, v1); + T d12 = glm::dot(v1, v2); + T denom = (d00 * d11 - d01 * d01); + + if (denom != 0) + { + u = (d11 * d02 - d01 * d12) / denom; + v = (d00 * d12 - d01 * d02) / denom; + } + else + u = v = 0; + + return ((u + v) < 1) && (u > 0) && (v > 0); + } + + T m_Polarweight; + T m_Radius; + T m_S; + T m_T; + T m_TempRad;//Precalc. + T m_AbsS; + T m_AbsT; + T m_St; + v2T m_A; + v2T m_B; + v2T m_C; + v2T m_D; + v2T m_E; + v2T m_F; + v2T m_G; + v2T m_H; + v2T m_I; + v2T m_J; + v2T m_K; + v2T m_L; +}; + +/// +/// crob. +/// This uses the input point in an extremely rare way since it changes it. +/// +template +class EMBER_API CrobVariation : public ParametricVariation +{ +public: + CrobVariation(T weight = 1.0) : ParametricVariation("crob", VAR_CROB, weight) + { + Init(); + } + + PARVARCOPY(CrobVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + T gradTmp, secTmp, xTmp, yTmp; + + if ((helper.In.x < m_LeftBorder) || (helper.In.x > m_RightBorder) || (helper.In.y < m_TopBorder) || (helper.In.y > m_BottomBorder)) + { + if (m_Blur == 0) + { + if (m_VarType == VARTYPE_PRE)//Setting input point. + { + helper.m_TransX = 0; + helper.m_TransY = 0; + } + else if (m_VarType == VARTYPE_REG) + { + helper.In.x = 0; + helper.In.y = 0; + } + else + { + outPoint.m_X = 0; + outPoint.m_Y = 0; + } + } + else + { + secTmp = rand.Frand01(); + + if (secTmp < m_SetProb) + { + do + { + yTmp = m_Top + rand.Frand01() * m_YInt2; + xTmp = m_Right - pow(rand.Frand01(), m_DirectBlur) * m_RatioBlur * m_MinInt2; + } while ((yTmp - m_Y0c) / (xTmp - m_X0c) < -1); + + if (secTmp < m_SetProbH) + xTmp = m_Left + m_Right - xTmp; + + if ((secTmp > m_SetProbQ) && (secTmp < m_SetProbTQ)) + yTmp = m_Bottom + m_Top - yTmp; + } + else + { + do + { + xTmp = m_Right - rand.Frand01() * m_XInt2; + yTmp = m_Top + std::pow(rand.Frand01(), m_DirectBlur) * m_RatioBlur * m_MinInt2; + gradTmp = (yTmp - m_Y0c) / (xTmp - m_X0c); + } while ((gradTmp <= 0) && (gradTmp > -1)); + + if (secTmp > m_SetProbH) + yTmp = m_Bottom + m_Top - yTmp; + + if ((secTmp > m_SetProbQ) && (secTmp < m_SetProbTQ)) + xTmp = m_Left + m_Right - xTmp; + } + + if (m_VarType == VARTYPE_PRE) + { + helper.m_TransX = xTmp; + helper.m_TransY = yTmp; + } + else if (m_VarType == VARTYPE_REG) + { + helper.In.x = xTmp; + helper.In.y = yTmp; + } + else + { + outPoint.m_X = xTmp; + outPoint.m_Y = yTmp; + } + } + } + + if (m_VarType == VARTYPE_PRE) + { + helper.Out.x = helper.m_TransX; + helper.Out.y = helper.m_TransY; + } + else if (m_VarType == VARTYPE_REG) + { + helper.Out.x = helper.In.x; + helper.Out.y = helper.In.y; + } + else + { + helper.Out.x = outPoint.m_X; + helper.Out.y = outPoint.m_Y; + } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber() << "]"; + string index = ss2.str(); + string top = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string bottom = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string left = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string right = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string blur = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string ratioBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string directBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string xInterval = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string yInterval = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string xInt2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string yInt2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string minInt2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string y0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string x0c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string y0c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setProb = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setProbH = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setProbQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setProbTQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setCompProb = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setCompProbH = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setCompProbQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string setCompProbTQ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string topBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string bottomBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string leftBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string rightBorder = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + << "\t\treal_t gradTmp, secTmp, xTmp, yTmp;\n" + << "\n" + << "\t\tif ((vIn.x < " << leftBorder << ") || (vIn.x > " << rightBorder << ") || (vIn.y < " << topBorder << ") || (vIn.y > " << bottomBorder << "))\n" + << "\t\t{\n" + << "\t\t if (" << blur << " == 0)\n" + << "\t\t {\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\t transX = 0;\n" + << "\t\t transY = 0;\n"; + } + else if (m_VarType == VARTYPE_REG) + { + ss + << "\t\t vIn.x = 0;\n" + << "\t\t vIn.y = 0;\n"; + } + else + { + ss + << "\t\t outPoint->m_X = 0;\n" + << "\t\t outPoint->m_Y = 0;\n"; + } + + ss + << "\t\t }\n" + << "\t\t else\n" + << "\t\t {\n" + << "\t\t secTmp = MwcNext01(mwc);\n" + << "\n" + << "\t\t if (secTmp < " << setProb << ")\n" + << "\t\t {\n" + << "\t\t do\n" + << "\t\t {\n" + << "\t\t yTmp = " << top << " + MwcNext01(mwc) * " << yInt2 << ";\n" + << "\t\t xTmp = " << right << " - pow(MwcNext01(mwc), " << directBlur << ") * " << ratioBlur << " * " << minInt2 << ";\n" + << "\t\t } while ((yTmp - " << y0c << ") / (xTmp - " << x0c << ") < -1);\n" + << "\n" + << "\t\t if (secTmp < " << setProbH << ")\n" + << "\t\t xTmp = " << left << " + " << right << " - xTmp;\n" + << "\n" + << "\t\t if ((secTmp > " << setProbQ << ") && (secTmp < " << setProbTQ << "))\n" + << "\t\t yTmp = " << bottom << " + " << top << " - yTmp;\n" + << "\t\t }\n" + << "\t\t else\n" + << "\t\t {\n" + << "\t\t do\n" + << "\t\t {\n" + << "\t\t xTmp = " << right << " - MwcNext01(mwc) * " << xInt2 << ";\n" + << "\t\t yTmp = " << top << " + pow(MwcNext01(mwc), " << directBlur << ") * " << ratioBlur << " * " << minInt2 << ";\n" + << "\t\t gradTmp = (yTmp - " << y0c << ") / (xTmp - " << x0c << ");\n" + << "\t\t } while ((gradTmp <= 0) && (gradTmp > -1));\n" + << "\n" + << "\t\t if (secTmp > " << setProbH << ")\n" + << "\t\t yTmp = " << bottom << " + " << top << " - yTmp;\n" + << "\n" + << "\t\t if ((secTmp > " << setProbQ << ") && (secTmp < " << setProbTQ << "))\n" + << "\t\t xTmp = " << left << " + " << right << " - xTmp;\n" + << "\t\t }\n" + << "\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\t transX = xTmp;\n" + << "\t\t transY = yTmp;\n"; + } + else if (m_VarType == VARTYPE_REG) + { + ss + << "\t\t vIn.x = xTmp;\n" + << "\t\t vIn.y = yTmp;\n"; + } + else + { + ss + << "\t\t outPoint->m_X = xTmp;\n" + << "\t\t outPoint->m_Y = yTmp;\n"; + } + + ss + << "\t\t\t}\n" + << "\t\t}\n" + << "\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\tvOut.x = transX;\n" + << "\t\tvOut.y = transY;\n"; + } + else if (m_VarType == VARTYPE_REG) + { + ss + << "\t\tvOut.x = vIn.x;\n" + << "\t\tvOut.y = vIn.y;\n"; + } + else + { + ss + << "\t\tvOut.x = outPoint->m_X;\n" + << "\t\tvOut.y = outPoint->m_Y;\n"; + } + + ss + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" + << "\t}\n"; + + return ss.str(); + } + + virtual void Precalc() override + { + if (m_Top > m_Bottom) + std::swap(m_Top, m_Bottom); + + if (m_Top == m_Bottom) + { + m_Top = -1; + m_Bottom = 1; + } + + if (m_Left > m_Right) + std::swap(m_Left, m_Right); + + if (m_Left == m_Right) + { + m_Left = -1; + m_Right = 1; + } + + if (m_DirectBlur < 0) + m_DirectBlur = 0; + + if (m_Blur != 0) + m_Blur = 1; + + m_XInterval = std::fabs(m_Right) - m_Left; + m_YInterval = std::fabs(m_Bottom) - m_Top; + m_XInt2 = m_XInterval / 2; + m_YInt2 = m_YInterval / 2; + + if (m_XInt2 > m_YInt2) + m_MinInt2 = m_YInt2; + else + m_MinInt2 = m_XInt2; + + m_X0 = m_Right - m_XInt2; + m_Y0 = m_Top + m_YInt2; + + if (m_XInt2 > m_YInt2) + { + m_X0c = m_Right - m_MinInt2; + m_Y0c = m_Y0; + } + else if (m_XInt2 < m_YInt2) + { + m_X0c = m_X0; + m_Y0c = m_Top + m_MinInt2; + } + else + { + m_X0c = m_X0; + m_Y0c = m_Y0; + } + + m_SetProb = m_YInterval / (m_XInterval + m_YInterval); + m_SetProbQ = T(0.25) * m_SetProb; + m_SetProbH = T(0.50) * m_SetProb; + m_SetProbTQ = T(0.75) * m_SetProb; + m_SetCompProb = T(1.0) - m_SetProb; + m_SetCompProbQ = m_SetProb + T(0.25) * m_SetCompProb; + m_SetCompProbH = m_SetProb + T(0.50) * m_SetCompProb; + m_SetCompProbTQ = m_SetProb + T(0.75) * m_SetCompProb; + + if (m_Blur == 0) + { + m_TopBorder = m_Top; + m_BottomBorder = m_Bottom; + m_LeftBorder = m_Left; + m_RightBorder = m_Right; + } + else + { + m_TopBorder = m_Top + m_MinInt2 * m_RatioBlur; + m_BottomBorder = m_Bottom - m_MinInt2 * m_RatioBlur; + m_LeftBorder = m_Left + m_MinInt2 * m_RatioBlur; + m_RightBorder = m_Right -m_MinInt2 * m_RatioBlur; + } + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + + m_Params.push_back(ParamWithName(&m_Top, prefix + "crob_top", -1)); + m_Params.push_back(ParamWithName(&m_Bottom, prefix + "crob_bottom", 1)); + m_Params.push_back(ParamWithName(&m_Left, prefix + "crob_left", -1)); + m_Params.push_back(ParamWithName(&m_Right, prefix + "crob_right", 1)); + m_Params.push_back(ParamWithName(&m_Blur, prefix + "crob_blur", 1, INTEGER)); + m_Params.push_back(ParamWithName(&m_RatioBlur, prefix + "crob_ratioBlur", T(0.5), REAL, 0, 1)); + m_Params.push_back(ParamWithName(&m_DirectBlur, prefix + "crob_directBlur", 2)); + m_Params.push_back(ParamWithName(true, &m_XInterval, prefix + "crob_xinterval")); + m_Params.push_back(ParamWithName(true, &m_YInterval, prefix + "crob_yinterval")); + m_Params.push_back(ParamWithName(true, &m_XInt2, prefix + "crob_xint2")); + m_Params.push_back(ParamWithName(true, &m_YInt2, prefix + "crob_yint2")); + m_Params.push_back(ParamWithName(true, &m_MinInt2, prefix + "crob_minint2")); + m_Params.push_back(ParamWithName(true, &m_X0, prefix + "crob_x0")); + m_Params.push_back(ParamWithName(true, &m_Y0, prefix + "crob_y0")); + m_Params.push_back(ParamWithName(true, &m_X0c, prefix + "crob_x0c")); + m_Params.push_back(ParamWithName(true, &m_Y0c, prefix + "crob_y0c")); + m_Params.push_back(ParamWithName(true, &m_SetProb, prefix + "crob_set_prob")); + m_Params.push_back(ParamWithName(true, &m_SetProbH, prefix + "crob_set_prob_h")); + m_Params.push_back(ParamWithName(true, &m_SetProbQ, prefix + "crob_set_prob_q")); + m_Params.push_back(ParamWithName(true, &m_SetProbTQ, prefix + "crob_set_prob_tq")); + m_Params.push_back(ParamWithName(true, &m_SetCompProb, prefix + "crob_set_comp_prob")); + m_Params.push_back(ParamWithName(true, &m_SetCompProbH, prefix + "crob_set_comp_prob_h")); + m_Params.push_back(ParamWithName(true, &m_SetCompProbQ, prefix + "crob_set_comp_prob_q")); + m_Params.push_back(ParamWithName(true, &m_SetCompProbTQ, prefix + "crob_set_comp_prob_tq")); + m_Params.push_back(ParamWithName(true, &m_TopBorder, prefix + "crob_top_border")); + m_Params.push_back(ParamWithName(true, &m_BottomBorder, prefix + "crob_bottom_border")); + m_Params.push_back(ParamWithName(true, &m_LeftBorder, prefix + "crob_left_border")); + m_Params.push_back(ParamWithName(true, &m_RightBorder, prefix + "crob_right_border")); + } + +private: + T m_Top; + T m_Bottom; + T m_Left; + T m_Right; + T m_Blur; + T m_RatioBlur; + T m_DirectBlur; + T m_XInterval;//Precalc. + T m_YInterval; + T m_XInt2; + T m_YInt2; + T m_MinInt2; + T m_X0; + T m_Y0; + T m_X0c; + T m_Y0c; + T m_SetProb; + T m_SetProbH; + T m_SetProbQ; + T m_SetProbTQ; + T m_SetCompProb; + T m_SetCompProbH; + T m_SetCompProbQ; + T m_SetCompProbTQ; + T m_TopBorder; + T m_BottomBorder; + T m_LeftBorder; + T m_RightBorder; +}; + +/// +/// bubbleT3D. +/// +template +class EMBER_API BubbleT3DVariation : public ParametricVariation +{ +public: + BubbleT3DVariation(T weight = 1.0) : ParametricVariation("bubbleT3D", VAR_BUBBLET3D, weight, true) + { + Init(); + } + + PARVARCOPY(BubbleT3DVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + T x = helper.In.x, y = helper.In.y, z = helper.In.z; + T xTmp, yTmp, angTmp, angRot, fac; + T rad = helper.m_PrecalcSumSquares / 4 + 1; + T angXY, angZ; + T c, s; + + angXY = std::atan2(x, y); + + if (angXY < 0) + angXY += M_2PI; + + if (m_AbsNumberStripes != 0) + { + while (angXY > m_AngStrip2) + { + angXY -= m_AngStrip2; + } + + if (m_InvStripes == 0) + { + if (angXY > m_AngStrip1) + { + if (m_ModusBlur == 0) + { + x = 0; + y = 0; + } + else + { + if (m_RatioStripes == 1) + { + xTmp = m_C * x - m_S * y; + yTmp = m_S * x + m_C * y; + x = xTmp; + y = yTmp; + } + else + { + angRot = (angXY - m_AngStrip1) / (m_AngStrip2 - m_AngStrip1); + angRot = angXY - angRot * m_AngStrip1; + sincos(angRot, &s, &c); + xTmp = c * x - s * y; + yTmp = s * x + c * y; + x = xTmp; + y = yTmp; + } + } + } + } + else + { + if (angXY < m_AngStrip1) + { + if (m_ModusBlur == 0) + { + x = 0; + y = 0; + } + else + { + if (m_AbsNumberStripes == 1) + { + xTmp = m_C * x - m_S * y; + yTmp = m_S * x + m_C * y; + x = xTmp; + y = yTmp; + } + else + { + angRot = (angXY - m_AngStrip1) / m_AngStrip1; + angRot = angXY - angRot * (m_AngStrip2 - m_AngStrip1); + sincos(angRot, &s, &c); + xTmp = c * x - s * y; + yTmp = s * x + c * y; + x = xTmp; + y = yTmp; + } + } + } + } + } + + x = x / rad; + y = y / rad; + + if ((x != 0) || (y != 0)) + { + z = 2 / std::pow(rad, m_ExponentZ) - 1; + + if (m_ExponentZ <= 2) + angZ = T(M_PI) - std::acos((z / (Sqr(x) + Sqr(y) + Sqr(z)))); + else + angZ = T(M_PI) - std::atan2(Sqr(Sqr(x) + Sqr(y)), z); + } + else + { + z = 0; + angZ = 0; + } + + if (m_SymmetryZ == 0) + { + if (m_InvHole == 0) + { + if (angZ > m_AngleHoleTemp) + { + if ((m_ModusBlur == 0) || (m_ExponentZ != 1)) + { + x = 0; + y = 0; + z = 0; + } + else + { + angTmp = (T(M_PI) - angZ) / m_AngHoleComp * m_AngleHoleTemp - T(M_PI_2); + angZ -= T(M_PI_2); + fac = std::cos(angTmp) / std::cos(angZ); + x = x * fac; + y = y * fac; + z = z * (std::sin(angTmp) / std::sin(angZ)); + } + } + } + else + { + if (angZ < m_AngleHoleTemp) + { + if ((m_ModusBlur == 0) || (m_ExponentZ != 1)) + { + x = 0; + y = 0; + z = 0; + } + else + { + angTmp = T(M_PI) - angZ / m_AngHoleComp * m_AngleHoleTemp - T(M_PI_2); + angZ -= T(M_PI_2); + fac = std::cos(angTmp) / std::cos(angZ); + x = x * fac; + y = y * fac; + z = z * (std::sin(angTmp) / std::sin(angZ)); + } + } + } + } + else + { + if ((angZ > m_AngleHoleTemp) || (angZ < (T(M_PI) - m_AngleHoleTemp))) + { + if ((m_ModusBlur == 0) || (m_ExponentZ != 1)) + { + x = 0; + y = 0; + z = 0; + } + else + { + if (angZ > m_AngleHoleTemp) + { + angTmp = (T(M_PI) - angZ) / m_AngHoleComp * (T(M_PI) - 2 * m_AngHoleComp) + m_AngHoleComp - T(M_PI_2); + } + else + { + angTmp = T(M_PI_2) - (angZ / m_AngHoleComp * (T(M_PI) - 2 * m_AngHoleComp) + m_AngHoleComp); + } + + angZ -= T(M_PI_2); + fac = std::cos(angTmp) / std::cos(angZ); + x = x * fac; + y = y * fac; + z = z * (std::sin(angTmp) / std::sin(angZ)); + } + } + } + + helper.Out.x = m_Weight * x; + helper.Out.y = m_Weight * y; + helper.Out.z = m_Weight * z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber(); + string index = ss2.str() + "]"; + + string numberStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string ratioStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angleHole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string exponentZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string symmetryZ = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string modusBlur = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string absNumberStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angHoleTemp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angStrip = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angStrip1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angStrip2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string invStripes = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string angHoleComp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string invHole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string s = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + "\t\treal_t x = vIn.x, y = vIn.y, z = vIn.z;\n" + "\t\treal_t xTmp, yTmp, angTmp, angRot, fac;\n" + "\t\treal_t rad = precalcSumSquares / 4 + 1;\n" + "\t\treal_t angXY, angZ;\n" + "\t\treal_t c, s;\n" + "\t\t\n" + "\t\tangXY = atan2(x, y);\n" + "\t\t\n" + "\t\tif (angXY < 0)\n" + "\t\t angXY += M_2PI;\n" + "\t\t\n" + "\t\tif (" << absNumberStripes << " != 0)\n" + "\t\t{\n" + "\t\t while (angXY > " << angStrip2 << ")\n" + "\t\t {\n" + "\t\t angXY -= " << angStrip2 << "; \n" + "\t\t }\n" + "\t\t\n" + "\t\t if (" << invStripes << " == 0)\n" + "\t\t {\n" + "\t\t if (angXY > " << angStrip1 << ")\n" + "\t\t {\n" + "\t\t if (" << modusBlur << " == 0)\n" + "\t\t {\n" + "\t\t x = 0;\n" + "\t\t y = 0;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t if (" << ratioStripes << " == 1)\n" + "\t\t {\n" + "\t\t xTmp = " << c << " * x - " << s << " * y;\n" + "\t\t yTmp = " << s << " * x + " << c << " * y;\n" + "\t\t x = xTmp;\n" + "\t\t y = yTmp;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t angRot = (angXY - " << angStrip1 << ") / (" << angStrip2 << " - " << angStrip1 << ");\n" + "\t\t angRot = angXY - angRot * " << angStrip1 << ";\n" + "\t\t s = sincos(angRot, &c);\n" + "\t\t xTmp = c * x - s * y;\n" + "\t\t yTmp = s * x + c * y;\n" + "\t\t x = xTmp;\n" + "\t\t y = yTmp;\n" + "\t\t }\n" + "\t\t }\n" + "\t\t }\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t if (angXY < " << angStrip1 << ")\n" + "\t\t {\n" + "\t\t if (" << modusBlur << " == 0)\n" + "\t\t {\n" + "\t\t x = 0;\n" + "\t\t y = 0;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t if (" << absNumberStripes << " == 1)\n" + "\t\t {\n" + "\t\t xTmp = " << c << " * x - " << s << " * y;\n" + "\t\t yTmp = " << s << " * x + " << c << " * y;\n" + "\t\t x = xTmp;\n" + "\t\t y = yTmp;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t angRot = (angXY - " << angStrip1 << ") / " << angStrip1 << ";\n" + "\t\t angRot = angXY - angRot * (" << angStrip2 << " - " << angStrip1 << ");\n" + "\t\t s = sincos(angRot, &c);\n" + "\t\t xTmp = c * x - s * y;\n" + "\t\t yTmp = s * x + c * y;\n" + "\t\t x = xTmp;\n" + "\t\t y = yTmp;\n" + "\t\t }\n" + "\t\t }\n" + "\t\t }\n" + "\t\t }\n" + "\t\t}\n" + "\t\t\n" + "\t\tx = x / rad;\n" + "\t\ty = y / rad;\n" + "\t\t\n" + "\t\tif ((x != 0) || (y != 0))\n" + "\t\t{\n" + "\t\t z = 2 / pow(rad, " << exponentZ << ") - 1; \n" + "\t\t\n" + "\t\t if (" << exponentZ << " <= 2)\n" + "\t\t angZ = M_PI - acos((z / (Sqr(x) + Sqr(y) + Sqr(z))));\n" + "\t\t else\n" + "\t\t angZ = M_PI - atan2(Sqr(Sqr(x) + Sqr(y)), z);\n" + "\t\t}\n" + "\t\telse\n" + "\t\t{\n" + "\t\t z = 0;\n" + "\t\t angZ = 0;\n" + "\t\t}\n" + "\t\t\n" + "\t\tif (" << symmetryZ << " == 0)\n" + "\t\t{\n" + "\t\t if (" << invHole << " == 0)\n" + "\t\t {\n" + "\t\t if (angZ > " << angHoleTemp << ")\n" + "\t\t {\n" + "\t\t if ((" << modusBlur << " == 0) || (" << exponentZ << " != 1))\n" + "\t\t {\n" + "\t\t x = 0;\n" + "\t\t y = 0;\n" + "\t\t z = 0;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t angTmp = (M_PI - angZ) / " << angHoleComp << " * " << angHoleTemp << " - M_PI_2; \n" + "\t\t angZ -= M_PI_2;\n" + "\t\t fac = cos(angTmp) / cos(angZ);\n" + "\t\t x = x * fac;\n" + "\t\t y = y * fac;\n" + "\t\t z = z * (sin(angTmp) / sin(angZ));\n" + "\t\t }\n" + "\t\t }\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t if (angZ < " << angHoleTemp << ")\n" + "\t\t {\n" + "\t\t if ((" << modusBlur << " == 0) || (" << exponentZ << " != 1))\n" + "\t\t {\n" + "\t\t x = 0;\n" + "\t\t y = 0;\n" + "\t\t z = 0;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t angTmp = M_PI - angZ / " << angHoleComp << " * " << angHoleTemp << " - M_PI_2; \n" + "\t\t angZ -= M_PI_2;\n" + "\t\t fac = cos(angTmp) / cos(angZ);\n" + "\t\t x = x * fac;\n" + "\t\t y = y * fac;\n" + "\t\t z = z * (sin(angTmp) / sin(angZ));\n" + "\t\t }\n" + "\t\t }\n" + "\t\t }\n" + "\t\t}\n" + "\t\telse\n" + "\t\t{\n" + "\t\t if ((angZ > " << angHoleTemp << ") || (angZ < (M_PI - " << angHoleTemp << ")))\n" + "\t\t {\n" + "\t\t if ((" << modusBlur << " == 0) || (" << exponentZ << " != 1))\n" + "\t\t {\n" + "\t\t x = 0;\n" + "\t\t y = 0;\n" + "\t\t z = 0;\n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t if (angZ > " << angHoleTemp << ")\n" + "\t\t {\n" + "\t\t angTmp = (M_PI - angZ) / " << angHoleComp << " * (M_PI - 2 * " << angHoleComp << ") + " << angHoleComp << " - M_PI_2; \n" + "\t\t }\n" + "\t\t else\n" + "\t\t {\n" + "\t\t angTmp = M_PI_2 - (angZ / " << angHoleComp << " * (M_PI - 2 * " << angHoleComp << ") + " << angHoleComp << ");\n" + "\t\t }\n" + "\t\t\n" + "\t\t angZ -= M_PI_2;\n" + "\t\t fac = cos(angTmp) / cos(angZ);\n" + "\t\t x = x * fac;\n" + "\t\t y = y * fac;\n" + "\t\t z = z * (sin(angTmp) / sin(angZ));\n" + "\t\t }\n" + "\t\t }\n" + "\t\t}\n" + "\t\t\n" + "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * x;\n" + "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * y;\n" + "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * z;\n" + "\t}\n"; + + return ss.str(); + } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr" }; + } + + virtual void Precalc() override + { + if (m_NumberStripes < 0) + { + m_AbsNumberStripes = std::fabs(m_NumberStripes); + m_InvStripes = 1; + } + else + { + m_AbsNumberStripes = m_NumberStripes; + m_InvStripes = 0; + } + + if (m_AbsNumberStripes != 0) + { + m_AngStrip = T(M_PI) / m_AbsNumberStripes; + m_AngStrip2 = 2 * m_AngStrip; + sincos(m_AngStrip, &m_S, &m_C); + ClampRef(m_RatioStripes, T(0.01), T(1.99)); + m_AngStrip1 = m_RatioStripes * m_AngStrip; + } + + if (m_SymmetryZ == 1) + { + if (m_AngleHole < 0) + m_AngleHoleTemp = std::fabs(m_AngleHole); + else if (m_AngleHole > T(179.9)) + m_AngleHoleTemp = T(179.9); + else + m_AngleHoleTemp = m_AngleHole; + } + else + m_AngleHoleTemp = m_AngleHole; + + if (m_AngleHoleTemp < 0) + { + m_AngleHoleTemp = std::fabs(m_AngleHole); + m_InvHole = 1; + m_AngleHoleTemp = (m_AngleHoleTemp / 360 * M_2PI) / 2; + } + else + { + m_InvHole = 0; + m_AngleHoleTemp = T(M_PI) - (m_AngleHoleTemp / 360 * M_2PI) / 2; + } + + m_AngHoleComp = T(M_PI) - m_AngleHoleTemp; + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.reserve(14); + m_Params.push_back(ParamWithName(&m_NumberStripes, prefix + "bubbleT3D_number_of_stripes", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_RatioStripes, prefix + "bubbleT3D_ratio_of_stripes", 1, REAL, 0, 2)); + m_Params.push_back(ParamWithName(&m_AngleHole, prefix + "bubbleT3D_angle_of_hole", 0, REAL, -360, 360)); + m_Params.push_back(ParamWithName(&m_ExponentZ, prefix + "bubbleT3D_exponentZ", 1)); + m_Params.push_back(ParamWithName(&m_SymmetryZ, prefix + "bubbleT3D_symmetryZ", 0, INTEGER, 0, 1)); + m_Params.push_back(ParamWithName(&m_ModusBlur, prefix + "bubbleT3D_modusBlur", 0, INTEGER, 0, 1)); + m_Params.push_back(ParamWithName(true, &m_AbsNumberStripes, prefix + "bubbleT3D_abs_number_of_stripes"));//Precalc. + m_Params.push_back(ParamWithName(true, &m_AngleHoleTemp, prefix + "bubbleT3D_ang_hole_temp")); + m_Params.push_back(ParamWithName(true, &m_AngStrip, prefix + "bubbleT3D_ang_strip")); + m_Params.push_back(ParamWithName(true, &m_AngStrip1, prefix + "bubbleT3D_ang_strip1")); + m_Params.push_back(ParamWithName(true, &m_AngStrip2, prefix + "bubbleT3D_ang_strip2")); + m_Params.push_back(ParamWithName(true, &m_InvStripes, prefix + "bubbleT3D_inv_stripes")); + m_Params.push_back(ParamWithName(true, &m_AngHoleComp, prefix + "bubbleT3D_ang_hole_comp")); + m_Params.push_back(ParamWithName(true, &m_InvHole, prefix + "bubbleT3D_inv_hole")); + m_Params.push_back(ParamWithName(true, &m_C, prefix + "bubbleT3D_c")); + m_Params.push_back(ParamWithName(true, &m_S, prefix + "bubbleT3D_s")); + + } + +private: + T m_NumberStripes; + T m_RatioStripes; + T m_AngleHole; + T m_ExponentZ; + T m_SymmetryZ; + T m_ModusBlur; + T m_AbsNumberStripes;//Precalc. + T m_AngleHoleTemp; + T m_AngStrip; + T m_AngStrip1; + T m_AngStrip2; + T m_InvStripes; + T m_AngHoleComp; + T m_InvHole; + T m_C; + T m_S; +}; + +// ------------------------------------------------------------- +// Modes +// "Lagacy" modes from v1 +#define MODE_SPHERICAL 0 +#define MODE_BUBBLE 1 +#define MODE_BLUR_LEGACY 2 +// New modes in v2 +#define MODE_BLUR_NEW 3 +#define MODE_BLUR_ZIGZAG 4 +#define MODE_RAWCIRCLE 5 +#define MODE_RAWX 6 +#define MODE_RAWY 7 +#define MODE_RAWXY 8 +#define MODE_SHIFTX 9 +#define MODE_SHIFTY 10 +#define MODE_SHIFTXY 11 +#define MODE_SINUSOIDAL 12 +#define MODE_SWIRL 13 +#define MODE_HYPERBOLIC 14 +#define MODE_JULIA 15 +#define MODE_DISC 16 +#define MODE_RINGS 17 +#define MODE_CYLINDER 18 +#define MODE_BLUR_RING 19 +#define MODE_BLUR_RING2 20 +#define MODE_SHIFTTHETA 21 + +// ------------------------------------------------------------- +// Wave types +#define WAVE_SIN 0 +#define WAVE_COS 1 +#define WAVE_SQUARE 2 +#define WAVE_SAW 3 +#define WAVE_TRIANGLE 4 +#define WAVE_CONCAVE 5 +#define WAVE_CONVEX 6 +#define WAVE_NGON 7 +// New wave types in v2 +#define WAVE_INGON 8 + +// ------------------------------------------------------------- +// Layer types +#define LAYER_ADD 0 +#define LAYER_MULT 1 +#define LAYER_MAX 2 +#define LAYER_MIN 3 + +// ------------------------------------------------------------- +// Interpolation types +#define LERP_LINEAR 0 +#define LERP_BEZIER 1 + +// ------------------------------------------------------------- +// Sine/Cosine interpretation types +#define SINCOS_MULTIPLY 0 +#define SINCOS_MIXIN 1 + +/// +/// synth. +/// +template +class EMBER_API SynthVariation : public ParametricVariation +{ +public: + SynthVariation(T weight = 1.0) : ParametricVariation("synth", VAR_SYNTH, weight, true, true, false, true) + { + Init(); + } + + PARVARCOPY(SynthVariation) + + virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override + { + T Vx, Vy, radius, theta; // Position vector in cartesian and polar co-ords + T thetaFactor; // Evaluation of synth() function for current point + T s, c, mu; // Handy temp variables, s & c => sine & cosine, mu = generic temp param + int synthMode = int(m_SynthMode); + SynthStruct synth; + + synth.SynthA = m_SynthA; + synth.SynthB = m_SynthB; + synth.SynthBPhs = m_SynthBPhs; + synth.SynthBFrq = m_SynthBFrq; + synth.SynthBSkew = m_SynthBSkew; + synth.SynthBType = int(m_SynthBType); + synth.SynthBLayer = int(m_SynthBLayer); + synth.SynthC = m_SynthC; + synth.SynthCPhs = m_SynthCPhs; + synth.SynthCFrq = m_SynthCFrq; + synth.SynthCSkew = m_SynthCSkew; + synth.SynthCType = int(m_SynthCType); + synth.SynthCLayer = int(m_SynthCLayer); + synth.SynthD = m_SynthD; + synth.SynthDPhs = m_SynthDPhs; + synth.SynthDFrq = m_SynthDFrq; + synth.SynthDSkew = m_SynthDSkew; + synth.SynthDType = int(m_SynthDType); + synth.SynthDLayer = int(m_SynthDLayer); + synth.SynthE = m_SynthE; + synth.SynthEPhs = m_SynthEPhs; + synth.SynthEFrq = m_SynthEFrq; + synth.SynthESkew = m_SynthESkew; + synth.SynthEType = int(m_SynthEType); + synth.SynthELayer = int(m_SynthELayer); + synth.SynthF = m_SynthF; + synth.SynthFPhs = m_SynthFPhs; + synth.SynthFFrq = m_SynthFFrq; + synth.SynthFSkew = m_SynthFSkew; + synth.SynthFType = int(m_SynthFType); + synth.SynthFLayer = int(m_SynthFLayer); + synth.SynthMix = m_SynthMix; + + switch (synthMode) + { + case MODE_SPHERICAL: // Power YES, Smooth YES + // Re-write of spherical with synth tweak + Vx = helper.In.x; + Vy = helper.In.y; + radius = std::pow(Zeps(helper.m_PrecalcSumSquares), (m_SynthPower + 1) / 2); + + // Get angle and angular factor + theta = helper.m_PrecalcAtanxy; + thetaFactor = SynthValue(synth, theta); + radius = Interpolate(radius, thetaFactor, synthMode); + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + + case MODE_BUBBLE: // Power NO, Smooth YES + // Re-write of bubble with synth tweak + Vx = helper.In.x; + Vy = helper.In.y; + radius = helper.m_PrecalcSqrtSumSquares / (helper.m_PrecalcSumSquares / 4 + 1); + + // Get angle and angular factor + theta = helper.m_PrecalcAtanxy; + thetaFactor = SynthValue(synth, theta); + radius = Interpolate(radius, thetaFactor, synthMode); + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + + case MODE_BLUR_LEGACY: // Power YES, Smooth YES + // "old" blur style, has some problems with moire-style artefacts + radius = (rand.Frand01() + rand.Frand01() + T(0.002) * rand.Frand01()) / T(2.002); + theta = M_2PI * rand.Frand01() - T(M_PI); + Vx = radius * std::sin(theta); + Vy = radius * std::cos(theta); + radius = std::pow(Zeps(radius * radius), m_SynthPower / 2); + + // Get angle and angular factor + thetaFactor = SynthValue(synth, theta); + radius = m_Weight * Interpolate(radius, thetaFactor, synthMode); + + // Write back to running totals for new vector + helper.Out.x = Vx * radius; + helper.Out.y = Vy * radius; + break; + + case MODE_BLUR_NEW: // Power YES, Smooth YES + // Blur style, with normal smoothing function + // Choose radius randomly, then adjust distribution using pow + radius = T(0.5) * (rand.Frand01() + rand.Frand01()); + theta = M_2PI * rand.Frand01() - T(M_PI); + radius = std::pow(Zeps(SQR(radius)), -m_SynthPower / 2); + + // Get angular factor defining the shape + thetaFactor = SynthValue(synth, theta); + + // Get final radius after synth applied + radius = Interpolate(radius, thetaFactor, synthMode); + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + + case MODE_BLUR_ZIGZAG: // Power YES, Smooth YES + // Blur effect based on line segment + // theta is used as x value + // Vy is y value + Vy = 1 + T(0.1) * (rand.Frand01() + rand.Frand01() - 1) * m_SynthPower; + theta = 2 * std::asin((rand.Frand01() - T(0.5)) * 2); + + // Get angular factor defining the shape + thetaFactor = SynthValue(synth, theta); + + // Get new location + Vy = Interpolate(Vy, thetaFactor, synthMode); + + // Write to running totals for transform + helper.Out.x = m_Weight * (theta / T(M_PI)); + helper.Out.y = m_Weight * (Vy - 1); + break; + + case MODE_RAWCIRCLE: // Power NO, Smooth YES + // Get current radius and angle + radius = helper.m_PrecalcSqrtSumSquares; + theta = helper.m_PrecalcAtanxy; + + // Calculate new radius + thetaFactor = SynthValue(synth, theta); + radius = Interpolate(radius, thetaFactor, synthMode); + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + + case MODE_RAWX: // Power NO, Smooth YES + // Use x and y values directly + Vx = helper.In.x; + Vy = helper.In.y; + + // x value will be mapped according to synth(y) value + thetaFactor = SynthValue(synth, Vy); + + // Write to running totals for transform + helper.Out.x = m_Weight * Interpolate(Vx, thetaFactor, synthMode); + helper.Out.y = m_Weight * Vy; + break; + + case MODE_RAWY: // Power NO, Smooth YES + // Use x and y values directly + Vx = helper.In.x; + Vy = helper.In.y; + + // y value will be mapped according to synth(x) value + thetaFactor = SynthValue(synth, Vx); + + // Write to running totals for transform + helper.Out.x = m_Weight * Vx; + helper.Out.y = m_Weight * Interpolate(Vy, thetaFactor, synthMode); + break; + + case MODE_RAWXY: // Power NO, Smooth YES + // Use x and y values directly + Vx = helper.In.x; + Vy = helper.In.y; + + // x value will be mapped according to synth(y) value + thetaFactor = SynthValue(synth, Vy); + helper.Out.x = m_Weight * Interpolate(Vx, thetaFactor, synthMode); + + // y value will be mapped according to synth(x) value + thetaFactor = SynthValue(synth, Vx); + helper.Out.y = m_Weight * Interpolate(Vy, thetaFactor, synthMode); + break; + + case MODE_SHIFTX: // Power NO, Smooth YES + // Use x and y values directly + Vx = helper.In.x; + Vy = helper.In.y; + + // Write to running totals for transform + helper.Out.x = m_Weight * (Vx + SynthValue(synth, Vy) - 1); + helper.Out.y = m_Weight * Vy; + break; + + case MODE_SHIFTY: // Power NO, Smooth NO + // Use x and y values directly + Vx = helper.In.x; + Vy = helper.In.y; + + // Write to running totals for transform + helper.Out.x = m_Weight * Vx; + helper.Out.y = m_Weight * (Vy + SynthValue(synth, Vx) - 1); + break; + + case MODE_SHIFTXY: // Power NO, Smooth NO + // Use x and y values directly + Vx = helper.In.x; + Vy = helper.In.y; + + // Write to running totals for transform + helper.Out.x = m_Weight * (Vx + SynthValue(synth, Vy) - 1); + helper.Out.y = m_Weight * (Vy + SynthValue(synth, Vx) - 1); + break; + + case MODE_SINUSOIDAL: // Power NO, Smooth NO + Vx = helper.In.x; + Vy = helper.In.y; + + // The default mix=0 is same as normal sin + helper.Out.x = m_Weight * (SynthValue(synth, Vx) - 1 + (1 - m_SynthMix) * std::sin(Vx)); + helper.Out.y = m_Weight * (SynthValue(synth, Vy) - 1 + (1 - m_SynthMix) * std::sin(Vy)); + break; + + case MODE_SWIRL: // Power YES, Smooth WAVE + Vx = helper.In.x; + Vy = helper.In.y; + + radius = std::pow(Zeps(helper.m_PrecalcSumSquares), m_SynthPower / 2); + + // Synth-modified sine & cosine + SynthSinCos(synth, radius, s, c, synthMode); + + helper.Out.x = m_Weight * (s * Vx - c * Vy); + helper.Out.y = m_Weight * (c * Vx + s * Vy); + break; + + case MODE_HYPERBOLIC: // Power YES, Smooth WAVE + Vx = helper.In.x; + Vy = helper.In.y; + + radius = std::pow(Zeps(helper.m_PrecalcSumSquares), m_SynthPower / 2); + theta = helper.m_PrecalcAtanxy; + + // Synth-modified sine & cosine + SynthSinCos(synth, theta, s, c, synthMode); + + helper.Out.x = m_Weight * s / radius; + helper.Out.y = m_Weight * c * radius; + break; + + case MODE_JULIA: // Power YES, Smooth WAVE + Vx = helper.In.x; + Vy = helper.In.y; + + radius = std::pow(Zeps(helper.m_PrecalcSumSquares), m_SynthPower / 4); + theta = helper.m_PrecalcAtanxy / 2; + + if (rand.Frand01() < T(0.5)) + theta += T(M_PI); + + // Synth-modified sine & cosine + SynthSinCos(synth, theta, s, c, synthMode); + + helper.Out.x = m_Weight * radius * c; + helper.Out.y = m_Weight * radius * s; + break; + + case MODE_DISC: // Power YES, Smooth WAVE + Vx = helper.In.x; + Vy = helper.In.y; + + theta = helper.m_PrecalcAtanxy / T(M_PI); + radius = T(M_PI) * std::pow(Zeps(helper.m_PrecalcSumSquares), m_SynthPower / 2); + + // Synth-modified sine & cosine + SynthSinCos(synth, radius, s, c, synthMode); + + helper.Out.x = m_Weight * s * theta; + helper.Out.y = m_Weight * c * theta; + break; + + case MODE_RINGS: // Power PARAM, Smooth WAVE + Vx = helper.In.x; + Vy = helper.In.y; + radius = helper.m_PrecalcSqrtSumSquares; + theta = helper.m_PrecalcAtanxy; + mu = Zeps(SQR(m_SynthPower)); + radius += -2 * mu * (int)((radius + mu) / (2 * mu)) + radius * (1 - mu); + + SynthSinCos(synth, radius, s, c, synthMode); + + helper.Out.x = m_Weight * s * theta; + helper.Out.y = m_Weight * c * theta; + break; + + case MODE_CYLINDER: // Power YES, Smooth WAVE + Vx = helper.In.x; + Vy = helper.In.y; + radius = std::pow(Zeps(helper.m_PrecalcSumSquares), m_SynthPower / 2); + + // Modified sine only used here + SynthSinCos(synth, Vx, s, c, synthMode); + + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * Vy; + break; + + case MODE_BLUR_RING: // Power YES, Smooth YES + // Blur style, with normal smoothing function + + radius = 1 + T(0.1) * (rand.Frand01() + rand.Frand01() - 1) * m_SynthPower; + theta = M_2PI * rand.Frand01() - T(M_PI); + + // Get angular factor defining the shape + thetaFactor = SynthValue(synth, theta); + + // Get final radius after synth applied + radius = Interpolate(radius, thetaFactor, synthMode); + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + + case MODE_BLUR_RING2: // Power YES, Smooth NO + // Simple, same-thickness ring + + // Choose radius randomly, then adjust distribution using pow + theta = M_2PI * rand.Frand01() - T(M_PI); + radius = std::pow(Zeps(rand.Frand01()), m_SynthPower); + + // Get final radius after synth applied + radius = SynthValue(synth, theta) + T(0.1) * radius; + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + + case MODE_SHIFTTHETA: // Power YES, Smooth NO + // Use (adjusted) radius to move point around circle + Vx = helper.In.x; + Vy = helper.In.y; + + radius = std::pow(Zeps(helper.m_PrecalcSumSquares), m_SynthPower / 2); + theta = helper.m_PrecalcAtanxy - 1 + SynthValue(synth, radius); + sincos(theta, &s, &c); + + // Write to running totals for transform + helper.Out.x = m_Weight * radius * s; + helper.Out.y = m_Weight * radius * c; + break; + } + + helper.Out.z = (m_VarType == VARTYPE_REG) ? 0 : helper.In.z; + } + + virtual string OpenCLString() const override + { + ostringstream ss, ss2; + intmax_t i = 0, varIndex = IndexInXform(); + ss2 << "_" << XformIndexInEmber(); + string index = ss2.str() + "]"; + + string synthA = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthMode = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthPower = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthMix = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthSmooth = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthB = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthBType = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthBSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthBFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthBPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthBLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthC = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthCType = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthCSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthCFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthCPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthCLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthD = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthDType = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthDSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthDFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthDPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthDLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthE = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthEType = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthESkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthEFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthEPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthELayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthF = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthFType = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthFSkew = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthFFrq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthFPhs = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + string synthFLayer = "parVars[" + ToUpper(m_Params[i++].Name()) + index; + + ss << "\t{\n" + << "\t\treal_t Vx, Vy, radius, theta;\n" + << "\t\treal_t thetaFactor;\n" + << "\t\treal_t s, c, mu;\n" + << "\t\tint synthMode = (int)" << synthMode << "; \n" + << "\t\tSynthStruct synth;\n" + << "\n" + << "\t\tsynth.SynthA = " << synthA << ";\n" + << "\t\tsynth.SynthB = " << synthB << ";\n" + << "\t\tsynth.SynthBPhs = " << synthBPhs << ";\n" + << "\t\tsynth.SynthBFrq = " << synthBFrq << ";\n" + << "\t\tsynth.SynthBSkew = " << synthBSkew << ";\n" + << "\t\tsynth.SynthBType = (int)" << synthBType << ";\n" + << "\t\tsynth.SynthBLayer = (int)" << synthBLayer << ";\n" + << "\t\tsynth.SynthC = " << synthC << ";\n" + << "\t\tsynth.SynthCPhs = " << synthCPhs << ";\n" + << "\t\tsynth.SynthCFrq = " << synthCFrq << ";\n" + << "\t\tsynth.SynthCSkew = " << synthCSkew << ";\n" + << "\t\tsynth.SynthCType = (int)" << synthCType << ";\n" + << "\t\tsynth.SynthCLayer = (int)" << synthCLayer << ";\n" + << "\t\tsynth.SynthD = " << synthD << ";\n" + << "\t\tsynth.SynthDPhs = " << synthDPhs << ";\n" + << "\t\tsynth.SynthDFrq = " << synthDFrq << ";\n" + << "\t\tsynth.SynthDSkew = " << synthDSkew << ";\n" + << "\t\tsynth.SynthDType = (int)" << synthDType << ";\n" + << "\t\tsynth.SynthDLayer = (int)" << synthDLayer << ";\n" + << "\t\tsynth.SynthE = " << synthE << ";\n" + << "\t\tsynth.SynthEPhs = " << synthEPhs << ";\n" + << "\t\tsynth.SynthEFrq = " << synthEFrq << ";\n" + << "\t\tsynth.SynthESkew = " << synthESkew << ";\n" + << "\t\tsynth.SynthEType = (int)" << synthEType << ";\n" + << "\t\tsynth.SynthELayer = (int)" << synthELayer << ";\n" + << "\t\tsynth.SynthF = " << synthF << ";\n" + << "\t\tsynth.SynthFPhs = " << synthFPhs << ";\n" + << "\t\tsynth.SynthFFrq = " << synthFFrq << ";\n" + << "\t\tsynth.SynthFSkew = " << synthFSkew << ";\n" + << "\t\tsynth.SynthFType = (int)" << synthFType << ";\n" + << "\t\tsynth.SynthFLayer = (int)" << synthFLayer << ";\n" + << "\t\tsynth.SynthMix = " << synthMix << ";\n" + << "\n" + << "\t\tswitch (synthMode)\n" + << "\t\t{\n" + << "\t\tcase MODE_SPHERICAL:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = pow(Zeps(precalcSumSquares), (" << synthPower << " + 1) / 2);\n" + << "\t\t theta = precalcAtanxy;\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t radius = Interpolate(radius, thetaFactor, synthMode);\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_BUBBLE:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = precalcSqrtSumSquares / (precalcSumSquares / 4 + 1);\n" + << "\t\t theta = precalcAtanxy;\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t radius = Interpolate(radius, thetaFactor, synthMode);\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_BLUR_LEGACY:\n" + << "\t\t radius = (MwcNext01(mwc) + MwcNext01(mwc) + 0.002 * MwcNext01(mwc)) / 2.002;\n" + << "\t\t theta = M_2PI * MwcNext01(mwc) - M_PI;\n" + << "\t\t Vx = radius * sin(theta);\n" + << "\t\t Vy = radius * cos(theta);\n" + << "\t\t radius = pow(Zeps(radius * radius), " << synthPower << " / 2);\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t radius = xform->m_VariationWeights[" << varIndex << "] * Interpolate(radius, thetaFactor, synthMode);\n" + << "\t\t vOut.x = Vx * radius;\n" + << "\t\t vOut.y = Vy * radius;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_BLUR_NEW:\n" + << "\t\t radius = 0.5 * (MwcNext01(mwc) + MwcNext01(mwc));\n" + << "\t\t theta = M_2PI * MwcNext01(mwc) - M_PI;\n" + << "\t\t radius = pow(Zeps(SQR(radius)), -" << synthPower << " / 2);\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t radius = Interpolate(radius, thetaFactor, synthMode);\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_BLUR_ZIGZAG:\n" + << "\t\t Vy = 1 + 0.1 * (MwcNext01(mwc) + MwcNext01(mwc) - 1) * " << synthPower << ";\n" + << "\t\t theta = 2 * asin((MwcNext01(mwc) - 0.5) * 2);\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t Vy = Interpolate(Vy, thetaFactor, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (theta / M_PI);\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (Vy - 1);\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_RAWCIRCLE:\n" + << "\t\t radius = precalcSqrtSumSquares;\n" + << "\t\t theta = precalcAtanxy;\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t radius = Interpolate(radius, thetaFactor, synthMode);\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_RAWX:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t thetaFactor = SynthValue(&synth, Vy);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * Interpolate(Vx, thetaFactor, synthMode);\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * Vy;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_RAWY:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t thetaFactor = SynthValue(&synth, Vx);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * Vx;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * Interpolate(Vy, thetaFactor, synthMode);\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_RAWXY:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t thetaFactor = SynthValue(&synth, Vy);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * Interpolate(Vx, thetaFactor, synthMode);\n" + << "\t\t thetaFactor = SynthValue(&synth, Vx);\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * Interpolate(Vy, thetaFactor, synthMode);\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_SHIFTX:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (Vx + SynthValue(&synth, Vy) - 1);\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * Vy;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_SHIFTY:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * Vx;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (Vy + SynthValue(&synth, Vx) - 1);\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_SHIFTXY:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (Vx + SynthValue(&synth, Vy) - 1);\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (Vy + SynthValue(&synth, Vx) - 1);\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_SINUSOIDAL:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (SynthValue(&synth, Vx) - 1 + (1 - " << synthMix << ") * sin(Vx));\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (SynthValue(&synth, Vy) - 1 + (1 - " << synthMix << ") * sin(Vy));\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_SWIRL:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n" + << "\t\t SynthSinCos(&synth, radius, &s, &c, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * (s * Vx - c * Vy);\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * (c * Vx + s * Vy);\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_HYPERBOLIC:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n" + << "\t\t theta = precalcAtanxy;\n" + << "\t\t SynthSinCos(&synth, theta, &s, &c, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * s / radius;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * c * radius;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_JULIA:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 4);\n" + << "\t\t theta = precalcAtanxy / 2;\n" + << "\n" + << "\t\t if (MwcNext01(mwc) < 0.5)\n" + << "\t\t theta += M_PI;\n" + << "\n" + << "\t\t SynthSinCos(&synth, theta, &s, &c, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_DISC:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t theta = precalcAtanxy / M_PI;\n" + << "\t\t radius = M_PI * pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n" + << "\t\t SynthSinCos(&synth, radius, &s, &c, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * s * theta;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * c * theta;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_RINGS:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = precalcSqrtSumSquares;\n" + << "\t\t theta = precalcAtanxy;\n" + << "\t\t mu = Zeps(SQR(" << synthPower << "));\n" + << "\t\t radius += -2 * mu * (int)((radius + mu) / (2 * mu)) + radius * (1 - mu);\n" + << "\t\t SynthSinCos(&synth, radius, &s, &c, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * s * theta;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * c * theta;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_CYLINDER:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n" + << "\t\t SynthSinCos(&synth, Vx, &s, &c, synthMode);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * Vy;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_BLUR_RING:\n" + << "\t\t radius = 1 + 0.1 * (MwcNext01(mwc) + MwcNext01(mwc) - 1) * " << synthPower << ";\n" + << "\t\t theta = M_2PI * MwcNext01(mwc) - M_PI;\n" + << "\t\t thetaFactor = SynthValue(&synth, theta);\n" + << "\t\t radius = Interpolate(radius, thetaFactor, synthMode);\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_BLUR_RING2:\n" + << "\t\t theta = M_2PI * MwcNext01(mwc) - M_PI;\n" + << "\t\t radius = pow(Zeps(MwcNext01(mwc)), " << synthPower << ");\n" + << "\t\t radius = SynthValue(&synth, theta) + 0.1 * radius;\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\n" + << "\t\tcase MODE_SHIFTTHETA:\n" + << "\t\t Vx = vIn.x;\n" + << "\t\t Vy = vIn.y;\n" + << "\t\t radius = pow(Zeps(precalcSumSquares), " << synthPower << " / 2);\n" + << "\t\t theta = precalcAtanxy - 1 + SynthValue(&synth, radius);\n" + << "\t\t s = sincos(theta, &c);\n" + << "\t\t vOut.x = xform->m_VariationWeights[" << varIndex << "] * radius * s;\n" + << "\t\t vOut.y = xform->m_VariationWeights[" << varIndex << "] * radius * c;\n" + << "\t\t break;\n" + << "\t\t}\n" + << "\n" + << "\t\tvOut.z = " << ((m_VarType == VARTYPE_REG) ? "0" : "vIn.z") << ";\n" + << "\t}\n"; + + return ss.str(); + } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Zeps" }; + } + + virtual string OpenCLFuncsString() const override + { + return + "#define MODE_SPHERICAL 0\n" + "#define MODE_BUBBLE 1\n" + "#define MODE_BLUR_LEGACY 2\n" + "#define MODE_BLUR_NEW 3\n" + "#define MODE_BLUR_ZIGZAG 4\n" + "#define MODE_RAWCIRCLE 5\n" + "#define MODE_RAWX 6\n" + "#define MODE_RAWY 7\n" + "#define MODE_RAWXY 8\n" + "#define MODE_SHIFTX 9\n" + "#define MODE_SHIFTY 10\n" + "#define MODE_SHIFTXY 11\n" + "#define MODE_SINUSOIDAL 12\n" + "#define MODE_SWIRL 13\n" + "#define MODE_HYPERBOLIC 14\n" + "#define MODE_JULIA 15\n" + "#define MODE_DISC 16\n" + "#define MODE_RINGS 17\n" + "#define MODE_CYLINDER 18\n" + "#define MODE_BLUR_RING 19\n" + "#define MODE_BLUR_RING2 20\n" + "#define MODE_SHIFTTHETA 21\n" + "#define WAVE_SIN 0\n" + "#define WAVE_COS 1\n" + "#define WAVE_SQUARE 2\n" + "#define WAVE_SAW 3\n" + "#define WAVE_TRIANGLE 4\n" + "#define WAVE_CONCAVE 5\n" + "#define WAVE_CONVEX 6\n" + "#define WAVE_NGON 7\n" + "#define WAVE_INGON 8\n" + "#define LAYER_ADD 0\n" + "#define LAYER_MULT 1\n" + "#define LAYER_MAX 2\n" + "#define LAYER_MIN 3\n" + "#define LERP_LINEAR 0\n" + "#define LERP_BEZIER 1\n" + "#define SINCOS_MULTIPLY 0\n" + "#define SINCOS_MIXIN 1\n" + "\n" + "typedef struct __attribute__ " ALIGN_CL " _SynthStruct\n" + "{\n" + " real_t SynthA;\n" + " real_t SynthB;\n" + " real_t SynthBPhs;\n" + " real_t SynthBFrq;\n" + " real_t SynthBSkew;\n" + " int SynthBType;\n" + " int SynthBLayer;\n" + " real_t SynthC;\n" + " real_t SynthCPhs;\n" + " real_t SynthCFrq;\n" + " real_t SynthCSkew;\n" + " int SynthCType;\n" + " int SynthCLayer;\n" + " real_t SynthD;\n" + " real_t SynthDPhs;\n" + " real_t SynthDFrq;\n" + " real_t SynthDSkew;\n" + " int SynthDType;\n" + " int SynthDLayer;\n" + " real_t SynthE;\n" + " real_t SynthEPhs;\n" + " real_t SynthEFrq;\n" + " real_t SynthESkew;\n" + " int SynthEType;\n" + " int SynthELayer;\n" + " real_t SynthF;\n" + " real_t SynthFPhs;\n" + " real_t SynthFFrq;\n" + " real_t SynthFSkew;\n" + " int SynthFType;\n" + " int SynthFLayer;\n" + " real_t SynthMix;\n" + "} SynthStruct;\n" + "\n" + "static void SynthValueProc(real_t* synthA, real_t* thetaFactor, real_t theta, real_t* synth, real_t* phs, real_t* frq, real_t* skew, real_t* x, real_t* y, real_t* z, int* type, int* layer)\n" + "{\n" + " if (*synth != 0)\n" + " {\n" + " *z = *phs + theta * *frq;\n" + " *y = *z / M_2PI;\n" + " *y -= floor(*y);\n" + "\n" + " if (*skew != 0)\n" + " {\n" + " *z = 0.5 + 0.5 * *skew;\n" + "\n" + " if (*y > *z)\n" + " *y = 0.5 + 0.5 * (*y - *z) / Zeps(1 - *z);\n" + " else\n" + " *y = 0.5 - 0.5 * (*z - *y) / Zeps(*z);\n" + " }\n" + "\n" + " switch (*type)\n" + " {\n" + " case WAVE_SIN:\n" + " *x = sin(*y * M_2PI);\n" + " break;\n" + " case WAVE_COS:\n" + " *x = cos(*y * M_2PI);\n" + " break;\n" + " case WAVE_SQUARE:\n" + " *x = *y > 0.5 ? 1.0 : -1.0;\n" + " break;\n" + " case WAVE_SAW:\n" + " *x = 1 - 2 * *y;\n" + " break;\n" + " case WAVE_TRIANGLE:\n" + " *x = *y > 0.5 ? 3 - 4 * *y : 2 * *y - 1;\n" + " break;\n" + " case WAVE_CONCAVE:\n" + " *x = 8 * (*y - 0.5) * (*y - 0.5) - 1;\n" + " break;\n" + " case WAVE_CONVEX:\n" + " *x = 2 * sqrt(*y) - 1;\n" + " break;\n" + " case WAVE_NGON:\n" + " *y -= 0.5;\n" + " *y *= M_2PI / *frq;\n" + " *x = 1 / Zeps(cos(*y)) - 1;\n" + " break;\n" + " case WAVE_INGON:\n" + " *y -= 0.5;\n" + " *y *= M_2PI / *frq;\n" + " *z = cos(*y);\n" + " *x = *z / Zeps(1 - *z);\n" + " break;\n" + " }\n" + "\n" + " switch (*layer)\n" + " {\n" + " case LAYER_ADD:\n" + " *thetaFactor += *synth * *x;\n" + " break;\n" + " case LAYER_MULT:\n" + " *thetaFactor *= (1 + *synth * *x);\n" + " break;\n" + " case LAYER_MAX:\n" + " *z = *synthA + *synth * *x;\n" + " *thetaFactor = (*thetaFactor > *z ? *thetaFactor : *z);\n" + " break;\n" + " case LAYER_MIN:\n" + " *z = *synthA + *synth * *x;\n" + " *thetaFactor = (*thetaFactor < *z ? *thetaFactor : *z);\n" + " break;\n" + " }\n" + " }\n" + "}\n" + "\n" + "static real_t SynthValue(SynthStruct* s, real_t theta)\n" + "{\n" + " real_t x, y, z;\n" + " real_t thetaFactor = s->SynthA;\n" + "\n" + " SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthB), &(s->SynthBPhs), &(s->SynthBFrq), &(s->SynthBSkew), &x, &y, &z, &(s->SynthBType), &(s->SynthBLayer));\n" + " SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthC), &(s->SynthCPhs), &(s->SynthCFrq), &(s->SynthCSkew), &x, &y, &z, &(s->SynthCType), &(s->SynthCLayer));\n" + " SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthD), &(s->SynthDPhs), &(s->SynthDFrq), &(s->SynthDSkew), &x, &y, &z, &(s->SynthDType), &(s->SynthDLayer));\n" + " SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthE), &(s->SynthEPhs), &(s->SynthEFrq), &(s->SynthESkew), &x, &y, &z, &(s->SynthEType), &(s->SynthELayer));\n" + " SynthValueProc(&(s->SynthA), &thetaFactor, theta, &(s->SynthF), &(s->SynthFPhs), &(s->SynthFFrq), &(s->SynthFSkew), &x, &y, &z, &(s->SynthFType), &(s->SynthFLayer));\n" + "\n" + " return thetaFactor * s->SynthMix + (1 - s->SynthMix);\n" + "}\n" + "\n" + "static real_t BezierQuadMap(real_t x, real_t m)\n" + "{\n" + " real_t a = 1;\n" + " real_t t = 0;\n" + "\n" + " if (m < 0) { m = -m; a = -1; }\n" + " if (x < 0) { x = -x; a = -a; }\n" + "\n" + " real_t iM = 1e10;\n" + "\n" + " if (m > 1.0e-10)\n" + " iM = 1 / m;\n" + "\n" + " real_t L = iM < m * 2 ? m * 2 : iM;\n" + "\n" + " if ((x > L) || (m == 1))\n" + " return a * x;\n" + "\n" + " if ((m < 1) && (x <= 1))\n" + " {\n" + " t = x;\n" + "\n" + " if (fabs(m - 0.5) > 1e-10)\n" + " t = (-1 * m + sqrt(m * m + (1 - 2 * m) * x)) / (1 - 2 * m);\n" + "\n" + " return a * (x + (m - 1) * t * t);\n" + " }\n" + "\n" + " if ((1 < m) && (x <= 1))\n" + " {\n" + " t = x;\n" + "\n" + " if (fabs(m - 2) > 1e-10)\n" + " t = (-1 * iM + sqrt(iM * iM + (1 - 2 * iM) * x)) / (1 - 2 * iM);\n" + "\n" + " return a * (x + (m - 1) * t * t);\n" + " }\n" + "\n" + " if (m < 1)\n" + " {\n" + " t = sqrt((x - 1) / (L - 1));\n" + " return a * (x + (m - 1) * t * t + 2 * (1 - m) * t + (m - 1));\n" + " }\n" + "\n" + " t = (1 - m) + sqrt((m - 1) * (m - 1) + (x - 1));\n" + " return a * (x + (m - 1) * t * t - 2 * (m - 1) * t + (m - 1));\n" + "}\n" + "\n" + "static real_t Interpolate(real_t x, real_t m, int lerpType)\n" + "{\n" + " switch (lerpType)\n" + " {\n" + " case LERP_LINEAR:\n" + " return x * m;\n" + " case LERP_BEZIER:\n" + " return BezierQuadMap(x, m);\n" + " }\n" + "\n" + " return x * m;\n" + "}\n" + "\n" + "static void SynthSinCos(SynthStruct* synth, real_t theta, real_t* s, real_t* c, int sineType)\n" + "{\n" + " *s = sincos(theta, c);\n" + "\n" + " switch (sineType)\n" + " {\n" + " case SINCOS_MULTIPLY:\n" + " *s = *s * SynthValue(synth, theta);\n" + " *c = *c * SynthValue(synth, theta + M_PI / 2);\n" + " break;\n" + " case SINCOS_MIXIN:\n" + " *s = (1 - synth->SynthMix) * *s + (SynthValue(synth, theta) - 1);\n" + " *c = (1 - synth->SynthMix) * *c + (SynthValue(synth, theta + M_PI / 2) - 1);\n" + " break;\n" + " }\n" + "\n" + " return;\n" + "}\n\n" + ; + } + +protected: + void Init() + { + string prefix = Prefix(); + + m_Params.clear(); + m_Params.reserve(34); + m_Params.push_back(ParamWithName(&m_SynthA, prefix + "synth_a")); + m_Params.push_back(ParamWithName(&m_SynthMode, prefix + "synth_mode", 3, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthPower, prefix + "synth_power", -2)); + m_Params.push_back(ParamWithName(&m_SynthMix, prefix + "synth_mix")); + m_Params.push_back(ParamWithName(&m_SynthSmooth, prefix + "synth_smooth", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthB, prefix + "synth_b")); + m_Params.push_back(ParamWithName(&m_SynthBType, prefix + "synth_b_type", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthBSkew, prefix + "synth_b_skew")); + m_Params.push_back(ParamWithName(&m_SynthBFrq, prefix + "synth_b_frq", 1, REAL)); + m_Params.push_back(ParamWithName(&m_SynthBPhs, prefix + "synth_b_phs")); + m_Params.push_back(ParamWithName(&m_SynthBLayer, prefix + "synth_b_layer", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthC, prefix + "synth_c")); + m_Params.push_back(ParamWithName(&m_SynthCType, prefix + "synth_c_type", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthCSkew, prefix + "synth_c_skew")); + m_Params.push_back(ParamWithName(&m_SynthCFrq, prefix + "synth_c_frq", 1, REAL)); + m_Params.push_back(ParamWithName(&m_SynthCPhs, prefix + "synth_c_phs")); + m_Params.push_back(ParamWithName(&m_SynthCLayer, prefix + "synth_c_layer", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthD, prefix + "synth_d")); + m_Params.push_back(ParamWithName(&m_SynthDType, prefix + "synth_d_type", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthDSkew, prefix + "synth_d_skew")); + m_Params.push_back(ParamWithName(&m_SynthDFrq, prefix + "synth_d_frq", 1, REAL)); + m_Params.push_back(ParamWithName(&m_SynthDPhs, prefix + "synth_d_phs")); + m_Params.push_back(ParamWithName(&m_SynthDLayer, prefix + "synth_d_layer", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthE, prefix + "synth_e")); + m_Params.push_back(ParamWithName(&m_SynthEType, prefix + "synth_e_type", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthESkew, prefix + "synth_e_skew")); + m_Params.push_back(ParamWithName(&m_SynthEFrq, prefix + "synth_e_frq", 1, REAL)); + m_Params.push_back(ParamWithName(&m_SynthEPhs, prefix + "synth_e_phs")); + m_Params.push_back(ParamWithName(&m_SynthELayer, prefix + "synth_e_layer", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthF, prefix + "synth_f")); + m_Params.push_back(ParamWithName(&m_SynthFType, prefix + "synth_f_type", 0, INTEGER)); + m_Params.push_back(ParamWithName(&m_SynthFSkew, prefix + "synth_f_skew")); + m_Params.push_back(ParamWithName(&m_SynthFFrq, prefix + "synth_f_frq", 1, REAL)); + m_Params.push_back(ParamWithName(&m_SynthFPhs, prefix + "synth_f_phs")); + m_Params.push_back(ParamWithName(&m_SynthFLayer, prefix + "synth_f_layer", 0, INTEGER)); + } + +private: + struct SynthStruct + { + T SynthA; + T SynthB; + T SynthBPhs; + T SynthBFrq; + T SynthBSkew; + int SynthBType; + int SynthBLayer; + T SynthC; + T SynthCPhs; + T SynthCFrq; + T SynthCSkew; + int SynthCType; + int SynthCLayer; + T SynthD; + T SynthDPhs; + T SynthDFrq; + T SynthDSkew; + int SynthDType; + int SynthDLayer; + T SynthE; + T SynthEPhs; + T SynthEFrq; + T SynthESkew; + int SynthEType; + int SynthELayer; + T SynthF; + T SynthFPhs; + T SynthFFrq; + T SynthFSkew; + int SynthFType; + int SynthFLayer; + T SynthMix; + }; + + inline void SynthValueProc(T& synthA, T& thetaFactor, T theta, T& synth, T& phs, T& frq, T& skew, T& x, T& y, T& z, int& type, int& layer) + { + if (synth != 0) + { + z = phs + theta * frq; + y = z / M_2PI; + y -= Floor(y); + + // y is in range 0 - 1. Now skew according to synth_f_skew + if (skew != 0) + { + z = T(0.5) + T(0.5) * skew; + + if (y > z) + y = T(0.5) + T(0.5) * (y - z) / Zeps(1 - z);// y is T(0.5) if equals z, up to 1.0 + else + y = T(0.5) - T(0.5) * (z - y) / Zeps(z);// y is T(0.5) if equals z, down to 0.0 + } + + switch (type) + { + case WAVE_SIN: + x = std::sin(y * M_2PI); + break; + case WAVE_COS: + x = std::cos(y * M_2PI); + break; + case WAVE_SQUARE: + x = y > T(0.5) ? T(1) : T(-1); + break; + case WAVE_SAW: + x = 1 - 2 * y; + break; + case WAVE_TRIANGLE: + x = y > T(0.5) ? 3 - 4 * y : 2 * y - 1; + break; + case WAVE_CONCAVE: + x = 8 * (y - T(0.5)) * (y - T(0.5)) - 1; + break; + case WAVE_CONVEX: + x = 2 * std::sqrt(y) - 1; + break; + case WAVE_NGON: + y -= T(0.5); + y *= M_2PI / frq; + x = 1 / Zeps(std::cos(y)) - 1; + break; + case WAVE_INGON: + y -= T(0.5); + y *= M_2PI / frq; + z = std::cos(y); + x = z / Zeps(1 - z); + break; + } + + switch (layer) + { + case LAYER_ADD: + thetaFactor += synth * x; + break; + case LAYER_MULT: + thetaFactor *= (1 + synth * x); + break; + case LAYER_MAX: + z = synthA + synth * x; + thetaFactor = (thetaFactor > z ? thetaFactor : z); + break; + case LAYER_MIN: + z = synthA + synth * x; + thetaFactor = (thetaFactor < z ? thetaFactor : z); + break; + } + } + } + + inline T SynthValue(SynthStruct& s, T theta) + { + T x, y, z; + T thetaFactor = s.SynthA; + + SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthB, s.SynthBPhs, s.SynthBFrq, s.SynthBSkew, x, y, z, s.SynthBType, s.SynthBLayer); + SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthC, s.SynthCPhs, s.SynthCFrq, s.SynthCSkew, x, y, z, s.SynthCType, s.SynthCLayer); + SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthD, s.SynthDPhs, s.SynthDFrq, s.SynthDSkew, x, y, z, s.SynthDType, s.SynthDLayer); + SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthE, s.SynthEPhs, s.SynthEFrq, s.SynthESkew, x, y, z, s.SynthEType, s.SynthELayer); + SynthValueProc(s.SynthA, thetaFactor, theta, s.SynthF, s.SynthFPhs, s.SynthFFrq, s.SynthFSkew, x, y, z, s.SynthFType, s.SynthFLayer); + + // Mix is applied here, assuming 1.0 to be the "flat" line for legacy support + return thetaFactor * s.SynthMix + (1 - s.SynthMix); + } + + inline T BezierQuadMap(T x, T m) + { + T a = 1; // a is used to control sign of result + T t = 0; // t is the Bezier curve parameter + + // Simply reflect in the y axis for negative values + if (m < 0) { m = -m; a = -1; } + if (x < 0) { x = -x; a = -a; } + + // iM is "inverse m" used in a few places below + T iM = T(1e10); + + if (m > 1.0e-10) + iM = 1 / m; + + // L is the upper bound on our curves, where we have rejoined the y = x line + T L = iM < m * 2 ? m * 2 : iM; + + // "Non Curved" + // Covers x >= L, or always true if m == 1.0 + // y = x i.e. not distorted + if ((x > L) || (m == 1)) + return a * x; + + if ((m < 1) && (x <= 1)) + { + // Bezier Curve #1 + // Covers 0 <= $m <= 1.0, 0 <= $x <= 1.0 + // Control points are (0,0), (m,m) and (1,m) + + t = x; // Special case when m == 0.5 + + if (std::fabs(m - T(0.5)) > 1e-10) + t = (-1 * m + sqrt(m * m + (1 - 2 * m) * x)) / (1 - 2 * m); + + return a * (x + (m - 1) * t * t); + } + + if ((1 < m) && (x <= 1)) + { + // Bezier Curve #2 + // Covers m >= 1.0, 0 <= x <= 1.0 + // Control points are (0,0), (iM,iM) and (1,m) + + t = x; // Special case when m == 2 + + if (std::fabs(m - 2) > 1e-10) + t = (-1 * iM + sqrt(iM * iM + (1 - 2 * iM) * x)) / (1 - 2 * iM); + + return a * (x + (m - 1) * t * t); + } + + if (m < 1) + { + // Bezier Curve #3 + // Covers 0 <= m <= 1.0, 1 <= x <= L + // Control points are (1,m), (1,1) and (L,L) + // (L is x value (>1) where we re-join y = x line, and is maximum( iM, 2 * m ) + + t = std::sqrt((x - 1) / (L - 1)); + return a * (x + (m - 1) * t * t + 2 * (1 - m) * t + (m - 1)); + } + + // Curve #4 + // Covers 1.0 <= m, 1 <= x <= L + // Control points are (1,m), (m,m) and (L,L) + // (L is x value (>1) where we re-join y = x line, and is maximum( iM, 2 * m ) + + t = (1 - m) + std::sqrt((m - 1) * (m - 1) + (x - 1)); + return a * (x + (m - 1) * t * t - 2 * (m - 1) * t + (m - 1)); + } + + inline T Interpolate(T x, T m, int lerpType) + { + switch (lerpType) + { + case LERP_LINEAR: + return x * m; + case LERP_BEZIER: + return BezierQuadMap(x, m); + } + + return x * m; + } + + inline void SynthSinCos(SynthStruct& synth, T theta, T& s, T& c, int sineType) + { + sincos(theta, &s, &c); + + switch (sineType) + { + case SINCOS_MULTIPLY: + s = s * SynthValue(synth, theta); + c = c * SynthValue(synth, theta + T(M_PI) / 2); + break; + case SINCOS_MIXIN: + s = (1 - m_SynthMix) * s + (SynthValue(synth, theta) - 1); + c = (1 - m_SynthMix) * c + (SynthValue(synth, theta + T(M_PI) / 2) - 1); + break; + } + + return; + } + + T m_SynthA; + T m_SynthMode; + T m_SynthPower; + T m_SynthMix; + T m_SynthSmooth; + T m_SynthB; + T m_SynthBType; + T m_SynthBSkew; + T m_SynthBFrq; + T m_SynthBPhs; + T m_SynthBLayer; + T m_SynthC; + T m_SynthCType; + T m_SynthCSkew; + T m_SynthCFrq; + T m_SynthCPhs; + T m_SynthCLayer; + T m_SynthD; + T m_SynthDType; + T m_SynthDSkew; + T m_SynthDFrq; + T m_SynthDPhs; + T m_SynthDLayer; + T m_SynthE; + T m_SynthEType; + T m_SynthESkew; + T m_SynthEFrq; + T m_SynthEPhs; + T m_SynthELayer; + T m_SynthF; + T m_SynthFType; + T m_SynthFSkew; + T m_SynthFFrq; + T m_SynthFPhs; + T m_SynthFLayer; +}; + +MAKEPREPOSTPARVAR(Hexes, hexes, HEXES) +MAKEPREPOSTPARVAR(Nblur, nBlur, NBLUR) +MAKEPREPOSTPARVAR(Octapol, octapol, OCTAPOL) +MAKEPREPOSTPARVAR(Crob, crob, CROB) +MAKEPREPOSTPARVAR(BubbleT3D, bubbleT3D, BUBBLET3D) +MAKEPREPOSTPARVAR(Synth, synth, SYNTH) +} \ No newline at end of file diff --git a/Source/Ember/VariationsDC.h b/Source/Ember/VariationsDC.h index a7464e4..1735da4 100644 --- a/Source/Ember/VariationsDC.h +++ b/Source/Ember/VariationsDC.h @@ -6,8 +6,7 @@ namespace EmberNs { /// /// DC Bubble. -/// This accesses the summed output point in a rare and different way -/// and therefore cannot be made into pre and post variations. +/// This accesses the summed output point in a rare and different way. /// template class EMBER_API DCBubbleVariation : public ParametricVariation @@ -30,8 +29,21 @@ public: helper.Out.y = r4_1 * helper.In.y; helper.Out.z = m_Weight * (2 / r4_1 - 1); - T tempX = helper.Out.x + outPoint.m_X; - T tempY = helper.Out.y + outPoint.m_Y; + T sumX, sumY; + + if (m_VarType == VARTYPE_PRE) + { + sumX = helper.In.x; + sumY = helper.In.y; + } + else + { + sumX = outPoint.m_X; + sumY = outPoint.m_Y; + } + + T tempX = helper.Out.x + sumX; + T tempY = helper.Out.y + sumY; outPoint.m_ColorX = fmod(fabs(m_Bdcs * (Sqr(tempX + m_CenterX) + Sqr(tempY + m_CenterY))), T(1.0)); } @@ -56,8 +68,24 @@ public: << "\t\tvOut.y = r4_1 * vIn.y;\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * (2 / r4_1 - 1);\n" << "\n" - << "\t\treal_t tempX = vOut.x + outPoint->m_X;\n" - << "\t\treal_t tempY = vOut.y + outPoint->m_Y;\n" + << "\t\treal_t sumX, sumY;\n\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\tsumX = vIn.x;\n" + << "\t\tsumY = vIn.y;\n"; + } + else + { + ss + << "\t\tsumX = outPoint->m_X;\n" + << "\t\tsumY = outPoint->m_Y;\n"; + } + + ss + << "\t\treal_t tempX = vOut.x + sumX;\n" + << "\t\treal_t tempY = vOut.y + sumY;\n" << "\n" << "\t\toutPoint->m_ColorX = fmod(fabs(" << bdcs << " * (Sqr(tempX + " << centerX << ") + Sqr(tempY + " << centerY << "))), (real_t)(1.0));\n" << "\t}\n"; @@ -65,6 +93,11 @@ public: return ss.str(); } + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "Sqr", "Zeps" }; + } + virtual void Precalc() override { m_Bdcs = 1 / (m_Scale == 0 ? T(10E-6) : m_Scale); @@ -255,7 +288,7 @@ public: << "\t\treal_t x, y, z;\n" << "\t\treal_t p = 2 * MwcNext01(mwc) - 1;\n" << "\t\treal_t q = 2 * MwcNext01(mwc) - 1;\n" - << "\t\tuint i = MwcNext(mwc) % 3;\n" + << "\t\tuint i = MwcNextRange(mwc, 3);\n" << "\t\tuint j = MwcNext(mwc) & 1;\n" << "\n" << "\t\tswitch (i)\n" @@ -356,8 +389,7 @@ private: /// /// DC Cylinder. -/// This accesses the summed output point in a rare and different way -/// and therefore cannot be made into pre and post variations. +/// This accesses the summed output point in a rare and different way. /// template class EMBER_API DCCylinderVariation : public ParametricVariation @@ -373,16 +405,29 @@ public: virtual void Func(IteratorHelper& helper, Point& outPoint, QTIsaac& rand) override { T temp = rand.Frand01() * M_2PI; - T sr = sin(temp); - T cr = cos(temp); + T sr = std::sin(temp); + T cr = std::cos(temp); T r = m_Blur * (rand.Frand01() + rand.Frand01() + rand.Frand01() + rand.Frand01() - 2); - helper.Out.x = m_Weight * sin(helper.In.x + r * sr) * m_X; + helper.Out.x = m_Weight * std::sin(helper.In.x + r * sr) * m_X; helper.Out.y = r + helper.In.y * m_Y; - helper.Out.z = m_Weight * cos(helper.In.x + r * cr); + helper.Out.z = m_Weight * std::cos(helper.In.x + r * cr); - T tempX = helper.Out.x + outPoint.m_X; - T tempY = helper.Out.y + outPoint.m_Y; + T sumX, sumY; + + if (m_VarType == VARTYPE_PRE) + { + sumX = helper.In.x; + sumY = helper.In.y; + } + else + { + sumX = outPoint.m_X; + sumY = outPoint.m_Y; + } + + T tempX = helper.Out.x + sumX; + T tempY = helper.Out.y + sumY; outPoint.m_ColorX = fmod(fabs(T(0.5) * (m_Ldcs * ((m_Cosa * tempX + m_Sina * tempY + m_Offset)) + 1)), T(1.0)); } @@ -413,8 +458,24 @@ public: << "\t\tvOut.y = r + vIn.y * " << y << ";\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * cos(vIn.x + r * cr);\n" << "\n" - << "\t\treal_t tempX = vOut.x + outPoint->m_X;\n" - << "\t\treal_t tempY = vOut.y + outPoint->m_Y;\n" + << "\t\treal_t sumX, sumY;\n\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\tsumX = vIn.x;\n" + << "\t\tsumY = vIn.y;\n"; + } + else + { + ss + << "\t\tsumX = outPoint->m_X;\n" + << "\t\tsumY = outPoint->m_Y;\n"; + } + + ss + << "\t\treal_t tempX = vOut.x + sumX;\n" + << "\t\treal_t tempY = vOut.y + sumY;\n" << "\n" << "\t\toutPoint->m_ColorX = fmod(fabs((real_t)(0.5) * (" << ldcs << " * ((" << cosa << " * tempX + " << sina << " * tempY + " << offset << ")) + (real_t)(1.0))), (real_t)(1.0));\n" << "\t}\n"; @@ -631,12 +692,16 @@ public: return ss.str(); } + + virtual vector OpenCLGlobalFuncNames() const override + { + return vector { "LRint" }; + } }; /// /// DC Linear. -/// This accesses the summed output point in a rare and different way -/// and therefore cannot be made into pre and post variations. +/// This accesses the summed output point in a rare and different way. /// template class EMBER_API DCLinearVariation : public ParametricVariation @@ -655,8 +720,21 @@ public: helper.Out.y = m_Weight * helper.In.y; helper.Out.z = m_Weight * helper.In.z; - T tempX = helper.Out.x + outPoint.m_X; - T tempY = helper.Out.y + outPoint.m_Y; + T sumX, sumY; + + if (m_VarType == VARTYPE_PRE) + { + sumX = helper.In.x; + sumY = helper.In.y; + } + else + { + sumX = outPoint.m_X; + sumY = outPoint.m_Y; + } + + T tempX = helper.Out.x + sumX; + T tempY = helper.Out.y + sumY; outPoint.m_ColorX = fmod(fabs(T(0.5) * (m_Ldcs * ((m_Cosa * tempX + m_Sina * tempY + m_Offset)) + T(1.0))), T(1.0)); } @@ -680,8 +758,24 @@ public: << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" << "\t\tvOut.z = xform->m_VariationWeights[" << varIndex << "] * vIn.z;\n" << "\n" - << "\t\treal_t tempX = vOut.x + outPoint->m_X;\n" - << "\t\treal_t tempY = vOut.y + outPoint->m_Y;\n" + << "\t\treal_t sumX, sumY;\n\n"; + + if (m_VarType == VARTYPE_PRE) + { + ss + << "\t\tsumX = vIn.x;\n" + << "\t\tsumY = vIn.y;\n"; + } + else + { + ss + << "\t\tsumX = outPoint->m_X;\n" + << "\t\tsumY = outPoint->m_Y;\n"; + } + + ss + << "\t\treal_t tempX = vOut.x + sumX;\n" + << "\t\treal_t tempY = vOut.y + sumY;\n" << "\n" << "\t\toutPoint->m_ColorX = fmod(fabs((real_t)(0.5) * (" << ldcs << " * ((" << cosa << " * tempX + " << sina << " * tempY + " << offset << ")) + (real_t)(1.0))), (real_t)(1.0));\n" << "\t}\n"; @@ -1034,9 +1128,12 @@ private: T m_X1_m_x0; }; +MAKEPREPOSTPARVAR(DCBubble, dc_bubble, DC_BUBBLE) MAKEPREPOSTPARVAR(DCCarpet, dc_carpet, DC_CARPET) MAKEPREPOSTPARVARASSIGN(DCCube, dc_cube, DC_CUBE, ASSIGNTYPE_SUM) +MAKEPREPOSTPARVAR(DCCylinder, dc_cylinder, DC_CYLINDER) MAKEPREPOSTVAR(DCGridOut, dc_gridout, DC_GRIDOUT) +MAKEPREPOSTPARVAR(DCLinear, dc_linear, DC_LINEAR) MAKEPREPOSTPARVAR(DCTriangle, dc_triangle, DC_TRIANGLE) MAKEPREPOSTPARVAR(DCZTransl, dc_ztransl, DC_ZTRANSL) } diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index fca3203..2d1cc7d 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -915,7 +915,6 @@ public: AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { for (auto var : variations) - //for (size_t i = 0; i < variations.size(); i++) { if (var->m_Weight != 0)//This should never happen, but just to be safe. { @@ -1273,7 +1272,7 @@ private: if (in == 0) return 0; else - return pow(T(10.0), -log(T(1.0) / T(in)) / log(T(2))); + return std::pow(T(10.0), -std::log(T(1.0) / T(in)) / std::log(T(2))); } vector m_Xaos;//Xaos vector which affects the probability that this xform is chosen. Usually empty. diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h index 1a4d6d4..6f4fbc7 100644 --- a/Source/Ember/XmlToEmber.h +++ b/Source/Ember/XmlToEmber.h @@ -80,81 +80,100 @@ public: if (!m_Init) { m_BadParamNames.reserve(100); - m_BadParamNames.push_back(pair("swtin_distort", "stwin_distort"));//stwin. - m_BadParamNames.push_back(pair("pow_numerator", "pow_block_numerator"));//pow_block. - m_BadParamNames.push_back(pair("pow_denominator", "pow_block_denominator")); - m_BadParamNames.push_back(pair("pow_root", "pow_block_root")); - m_BadParamNames.push_back(pair("pow_correctn", "pow_block_correctn")); - m_BadParamNames.push_back(pair("pow_correctd", "pow_block_correctd")); - m_BadParamNames.push_back(pair("pow_power", "pow_block_power")); - m_BadParamNames.push_back(pair("lT", "linearT_powX"));//linearT. - m_BadParamNames.push_back(pair("lT", "linearT_powY")); - m_BadParamNames.push_back(pair("Re_A", "Mobius_Re_A"));//Mobius. - m_BadParamNames.push_back(pair("Im_A", "Mobius_Im_A")); - m_BadParamNames.push_back(pair("Re_B", "Mobius_Re_B")); - m_BadParamNames.push_back(pair("Im_B", "Mobius_Im_B")); - m_BadParamNames.push_back(pair("Re_C", "Mobius_Re_C")); - m_BadParamNames.push_back(pair("Im_C", "Mobius_Im_C")); - m_BadParamNames.push_back(pair("Re_D", "Mobius_Re_D")); - m_BadParamNames.push_back(pair("Im_D", "Mobius_Im_D")); - m_BadParamNames.push_back(pair("rx_sin", "rotate_x_sin"));//rotate_x. - m_BadParamNames.push_back(pair("rx_cos", "rotate_x_cos")); - m_BadParamNames.push_back(pair("ry_sin", "rotate_y_sin"));//rotate_y. - m_BadParamNames.push_back(pair("ry_cos", "rotate_y_cos")); - m_BadParamNames.push_back(pair("intrfr2_a1", "interference2_a1"));//interference2. - m_BadParamNames.push_back(pair("intrfr2_b1", "interference2_b1")); - m_BadParamNames.push_back(pair("intrfr2_c1", "interference2_c1")); - m_BadParamNames.push_back(pair("intrfr2_p1", "interference2_p1")); - m_BadParamNames.push_back(pair("intrfr2_t1", "interference2_t1")); - m_BadParamNames.push_back(pair("intrfr2_a2", "interference2_a2")); - m_BadParamNames.push_back(pair("intrfr2_b2", "interference2_b2")); - m_BadParamNames.push_back(pair("intrfr2_c2", "interference2_c2")); - m_BadParamNames.push_back(pair("intrfr2_p2", "interference2_p2")); - m_BadParamNames.push_back(pair("intrfr2_t2", "interference2_t2")); - m_BadParamNames.push_back(pair("octa_x", "octagon_x"));//octagon. - m_BadParamNames.push_back(pair("octa_y", "octagon_y")); - m_BadParamNames.push_back(pair("octa_z", "octagon_z")); - m_BadParamNames.push_back(pair("bubble_x", "bubble2_x"));//bubble2. - m_BadParamNames.push_back(pair("bubble_y", "bubble2_y")); - m_BadParamNames.push_back(pair("bubble_z", "bubble2_z")); - m_BadParamNames.push_back(pair("cubic3D_xpand", "cubicLattice_3D_xpand"));//cubicLattice_3D. - m_BadParamNames.push_back(pair("cubic3D_style", "cubicLattice_3D_style")); - m_BadParamNames.push_back(pair("splitb_x", "SplitBrdr_x"));//SplitBrdr. - m_BadParamNames.push_back(pair("splitb_y", "SplitBrdr_y")); - m_BadParamNames.push_back(pair("splitb_px", "SplitBrdr_px")); - m_BadParamNames.push_back(pair("splitb_py", "SplitBrdr_py")); - m_BadParamNames.push_back(pair("dc_cyl_offset", "dc_cylinder_offset"));//dc_cylinder. - m_BadParamNames.push_back(pair("dc_cyl_angle", "dc_cylinder_angle")); - m_BadParamNames.push_back(pair("dc_cyl_scale", "dc_cylinder_scale")); - m_BadParamNames.push_back(pair("cyl_x", "dc_cylinder_x")); - m_BadParamNames.push_back(pair("cyl_y", "dc_cylinder_y")); - m_BadParamNames.push_back(pair("cyl_blur", "dc_cylinder_blur")); - m_BadParamNames.push_back(pair("mobius_radius", "mobius_strip_radius"));//mobius_strip. - m_BadParamNames.push_back(pair("mobius_width", "mobius_strip_width")); - m_BadParamNames.push_back(pair("mobius_rect_x", "mobius_strip_rect_x")); - m_BadParamNames.push_back(pair("mobius_rect_y", "mobius_strip_rect_y")); - m_BadParamNames.push_back(pair("mobius_rotate_x", "mobius_strip_rotate_x")); - m_BadParamNames.push_back(pair("mobius_rotate_y", "mobius_strip_rotate_y")); - m_BadParamNames.push_back(pair("bwraps2_cellsize", "bwraps_cellsize"));//bwraps2. - m_BadParamNames.push_back(pair("bwraps2_space", "bwraps_space")); - m_BadParamNames.push_back(pair("bwraps2_gain", "bwraps_gain")); - m_BadParamNames.push_back(pair("bwraps2_inner_twist", "bwraps_inner_twist")); - m_BadParamNames.push_back(pair("bwraps2_outer_twist", "bwraps_outer_twist")); - m_BadParamNames.push_back(pair("bwraps7_cellsize", "bwraps_cellsize"));//bwraps7. - m_BadParamNames.push_back(pair("bwraps7_space", "bwraps_space")); - m_BadParamNames.push_back(pair("bwraps7_gain", "bwraps_gain")); - m_BadParamNames.push_back(pair("bwraps7_inner_twist", "bwraps_inner_twist")); - m_BadParamNames.push_back(pair("bwraps7_outer_twist", "bwraps_outer_twist")); - m_BadParamNames.push_back(pair("pre_bwraps2_cellsize", "pre_bwraps_cellsize")); - m_BadParamNames.push_back(pair("pre_bwraps2_space", "pre_bwraps_space")); - m_BadParamNames.push_back(pair("pre_bwraps2_gain", "pre_bwraps_gain")); - m_BadParamNames.push_back(pair("pre_bwraps2_inner_twist", "pre_bwraps_inner_twist")); - m_BadParamNames.push_back(pair("pre_bwraps2_outer_twist", "pre_bwraps_outer_twist")); - m_BadParamNames.push_back(pair("post_bwraps2_cellsize", "post_bwraps_cellsize")); - m_BadParamNames.push_back(pair("post_bwraps2_space", "post_bwraps_space")); - m_BadParamNames.push_back(pair("post_bwraps2_gain", "post_bwraps_gain")); - m_BadParamNames.push_back(pair("post_bwraps2_inner_twist", "post_bwraps_inner_twist")); - m_BadParamNames.push_back(pair("post_bwraps2_outer_twist", "post_bwraps_outer_twist")); + m_BadParamNames["swtin_distort"] = "stwin_distort";//stwin. + m_BadParamNames["pow_numerator"] = "pow_block_numerator";//pow_block. + m_BadParamNames["pow_denominator"] = "pow_block_denominator"; + m_BadParamNames["pow_root"] = "pow_block_root"; + m_BadParamNames["pow_correctn"] = "pow_block_correctn"; + m_BadParamNames["pow_correctd"] = "pow_block_correctd"; + m_BadParamNames["pow_power"] = "pow_block_power"; + m_BadParamNames["lt"] = "linearT_powX";//linearT. + m_BadParamNames["lt"] = "linearT_powY"; + m_BadParamNames["re_a"] = "Mobius_Re_A";//Mobius. + m_BadParamNames["im_a"] = "Mobius_Im_A"; + m_BadParamNames["re_b"] = "Mobius_Re_B"; + m_BadParamNames["im_b"] = "Mobius_Im_B"; + m_BadParamNames["re_c"] = "Mobius_Re_C"; + m_BadParamNames["im_c"] = "Mobius_Im_C"; + m_BadParamNames["re_d"] = "Mobius_Re_D"; + m_BadParamNames["im_d"] = "Mobius_Im_D"; + m_BadParamNames["rx_sin"] = "rotate_x_sin";//rotate_x. + m_BadParamNames["rx_cos"] = "rotate_x_cos"; + m_BadParamNames["ry_sin"] = "rotate_y_sin";//rotate_y. + m_BadParamNames["ry_cos"] = "rotate_y_cos"; + m_BadParamNames["intrfr2_a1"] = "interference2_a1";//interference2. + m_BadParamNames["intrfr2_b1"] = "interference2_b1"; + m_BadParamNames["intrfr2_c1"] = "interference2_c1"; + m_BadParamNames["intrfr2_p1"] = "interference2_p1"; + m_BadParamNames["intrfr2_t1"] = "interference2_t1"; + m_BadParamNames["intrfr2_a2"] = "interference2_a2"; + m_BadParamNames["intrfr2_b2"] = "interference2_b2"; + m_BadParamNames["intrfr2_c2"] = "interference2_c2"; + m_BadParamNames["intrfr2_p2"] = "interference2_p2"; + m_BadParamNames["intrfr2_t2"] = "interference2_t2"; + m_BadParamNames["octa_x"] = "octagon_x";//octagon. + m_BadParamNames["octa_y"] = "octagon_y"; + m_BadParamNames["octa_z"] = "octagon_z"; + m_BadParamNames["bubble_x"] = "bubble2_x";//bubble2. + m_BadParamNames["bubble_y"] = "bubble2_y"; + m_BadParamNames["bubble_z"] = "bubble2_z"; + m_BadParamNames["cubic3d_xpand"] = "cubicLattice_3D_xpand";//cubicLattice_3D. + m_BadParamNames["cubic3d_style"] = "cubicLattice_3D_style"; + m_BadParamNames["splitb_x"] = "SplitBrdr_x";//SplitBrdr. + m_BadParamNames["splitb_y"] = "SplitBrdr_y"; + m_BadParamNames["splitb_px"] = "SplitBrdr_px"; + m_BadParamNames["splitb_py"] = "SplitBrdr_py"; + m_BadParamNames["dc_cyl_offset"] = "dc_cylinder_offset";//dc_cylinder. + m_BadParamNames["dc_cyl_angle"] = "dc_cylinder_angle"; + m_BadParamNames["dc_cyl_scale"] = "dc_cylinder_scale"; + m_BadParamNames["cyl_x"] = "dc_cylinder_x"; + m_BadParamNames["cyl_y"] = "dc_cylinder_y"; + m_BadParamNames["cyl_blur"] = "dc_cylinder_blur"; + m_BadParamNames["mobius_radius"] = "mobius_strip_radius";//mobius_strip. + m_BadParamNames["mobius_width"] = "mobius_strip_width"; + m_BadParamNames["mobius_rect_x"] = "mobius_strip_rect_x"; + m_BadParamNames["mobius_rect_y"] = "mobius_strip_rect_y"; + m_BadParamNames["mobius_rotate_x"] = "mobius_strip_rotate_x"; + m_BadParamNames["mobius_rotate_y"] = "mobius_strip_rotate_y"; + m_BadParamNames["bwraps2_cellsize"] = "bwraps_cellsize";//bwraps2. + m_BadParamNames["bwraps2_space"] = "bwraps_space"; + m_BadParamNames["bwraps2_gain"] = "bwraps_gain"; + m_BadParamNames["bwraps2_inner_twist"] = "bwraps_inner_twist"; + m_BadParamNames["bwraps2_outer_twist"] = "bwraps_outer_twist"; + m_BadParamNames["bwraps7_cellsize"] = "bwraps_cellsize";//bwraps7. + m_BadParamNames["bwraps7_space"] = "bwraps_space"; + m_BadParamNames["bwraps7_gain"] = "bwraps_gain"; + m_BadParamNames["bwraps7_inner_twist"] = "bwraps_inner_twist"; + m_BadParamNames["bwraps7_outer_twist"] = "bwraps_outer_twist"; + m_BadParamNames["pre_bwraps2_cellsize"] = "pre_bwraps_cellsize"; + m_BadParamNames["pre_bwraps2_space"] = "pre_bwraps_space"; + m_BadParamNames["pre_bwraps2_gain"] = "pre_bwraps_gain"; + m_BadParamNames["pre_bwraps2_inner_twist"] = "pre_bwraps_inner_twist"; + m_BadParamNames["pre_bwraps2_outer_twist"] = "pre_bwraps_outer_twist"; + m_BadParamNames["post_bwraps2_cellsize"] = "post_bwraps_cellsize"; + m_BadParamNames["post_bwraps2_space"] = "post_bwraps_space"; + m_BadParamNames["post_bwraps2_gain"] = "post_bwraps_gain"; + m_BadParamNames["post_bwraps2_inner_twist"] = "post_bwraps_inner_twist"; + m_BadParamNames["post_bwraps2_outer_twist"] = "post_bwraps_outer_twist"; + m_BadParamNames["hexa3d_majp"] = "hexaplay3D_majp"; + m_BadParamNames["hexa3d_scale"] = "hexaplay3D_scale"; + m_BadParamNames["hexa3d_zlift"] = "hexaplay3D_zlift"; + m_BadParamNames["nb_numedges"] = "nBlur_numEdges"; + m_BadParamNames["nb_numstripes"] = "nBlur_numStripes"; + m_BadParamNames["nb_ratiostripes"] = "nBlur_ratioStripes"; + m_BadParamNames["nb_ratiohole"] = "nBlur_ratioHole"; + m_BadParamNames["nb_circumcircle"] = "nBlur_circumCircle"; + m_BadParamNames["nb_adjusttolinear"] = "nBlur_adjustToLinear"; + m_BadParamNames["nb_equalblur"] = "nBlur_equalBlur"; + m_BadParamNames["nb_exactcalc"] = "nBlur_exactCalc"; + m_BadParamNames["nb_highlightedges"] = "nBlur_highlightEdges"; + m_BadParamNames["octapol_r"] = "octapol_radius"; + m_BadParamNames["number_of_stripes"] = "bubbleT3D_number_of_stripes"; + m_BadParamNames["ratio_of_stripes"] = "bubbleT3D_ratio_of_stripes"; + m_BadParamNames["angle_of_hole"] = "bubbleT3D_angle_of_hole"; + m_BadParamNames["exponentZ"] = "bubbleT3D_exponentZ"; + m_BadParamNames["_symmetryZ"] = "bubbleT3D_symmetryZ"; + m_BadParamNames["_modusBlur"] = "bubbleT3D_modusBlur"; m_FlattenNames.reserve(24); m_FlattenNames.push_back("pre_crop"); @@ -318,7 +337,7 @@ public: for (size_t i = 1; i < emberSize; i++) { //Only do this adjustment if not in compat mode.. - if (embers[i - 1].m_AffineInterp != INTERP_COMPAT && embers[i - 1].m_AffineInterp != INTERP_OLDER) + if (embers[i - 1].m_AffineInterp != AFFINE_INTERP_COMPAT && embers[i - 1].m_AffineInterp != AFFINE_INTERP_OLDER) { while (embers[i].m_Rotate < embers[i - 1].m_Rotate - 180) embers[i].m_Rotate += 360; @@ -524,7 +543,7 @@ private: if (ParseAndAssign(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) { } else if (ParseAndAssign(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; } else if (ParseAndAssign(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { } - else if (ParseAndAssign(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { } + else if (ParseAndAssign(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { ClampGteRef(currentEmber.m_Zoom, 0); } else if (ParseAndAssign(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) { } else if (ParseAndAssign(curAtt->name, attStr, "temporal_filter_width", currentEmber.m_TemporalFilterWidth, ret)) { } else if (ParseAndAssign(curAtt->name, attStr, "temporal_filter_exp", currentEmber.m_TemporalFilterExp, ret)) { } @@ -576,13 +595,13 @@ private: else if (!Compare(curAtt->name, "interpolation_space") || !Compare(curAtt->name, "interpolation_type")) { if (!_stricmp("linear", attStr)) - currentEmber.m_AffineInterp = INTERP_LINEAR; + currentEmber.m_AffineInterp = AFFINE_INTERP_LINEAR; else if (!_stricmp("log", attStr)) - currentEmber.m_AffineInterp = INTERP_LOG; + currentEmber.m_AffineInterp = AFFINE_INTERP_LOG; else if (!_stricmp("old", attStr)) - currentEmber.m_AffineInterp = INTERP_COMPAT; + currentEmber.m_AffineInterp = AFFINE_INTERP_COMPAT; else if (!_stricmp("older", attStr)) - currentEmber.m_AffineInterp = INTERP_OLDER; + currentEmber.m_AffineInterp = AFFINE_INTERP_OLDER; else m_ErrorReport.push_back(string(loc) + " : Unrecognized interpolation type " + string(attStr)); } @@ -593,7 +612,7 @@ private: } else if (!Compare(curAtt->name, "version")) { - if (ToLower(string(attStr)).find_first_of("ember") != string::npos) + if (ToLower(string(attStr)).find("ember") != string::npos) fromEmber = true; } else if (!Compare(curAtt->name, "size")) @@ -1050,8 +1069,8 @@ private: } } - //if (!newLinear) - // currentEmber.Flatten(m_FlattenNames); + if (!fromEmber && !newLinear) + currentEmber.Flatten(m_FlattenNames); for (i = 0; i < currentEmber.XformCount(); i++) if (soloXform >= 0 && i != soloXform) @@ -1342,16 +1361,17 @@ private: /// Some Apophysis plugins use an inconsistent naming scheme for the parametric variation variables. /// This function identifies and converts them to Ember's consistent naming convention. /// - /// The vector of corrected names to search - /// The current Xml node to check + /// The map of corrected names to search + /// The current Xml node to check /// The corrected name if one was found, else the passed in name. - static string GetCorrectedParamName(vector>& vec, const char* name) + static string GetCorrectedParamName(const unordered_map& names, const char* name) { - for (auto& v : vec) - if (!_stricmp(v.first.c_str(), name)) - return v.second; + auto& newName = names.find(ToLower(name)); - return name; + if (newName != names.end()) + return newName->second; + else + return name; } /// @@ -1503,7 +1523,7 @@ private: } static bool m_Init; - static vector> m_BadParamNames; + static unordered_map m_BadParamNames; static vector, vector>> m_BadVariationNames; VariationList m_VariationList;//The variation list used to make copies of variations to populate the embers with. PaletteList m_PaletteList; diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp index c03fc44..49fe753 100644 --- a/Source/EmberAnimate/EmberAnimate.cpp +++ b/Source/EmberAnimate/EmberAnimate.cpp @@ -29,7 +29,7 @@ bool EmberAnimate(EmberOptions& opt) Timing t; bool unsorted = false; uint channels, padding; - size_t i; + size_t i, firstUnsortedIndex = 0; string inputPath = GetPath(opt.Input()); vector> embers; XmlToEmber parser; @@ -128,6 +128,12 @@ bool EmberAnimate(EmberOptions& opt) if (!ParseEmberFile(parser, opt.Input(), embers)) return false; + if (embers.size() <= 1) + { + cout << "Read " << embers.size() << " embers from file. At least 2 required to animate, exiting." << endl; + return false; + } + if (opt.Format() != "jpg" && opt.Format() != "png" && opt.Format() != "ppm" && @@ -206,7 +212,18 @@ bool EmberAnimate(EmberOptions& opt) for (i = 0; i < embers.size(); i++) { if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time) + { + if (!unsorted) + firstUnsortedIndex = i; + unsorted = true; + } + + if (i > 0 && embers[i].m_Time == embers[i - 1].m_Time) + { + cout << "Image " << i << " time of " << embers[i].m_Time << " equaled previous image time of " << embers[i - 1].m_Time << ". Adjusting up by 1." << endl; + embers[i].m_Time++; + } if (opt.Supersample() > 0) embers[i].m_Supersample = opt.Supersample(); @@ -215,8 +232,8 @@ bool EmberAnimate(EmberOptions& opt) embers[i].m_SubBatchSize = opt.SubBatchSize(); embers[i].m_Quality *= T(opt.QualityScale()); - embers[i].m_FinalRasW = uint(T(embers[i].m_FinalRasW) * opt.SizeScale()); - embers[i].m_FinalRasH = uint(T(embers[i].m_FinalRasH) * opt.SizeScale()); + embers[i].m_FinalRasW = size_t(T(embers[i].m_FinalRasW) * opt.SizeScale()); + embers[i].m_FinalRasH = size_t(T(embers[i].m_FinalRasH) * opt.SizeScale()); embers[i].m_PixelsPerUnit *= T(opt.SizeScale()); //Cast to double in case the value exceeds 2^32. @@ -251,17 +268,18 @@ bool EmberAnimate(EmberOptions& opt) if (unsorted) { - cout << "Embers were unsorted by time. First out of order index was " << i << ". Sorting." << endl; + cout << "Embers were unsorted by time. First out of order index was " << firstUnsortedIndex << ". Sorting." << endl; std::sort(embers.begin(), embers.end(), &CompareEmbers); } if (!opt.Time() && !opt.Frame()) { if (opt.FirstFrame() == UINT_MAX) - opt.FirstFrame(int(embers[0].m_Time)); + opt.FirstFrame(size_t(embers[0].m_Time)); if (opt.LastFrame() == UINT_MAX) - opt.LastFrame(ClampGte(size_t(embers.back().m_Time - 1), opt.FirstFrame())); + opt.LastFrame(ClampGte(size_t(embers.back().m_Time),//Make sure time - 1 is positive before converting to size_t. + opt.FirstFrame() + opt.Dtime()));//Make sure the final value is at least first frame + dtime. } if (!opt.Out().empty()) @@ -271,7 +289,7 @@ bool EmberAnimate(EmberOptions& opt) } //Final setup steps before running. - padding = uint(log10(double(embers.size()))) + 1; + padding = uint(std::log10(double(embers.size()))) + 1; for (auto& r : renderers) { @@ -284,7 +302,7 @@ bool EmberAnimate(EmberOptions& opt) r->Transparency(opt.Transparency()); r->NumChannels(channels); r->BytesPerChannel(opt.BitsPerChannel() / 8); - r->Priority(eThreadPriority(Clamp(int(opt.Priority()), int(eThreadPriority::LOWEST), int(eThreadPriority::HIGHEST)))); + r->Priority(eThreadPriority(Clamp(intmax_t(opt.Priority()), intmax_t(eThreadPriority::LOWEST), intmax_t(eThreadPriority::HIGHEST)))); } std::function&, string, EmberImageComments, size_t, size_t, size_t)> saveFunc = [&](vector& finalImage, diff --git a/Source/EmberCL/DEOpenCLKernelCreator.cpp b/Source/EmberCL/DEOpenCLKernelCreator.cpp index e5ad8f7..96016fb 100644 --- a/Source/EmberCL/DEOpenCLKernelCreator.cpp +++ b/Source/EmberCL/DEOpenCLKernelCreator.cpp @@ -787,7 +787,8 @@ string DEOpenCLKernelCreator::CreateGaussianDEKernelNoLocalCache(size_t ss) "\n"; if (doScf) - os << " filterSelect *= scfact;\n"; + os << + " filterSelect *= scfact;\n"; } else { @@ -830,7 +831,7 @@ string DEOpenCLKernelCreator::CreateGaussianDEKernelNoLocalCache(size_t ss) " }\n" " }\n"//bucket.w != 0. " }\n"//In bounds. - "\n" + //"\n" //" barrier(CLK_GLOBAL_MEM_FENCE);\n"//Just to be safe. "}\n"; diff --git a/Source/EmberCL/EmberCLFunctions.h b/Source/EmberCL/EmberCLFunctions.h index c9048c7..08b44bd 100644 --- a/Source/EmberCL/EmberCLFunctions.h +++ b/Source/EmberCL/EmberCLFunctions.h @@ -149,8 +149,8 @@ static const char* CalcAlphaFunctionString = static const char* CurveAdjustFunctionString = "static inline void CurveAdjust(__constant real4reals_bucket* csa, float* a, uint index)\n" "{\n" -" uint tempIndex = (uint)Clamp(*a, 0.0, (float)COLORMAP_LENGTH_MINUS_1);\n" -" uint tempIndex2 = (uint)Clamp(csa[tempIndex].m_Real4.x, 0.0, (real_t)COLORMAP_LENGTH_MINUS_1);\n" +" uint tempIndex = (uint)clamp(*a, (float)0.0, (float)COLORMAP_LENGTH_MINUS_1);\n" +" uint tempIndex2 = (uint)clamp((float)csa[tempIndex].m_Real4.x, (float)0.0, (float)COLORMAP_LENGTH_MINUS_1);\n" "\n" " *a = (float)round(csa[tempIndex2].m_Reals[index]);\n" "}\n"; @@ -194,135 +194,6 @@ static const char* RandFunctionString = "}\n" "\n"; -/// -/// OpenCL equivalent of the global ClampRef(). -/// -static const char* ClampRealFunctionString = - "inline real_t Clamp(real_t val, real_t min, real_t max)\n" - "{\n" - " if (val < min)\n" - " return min;\n" - " else if (val > max)\n" - " return max;\n" - " else\n" - " return val;\n" - "}\n" - "\n" - "inline void ClampRef(real_t* val, real_t min, real_t max)\n" - "{\n" - " if (*val < min)\n" - " *val = min;\n" - " else if (*val > max)\n" - " *val = max;\n" - "}\n" - "\n" - "inline real_t ClampGte(real_t val, real_t gte)\n" - "{\n" - " return (val < gte) ? gte : val;\n" - "}\n" - "\n"; - -/// -/// OpenCL equivalent of the global LRint(). -/// -static const char* InlineMathFunctionsString = - "inline real_t LRint(real_t x)\n" - "{\n" - " intPrec temp = (x >= 0.0 ? (intPrec)(x + 0.5) : (intPrec)(x - 0.5));\n" - " return (real_t)temp;\n" - "}\n" - "\n" - "inline real_t Round(real_t r)\n" - "{\n" - " return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);\n" - "}\n" - "\n" - "inline real_t Sign(real_t v)\n" - "{\n" - " return (v < 0.0) ? -1 : (v > 0.0) ? 1 : 0.0;\n" - "}\n" - "\n" - "inline real_t SignNz(real_t v)\n" - "{\n" - " return (v < 0.0) ? -1.0 : 1.0;\n" - "}\n" - "\n" - "inline real_t Sqr(real_t v)\n" - "{\n" - " return v * v;\n" - "}\n" - "\n" - "inline real_t SafeSqrt(real_t x)\n" - "{\n" - " if (x <= 0.0)\n" - " return 0.0;\n" - "\n" - " return sqrt(x);\n" - "}\n" - "\n" - "inline real_t Cube(real_t v)\n" - "{\n" - " return v * v * v;\n" - "}\n" - "\n" - "inline real_t Hypot(real_t x, real_t y)\n" - "{\n" - " return sqrt(SQR(x) + SQR(y));\n" - "}\n" - "\n" - "inline real_t Spread(real_t x, real_t y)\n" - "{\n" - " return Hypot(x, y) * ((x) > 0.0 ? 1.0 : -1.0);\n" - "}\n" - "\n" - "inline real_t Powq4(real_t x, real_t y)\n" - "{\n" - " return pow(fabs(x), y) * SignNz(x);\n" - "}\n" - "\n" - "inline real_t Powq4c(real_t x, real_t y)\n" - "{\n" - " return y == 1.0 ? x : Powq4(x, y);\n" - "}\n" - "\n" - "inline real_t Zeps(real_t x)\n" - "{\n" - " return x == 0.0 ? EPS : x;\n" - "}\n" - "\n" - "inline real_t Lerp(real_t a, real_t b, real_t p)\n" - "{\n" - " return a + (b - a) * p;\n" - "}\n" - "\n" - "inline real_t Fabsmod(real_t v)\n" - "{\n" - " real_t dummy;\n" - "\n" - " return modf(v, &dummy);\n" - "}\n" - "\n" - "inline real_t Fosc(real_t p, real_t amp, real_t ph)\n" - "{\n" - " return 0.5 - cos(p * amp + ph) * 0.5;\n" - "}\n" - "\n" - "inline real_t Foscn(real_t p, real_t ph)\n" - "{\n" - " return 0.5 - cos(p + ph) * 0.5;\n" - "}\n" - "\n" - "inline real_t LogScale(real_t x)\n" - "{\n" - " return x == 0.0 ? 0.0 : log((fabs(x) + 1) * M_E) * SignNz(x) / M_E;\n" - "}\n" - "\n" - "inline real_t LogMap(real_t x)\n" - "{\n" - " return x == 0.0 ? 0.0 : (M_E + log(x * M_E)) * 0.25 * SignNz(x);\n" - "}\n" - "\n"; - /// /// OpenCL equivalent Renderer::AddToAccum(). /// diff --git a/Source/EmberCL/EmberCLPch.h b/Source/EmberCL/EmberCLPch.h index 2de2606..26d0506 100644 --- a/Source/EmberCL/EmberCLPch.h +++ b/Source/EmberCL/EmberCLPch.h @@ -44,9 +44,11 @@ #include #include #include +#include #include #include #include +#include #ifdef _WIN32 #if defined(BUILDING_EMBERCL) diff --git a/Source/EmberCL/EmberCLStructs.h b/Source/EmberCL/EmberCLStructs.h index fa31933..6b3a98a 100644 --- a/Source/EmberCL/EmberCLStructs.h +++ b/Source/EmberCL/EmberCLStructs.h @@ -13,15 +13,6 @@ namespace EmberCLns { -//These two must always match. -#ifdef WIN32 - #define ALIGN __declspec(align(16)) -#else - #define ALIGN __attribute__ ((aligned (16))) -#endif - -#define ALIGN_CL "((aligned (16)))"//The extra parens are necessary. - /// /// Various constants needed for rendering. /// @@ -32,20 +23,23 @@ static string ConstantDefinesString(bool doublePrecision) if (doublePrecision) { os << "#if defined(cl_amd_fp64)\n"//AMD extension available? - << " #pragma OPENCL EXTENSION cl_amd_fp64 : enable\n" - << "#endif\n" - << "#if defined(cl_khr_fp64)\n"//Khronos extension available? - << " #pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" - << "#endif\n" - << "#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable\n"//Only supported on nVidia. - << "typedef long intPrec;\n" - << "typedef uint atomi;\n"//Same size as real_bucket_t, always 4 bytes. - << "typedef double real_t;\n" - << "typedef float real_bucket_t;\n"//Assume buckets are always float, even though iter calcs are in double. - << "typedef double4 real4;\n" - << "typedef float4 real4_bucket;\n"//And here too. - << "#define EPS (DBL_EPSILON)\n" - ; + " #pragma OPENCL EXTENSION cl_amd_fp64 : enable\n" + "#endif\n" + "#if defined(cl_khr_fp64)\n"//Khronos extension available? + " #pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + "#endif\n" + "#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable\n"//Only supported on nVidia. + "typedef long intPrec;\n" + "typedef uint atomi;\n"//Same size as real_bucket_t, always 4 bytes. + "typedef double real_t;\n" + "typedef float real_bucket_t;\n"//Assume buckets are always float, even though iter calcs are in double. + "typedef double2 real2;\n" + "typedef double4 real4;\n" + "typedef float4 real4_bucket;\n"//And here too. + "#define EPS (DBL_EPSILON)\n" + "#define TLOW (DBL_MIN)\n" + "#define TMAX (DBL_MAX)\n" + ; } else { @@ -53,9 +47,12 @@ static string ConstantDefinesString(bool doublePrecision) "typedef uint atomi;\n" "typedef float real_t;\n" "typedef float real_bucket_t;\n" + "typedef float2 real2;\n" "typedef float4 real4;\n" "typedef float4 real4_bucket;\n" "#define EPS (FLT_EPSILON)\n" + "#define TLOW (FLT_MIN)\n" + "#define TMAX (FLT_MAX)\n" ; } diff --git a/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp b/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp index 7ebf7ee..ae322e1 100644 --- a/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp +++ b/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp @@ -186,7 +186,6 @@ string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyCli os << ConstantDefinesString(m_DoublePrecision) << - ClampRealFunctionString << UnionCLStructString << RgbToHsvFunctionString << HsvToRgbFunctionString << @@ -484,7 +483,6 @@ string FinalAccumOpenCLKernelCreator::CreateGammaCorrectionKernelString(bool alp os << ConstantDefinesString(m_DoublePrecision) << - ClampRealFunctionString << UnionCLStructString << RgbToHsvFunctionString << HsvToRgbFunctionString << diff --git a/Source/EmberCL/FunctionMapper.cpp b/Source/EmberCL/FunctionMapper.cpp new file mode 100644 index 0000000..cfc5a12 --- /dev/null +++ b/Source/EmberCL/FunctionMapper.cpp @@ -0,0 +1,151 @@ +#include "EmberCLPch.h" +#include "FunctionMapper.h" + +namespace EmberCLns +{ +std::unordered_map FunctionMapper::m_GlobalMap; + +FunctionMapper::FunctionMapper() +{ + if (m_GlobalMap.empty()) + { + m_GlobalMap["LRint"] = + "inline real_t LRint(real_t x)\n" + "{\n" + " intPrec temp = (x >= 0.0 ? (intPrec)(x + 0.5) : (intPrec)(x - 0.5));\n" + " return (real_t)temp;\n" + "}\n"; + + m_GlobalMap["Round"] = + "inline real_t Round(real_t r)\n" + "{\n" + " return (r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5);\n" + "}\n"; + + m_GlobalMap["Sign"] = + "inline real_t Sign(real_t v)\n" + "{\n" + " return (v < 0.0) ? -1 : (v > 0.0) ? 1 : 0.0;\n" + "}\n"; + + m_GlobalMap["SignNz"] = + "inline real_t SignNz(real_t v)\n" + "{\n" + " return (v < 0.0) ? -1.0 : 1.0;\n" + "}\n"; + + m_GlobalMap["Sqr"] = + "inline real_t Sqr(real_t v)\n" + "{\n" + " return v * v;\n" + "}\n"; + + m_GlobalMap["SafeSqrt"] = + "inline real_t SafeSqrt(real_t x)\n" + "{\n" + " if (x <= 0.0)\n" + " return 0.0;\n" + "\n" + " return sqrt(x);\n" + "}\n"; + + m_GlobalMap["Cube"] = + "inline real_t Cube(real_t v)\n" + "{\n" + " return v * v * v;\n" + "}\n"; + + m_GlobalMap["Hypot"] = + "inline real_t Hypot(real_t x, real_t y)\n" + "{\n" + " return sqrt(SQR(x) + SQR(y));\n" + "}\n"; + + m_GlobalMap["Spread"] = + "inline real_t Spread(real_t x, real_t y)\n" + "{\n" + " return Hypot(x, y) * ((x) > 0.0 ? 1.0 : -1.0);\n" + "}\n"; + + m_GlobalMap["Powq4"] = + "inline real_t Powq4(real_t x, real_t y)\n" + "{\n" + " return pow(fabs(x), y) * SignNz(x);\n" + "}\n"; + + m_GlobalMap["Powq4c"] = + "inline real_t Powq4c(real_t x, real_t y)\n" + "{\n" + " return y == 1.0 ? x : Powq4(x, y);\n" + "}\n"; + + m_GlobalMap["Zeps"] = + "inline real_t Zeps(real_t x)\n" + "{\n" + " return x == 0.0 ? EPS : x;\n" + "}\n"; + + m_GlobalMap["Lerp"] = + "inline real_t Lerp(real_t a, real_t b, real_t p)\n" + "{\n" + " return a + (b - a) * p;\n" + "}\n"; + + m_GlobalMap["Fabsmod"] = + "inline real_t Fabsmod(real_t v)\n" + "{\n" + " real_t dummy;\n" + "\n" + " return modf(v, &dummy);\n" + "}\n"; + + m_GlobalMap["Fosc"] = + "inline real_t Fosc(real_t p, real_t amp, real_t ph)\n" + "{\n" + " return 0.5 - cos(p * amp + ph) * 0.5;\n" + "}\n"; + + m_GlobalMap["Foscn"] = + "inline real_t Foscn(real_t p, real_t ph)\n" + "{\n" + " return 0.5 - cos(p + ph) * 0.5;\n" + "}\n"; + + m_GlobalMap["LogScale"] = + "inline real_t LogScale(real_t x)\n" + "{\n" + " return x == 0.0 ? 0.0 : log((fabs(x) + 1) * M_E) * SignNz(x) / M_E;\n" + "}\n"; + + m_GlobalMap["LogMap"] = + "inline real_t LogMap(real_t x)\n" + "{\n" + " return x == 0.0 ? 0.0 : (M_E + log(x * M_E)) * 0.25 * SignNz(x);\n" + "}\n"; + + m_GlobalMap["ClampGte"] = + "inline real_t ClampGte(real_t val, real_t gte)\n" + "{\n" + " return (val < gte) ? gte : val;\n" + "}\n"; + + m_GlobalMap["Swap"] = + "inline void Swap(real_t* val1, real_t* val2)\n" + "{\n" + " real_t tmp = *val1;\n" + " *val1 = *val2;\n" + " *val2 = tmp;\n" + "}\n"; + } +} + +const string* FunctionMapper::GetGlobalFunc(const string& func) +{ + auto& text = m_GlobalMap.find(func); + + if (text != m_GlobalMap.end()) + return &text->second; + else + return nullptr; +} +} diff --git a/Source/EmberCL/FunctionMapper.h b/Source/EmberCL/FunctionMapper.h new file mode 100644 index 0000000..8e3828a --- /dev/null +++ b/Source/EmberCL/FunctionMapper.h @@ -0,0 +1,21 @@ +#pragma once + +#include "EmberCLPch.h" + +namespace EmberCLns +{ +/// +/// Functionality to map OpenCL function names to their full function body program strings. +/// This is used to ensure only the functions that are needed by a program are included once +/// in the program string. +/// +class EMBERCL_API FunctionMapper +{ +public: + FunctionMapper(); + static const string* GetGlobalFunc(const string& func); + +private: + static std::unordered_map m_GlobalMap; +}; +} \ No newline at end of file diff --git a/Source/EmberCL/IterOpenCLKernelCreator.cpp b/Source/EmberCL/IterOpenCLKernelCreator.cpp index 7de6067..c5230a3 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.cpp +++ b/Source/EmberCL/IterOpenCLKernelCreator.cpp @@ -2,7 +2,6 @@ #include "IterOpenCLKernelCreator.h" //#define STRAIGHT_RAND 1 -#define USE_CASE 1 namespace EmberCLns { @@ -39,16 +38,20 @@ template const string& IterOpenCLKernelCreator::IterEntryPoint() /// Debugging parameter to include or omit accumulating to the histogram. Default: true. /// The kernel string template -string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, string& parVarDefines, bool lockAccum, bool doAccum) +string IterOpenCLKernelCreator::CreateIterKernelString(const Ember& ember, string& parVarDefines, bool lockAccum, bool doAccum) { bool doublePrecision = typeid(T) == typeid(double); size_t i, v, varIndex, varCount, totalXformCount = ember.TotalXformCount(); ostringstream kernelIterBody, xformFuncs, os; vector*> variations; - xformFuncs << "\n" << parVarDefines << endl; + xformFuncs << VariationStateString(ember); + xformFuncs << parVarDefines << endl; ember.GetPresentVariations(variations); - for (auto var : variations) if (var) xformFuncs << var->OpenCLFuncsString(); + + for (auto var : variations) + if (var) + xformFuncs << var->OpenCLFuncsString(); for (i = 0; i < totalXformCount; i++) { @@ -62,7 +65,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin v = varIndex = varCount = 0; xformFuncs << - "void Xform" << i << "(__constant XformCL* xform, __constant real_t* parVars, Point* inPoint, Point* outPoint, uint2* mwc)\n" << + "void Xform" << i << "(__constant XformCL* xform, __constant real_t* parVars, Point* inPoint, Point* outPoint, uint2* mwc, VariationState* varState)\n" << "{\n" " real_t transX, transY, transZ;\n" " real4 vIn, vOut = 0.0;\n"; @@ -215,8 +218,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin os << ConstantDefinesString(doublePrecision) << - InlineMathFunctionsString << - ClampRealFunctionString << + GlobalFunctionsString(ember) << RandFunctionString << PointCLStructString << XformCLStructString << @@ -237,12 +239,13 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin " __constant EmberCL* ember,\n" " __constant XformCL* xforms,\n" " __constant real_t* parVars,\n" - " __global uchar* xformDistributions,\n"//Using uchar is quicker than uint. Can't be constant because the size can be too large to fit when using xaos.//FINALOPT + " __global uchar* xformDistributions,\n"//Using uchar is quicker than uint. Can't be constant because the size can be too large to fit when using xaos. " __constant CarToRasCL* carToRas,\n" " __global real4reals_bucket* histogram,\n" " uint histSize,\n" " __read_only image2d_t palette,\n" " __global Point* points\n" + //" uint startRender\n" "\t)\n" "{\n" " bool fuse, ok;\n" @@ -261,8 +264,9 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin " CLK_ADDRESS_CLAMP_TO_EDGE |\n"//Clamp to edge " CLK_FILTER_NEAREST;\n"//Don't interpolate " uint threadXY = (THREAD_ID_X + THREAD_ID_Y);\n" - " uint threadXDivRows = (THREAD_ID_X / (NTHREADS / THREADS_PER_WARP));\n" + " uint threadXDivRows = (THREAD_ID_X / NWARPS);\n" " uint threadsMinus1 = NTHREADS - 1;\n" + " VariationState varState;\n" ; os << @@ -278,6 +282,9 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin " {\n" " fuse = true;\n" " itersToDo = fuseCount;\n" + //Calling MwcNextNeg1Pos1() twice is deliberate. The first call to mwc is not very random since it just does + //an xor. So it must be called twice to get it in a good random state. + " firstPoint.m_X = MwcNextNeg1Pos1(&mwc);\n" " firstPoint.m_X = MwcNextNeg1Pos1(&mwc);\n" " firstPoint.m_Y = MwcNextNeg1Pos1(&mwc);\n" " firstPoint.m_Z = 0.0;\n" @@ -290,7 +297,13 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin " itersToDo = iterCount;\n" " firstPoint = points[pointsIndex];\n" " }\n" - "\n"; + "\n" + ; + + auto varStateString = VariationStateInitString(ember); + + if (!varStateString.empty()) + os << varStateString << "\n\n"; //This is done once initially here and then again after each swap-sync in the main loop. //This along with the randomness that the point shuffle provides gives sufficient randomness @@ -336,7 +349,6 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin for (i = 0; i < ember.XformCount(); i++) { -#ifdef USE_CASE if (i == 0) { os << @@ -347,7 +359,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin os << " case " << i << ":\n" " {\n" << - " Xform" << i << "(&(xforms[" << i << "]), parVars, &firstPoint, &secondPoint, &mwc);\n" << + " Xform" << i << "(&(xforms[" << i << "]), parVars, &firstPoint, &secondPoint, &mwc, &varState);\n" << " break;\n" " }\n"; @@ -356,19 +368,6 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin os << " }\n"; } -#else - if (i == 0) - os << - " if (secondPoint.m_LastXfUsed == " << i << ")\n"; - else - os << - " else if (secondPoint.m_LastXfUsed == " << i << ")\n"; - - os << - " {\n" << - " Xform" << i << "(&(xforms[" << i << "]), parVars, &firstPoint, &secondPoint, &mwc);\n" << - " }\n"; -#endif } os << @@ -438,7 +437,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin " if ((xforms[" << finalIndex << "].m_Opacity == 1) || (MwcNext01(&mwc) < xforms[" << finalIndex << "].m_Opacity))\n" " {\n" " tempPoint.m_LastXfUsed = secondPoint.m_LastXfUsed;\n" - " Xform" << finalIndex << "(&(xforms[" << finalIndex << "]), parVars, &secondPoint, &tempPoint, &mwc);\n" + " Xform" << finalIndex << "(&(xforms[" << finalIndex << "]), parVars, &secondPoint, &tempPoint, &mwc, &varState);\n" " secondPoint = tempPoint;\n" " }\n" "\n"; @@ -543,6 +542,50 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin return os.str(); } +/// +/// Return a string containing all of the global functions needed by the passed in ember. +/// +/// The ember to create the global function strings from +/// String of all global function names and bodies +template +string IterOpenCLKernelCreator::GlobalFunctionsString(const Ember& ember) +{ + size_t i, j, xformCount = ember.TotalXformCount(); + vector funcNames;//Can't use a set here because they sort and we must preserve the insertion order due to nested function calls. + ostringstream os; + static string zeps = "Zeps"; + + for (i = 0; i < xformCount; i++) + { + if (auto xform = ember.GetTotalXform(i)) + { + size_t varCount = xform->TotalVariationCount(); + + if (xform->NeedPrecalcAngles()) + if (!Contains(funcNames, zeps)) + funcNames.push_back(zeps); + + for (j = 0; j < varCount; j++) + { + if (auto var = xform->GetVariation(j)) + { + auto names = var->OpenCLGlobalFuncNames(); + + for (auto& name : names) + if (!Contains(funcNames, name)) + funcNames.push_back(name); + } + } + } + } + + for (auto& funcName : funcNames) + if(auto text = m_FunctionMapper.GetGlobalFunc(funcName)) + os << *text << endl; + + return os.str(); +} + /// /// Create an OpenCL string of #defines and a corresponding host side vector for parametric variation values. /// Parametric variations present a special problem in the iteration code. @@ -571,9 +614,9 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin /// #define CURL_C2_2 3 /// #define BLOB_LOW_3 4 /// #define BLOB_HIGH_3 5 -/// #define BLOB_WAVES_ 6 +/// #define BLOB_WAVES_3 6 /// -/// The variations the use these #defines by first looking up the index of the +/// The variations use these #defines by first looking up the index of the /// xform they belong to in the parent ember and generating the OpenCL string based on that /// in their overridden OpenCLString() functions. /// Template argument expected to be float or double. @@ -583,10 +626,9 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin /// True if the vector should be populated, else false. Default: true. /// True if the string should be populated, else false. Default: true. template -void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pair>& params, bool doVals, bool doString) +void IterOpenCLKernelCreator::ParVarIndexDefines(const Ember& ember, pair>& params, bool doVals, bool doString) { size_t i, j, k, size = 0, xformCount = ember.TotalXformCount(); - Xform* xform; ostringstream os; if (doVals) @@ -594,23 +636,26 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pairTotalVariationCount(); for (j = 0; j < varCount; j++) { - if (ParametricVariation* parVar = dynamic_cast*>(xform->GetVariation(j))) + if (auto parVar = dynamic_cast*>(xform->GetVariation(j))) { for (k = 0; k < parVar->ParamCount(); k++) { - if (doString) - os << "#define " << ToUpper(parVar->Params()[k].Name()) << "_" << i << " " << size << endl;//Uniquely identify this param in this variation in this xform. + if (!parVar->Params()[k].IsState()) + { + if (doString) + os << "#define " << ToUpper(parVar->Params()[k].Name()) << "_" << i << " " << size << endl;//Uniquely identify this param in this variation in this xform. - if (doVals) - params.second.push_back(parVar->Params()[k].ParamVal()); + if (doVals) + params.second.push_back(parVar->Params()[k].ParamVal()); - size++; + size++; + } } } } @@ -624,6 +669,69 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pair +/// Create the string needed for the struct whose values will change between each iteration. +/// This is only needed for variations whose state changes. +/// If none are present, the struct will be empty. +/// +/// The ember to generate the variation state struct string for +/// The variation state struct string +template +string IterOpenCLKernelCreator::VariationStateString(const Ember& ember) +{ + ostringstream os; + + os << "typedef struct __attribute__ " ALIGN_CL " _VariationState\n{"; + + for (size_t i = 0; i < ember.TotalXformCount(); i++) + { + if (auto xform = ember.GetTotalXform(i)) + { + for (size_t j = 0; j < xform->TotalVariationCount(); j++) + { + if (auto var = xform->GetVariation(j)) + { + os << var->StateOpenCLString(); + } + } + } + } + + os << "\n} VariationState;\n\n"; + + return os.str(); +} + +/// +/// Create the string needed for the initial state of the struct whose values will change between each iteration. +/// This is only needed for variations whose state changes. +/// If none are present, the returned init string will be empty. +/// This will be called at the beginning of each kernel. +/// +/// The ember to generate the variation state struct init string for +/// The variation state struct init string +template +string IterOpenCLKernelCreator::VariationStateInitString(const Ember& ember) +{ + ostringstream os; + + for (size_t i = 0; i < ember.TotalXformCount(); i++) + { + if (auto xform = ember.GetTotalXform(i)) + { + for (size_t j = 0; j < xform->TotalVariationCount(); j++) + { + if (auto var = xform->GetVariation(j)) + { + os << var->StateInitOpenCLString(); + } + } + } + } + + return os.str(); +} + /// /// Determine whether the two embers passed in differ enough /// to require a rebuild of the iteration code. @@ -641,7 +749,7 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pairThe second ember to compare /// True if a rebuild is required, else false template -bool IterOpenCLKernelCreator::IsBuildRequired(Ember& ember1, Ember& ember2) +bool IterOpenCLKernelCreator::IsBuildRequired(const Ember& ember1, const Ember& ember2) { size_t i, j, xformCount = ember1.TotalXformCount(); @@ -688,7 +796,7 @@ bool IterOpenCLKernelCreator::IsBuildRequired(Ember& ember1, Ember& emb /// /// The kernel string template -string IterOpenCLKernelCreator::CreateZeroizeKernelString() +string IterOpenCLKernelCreator::CreateZeroizeKernelString() const { ostringstream os; @@ -707,8 +815,16 @@ string IterOpenCLKernelCreator::CreateZeroizeKernelString() return os.str(); } +/// +/// Create the histogram summing kernel string. +/// This is used when running with multiple GPUs. It takes +/// two histograms present on a single device, source and dest, +/// and adds the values of source to dest. +/// It optionally sets all values of source to zero. +/// +/// The kernel string template -string IterOpenCLKernelCreator::CreateSumHistKernelString() +string IterOpenCLKernelCreator::CreateSumHistKernelString() const { ostringstream os; @@ -739,7 +855,7 @@ string IterOpenCLKernelCreator::CreateSumHistKernelString() /// The ember to create the projection string for /// The kernel string template -string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) +string IterOpenCLKernelCreator::CreateProjectionString(const Ember& ember) const { size_t projBits = ember.ProjBits(); ostringstream os; diff --git a/Source/EmberCL/IterOpenCLKernelCreator.h b/Source/EmberCL/IterOpenCLKernelCreator.h index fdb5db5..3a13da0 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.h +++ b/Source/EmberCL/IterOpenCLKernelCreator.h @@ -3,6 +3,7 @@ #include "EmberCLPch.h" #include "EmberCLStructs.h" #include "EmberCLFunctions.h" +#include "FunctionMapper.h" /// /// IterOpenCLKernelCreator class. @@ -29,20 +30,24 @@ public: const string& SumHistKernel() const; const string& SumHistEntryPoint() const; const string& IterEntryPoint() const; - string CreateIterKernelString(Ember& ember, string& parVarDefines, bool lockAccum = false, bool doAccum = true); - static void ParVarIndexDefines(Ember& ember, pair>& params, bool doVals = true, bool doString = true); - static bool IsBuildRequired(Ember& ember1, Ember& ember2); + string CreateIterKernelString(const Ember& ember, string& parVarDefines, bool lockAccum = false, bool doAccum = true); + string GlobalFunctionsString(const Ember& ember); + static void ParVarIndexDefines(const Ember& ember, pair>& params, bool doVals = true, bool doString = true); + static string VariationStateString(const Ember& ember); + static string VariationStateInitString(const Ember& ember); + static bool IsBuildRequired(const Ember& ember1, const Ember& ember2); private: - string CreateZeroizeKernelString(); - string CreateSumHistKernelString(); - string CreateProjectionString(Ember& ember); + string CreateZeroizeKernelString() const; + string CreateSumHistKernelString() const; + string CreateProjectionString(const Ember& ember) const; string m_IterEntryPoint; string m_ZeroizeKernel; string m_ZeroizeEntryPoint; string m_SumHistKernel; string m_SumHistEntryPoint; + FunctionMapper m_FunctionMapper; }; #ifdef OPEN_CL_TEST_AREA diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index 6005364..6048744 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -354,7 +354,7 @@ bool RendererCL::WritePoints(size_t device, vector>& vec) #ifdef TEST_CL template -bool RendererCL::WriteRandomPoints() +bool RendererCL::WriteRandomPoints(size_t device) { size_t size = IterGridKernelCount(); vector> vec(size); @@ -368,7 +368,7 @@ bool RendererCL::WriteRandomPoints() vec[i].m_LastXfUsed = 0; } - return WritePoints(vec); + return WritePoints(device, vec); } #endif @@ -613,6 +613,8 @@ vector RendererCL::ErrorReport() /// /// Set the vector of random contexts on every device. /// Call the base, and reset the seeds vector. +/// Used on the command line when the user wants a specific set of seeds to start with to +/// produce an exact result. Mostly for debugging. /// /// The vector of random contexts to assign /// True if the size of the vector matched the number of threads used for rendering and writing seeds to OpenCL succeeded, else false. @@ -707,9 +709,10 @@ bool RendererCL::ResetBuckets(bool resetHist, bool resetAccum) /// /// Perform log scale density filtering on the primary device. /// +/// Whether this output was forced due to an interactive render /// True if success and not aborted, else false. template -eRenderStatus RendererCL::LogScaleDensityFilter() +eRenderStatus RendererCL::LogScaleDensityFilter(bool forceOutput) { return RunLogScaleFilter(); } @@ -804,10 +807,10 @@ EmberStats RendererCL::Iterate(size_t iterCount, size_t temporalSamp { auto& wrapper = device->m_Wrapper; - if (b && !(b = wrapper.WriteBuffer (m_EmberBufferName, reinterpret_cast(&m_EmberCL), sizeof(m_EmberCL)))) { this->m_ErrorReport.push_back(loc); } - if (b && !(b = wrapper.WriteBuffer (m_XformsBufferName, reinterpret_cast(m_XformsCL.data()), sizeof(m_XformsCL[0]) * m_XformsCL.size()))) { this->m_ErrorReport.push_back(loc); } - if (b && !(b = wrapper.AddAndWriteBuffer(m_DistBufferName, reinterpret_cast(const_cast(XformDistributions())), XformDistributionsSize()))) { this->m_ErrorReport.push_back(loc); }//Will be resized for xaos. - if (b && !(b = wrapper.WriteBuffer (m_CarToRasBufferName, reinterpret_cast(&m_CarToRasCL), sizeof(m_CarToRasCL)))) { this->m_ErrorReport.push_back(loc); } + if (b && !(b = wrapper.WriteBuffer (m_EmberBufferName, reinterpret_cast(&m_EmberCL), sizeof(m_EmberCL)))) { this->m_ErrorReport.push_back(loc); } + if (b && !(b = wrapper.WriteBuffer (m_XformsBufferName, reinterpret_cast(m_XformsCL.data()), sizeof(m_XformsCL[0]) * m_XformsCL.size()))) { this->m_ErrorReport.push_back(loc); } + if (b && !(b = wrapper.AddAndWriteBuffer(m_DistBufferName, reinterpret_cast(const_cast(XformDistributions())), XformDistributionsSize()))) { this->m_ErrorReport.push_back(loc); }//Will be resized for xaos. + if (b && !(b = wrapper.WriteBuffer (m_CarToRasBufferName, reinterpret_cast(&m_CarToRasCL), sizeof(m_CarToRasCL)))) { this->m_ErrorReport.push_back(loc); } if (b && !(b = wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Dmap.m_Entries.size(), 1, 0, m_Dmap.m_Entries.data()))) { this->m_ErrorReport.push_back(loc); } @@ -966,7 +969,7 @@ bool RendererCL::RunIter(size_t iterCount, size_t temporalSample, si { cl_uint argIndex = 0; #ifdef TEST_CL - fuse = 0; + uint fuse = 0; #else uint fuse = uint((m_Devices[dev]->m_Calls % fuseFreq) == 0u ? FuseCount() : 0u); #endif diff --git a/Source/EmberCL/RendererCL.h b/Source/EmberCL/RendererCL.h index 507bb4c..21c0caa 100644 --- a/Source/EmberCL/RendererCL.h +++ b/Source/EmberCL/RendererCL.h @@ -129,7 +129,7 @@ public: bool ClearAccum(); bool WritePoints(size_t device, vector>& vec); #ifdef TEST_CL - bool WriteRandomPoints(); + bool WriteRandomPoints(size_t device); #endif const string& IterKernel() const; const string& DEKernel() const; @@ -159,7 +159,7 @@ protected: //Protected virtual functions overridden from Renderer. virtual bool Alloc(bool histOnly = false) override; virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true) override; - virtual eRenderStatus LogScaleDensityFilter() override; + virtual eRenderStatus LogScaleDensityFilter(bool forceOutput = false) override; virtual eRenderStatus GaussianDensityFilter() override; virtual eRenderStatus AccumulatorToFinalImage(byte* pixels, size_t finalOffset) override; virtual EmberStats Iterate(size_t iterCount, size_t temporalSample) override; diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index 09d8077..f86c5ea 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -321,8 +321,8 @@ bool EmberGenome(EmberOptions& opt) embers[i].DeleteMotionElements(); } - firstFrame = uint(opt.FirstFrame() == UINT_MAX ? embers[0].m_Time : opt.FirstFrame()); - lastFrame = uint(opt.LastFrame() == UINT_MAX ? embers.back().m_Time : opt.LastFrame()); + firstFrame = size_t(opt.FirstFrame() == UINT_MAX ? embers[0].m_Time : opt.FirstFrame()); + lastFrame = size_t(opt.LastFrame() == UINT_MAX ? embers.back().m_Time : opt.LastFrame()); if (lastFrame < firstFrame) lastFrame = firstFrame; @@ -335,7 +335,7 @@ bool EmberGenome(EmberOptions& opt) for (i = 0; i < embers.size(); i++) { - if (ftime == uint(embers[i].m_Time)) + if (ftime == size_t(embers[i].m_Time)) { interpolated = embers[i]; exactTimeMatch = true; @@ -349,7 +349,7 @@ bool EmberGenome(EmberOptions& opt) for (i = 0; i < embers.size(); i++) { - if (ftime == uint(embers[i].m_Time - 1)) + if (ftime == size_t(embers[i].m_Time - 1)) { exactTimeMatch = true; break; @@ -357,7 +357,7 @@ bool EmberGenome(EmberOptions& opt) } if (!exactTimeMatch) - interpolated.m_AffineInterp = INTERP_LINEAR; + interpolated.m_AffineInterp = AFFINE_INTERP_LINEAR; } if (pTemplate) @@ -400,23 +400,12 @@ bool EmberGenome(EmberOptions& opt) if (i < embers.size() - 1) { - vector> interpEmbers; - - interpEmbers.push_back(embers[i]); - interpEmbers.push_back(embers[i + 1]); - - if (opt.Loops() > 0) - { - //We might have looped a non-integral number of times, so store the last result as our flame to interpolate from. - interpEmbers[i] = result; - } - for (frame = 0; frame < opt.Frames(); frame++) { seqFlag = (frame == 0 || frame == opt.Frames() - 1); blend = frame / T(opt.Frames()); result.Clear(); - tools.SpinInter(&interpEmbers[i], pTemplate, result, frameCount++, seqFlag, blend); + tools.SpinInter(&embers[i], pTemplate, result, frameCount++, seqFlag, blend); cout << emberToXml.ToString(result, opt.Extras(), opt.PrintEditDepth(), !opt.NoEdits(), false, opt.HexPalette()); } } @@ -500,7 +489,7 @@ bool EmberGenome(EmberOptions& opt) oldX = embers[i].m_CenterX; oldY = embers[i].m_CenterY; - embers[i].m_FinalRasH = uint(T(embers[i].m_FinalRasH) / T(opt.Frames())); + embers[i].m_FinalRasH = size_t(T(embers[i].m_FinalRasH) / T(opt.Frames())); embers[i].m_CenterY = embers[i].m_CenterY - ((opt.Frames() - 1) * embers[i].m_FinalRasH) / (2 * embers[i].m_PixelsPerUnit * pow(T(2.0), embers[i].m_Zoom)); @@ -596,7 +585,7 @@ bool EmberGenome(EmberOptions& opt) mutMeth = MUTATE_NOT_SPECIFIED; } - os << tools.Mutate(orig, mutMeth, vars, opt.Symmetry(), T(opt.Speed())); + os << tools.Mutate(orig, mutMeth, vars, opt.Symmetry(), T(opt.Speed()), MAX_CL_VARS); //Scan string returned for 'mutate color'. if (strstr(os.str().c_str(), "mutate color")) @@ -647,7 +636,7 @@ bool EmberGenome(EmberOptions& opt) { os << "random"; randomMode = true; - tools.Random(orig, vars, opt.Symmetry(), 0); + tools.Random(orig, vars, opt.Symmetry(), 0, MAX_CL_VARS); aselp0 = nullptr; aselp1 = nullptr; } diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp index 582aa37..27cc6c8 100644 --- a/Source/EmberRender/EmberRender.cpp +++ b/Source/EmberRender/EmberRender.cpp @@ -149,7 +149,7 @@ bool EmberRender(EmberOptions& opt) //Final setup steps before running. os.imbue(std::locale("")); - padding = uint(log10(double(embers.size()))) + 1; + padding = uint(std::log10(double(embers.size()))) + 1; renderer->EarlyClip(opt.EarlyClip()); renderer->YAxisUp(opt.YAxisUp()); renderer->LockAccum(opt.LockAccum()); @@ -158,7 +158,7 @@ bool EmberRender(EmberOptions& opt) renderer->Transparency(opt.Transparency()); renderer->NumChannels(channels); renderer->BytesPerChannel(opt.BitsPerChannel() / 8); - renderer->Priority(eThreadPriority(Clamp(int(opt.Priority()), int(eThreadPriority::LOWEST), int(eThreadPriority::HIGHEST)))); + renderer->Priority(eThreadPriority(Clamp(intmax_t(opt.Priority()), intmax_t(eThreadPriority::LOWEST), intmax_t(eThreadPriority::HIGHEST)))); renderer->Callback(opt.DoProgress() ? progress.get() : nullptr); for (i = 0; i < embers.size(); i++) @@ -176,8 +176,8 @@ bool EmberRender(EmberOptions& opt) embers[i].m_TemporalSamples = 1;//Force temporal samples to 1 for render. embers[i].m_Quality *= T(opt.QualityScale()); - embers[i].m_FinalRasW = uint(T(embers[i].m_FinalRasW) * opt.SizeScale()); - embers[i].m_FinalRasH = uint(T(embers[i].m_FinalRasH) * opt.SizeScale()); + embers[i].m_FinalRasW = size_t(T(embers[i].m_FinalRasW) * opt.SizeScale()); + embers[i].m_FinalRasH = size_t(T(embers[i].m_FinalRasH) * opt.SizeScale()); embers[i].m_PixelsPerUnit *= T(opt.SizeScale()); if (embers[i].m_FinalRasW == 0 || embers[i].m_FinalRasH == 0) @@ -309,9 +309,11 @@ bool EmberRender(EmberOptions& opt) { if (auto rendererCL = dynamic_cast*>(renderer.get())) { - cout << "Iteration kernel: \n" << + cout << "Iteration kernel:\n" << rendererCL->IterKernel() << "\n\n" << + "Density filter kernel:\n" << rendererCL->DEKernel() << "\n\n" << + "Final accumulation kernel:\n" << rendererCL->FinalAccumKernel() << endl; } } diff --git a/Source/EmberTester/EmberTester.cpp b/Source/EmberTester/EmberTester.cpp index e3e5ffa..db04a25 100644 --- a/Source/EmberTester/EmberTester.cpp +++ b/Source/EmberTester/EmberTester.cpp @@ -136,6 +136,12 @@ void MakeTestAllVarsRegPrePost(vector>& embers) while (index < varList.RegSize()) { + /*if (index != VAR_SYNTH) + { + index++; + continue; + } +*/ Ember ember1; unique_ptr> regVar(varList.GetVariationCopy(index, VARTYPE_REG)); unique_ptr> preVar(varList.GetVariationCopy("pre_" + regVar->Name())); @@ -422,7 +428,7 @@ bool TestVarUnique() for (size_t i = 0; i < vl.Size(); i++) { - Variation* var = vl.GetVariation(i); + auto var = vl.GetVariation(i); if (std::find(ids.begin(), ids.end(), var->VariationId()) != ids.end()) { @@ -490,7 +496,7 @@ bool TestVarPrecalcEqual(const Variation* var1, const Variation
* var2) } template -bool TestVarEqual(Variation* var1, Variation
* var2) +bool TestVarEqual(const Variation* var1, const Variation
* var2) { bool success = true; @@ -530,8 +536,8 @@ bool TestVarEqual(Variation* var1, Variation
* var2) success = false; } - ParametricVariation* parVar1 = dynamic_cast*>(var1); - ParametricVariation
* parVar2 = dynamic_cast*>(var2); + auto parVar1 = dynamic_cast*>(var1); + auto parVar2 = dynamic_cast*>(var2); if (parVar1 && parVar2) { @@ -585,10 +591,13 @@ bool TestVarEqual(Variation* var1, Variation
* var2) } } - if (!IsClose(params1[i].ParamVal(), (sT)params2[i].ParamVal(), sT(1e-4))) + if (!params1[i].IsState() && !params2[i].IsState())//Don't compare state params, they can be different if set to random vals. { - cout << "Param " << params1[i].Name() << " Val were not equal: " << params1[i].ParamVal() << " != " << params2[i].ParamVal() << endl; - success = false; + if (!IsClose(params1[i].ParamVal(), (sT)params2[i].ParamVal(), sT(1e-4))) + { + cout << "Param " << params1[i].Name() << " Val were not equal: " << params1[i].ParamVal() << " != " << params2[i].ParamVal() << endl; + success = false; + } } } } @@ -669,7 +678,7 @@ bool TestVarCopy() for (size_t i = 0; i < vlf.Size(); i++) { - Variation* var = vlf.GetVariation(i); + auto var = vlf.GetVariation(i); Variation
* destVar = NULL; unique_ptr> copyVar(var->Copy());//Test Copy(). @@ -1126,6 +1135,36 @@ bool TestConstants() return success; } +bool TestGlobalFuncs() +{ + bool success = true; + VariationList vlf; + vector funcs; + FunctionMapper mapper; + + for (size_t i = 0; i < vlf.Size(); i++) + { + auto var = vlf.GetVariation(i); + + funcs = var->OpenCLGlobalFuncNames(); + + for (auto& func : funcs) + { + if (!mapper.GetGlobalFunc(func)) + { + cout << "Variation " << var->Name() << " used unknown global funcion " << func << endl; + success = false; + } + else + { + //cout << "Variation " << var->Name() << " used valid global funcion " << func << endl; + } + } + } + + return success; +} + void PrintAllVars() { uint i = 0; @@ -1506,17 +1545,20 @@ void TestVarsSimilar() #ifdef TEST_CL template -void TestAllVarsCLBuild(bool printSuccess = true) +bool TestAllVarsCLBuild(size_t platform, size_t device, bool printSuccess = true) { + bool success = true; vector> embers; QTIsaac rand; - RendererCL renderer; + vector> devices{ std::make_pair(platform, device) }; + RendererCL renderer(devices); + const char* loc = __FUNCTION__; - if (!renderer.Init(1, 0, false, 0)) + if (!renderer.Ok()) { cout << loc << "Creating RendererCL failed, tests will not be run." << endl; - return; + return false; } MakeTestAllVarsRegPrePost(embers); @@ -1531,12 +1573,18 @@ void TestAllVarsCLBuild(bool printSuccess = true) cout << loc << ": Build succeeded for ember " << it.m_Name << endl; } else - cout << loc << ": OpenCL program build failed:\n" << renderer.ErrorReport() << endl; + { + success = false; + cout << loc << ": OpenCL program build failed for ember " << it.m_Name << ":\n" << renderer.ErrorReportString() << endl; + break; + } } + + return success; } template -void TestCpuGpuResults() +void TestCpuGpuResults(size_t platform, size_t device) { bool breakOnBad = true; int i = 0;//(int)VAR_TARGET;//Start at the one you want to test. @@ -1547,10 +1595,8 @@ void TestCpuGpuResults() VariationList vlf; QTIsaac rand; vector> points; - RendererCL renderer; - - if (!renderer.Init(1, 0, false, 0)) - return; + vector> devices{ std::make_pair(platform, device) }; + RendererCL renderer(devices); points.resize(renderer.TotalIterKernelCount()); @@ -1637,7 +1683,7 @@ void TestCpuGpuResults() } template -void TestGpuVectorRead() +void TestGpuVectorRead(size_t platform, size_t device) { T minx = TMAX, miny = TMAX, minz = TMAX, mincolorx = TMAX; T maxx = TLOW, maxy = TLOW, maxz = TLOW, maxcolorx = TLOW; @@ -1649,10 +1695,8 @@ void TestGpuVectorRead() VariationList vlf; QTIsaac rand; vector> points; - RendererCL renderer; - - if (!renderer.Init(1, 0, false, 0)) - return; + vector> devices{ std::make_pair(platform, device) }; + RendererCL renderer(devices); points.resize(renderer.TotalIterKernelCount()); @@ -1918,17 +1962,110 @@ void TestThreadedKernel() } } +template +void DistribTester() +{ + size_t i; + size_t distribCount = 1; + size_t xformCount = 3; + vector m_XformDistributions; + //const Xform* xforms = 3; + size_t j = 0; + vector weights { T(0.333333), T(1.0), T(0.25) }; + double tempDensity = 0, currentDensityLimit = 0, densityPerElement; + + if (m_XformDistributions.size() < CHOOSE_XFORM_GRAIN * distribCount) + m_XformDistributions.resize(CHOOSE_XFORM_GRAIN * distribCount); + + if (m_XformDistributions.size() < CHOOSE_XFORM_GRAIN * distribCount) + return; + + for (size_t distrib = 0; distrib < distribCount; distrib++) + { + double totalDensity = 0; + + //First find the total densities of all xforms. + for (i = 0; i < xformCount; i++) + { + T d = weights[i]; + + totalDensity += d; + } + + //Original returned false if all were 0, but it's allowed here + //which will just end up setting all elements to 0 which means + //only the first xform will get used. + + //Calculate how much of a fraction of a the total density each element represents. + j = 0; + tempDensity = 0; + currentDensityLimit = 0; + densityPerElement = totalDensity / CHOOSE_XFORM_GRAIN; + + //Assign xform indices in order to each element of m_XformDistributions. + //The number of elements assigned a given index is proportional to that xform's + //density relative to the sum of all densities. + for (i = 0; i < xformCount; i++) + { + T temp = weights[i]; + currentDensityLimit += temp; + + //Populate points corresponding to this xform's weight/density. + //Also check that j is within the bounds of the distribution array just to be safe in the case of a rounding error. + while (tempDensity < currentDensityLimit && j < CHOOSE_XFORM_GRAIN) + { +#ifdef _DEBUG + //Ensure distribution contains no out of bounds indices. + if (byte(i) >= xformCount) + throw "Out of bounds xform index in selection distribution."; +#endif + //printf("offset = %d, xform = %d, running sum = %f\n", j, i, tempDensity); + m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + j] = byte(i); + tempDensity += densityPerElement; + j++; + } + } + + + //Flam3 did this, which gives the same result. + //T t = xforms[0].m_Weight; + // + //if (distrib > 0) + // t *= xforms[distrib - 1].Xaos(0); + // + //T r = 0; + // + //for (i = 0; i < CHOOSE_XFORM_GRAIN; i++) + //{ + // while (r >= t) + // { + // j++; + // + // if (distrib > 0) + // t += xforms[j].m_Weight * xforms[distrib - 1].Xaos(j); + // else + // t += xforms[j].m_Weight; + // } + // + // m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + i] = j; + // r += densityPerElement; + //} + } +} + int _tmain(int argc, _TCHAR* argv[]) { //int i; + bool b = true; Timing t(4); QTIsaac rand(1, 2, 3); mt19937 meow(1729); - MakeTestAllVarsRegPrePostComboFile("testallvarsout.flame"); + + /*MakeTestAllVarsRegPrePostComboFile("testallvarsout.flame"); return 0; - /*TestThreadedKernel(); + TestThreadedKernel(); PaletteList palf; Palette* pal = palf.GetRandomPalette(); @@ -1939,7 +2076,7 @@ int _tmain(int argc, _TCHAR* argv[]) for (int i = 0; i < 10; i++) { - cout << "log10(" << d << ") = " << std::max(1u, uint(log10(d)) + 1u) << endl; + cout << "log10(" << d << ") = " << std::max(1u, uint(std::log10(d)) + 1u) << endl; d *= 10; } @@ -2041,7 +2178,7 @@ int _tmain(int argc, _TCHAR* argv[]) //cd2 = sin(cd); - /*t.Tic(); + t.Tic(); TestCasting(); t.Toc("TestCasting()"); @@ -2088,6 +2225,7 @@ int _tmain(int argc, _TCHAR* argv[]) TestVarCopy(); t.Toc("TestVarCopy()"); #endif + t.Tic(); TestVarRegPrePost(); t.Toc("TestVarRegPrePost()"); @@ -2121,17 +2259,22 @@ int _tmain(int argc, _TCHAR* argv[]) t.Toc("TestConstants()"); t.Tic(); + TestGlobalFuncs(); + t.Toc("TestGlobalFuncs()"); + + /*t.Tic(); TestXformsInOutPoints(); t.Toc("TestXformsInOutPoints()"); t.Tic(); TestVarTime(); t.Toc("TestVarTime()"); - + */ + t.Tic(); TestOperations(); t.Toc("TestOperations()"); - */ + //t.Tic(); //TestVarsSimilar(); //t.Toc("TestVarsSimilar()"); @@ -2141,18 +2284,34 @@ int _tmain(int argc, _TCHAR* argv[]) //TestCpuGpuResults(); //t.Toc("TestCpuGpuResults()"); - t.Tic(); - TestAllVarsCLBuild(); - t.Toc("TestAllVarsCLBuild()"); + //t.Tic(); + //b = TestAllVarsCLBuild(0, 0, true); + //t.Toc("TestAllVarsCLBuild()"); + + if (b) + { + t.Tic(); + b = TestAllVarsCLBuild(1, 0, true); + t.Toc("TestAllVarsCLBuild()"); + } #ifdef DO_DOUBLE //t.Tic(); //TestCpuGpuResults(); //t.Toc("TestCpuGpuResults()"); + if (b) + { + t.Tic(); + TestAllVarsCLBuild(0, 0, true); + t.Toc("TestAllVarsCLBuild()"); - t.Tic(); - TestAllVarsCLBuild(); - t.Toc("TestAllVarsCLBuild()"); + if (b) + { + t.Tic(); + TestAllVarsCLBuild(1, 0, true); + t.Toc("TestAllVarsCLBuild()"); + } + } #endif #endif diff --git a/Source/Fractorium/EmberFile.h b/Source/Fractorium/EmberFile.h index f923996..25bfbd8 100644 --- a/Source/Fractorium/EmberFile.h +++ b/Source/Fractorium/EmberFile.h @@ -114,7 +114,7 @@ public: { if (i != j && m_Embers[i].m_Name == m_Embers[j].m_Name) { - m_Embers[j].m_Name = m_Embers[j].m_Name + "_" + ToString(++x).toStdString(); + m_Embers[j].m_Name = IncrementTrailingUnderscoreInt(QString::fromStdString(m_Embers[j].m_Name)).toStdString(); j = 0; } } @@ -130,6 +130,33 @@ public: return "Flame_" + QDateTime(QDateTime::currentDateTime()).toString("yyyy-MM-dd-hhmmss"); } + /// + /// Return a copy of the string which ends with _# where # is the + /// previous number at that position incremented by one. + /// If the original string did not end with _#, the returned + /// string will just have _1 appended to it. + /// + /// The string to process + /// The original string with the number after the final _ character incremented by one + static QString IncrementTrailingUnderscoreInt(const QString& str) + { + bool ok = false; + size_t num = 0; + QString endSection; + QString ret = str; + int lastUnderscore = str.lastIndexOf('_'); + + if (lastUnderscore != -1) + { + endSection = str.section('_', -1); + num = endSection.toULongLong(&ok); + ret.chop(str.size() - lastUnderscore); + } + + ret += "_" + QString::number(num + 1); + return ret; + } + /// /// Ensures a given input filename is unique by appending a count to the end. /// @@ -146,10 +173,11 @@ public: QString path = original.absolutePath() + '/'; QString base = original.completeBaseName(); QString extension = original.suffix(); - + do { - newPath = path + base + "_" + ToString(counter++) + "." + extension; + base = IncrementTrailingUnderscoreInt(base); + newPath = path + base + "." + extension; } while (QFile::exists(newPath)); @@ -164,7 +192,7 @@ public: /// The default ember name static QString DefaultEmberName(uint i) { - return DefaultFilename() + "-" + ToString(i); + return DefaultFilename() + "_" + ToString(i); } QString m_Filename; diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index 59015db..cdd6e67 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -331,6 +331,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e) } else if (QKeyEvent* ke = dynamic_cast(e)) { + bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); + if (ke->key() >= Qt::Key_F1 && ke->key() <= Qt::Key_F32) { int val = ke->key() - (int)Qt::Key_F1; @@ -340,7 +342,8 @@ bool Fractorium::eventFilter(QObject* o, QEvent* e) } else if (o == ui.LibraryTree) { - if (ke->key() == Qt::Key_Delete && e->type() == QEvent::KeyRelease) + //Require shift for deleting to prevent it from triggering when the user enters delete in the edit box. + if (ke->key() == Qt::Key_Delete && e->type() == QEvent::KeyRelease && shift) { auto p = GetCurrentEmberIndex(); diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index b29f075..34d0728 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -5046,6 +5046,9 @@ 0 + + true + Qt::WheelFocus @@ -5065,10 +5068,10 @@ QAbstractItemView::NoEditTriggers - QAbstractItemView::NoSelection + QAbstractItemView::SingleSelection - QAbstractItemView::SelectItems + QAbstractItemView::SelectRows 12 diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index e595440..003a9a7 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -213,6 +213,12 @@ void FractoriumEmberController::EmberTreeItemChanged(QTreeWidgetItem* item, i if (emberItem) { + if (emberItem->text(0).isEmpty())//Prevent empty string. + { + emberItem->UpdateEditText(); + return; + } + string oldName = emberItem->GetEmber()->m_Name;//First preserve the previous name. tree->blockSignals(true); diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index eb659c9..bf99e46 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -65,10 +65,10 @@ void FractoriumEmberController::NewFlock(size_t count) for (size_t i = 0; i < count; i++) { - m_SheepTools->Random(ember, m_FilteredVariations, static_cast(QTIsaac::GlobalRand->Frand(-2, 2)), 0); + m_SheepTools->Random(ember, m_FilteredVariations, static_cast(QTIsaac::GlobalRand->Frand(-2, 2)), 0, MAX_CL_VARS); ParamsToEmber(ember); ember.m_Index = i; - ember.m_Name = m_EmberFile.m_Filename.toStdString() + "-" + ToString(i + 1ULL).toStdString(); + ember.m_Name = m_EmberFile.m_Filename.toStdString() + "_" + ToString(i + 1ULL).toStdString(); m_EmberFile.m_Embers.push_back(ember); } @@ -126,7 +126,7 @@ void FractoriumEmberController::NewRandomFlameInCurrentFile() Ember ember; StopPreviewRender(); - m_SheepTools->Random(ember, m_FilteredVariations, static_cast(QTIsaac::GlobalRand->Frand(-2, 2)), 0); + m_SheepTools->Random(ember, m_FilteredVariations, static_cast(QTIsaac::GlobalRand->Frand(-2, 2)), 0, MAX_CL_VARS); ParamsToEmber(ember); ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.Size() + 1).toStdString(); ember.m_Index = m_EmberFile.Size(); diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp index 19e2ba1..0146c2b 100644 --- a/Source/Fractorium/FractoriumParams.cpp +++ b/Source/Fractorium/FractoriumParams.cpp @@ -79,7 +79,7 @@ void Fractorium::InitParamsUI() SetupCombo(table, this, row, 1, m_TemporalFilterTypeCombo, comboVals, SIGNAL(currentIndexChanged(const QString&)), SLOT(OnTemporalFilterTypeComboCurrentIndexChanged(const QString&))); SetupSpinner(table, this, row, 1, m_DEFilterMinRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMinRadiusWidthChanged(double)), true, 0, 0, 0); - SetupSpinner(table, this, row, 1, m_DEFilterMaxRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMaxRadiusWidthChanged(double)), true, 9.0, 9.0, 0); + SetupSpinner(table, this, row, 1, m_DEFilterMaxRadiusSpin, spinHeight, 0, 25, 1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterMaxRadiusWidthChanged(double)), true, 0.0, 9.0, 0); SetupSpinner(table, this, row, 1, m_DECurveSpin, spinHeight, 0.15, 5, 0.1, SIGNAL(valueChanged(double)), SLOT(OnDEFilterCurveWidthChanged(double)), true, 0.4, 0.4, 0.4); //Iteration. @@ -89,7 +89,7 @@ void Fractorium::InitParamsUI() SetupSpinner( table, this, row, 1, m_FuseSpin, spinHeight, 1, 1000, 5, SIGNAL(valueChanged(int)), SLOT(OnFuseChanged(int)), true, 15, 15, 15); SetupSpinner(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 10, 10, 10); SetupSpinner( table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1); - SetupSpinner( table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 50, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000); + SetupSpinner( table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 1, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000); comboVals.clear(); comboVals.push_back("Step"); @@ -412,8 +412,8 @@ void Fractorium::OnFuseChanged(int d) { m_Controller->FuseChanged(d); } /// the rendering process is continued, else it's reset. ///
/// The quality in terms of iterations per pixel -template void FractoriumEmberController::QualityChanged(double d) { Update([&] { m_Ember.m_Quality = d; }, true, d > m_Ember.m_Quality ? KEEP_ITERATING : FULL_RENDER); } -void Fractorium::OnQualityChanged(double d) { m_Controller->QualityChanged(d); } +template void FractoriumEmberController::QualityChanged(double d) { /*Update([&] { m_Ember.m_Quality = d; }, true, d > m_Ember.m_Quality ? KEEP_ITERATING : FULL_RENDER);*/ } +void Fractorium::OnQualityChanged(double d) { /*m_Controller->QualityChanged(d);*/ } /// /// Set the supersample. @@ -452,11 +452,11 @@ void FractoriumEmberController::AffineInterpTypeChanged(int i) Update([&] { if (i == 0) - m_Ember.m_AffineInterp = INTERP_LINEAR; + m_Ember.m_AffineInterp = AFFINE_INTERP_LINEAR; else if (i == 1) - m_Ember.m_AffineInterp = INTERP_LOG; + m_Ember.m_AffineInterp = AFFINE_INTERP_LOG; else - m_Ember.m_AffineInterp = INTERP_LINEAR; + m_Ember.m_AffineInterp = AFFINE_INTERP_LINEAR; }, true, NOTHING); } diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index 1178f1e..86a874d 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -301,7 +301,33 @@ bool FractoriumEmberController::Render() bool success = true; GLWidget* gl = m_Fractorium->ui.GLDisplay; RendererCL* rendererCL = nullptr; - eProcessAction action = CondenseAndClearProcessActions(); + eProcessAction qualityAction, action; + + //Quality is the only parameter we update inside the timer. + //This is to allow the user to rapidly increase the quality spinner + //without fully resetting the render. Instead, it will just keep iterating + //where it last left off in response to an increase. + T d = T(m_Fractorium->m_QualitySpin->value()); + + if (d < m_Ember.m_Quality)//Full restart if quality decreased. + { + m_Ember.m_Quality = d; + qualityAction = eProcessAction::FULL_RENDER; + } + else if (d > m_Ember.m_Quality && ProcessState() == ACCUM_DONE)//If quality increased, keep iterating after current render finishes. + { + m_Ember.m_Quality = d; + qualityAction = eProcessAction::KEEP_ITERATING; + } + else if (IsClose(d, m_Ember.m_Quality)) + qualityAction = eProcessAction::NOTHING; + + if (qualityAction == eProcessAction::FULL_RENDER) + Update([&] {});//Stop the current render, a full restart is needed. + else if (qualityAction == eProcessAction::KEEP_ITERATING) + m_ProcessActions.push_back(qualityAction);//Special, direct call to avoid resetting the render inside Update() because only KEEP_ITERATING is needed. + + action = CondenseAndClearProcessActions();//Combine with all other previously requested actions. if (m_Renderer->RendererType() == OPENCL_RENDERER) rendererCL = dynamic_cast*>(m_Renderer.get()); @@ -391,7 +417,7 @@ bool FractoriumEmberController::Render() //Only certain stats can be reported with OpenCL. if (m_Renderer->RendererType() == OPENCL_RENDERER) { - m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Total time: " + QString::fromStdString(renderTime)); + m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Total time: " + QString::fromStdString(renderTime) + "."); } else { @@ -399,7 +425,7 @@ bool FractoriumEmberController::Render() QString badVals = ToString(stats.m_Badvals); QString badPercent = QLocale::system().toString(percent * 100, 'f', 2); - m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime)); + m_Fractorium->m_RenderStatusLabel->setText("Iters: " + iters + ". Scaled quality: " + scaledQuality + ". Bad values: " + badVals + " (" + badPercent + "%). Total time: " + QString::fromStdString(renderTime) + "."); } if (m_LastEditWasUndoRedo && (m_UndoIndex == m_UndoList.size() - 1))//Traversing through undo list, reached the end, so put back in regular edit mode. diff --git a/Source/Fractorium/OptionsDialog.cpp b/Source/Fractorium/OptionsDialog.cpp index dc7e10e..78d96f1 100644 --- a/Source/Fractorium/OptionsDialog.cpp +++ b/Source/Fractorium/OptionsDialog.cpp @@ -18,8 +18,8 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(FractoriumSettings* settings, Q m_Settings = settings; QTableWidget* table = ui.OptionsXmlSavingTable; ui.ThreadCountSpin->setRange(1, Timing::ProcessorCount()); - connect(ui.OpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection); - connect(ui.DeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection); + connect(ui.OpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection); + connect(ui.DeviceTable, SIGNAL(cellChanged(int, int)), this, SLOT(OnDeviceTableCellChanged(int, int)), Qt::QueuedConnection); SetupSpinner(table, this, row, 1, m_XmlTemporalSamplesSpin, spinHeight, 1, 1000, 100, "", "", true, 1000); SetupSpinner(table, this, row, 1, m_XmlQualitySpin, spinHeight, 1, 200000, 50, "", "", true, 1000); diff --git a/Source/Fractorium/QssDialog.cpp b/Source/Fractorium/QssDialog.cpp index 330043a..a30a006 100644 --- a/Source/Fractorium/QssDialog.cpp +++ b/Source/Fractorium/QssDialog.cpp @@ -70,7 +70,6 @@ QssDialog::QssDialog(Fractorium* parent) : connect(ui->QssLoadButton, SIGNAL(clicked()), this, SLOT(LoadButton_clicked()), Qt::QueuedConnection); connect(ui->QssSaveButton, SIGNAL(clicked()), this, SLOT(SaveButton_clicked()), Qt::QueuedConnection); - connect(ui->QssSaveDefaultButton, SIGNAL(clicked()), this, SLOT(SaveDefaultButton_clicked()), Qt::QueuedConnection); connect(ui->QssBasicButton, SIGNAL(clicked()), this, SLOT(BasicButton_clicked()), Qt::QueuedConnection); connect(ui->QssMediumButton, SIGNAL(clicked()), this, SLOT(MediumButton_clicked()), Qt::QueuedConnection); connect(ui->QssAdvancedButton, SIGNAL(clicked()), this, SLOT(AdvancedButton_clicked()), Qt::QueuedConnection); @@ -310,7 +309,7 @@ void QssDialog::accept() if (m_Theme) m_Parent->m_Settings->Theme(m_Theme->objectName()); - SaveDefaultButton_clicked(); + SaveAsDefault(); QDialog::accept(); } @@ -506,11 +505,20 @@ void QssDialog::LoadButton_clicked() /// /// Save the stylesheet to disk. /// Called when the user clicks the save button. +/// The user cannot save to default.qss, as it's a special placeholder. +/// When they exit the dialog by clicking OK, the currently displayed stylesheet +/// will be saved to default.qss. /// void QssDialog::SaveButton_clicked() { auto path = SaveFile(); + if (path.toLower().endsWith("default.qss")) + { + QMessageBox::critical(this, "File save error", "Stylesheet cannot be saved to default.qss. Save it to a different file name, then exit the dialog by clicking OK which will set it as the default."); + return; + } + if (!path.isEmpty()) { ofstream of(path.toStdString()); @@ -522,16 +530,16 @@ void QssDialog::SaveButton_clicked() of.close(); } else - QMessageBox::critical(this, "File open error", "Failed to open " + path + ", style will not be set as default"); + QMessageBox::critical(this, "File save error", "Failed to save " + path + ", style will not be set as default"); } } /// /// Save the stylesheet to the default.qss on disk. /// This will be loaded the next time Fractorium runs. -/// Called when the user clicks the save as default button. +/// Called when the user clicks ok. /// -void QssDialog::SaveDefaultButton_clicked() +void QssDialog::SaveAsDefault() { auto path = m_Parent->m_SettingsPath + "/default.qss"; ofstream of(path.toStdString()); @@ -543,7 +551,7 @@ void QssDialog::SaveDefaultButton_clicked() of.close(); } else - QMessageBox::critical(this, "File open error", "Failed to open " + path + ", style will not be set as default"); + QMessageBox::critical(this, "File save error", "Failed to save " + path + ", style will not be set as default"); } /// diff --git a/Source/Fractorium/QssDialog.h b/Source/Fractorium/QssDialog.h index 958d556..9c66a27 100644 --- a/Source/Fractorium/QssDialog.h +++ b/Source/Fractorium/QssDialog.h @@ -107,12 +107,12 @@ private slots: void LoadButton_clicked(); void SaveButton_clicked(); - void SaveDefaultButton_clicked(); void BasicButton_clicked(); void MediumButton_clicked(); void AdvancedButton_clicked(); private: + void SaveAsDefault(); void InsertCssProperty(const QString &name, const QString &value); void SetupFileDialog(); QString OpenFile(); diff --git a/Source/Fractorium/QssDialog.ui b/Source/Fractorium/QssDialog.ui index 5120819..5ba232a 100644 --- a/Source/Fractorium/QssDialog.ui +++ b/Source/Fractorium/QssDialog.ui @@ -47,13 +47,6 @@ - - - - Save as default - - - diff --git a/Source/Fractorium/qcssparser.cpp b/Source/Fractorium/qcssparser.cpp index 9f444b7..9737f76 100644 --- a/Source/Fractorium/qcssparser.cpp +++ b/Source/Fractorium/qcssparser.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ #include "FractoriumPch.h" -#include "qcssparser.h" #include "qcssscanner.h" ///