diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index e9b69e8..728785d 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -13,7 +13,7 @@ - + + @@ -313,6 +314,7 @@ Create + diff --git a/Builds/MSVC/VS2013/Ember.vcxproj.filters b/Builds/MSVC/VS2013/Ember.vcxproj.filters index 16ebec4..32450ef 100644 --- a/Builds/MSVC/VS2013/Ember.vcxproj.filters +++ b/Builds/MSVC/VS2013/Ember.vcxproj.filters @@ -110,6 +110,9 @@ Header Files\Variations + + Header Files + @@ -127,5 +130,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj b/Builds/MSVC/VS2013/Fractorium.vcxproj index fe46e6f..0bc1f0f 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj @@ -245,6 +245,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true false + /bigobj -Zm150 %(AdditionalOptions) Windows @@ -276,6 +277,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true false + /bigobj -Zm150 %(AdditionalOptions) Windows @@ -399,7 +401,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true - + true true true @@ -479,11 +481,11 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true - - true - true + true true + true + true true @@ -545,7 +547,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true - + true true true @@ -701,31 +703,31 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)""$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/FractoriumSettings.h" "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/FractoriumSettings.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." - - $(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) - Moc%27ing TwoButtonWidget.h... + + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) + Moc%27ing TwoButtonComboWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." - $(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) - Moc%27ing TwoButtonWidget.h... + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonComboWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) + Moc%27ing TwoButtonComboWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." - $(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) - $(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) - Moc%27ing TwoButtonWidget.h... - Moc%27ing TwoButtonWidget.h... + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonComboWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) + Moc%27ing TwoButtonComboWidget.h... + Moc%27ing TwoButtonComboWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." - $(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) - $(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) - Moc%27ing TwoButtonWidget.h... - Moc%27ing TwoButtonWidget.h... + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonComboWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonComboWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) + $(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath);%(AdditionalInputs) + Moc%27ing TwoButtonComboWidget.h... + Moc%27ing TwoButtonComboWidget.h... .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." - "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonComboWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/TwoButtonComboWidget.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." @@ -1119,7 +1121,7 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)" - + \ No newline at end of file diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters index cdf1d0e..bfb6e5e 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters @@ -133,15 +133,6 @@ Controllers - - Generated Files\Debug - - - Generated Files\Release - - - Generated Files\ReleaseNvidia - Generated Files\Debug @@ -232,6 +223,15 @@ Generated Files\ReleaseNvidia + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\ReleaseNvidia + @@ -323,7 +323,7 @@ Header Files - + Widgets diff --git a/Data/Version History.txt b/Data/Version History.txt index 2063f77..f364bb8 100644 --- a/Data/Version History.txt +++ b/Data/Version History.txt @@ -1,3 +1,35 @@ +0.4.1.3 Beta 10/14/2014 +--User Changes + Size is no longer fixed to the window size. + Size scaling is done differently in the final render dialog. This fixes several bugs. + Remove Xml saving size from settings and options dialog, it no longer applies. + Final render can be broken into strips. + Set default save path to the desktop if none is found in the settings file. + Set default output size to 1920x1080 if none is found in the settings file. + +--Bug Fixes + Better memory size reporting in final render dialog. + +--Code Changes + Migrate to C++11, Qt 5.3.1, and Visual Studio 2013. + Change most instances of unsigned int to size_t, and int to intmax_t. + Add m_OrigPixPerUnit and m_ScaleType to Ember for scaling purposes. + Replace some sprintf_s() calls in XmlToEmber with ostringstream. + Move more non-templated members into RendererBase. + Add CopyVec() overload that takes a per element function pointer. + Add vector Memset(). + Replace '&' with '+' instead of "&" in XmlToEmber for much faster parsing. + Break strips rendering out into EmberCommon and call from EmberRender and Fractorium. + Make AddAndWriteBuffer() just call WriteBuffer(). + Make AddAndWriteImage() delete the existing image first before replacing it. + Add SetOutputTexture() to RendererCL to support making new textures in response to resize events. + Remove multiple return statements in RendererCL, and replace with a bool that tracks results. + Add ToDouble(), MakeEnd(), ToString() and Exists() wrappers in Fractorium. + Add Size() wrapper in EmberFile. + Make QString function arguments const QString&, and string with const string&. + Make ShowCritical() wrapper for invoking a message box from another thread. + Add combo box to TwoButtonWidget and rename. + 0.4.1.2 Beta 08/05/2014 --User Changes Add --yaxisup and --supersample options for command line programs. diff --git a/Source/Ember/CarToRas.h b/Source/Ember/CarToRas.h index 8590b78..af920c5 100644 --- a/Source/Ember/CarToRas.h +++ b/Source/Ember/CarToRas.h @@ -39,7 +39,7 @@ public: /// The width in pixels of the raster image/histogram /// The height in pixels of the raster image/histogram /// The aspect ratio, generally 1 - CarToRas(T carLlX, T carLlY, T carUrX, T carUrY, unsigned int rasW, unsigned int rasH, T aspectRatio) + CarToRas(T carLlX, T carLlY, T carUrX, T carUrY, size_t rasW, size_t rasH, T aspectRatio) { Init(carLlX, carLlY, carUrX, carUrY, rasW, rasH, aspectRatio); } @@ -113,7 +113,7 @@ public: /// The width in pixels of the raster image/histogram /// The height in pixels of the raster image/histogram /// The aspect ratio, generally 1 - void Init(T carLlX, T carLlY, T carUrX, T carUrY, unsigned int rasW, unsigned int rasH, T aspectRatio) + void Init(T carLlX, T carLlY, T carUrX, T carUrY, size_t rasW, size_t rasH, T aspectRatio) { m_RasWidth = rasW; m_RasHeight = rasH; @@ -156,10 +156,10 @@ public: /// The cartesian y /// The converted raster x /// The converted raster y - inline void Convert(T cartX, T cartY, unsigned int& rasX, unsigned int& rasY) + inline void Convert(T cartX, T cartY, size_t& rasX, size_t& rasY) { - rasX = (unsigned int)(m_PixPerImageUnitW * cartX - m_RasLlX); - rasY = (unsigned int)(m_RasLlY - (m_PixPerImageUnitH * cartY)); + rasX = (size_t)(m_PixPerImageUnitW * cartX - m_RasLlX); + rasY = (size_t)(m_RasLlY - (m_PixPerImageUnitH * cartY)); } /// @@ -173,9 +173,9 @@ public: /// The cartesian x /// The cartesian y /// The converted single raster buffer index - inline void Convert(T cartX, T cartY, unsigned int& singleBufferIndex) + inline void Convert(T cartX, T cartY, size_t& singleBufferIndex) { - singleBufferIndex = (unsigned int)(m_PixPerImageUnitW * cartX - m_RasLlX) + (m_RasWidth * (unsigned int)(m_PixPerImageUnitH * cartY - m_RasLlY)); + singleBufferIndex = (size_t)(m_PixPerImageUnitW * cartX - m_RasLlX) + (m_RasWidth * (size_t)(m_PixPerImageUnitH * cartY - m_RasLlY)); } /// @@ -190,9 +190,9 @@ public: /// /// The cartesian y /// The converted single raster buffer index - inline void Convert(Point& point, unsigned int& singleBufferIndex) + inline void Convert(Point& point, size_t& singleBufferIndex) { - singleBufferIndex = (unsigned int)(m_PixPerImageUnitW * point.m_X - m_RasLlX) + (m_RasWidth * (unsigned int)(m_PixPerImageUnitH * point.m_Y - m_RasLlY)); + singleBufferIndex = (size_t)(m_PixPerImageUnitW * point.m_X - m_RasLlX) + (m_RasWidth * (size_t)(m_PixPerImageUnitH * point.m_Y - m_RasLlY)); } /// @@ -221,8 +221,8 @@ public: /// /// Accessors. /// - inline unsigned int RasWidth() const { return m_RasWidth; } - inline unsigned int RasHeight() const { return m_RasHeight; } + inline size_t RasWidth() const { return m_RasWidth; } + inline size_t RasHeight() const { return m_RasHeight; } inline T OneRow() const { return m_OneRow; } inline T OneCol() const { return m_OneCol; } inline T PixPerImageUnitW() const { return m_PixPerImageUnitW; } @@ -239,7 +239,7 @@ public: inline T PadCarUrY() const { return m_PadCarUrY; } private: - unsigned int m_RasWidth, m_RasHeight;//The width and height of the raster image. + size_t m_RasWidth, m_RasHeight;//The width and height of the raster image. T m_OneRow;//The distance that one raster row represents in the cartesian plane. T m_OneCol;//The distance that one raster column represents in the cartesian plane. T m_PixPerImageUnitW;//The number of columns in the raster plane that a horizontal distance of 1 in the cartesian plane represents. The higher the number, the more zoomed in. diff --git a/Source/Ember/DensityFilter.h b/Source/Ember/DensityFilter.h index 9ab3216..ec6436e 100644 --- a/Source/Ember/DensityFilter.h +++ b/Source/Ember/DensityFilter.h @@ -18,7 +18,7 @@ public: DensityFilterBase() { } virtual ~DensityFilterBase() { } - virtual int FilterWidth() const { return 0; } + virtual intmax_t FilterWidth() const { return 0; } }; /// @@ -42,7 +42,7 @@ public: /// The maximum filter radius /// The curve of the filter /// The supersample of the ember this filter will be used with - DensityFilter(T minRad, T maxRad, T curve, unsigned int supersample) + DensityFilter(T minRad, T maxRad, T curve, size_t supersample) { m_MinRad = minRad; m_MaxRad = maxRad; @@ -99,10 +99,10 @@ public: /// True if success, else false. bool Create() { - int i, j, w; + size_t w; int intFilterCount, maxIndex; int rowSize; - int filterLoop; + size_t filterLoop; int keepThresh = 100; unsigned int filterCoefIndex = 0; T decFilterCount; @@ -147,8 +147,8 @@ public: //Generate the filter coefficients. for (filterLoop = 0; filterLoop < maxIndex; filterLoop++) { - int dej, dek; - int coefIndex; + intmax_t dej, dek; + size_t coefIndex; T filterSum = 0.0; T filterVal; T filterHeight; @@ -218,9 +218,9 @@ public: //This will populate one quadrant of filter indices. //Really only need 1/8th, but that would require a sparse matrix. - for (j = 0; j <= m_FilterWidth; j++) + for (intmax_t j = 0; j <= m_FilterWidth; j++) { - for (i = 0; i <= j; i++, filterCoefIndex++) + for (intmax_t i = 0; i <= j; i++, filterCoefIndex++) { if (j == 0 && i == 0) { @@ -265,7 +265,7 @@ public: /// The string representation of this density estimation filter string ToString() const { - unsigned int i, j, coefIndex = 0, w = m_FilterWidth + 1; + size_t i, j, coefIndex = 0, w = m_FilterWidth + 1; stringstream ss; ss @@ -312,15 +312,15 @@ public: inline T MinRad() const { return m_MinRad; } inline T MaxRad() const { return m_MaxRad; } inline T Curve() const { return m_Curve; } - inline unsigned int Supersample() const { return m_Supersample; } - inline unsigned int KernelSize() const { return m_KernelSize; } - inline unsigned int MaxFilterIndex() const { return m_MaxFilterIndex; } - inline unsigned int MaxFilteredCounts() const { return m_MaxFilteredCounts; } - virtual int FilterWidth() const override { return m_FilterWidth; } - inline unsigned int BufferSize() const { return (unsigned int)m_Widths.size(); } - inline unsigned int CoefsSizeBytes() const { return BufferSize() * m_KernelSize * sizeof(T); } - inline unsigned int WidthsSizeBytes() const { return BufferSize() * sizeof(T); } - inline unsigned int CoefsIndicesSizeBytes() const { return (unsigned int)(m_CoefIndices.size() * sizeof(unsigned int)); } + inline size_t Supersample() const { return m_Supersample; } + inline size_t KernelSize() const { return m_KernelSize; } + inline size_t MaxFilterIndex() const { return m_MaxFilterIndex; } + inline size_t MaxFilteredCounts() const { return m_MaxFilteredCounts; } + virtual intmax_t FilterWidth() const override { return m_FilterWidth; } + inline size_t BufferSize() const { return m_Widths.size(); } + inline size_t CoefsSizeBytes() const { return BufferSize() * m_KernelSize * sizeof(T); } + inline size_t WidthsSizeBytes() const { return BufferSize() * sizeof(T); } + inline size_t CoefsIndicesSizeBytes() const { return (m_CoefIndices.size() * sizeof(m_CoefIndices[0])); } inline const T* Coefs() const { return m_Coefs.data(); } inline const T* Widths() const { return m_Widths.data(); } inline const unsigned int* CoefIndices() const { return m_CoefIndices.data(); } @@ -329,11 +329,11 @@ private: T m_MinRad; T m_MaxRad;//The original specified filter radius. T m_Curve; - unsigned int m_Supersample; - unsigned int m_KernelSize; - unsigned int m_MaxFilterIndex; - unsigned int m_MaxFilteredCounts; - int m_FilterWidth;//The new radius after scaling for super sample and rounding. This is what's actually used. + size_t m_Supersample; + size_t m_KernelSize; + size_t m_MaxFilterIndex; + size_t m_MaxFilteredCounts; + intmax_t m_FilterWidth;//The new radius after scaling for super sample and rounding. This is what's actually used. vector m_Coefs; vector m_Widths; vector m_CoefIndices; diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index 22aec38..0bbd8f2 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -91,6 +91,7 @@ public: m_FinalRasH = ember.m_FinalRasH; m_OrigFinalRasW = ember.m_OrigFinalRasW; m_OrigFinalRasH = ember.m_OrigFinalRasH; + m_OrigPixPerUnit = ember.m_OrigPixPerUnit; m_Supersample = ember.m_Supersample; m_Passes = ember.m_Passes; m_TemporalSamples = ember.m_TemporalSamples; @@ -137,11 +138,12 @@ public: m_ParentFilename = ember.m_ParentFilename; m_Index = ember.m_Index; + m_ScaleType = ember.ScaleType(); m_Palette = ember.m_Palette; m_Xforms.clear(); - for (unsigned int i = 0; i < ember.XformCount(); i++) + for (size_t i = 0; i < ember.XformCount(); i++) { if (Xform* p = ember.GetXform(i)) { @@ -181,6 +183,7 @@ public: m_FinalRasH = 1080; m_OrigFinalRasW = 1920; m_OrigFinalRasH = 1080; + m_OrigPixPerUnit = 240; m_Supersample = 1; m_Passes = 1; m_TemporalSamples = 1000; @@ -233,6 +236,7 @@ public: //Internal values. m_Index = 0; + m_ScaleType = eScaleType::SCALE_NONE; m_Xforms.reserve(12); m_Edits = nullptr; @@ -253,9 +257,9 @@ public: /// Add the specified number of empty xforms. /// /// The number of xforms to add - void AddXforms(unsigned int count) + void AddXforms(size_t count) { - for (unsigned int i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { Xform xform; @@ -267,7 +271,7 @@ public: /// Add empty padding xforms until the total xform count is xformPad. /// /// The total number of xforms to finish with - void PadXforms(unsigned int xformPad) + void PadXforms(size_t xformPad) { if (xformPad > XformCount()) AddXforms(xformPad - XformCount()); @@ -279,7 +283,7 @@ public: /// The total number of xforms if additional padding xforms are desired. Default: 0. /// Whether to copy the final xform. Default: false. /// The newly constructed ember - Ember Copy(unsigned int xformPad = 0, bool doFinal = false) + Ember Copy(size_t xformPad = 0, bool doFinal = false) { Ember ember(*this); @@ -311,7 +315,7 @@ public: /// /// The index to delete /// True if success, else false. - bool DeleteXform(unsigned int i) + bool DeleteXform(size_t i) { Xform* xform; @@ -320,11 +324,11 @@ public: m_Xforms.erase(m_Xforms.begin() + i); //Now shuffle xaos values from i on back by 1 for every xform. - for (unsigned int x1 = 0; x1 < XformCount(); x1++) + for (size_t x1 = 0; x1 < XformCount(); x1++) { if ((xform = GetXform(x1))) { - for (unsigned int x2 = i + 1; x2 <= XformCount(); x2++)//Iterate from the position after the deletion index up to the old count. + for (size_t x2 = i + 1; x2 <= XformCount(); x2++)//Iterate from the position after the deletion index up to the old count. xform->SetXaos(x2 - 1, xform->Xaos(x2)); xform->TruncateXaos();//Make sure no old values are hanging around in case more xforms are added to this ember later. @@ -342,7 +346,7 @@ public: /// /// The index to delete /// True if success, else false. - bool DeleteTotalXform(unsigned int i) + bool DeleteTotalXform(size_t i) { if (DeleteXform(i)) { } @@ -359,7 +363,7 @@ public: /// /// The index to get /// A pointer to the xform at the index if successful, else nullptr. - Xform* GetXform(unsigned int i) const + Xform* GetXform(size_t i) const { if (i < XformCount()) return (Xform*)&m_Xforms[i]; @@ -373,7 +377,7 @@ public: /// The index to get /// If true, return the final xform when its index is requested even if one is not present /// A pointer to the xform at the index if successful, else nullptr. - Xform* GetTotalXform(unsigned int i, bool forceFinal = false) const + Xform* GetTotalXform(size_t i, bool forceFinal = false) const { if (i < XformCount()) return (Xform*)&m_Xforms[i]; @@ -388,13 +392,13 @@ public: /// /// A pointer to the xform to find /// The index of the matched xform if found, else -1. - int GetXformIndex(Xform* xform) const + intmax_t GetXformIndex(Xform* xform) const { - int index = -1; + intmax_t index = -1; - for (unsigned int i = 0; i < m_Xforms.size(); i++) + for (size_t i = 0; i < m_Xforms.size(); i++) if (GetXform(i) == xform) - return (int)i; + return (intmax_t)i; return index; } @@ -404,13 +408,13 @@ public: /// /// A pointer to the xform to find /// The index of the matched xform if found, else -1. - int GetTotalXformIndex(Xform* xform) const + intmax_t GetTotalXformIndex(Xform* xform) const { - unsigned int totalXformCount = TotalXformCount(); + size_t totalXformCount = TotalXformCount(); - for (unsigned int i = 0; i < totalXformCount; i++) + for (size_t i = 0; i < totalXformCount; i++) if (GetTotalXform(i) == xform) - return (int)i; + return (intmax_t)i; return -1; } @@ -449,7 +453,7 @@ public: /// void DeleteMotionElements() { - for (unsigned int i = 0; i < TotalXformCount(); i++) + for (size_t i = 0; i < TotalXformCount(); i++) GetTotalXform(i)->DeleteMotionElements(); } @@ -458,7 +462,7 @@ public: /// void CacheXforms() { - for (unsigned int i = 0; i < TotalXformCount(); i++) + for (size_t i = 0; i < TotalXformCount(); i++) { Xform* xform = GetTotalXform(i); @@ -467,9 +471,13 @@ public: } } + /// + /// Set the projection function pointer based on the + /// values of the 3D fields. + /// void SetProjFunc() { - unsigned int projBits = ProjBits(); + size_t projBits = ProjBits(); if (!projBits)//No 3D at all, then do nothing. { @@ -514,11 +522,11 @@ public: /// Determine whether xaos is used in any xform, excluding final. /// /// True if any xaos found, else false. - bool XaosPresent() + bool XaosPresent() const { bool b = false; - ForEach(m_Xforms, [&](Xform& xform) { b |= xform.XaosPresent(); });//If at least one entry is not equal to 1, then xaos is present. + ForEach(m_Xforms, [&](const Xform& xform) { b |= xform.XaosPresent(); });//If at least one entry is not equal to 1, then xaos is present. return b; } @@ -538,20 +546,41 @@ public: /// New width /// New height /// True to only scale if the new dimensions are smaller than the original, else always scale. - void SetSizeAndAdjustScale(unsigned int width, unsigned int height, bool onlyScaleIfNewIsSmaller, eScaleType scaleType) + void SetSizeAndAdjustScale(size_t width, size_t height, bool onlyScaleIfNewIsSmaller, eScaleType scaleType) { - if ((onlyScaleIfNewIsSmaller && (width < m_FinalRasW || height < m_FinalRasH)) || !onlyScaleIfNewIsSmaller) + if ((onlyScaleIfNewIsSmaller && (width < m_OrigFinalRasW || height < m_OrigFinalRasH)) || !onlyScaleIfNewIsSmaller) { if (scaleType == SCALE_WIDTH) - m_PixelsPerUnit *= T(width) / T(m_FinalRasW); + m_PixelsPerUnit = m_OrigPixPerUnit * (T(width) / T(m_OrigFinalRasW)); else if (scaleType == SCALE_HEIGHT) - m_PixelsPerUnit *= T(height) / T(m_FinalRasH); + m_PixelsPerUnit = m_OrigPixPerUnit * (T(height) / T(m_OrigFinalRasH)); } + m_ScaleType = scaleType; m_FinalRasW = width; m_FinalRasH = height; } + /// + /// Set the original final output image dimensions to be equal to the current ones. + /// + void SyncSize() + { + m_OrigFinalRasW = m_FinalRasW; + m_OrigFinalRasH = m_FinalRasH; + m_OrigPixPerUnit = m_PixelsPerUnit; + } + + /// + /// Set the current final output image dimensions to be equal to the original ones. + /// + void RestoreSize() + { + m_FinalRasW = m_OrigFinalRasW; + m_FinalRasH = m_OrigFinalRasH; + m_PixelsPerUnit = m_OrigPixPerUnit; + } + /// /// Set all xform weights to 1 / xform count. /// @@ -586,7 +615,7 @@ public: /// void GetPresentVariations(vector*>& variations, bool baseOnly = true) const { - unsigned int i = 0, xformIndex = 0, totalVarCount = m_FinalXform.TotalVariationCount(); + size_t i = 0, xformIndex = 0, totalVarCount = m_FinalXform.TotalVariationCount(); variations.clear(); ForEach(m_Xforms, [&](const Xform& xform) { totalVarCount += xform.TotalVariationCount(); }); @@ -675,7 +704,7 @@ public: return; bool allID, final; - unsigned int i, j, k, l, maxXformCount, totalXformCount; + size_t l, maxXformCount, totalXformCount; T bgAlphaSave = m_Background.a; T coefSave[2] {0, 0}; vector*> xformVec; @@ -683,15 +712,15 @@ public: //Palette and others if (embers[0].m_PaletteInterp == INTERP_HSV) { - for (i = 0; i < 256; i++) + for (glm::length_t i = 0; i < 256; i++) { T t[3], s[4] = { 0, 0, 0, 0 }; - for (k = 0; k < size; k++) + for (glm::length_t k = 0; k < size; k++) { Palette::RgbToHsv(glm::value_ptr(embers[k].m_Palette[i]), t); - for (j = 0; j < 3; j++) + for (size_t j = 0; j < 3; j++) s[j] += coefs[k] * t[j]; s[3] += coefs[k] * embers[k].m_Palette[i][3]; @@ -700,16 +729,16 @@ public: Palette::HsvToRgb(s, glm::value_ptr(m_Palette[i])); m_Palette[i][3] = s[3]; - for (j = 0; j < 4; j++) + for (glm::length_t j = 0; j < 4; j++) Clamp(m_Palette[i][j], 0, 1); } } else if (embers[0].m_PaletteInterp == INTERP_SWEEP) { //Sweep - not the best option for float indices. - for (i = 0; i < 256; i++) + for (glm::length_t i = 0; i < 256; i++) { - j = (i < (256 * coefs[0])) ? 0 : 1; + size_t j = (i < (256 * coefs[0])) ? 0 : 1; m_Palette[i] = embers[j].m_Palette[i]; } } @@ -764,9 +793,9 @@ public: xformVec.reserve(size); //Populate the xform list member such that each element is a merge of all of the xforms at that position in all of the embers. - for (i = 0; i < totalXformCount; i++)//For each xform to populate. + for (size_t i = 0; i < totalXformCount; i++)//For each xform to populate. { - for (j = 0; j < size; j++)//For each ember in the list. + for (size_t j = 0; j < size; j++)//For each ember in the list. { if (i < embers[j].TotalXformCount())//Xform in this position in this ember. { @@ -784,7 +813,7 @@ public: //Now have a merged list, so interpolate the weight values. //This includes all xforms plus final. - for (i = 0; i < totalXformCount; i++) + for (size_t i = 0; i < totalXformCount; i++) { Xform* thisXform = GetTotalXform(i); @@ -796,7 +825,7 @@ public: coefs[1] = 1 - coefs[0]; } - for (j = 0; j < thisXform->TotalVariationCount(); j++)//For each variation in this xform. + for (size_t j = 0; j < thisXform->TotalVariationCount(); j++)//For each variation in this xform. { Variation* var = thisXform->GetVariation(j); ParametricVariation* parVar = dynamic_cast*>(var);//Will use below if it's parametric. @@ -806,7 +835,7 @@ public: if (parVar != nullptr) parVar->Clear(); - for (k = 0; k < size; k++)//For each ember in the list. + for (size_t k = 0; k < size; k++)//For each ember in the list. { Xform* tempXform = embers[k].GetTotalXform(i);//Xform in this position in this ember, including final. @@ -867,7 +896,7 @@ public: //Post part. allID = true; - for (k = 0; k < size; k++)//For each ember in the list. + for (size_t k = 0; k < size; k++)//For each ember in the list. { if (i < embers[k].TotalXformCount())//Xform in this position in this ember. { @@ -896,7 +925,7 @@ public: thisXform->m_Affine.m_Mat = m23T(0); thisXform->m_Post.m_Mat = m23T(0); - for (k = 0; k < size; k++) + for (size_t k = 0; k < size; k++) { Xform* tempXform = embers[k].GetTotalXform(i);//Xform in this position in this ember. @@ -930,23 +959,23 @@ public: //Omit final xform from chaos processing. if (Interpolater::AnyXaosPresent(embers, size)) { - for (i = 0; i < XformCount(); i++) + for (size_t i = 0; i < XformCount(); i++) { m_Xforms[i].SetXaos(i, 0);//First make each xform xaos array be maxXformCount elements long and set them to zero. //Now fill them with interpolated values. - for (j = 0; j < size; j++)//For each ember in the list. + for (size_t j = 0; j < size; j++)//For each ember in the list. { Xform* tempXform = embers[j].GetXform(i); - for (k = 0; k < XformCount(); k++)//For each xaos entry in this xform's xaos array, sum it with the same entry in all of the embers multiplied by the coef for that ember. + for (size_t k = 0; k < XformCount(); k++)//For each xaos entry in this xform's xaos array, sum it with the same entry in all of the embers multiplied by the coef for that ember. { m_Xforms[i].SetXaos(k, m_Xforms[i].Xaos(k) + tempXform->Xaos(k) * coefs[j]); } } //Make sure no xaos entries for this xform were less than zero. - for (k = 0; k < XformCount(); k++) + for (size_t k = 0; k < XformCount(); k++) if (m_Xforms[i].Xaos(k) < 0) m_Xforms[i].SetXaos(k, 0); } @@ -994,7 +1023,7 @@ public: /// The angle to rotate by void RotateAffines(T angle) { - for (unsigned int i = 0; i < XformCount(); i++)//Only look at normal xforms, exclude final. + for (size_t i = 0; i < XformCount(); i++)//Only look at normal xforms, exclude final. { //Don't rotate xforms with animate set to 0. if (m_Xforms[i].m_Animate == 0) @@ -1021,7 +1050,7 @@ public: /// The random context to use for generating random symmetry void AddSymmetry(int sym, QTIsaac& rand) { - int i, k, result = 0; + size_t i, k, result = 0; T a; if (sym == 0) @@ -1102,9 +1131,9 @@ 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 - unsigned int ProjBits() + size_t ProjBits() { - unsigned int val = 0; + size_t val = 0; if (m_CamZPos != 0) val |= PROJBITS_ZPOS; if (m_CamPerspective != 0) val |= PROJBITS_PERSP; @@ -1251,6 +1280,7 @@ public: m_PaletteInterp = INTERP_HSV; m_Index = 0; m_ParentFilename = ""; + m_ScaleType = eScaleType::SCALE_NONE; if (useDefaults) { @@ -1339,20 +1369,21 @@ public: /// The string representation of this ember string ToString() const { - unsigned int i; + size_t i; ostringstream ss; - ss << "FinalRasW: " << m_FinalRasW << endl - << "FinalRasH: " << m_FinalRasH << endl - << "OrigRasW: " << m_OrigFinalRasW << endl - << "OrigRasH: " << m_OrigFinalRasH << endl + ss << "Final Raster Width: " << m_FinalRasW << endl + << "Final Raster Height: " << m_FinalRasH << endl + << "Original Raster Width: " << m_OrigFinalRasW << endl + << "Original Raster Height: " << m_OrigFinalRasH << endl << "Supersample: " << m_Supersample << endl << "Passes: " << m_Passes << endl - << "TemporalSamples: " << m_TemporalSamples << endl + << "Temporal Samples: " << m_TemporalSamples << endl << "Symmetry: " << m_Symmetry << endl << "Quality: " << m_Quality << endl - << "PixelsPerUnit: " << m_PixelsPerUnit << endl + << "Pixels Per Unit: " << m_PixelsPerUnit << endl + << "Original Pixels Per Unit: " << m_OrigPixPerUnit << endl << "Zoom: " << m_Zoom << endl << "ZPos: " << m_CamZPos << endl << "Perspective: " << m_CamPerspective << endl @@ -1366,8 +1397,8 @@ public: << "Brightness: " << m_Brightness << endl << "Gamma: " << m_Gamma << endl << "Vibrancy: " << m_Vibrancy << endl - << "GammaThresh: " << m_GammaThresh << endl - << "HighlightPower: " << m_HighlightPower << endl + << "Gamma Threshold: " << m_GammaThresh << endl + << "Highlight Power: " << m_HighlightPower << endl << "Time: " << m_Time << endl << "Background: " << m_Background.r << ", " << m_Background.g << ", " << m_Background.b << ", " << m_Background.a << endl @@ -1391,6 +1422,8 @@ public: //Add palette info here if needed. << "Name: " << m_Name << endl + << "Index: " << m_Index << endl + << "Scale Type: " << m_ScaleType << endl << "Parent Filename: " << m_ParentFilename << endl << endl; @@ -1410,34 +1443,36 @@ public: /// inline const Xform* Xforms() const { return &m_Xforms[0]; } inline Xform* NonConstXforms() { return &m_Xforms[0]; } - inline unsigned int XformCount() const { return (unsigned int)m_Xforms.size(); } + inline size_t XformCount() const { return m_Xforms.size(); } inline const Xform* FinalXform() const { return &m_FinalXform; } inline Xform* NonConstFinalXform() { return &m_FinalXform; } inline bool UseFinalXform() const { return !m_FinalXform.Empty(); } - inline unsigned int TotalXformCount() const { return XformCount() + (UseFinalXform() ? 1 : 0); } + inline size_t TotalXformCount() const { return XformCount() + (UseFinalXform() ? 1 : 0); } inline int PaletteIndex() const { return m_Palette.m_Index; } inline T BlurCoef() { return m_BlurCoef; } + inline eScaleType ScaleType() const { return m_ScaleType; } //The width and height in pixels of the final output image. The size of the histogram and DE filtering buffers will differ from this. //Xml fields: "size". - unsigned int m_FinalRasW; - unsigned int m_FinalRasH; - unsigned int m_OrigFinalRasW;//Keep track of the originals read from the Xml, because... - unsigned int m_OrigFinalRasH;//the dimension may change in an editor and the originals are needed for the aspect ratio. + size_t m_FinalRasW; + size_t m_FinalRasH; + size_t m_OrigFinalRasW;//Keep track of the originals read from the Xml, because... + size_t m_OrigFinalRasH;//the dimension may change in an editor and the originals are needed for the aspect ratio. + T m_OrigPixPerUnit; //The multiplier in size of the histogram and DE filtering buffers. Must be at least one, preferrably never larger than 4, only useful at 2. //Xml field: "supersample" or "overample (deprecated)". - unsigned int m_Supersample; + size_t m_Supersample; //Times to run the algorithm while clearing the histogram, but not the filter. Almost always set to 1 and may even be deprecated. //Xml field: "passes". - unsigned int m_Passes; + size_t m_Passes; //When animating, split each pass into this many pieces, each doing a fraction of the total iterations. Each temporal sample //will render an interpolated instance of the ember that is a fraction of the current ember and the next one. //When rendering a single image, this field is always set to 1. //Xml field: "temporal_samples". - unsigned int m_TemporalSamples; + size_t m_TemporalSamples; //Whether or not any symmetry was added. This field is in a bit of a state of conflict right now as flam3 has a severe bug. //Xml field: "symmetry". @@ -1611,9 +1646,14 @@ public: xmlDocPtr m_Edits; //The 0-based position of this ember in the file it was contained in. - int m_Index; + size_t m_Index; private: + /// + /// The type of scaling used when resizing. + /// + eScaleType m_ScaleType; + /// /// Interpolation function that takes the address of a member variable of type T as a template parameter. /// This is an alternative to using macros. @@ -1651,7 +1691,7 @@ private: /// The list of embers to interpolate /// The list of coefficients to interpolate /// The size of the lists, both must match. - template ::*m> + template ::*m> void InterpI(Ember* embers, vector& coefs, size_t size) { T t = 0; @@ -1659,7 +1699,7 @@ private: for (size_t k = 0; k < size; k++) t += coefs[k] * embers[k].*m; - this->*m = (int)Rint(t); + this->*m = (size_t)Rint(t); } /// @@ -1672,7 +1712,7 @@ private: /// The list of coefficients to interpolate /// The size of the lists, both must match. template ::*m> - void InterpXform(Xform* xform, unsigned int i, Ember* embers, vector& coefs, size_t size) + void InterpXform(Xform* xform, size_t i, Ember* embers, vector& coefs, size_t size) { xform->*m = T(0); diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index e1e1a14..e949f12 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -40,7 +40,7 @@ public: /// Whether a new file is to be started /// Whether an existing file is to be ended /// True if successful, else false - bool Save(string filename, Ember& ember, unsigned int printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false) + bool Save(const string& filename, Ember& ember, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false) { vector> vec; @@ -61,7 +61,7 @@ public: /// Whether a new file is to be started /// Whether an existing file is to be ended /// True if successful, else false - bool Save(string filename, vector>& embers, unsigned int printEditDepth, bool doEdits, bool intPalette, bool hexPalette, bool append = false, bool start = false, bool finish = false) + 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; string temp; @@ -124,9 +124,9 @@ public: /// If true use integers instead of floating point numbers when embedding a non-hex formatted palette, else use floating point numbers. /// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags. /// The Xml string representation of the passed in ember - string ToString(Ember& ember, string extraAttributes, unsigned int printEditDepth, bool doEdits, bool intPalette, bool hexPalette = true) + string ToString(Ember& ember, string extraAttributes, size_t printEditDepth, bool doEdits, bool intPalette, bool hexPalette = true) { - unsigned int i, j; + size_t i, j; string s; ostringstream os; vector*> variations; @@ -144,7 +144,7 @@ public: os << " zoom=\"" << ember.m_Zoom << "\""; os << " rotate=\"" << ember.m_Rotate << "\""; - os << " supersample=\"" << max(1u, ember.m_Supersample) << "\""; + os << " supersample=\"" << max(1, ember.m_Supersample) << "\""; os << " filter=\"" << ember.m_SpatialFilterRadius << "\""; os << " filter_shape=\"" << ToLower(SpatialFilterCreator::ToString(ember.m_SpatialFilterType)) << "\""; @@ -227,7 +227,7 @@ public: for (j = 0; j < 8; j++) { - int idx = 8 * i + j; + size_t idx = 8 * i + j; os << hex << setw(2) << setfill('0') << (int)Rint(ember.m_Palette[idx][0] * 255); os << hex << setw(2) << setfill('0') << (int)Rint(ember.m_Palette[idx][1] * 255); @@ -295,13 +295,13 @@ public: xmlDocPtr CreateNewEditdoc(Ember* parent0, Ember* parent1, string action, string nick, string url, string id, string comment, int sheepGen = 0, int sheepId = 0) { char timeString[128]; - char buffer[128]; - char commentString[128]; time_t myTime; + string s; xmlDocPtr commentDoc = nullptr; xmlDocPtr doc = xmlNewDoc(XC "1.0"); xmlNodePtr rootNode = nullptr, node = nullptr, nodeCopy = nullptr; xmlNodePtr rootComment = nullptr; + ostringstream os; //Create the root node, called "edit". rootNode = xmlNewNode(nullptr, XC "edit"); @@ -342,25 +342,32 @@ public: node = xmlNewChild(rootNode, nullptr, XC "sheep", nullptr); //Create the sheep attributes. - sprintf_s(buffer, 128, "%d", sheepGen); - xmlNewProp(node, XC "generation", XC buffer); + os << sheepGen; + s = os.str(); + xmlNewProp(node, XC "generation", XC s.c_str()); + os.str(""); - sprintf_s(buffer, 128, "%d", sheepId); - xmlNewProp(node, XC "id", XC buffer); + os << sheepId; + s = os.str(); + xmlNewProp(node, XC "id", XC s.c_str()); + os.str(""); } //Check for the parents. //If parent 0 not specified, this is a randomly generated genome. if (parent0) { + os << parent0->m_Index; + s = os.str(); + if (parent0->m_Edits) { //Copy the node from the parent. node = xmlDocGetRootElement(parent0->m_Edits); nodeCopy = xmlCopyNode(node, 1); AddFilenameWithoutAmpersand(nodeCopy, parent0->m_ParentFilename); - sprintf_s(buffer, 128, "%d", parent0->m_Index); - xmlNewProp(nodeCopy, XC "index", XC buffer); + + xmlNewProp(nodeCopy, XC "index", XC s.c_str()); xmlAddChild(rootNode, nodeCopy); } else @@ -368,21 +375,24 @@ public: //Insert a (parent has no edit) message. nodeCopy = xmlNewChild(rootNode, nullptr, XC "edit", nullptr); AddFilenameWithoutAmpersand(nodeCopy, parent0->m_ParentFilename); - sprintf_s(buffer, 128, "%d", parent0->m_Index); - xmlNewProp(nodeCopy, XC "index", XC buffer); + xmlNewProp(nodeCopy, XC "index", XC s.c_str()); } + + os.str(""); } if (parent1) { + os << parent1->m_Index; + s = os.str(); + if (parent1->m_Edits) { //Copy the node from the parent. node = xmlDocGetRootElement(parent1->m_Edits); nodeCopy = xmlCopyNode(node, 1); AddFilenameWithoutAmpersand(nodeCopy, parent1->m_ParentFilename); - sprintf_s(buffer, 128, "%d", parent1->m_Index); - xmlNewProp(nodeCopy, XC "index", XC buffer); + xmlNewProp(nodeCopy, XC "index", XC s.c_str()); xmlAddChild(rootNode, nodeCopy); } else @@ -390,22 +400,25 @@ public: //Insert a (parent has no edit) message. nodeCopy = xmlNewChild(rootNode, nullptr, XC "edit",nullptr); AddFilenameWithoutAmpersand(nodeCopy, parent1->m_ParentFilename); - sprintf_s(buffer, 128, "%d", parent1->m_Index); - xmlNewProp(nodeCopy, XC "index", XC buffer); + xmlNewProp(nodeCopy, XC "index", XC s.c_str()); } + + os.str(""); } //Comment string: //This one's hard, since the comment string must be treated as - //a valid XML document. Create a new document using the comment + //a valid XML document. Create a new document using the comment //string as the in-memory document, and then copy all children of //the root node into the edit structure //Parsing the comment string should be done once and then copied //for each new edit doc, but that's for later. if (comment != "") { - sprintf_s(commentString, 128, "%s", comment.c_str()); - commentDoc = xmlReadMemory(commentString, (int)strlen(commentString), "comment.env", nullptr, XML_PARSE_NONET); + os << "" << comment << ""; + s = os.str(); + commentDoc = xmlReadMemory(s.c_str(), (int)s.length(), "comment.env", nullptr, XML_PARSE_NONET); + os.str(""); //Check for errors. if (commentDoc != nullptr) @@ -429,7 +442,7 @@ public: } } - //Return the xml doc. + //Return the Xml doc. return doc; } @@ -442,9 +455,9 @@ private: /// True if the xform is the final xform in the ember, else false. /// If true, include motion elements in the Xml string, else omit. /// The Xml string representation of the passed in xform - string ToString(Xform& xform, unsigned int xformCount, bool isFinal, bool doMotion) + string ToString(Xform& xform, size_t xformCount, bool isFinal, bool doMotion) { - unsigned int i, j; + size_t i, j; ostringstream os; if (doMotion) @@ -561,13 +574,13 @@ private: /// If true, include newlines and tabs, else don't. /// How deep the edit depth goes /// The edit node Xml string - string ToString(xmlNodePtr editNode, unsigned int tabs, bool formatting, unsigned int printEditDepth) + string ToString(xmlNodePtr editNode, size_t tabs, bool formatting, size_t printEditDepth) { bool indentPrinted = false; const char* tabString = " ", *attStr; const char* editString = "edit"; const char* sheepString = "sheep"; - unsigned int ti;//, editOrSheep = 0; + size_t ti;//, editOrSheep = 0; xmlAttrPtr attPtr = nullptr, curAtt = nullptr; xmlNodePtr childPtr = nullptr, curChild = nullptr; ostringstream os; diff --git a/Source/Ember/Interpolate.h b/Source/Ember/Interpolate.h index 7c3d0da..d06b541 100644 --- a/Source/Ember/Interpolate.h +++ b/Source/Ember/Interpolate.h @@ -36,11 +36,11 @@ public: /// The array of embers to align /// The array which will contain the aligned embers /// The number of elements in sourceEmbers - static void Align(Ember* sourceEmbers, Ember* destEmbers, unsigned int count) + static void Align(Ember* sourceEmbers, Ember* destEmbers, size_t count) { bool aligned = true; bool currentFinal, final = sourceEmbers[0].UseFinalXform(); - unsigned int i, xf, currentCount, maxCount = sourceEmbers[0].XformCount(); + size_t i, xf, currentCount, maxCount = sourceEmbers[0].XformCount(); Xform* destXform; Xform* destOtherXform; @@ -80,7 +80,7 @@ public: //All embers will have the same number of xforms at this point. for (i = 0; i < count; i++) { - unsigned int ii; + size_t ii; for (xf = 0; xf < maxCount; xf++)//This will include both normal xforms and the final. { @@ -104,7 +104,7 @@ public: //If the current xform index is greater than what the original xform count was for this ember, then it's a padding xform. if (xf >= sourceEmbers[i].TotalXformCount() && !aligned) { - unsigned int found = 0; + size_t found = 0; //Remove linear. destXform->DeleteVariationById(VAR_LINEAR); @@ -304,7 +304,7 @@ public: /// True if at least one ember contained xaos, else false. static bool AnyXaosPresent(Ember* embers, size_t size) { - for (unsigned int i = 0; i < size; i++) + for (size_t i = 0; i < size; i++) if (embers[i].XaosPresent()) return true; @@ -316,7 +316,7 @@ public: /// /// The vector of embers to inspect for the greatest xform count /// The greatest non-final xform count in any of the embers - static unsigned int MaxXformCount(vector>& embers) + static size_t MaxXformCount(vector>& embers) { return MaxXformCount(embers.data(), embers.size()); } @@ -327,9 +327,9 @@ public: /// The array of embers to inspect /// The size of the embers array /// The greatest non-final xform count in any of the embers - static unsigned int MaxXformCount(Ember* embers, size_t size) + static size_t MaxXformCount(Ember* embers, size_t size) { - unsigned int i, maxCount = 0; + size_t i, maxCount = 0; for (i = 0; i < size; i++) if (embers[i].XformCount() > maxCount) @@ -473,7 +473,7 @@ public: { Xform xform; - for (unsigned int xf = 0; xf < xforms.size(); xf++) + for (size_t xf = 0; xf < xforms.size(); xf++) MergeXformVariations1Way(xforms[xf], &xform, false, clearWeights); return xform; @@ -488,7 +488,7 @@ public: /// If true, set variation weights in dest to 0, else copy weights static void MergeXformVariations1Way(Xform* source, Xform* dest, bool parVarsOnly, bool clearWeights) { - for (unsigned int i = 0; i < source->TotalVariationCount(); i++)//Iterate through the first xform's variations. + for (size_t i = 0; i < source->TotalVariationCount(); i++)//Iterate through the first xform's variations. { Variation* var = source->GetVariation(i);//Grab the variation at index in in the first xform. Variation* var2 = dest->GetVariationById(var->VariationId());//See if the same variation exists in the second xform. @@ -551,19 +551,19 @@ public: ParamWithName* secondParams = second->Params(); //Iterate through each of the source variations. - for (unsigned int i = 0; i < first.size(); i++) + for (size_t i = 0; i < first.size(); i++) { ParametricVariation* firstVar = first[i]; //Make sure the source variation at this index is the same type as the variation being written to. if (firstVar->VariationId() == second->VariationId()) { - unsigned int size = firstVar->ParamCount(); + size_t size = firstVar->ParamCount(); ParamWithName* firstParams = firstVar->Params(); //Multiply each parameter of the variation at this index by the coefficient at this index, and add //the result to the corresponding parameter in second. - for (unsigned int j = 0; j < size; j++) + for (size_t j = 0; j < size; j++) { if (!firstParams[j].IsPrecalc()) *(secondParams[j].Param()) += c[i] * firstParams[j].ParamVal(); @@ -584,7 +584,7 @@ public: /// The vec2 vector to store the polar angular values /// The vec2 vector to store the polar magnitude values /// The vec2 vector to store the polar translation values - static void ConvertLinearToPolar(vector>& embers, int xfi, int cflag, vector& cxAng, vector& cxMag, vector& cxTrn) + static void ConvertLinearToPolar(vector>& embers, size_t xfi, size_t cflag, vector& cxAng, vector& cxMag, vector& cxTrn) { ConvertLinearToPolar(embers.data(), embers.size(), xfi, cflag, cxAng, cxMag, cxTrn); } @@ -600,7 +600,7 @@ public: /// The vec2 vector to store the polar angular values /// The vec2 vector to store the polar magnitude values /// The vec2 vector to store the polar translation values - static void ConvertLinearToPolar(Ember* embers, size_t size, int xfi, int cflag, vector& cxAng, vector& cxMag, vector& cxTrn) + static void ConvertLinearToPolar(Ember* embers, size_t size, size_t xfi, size_t cflag, vector& cxAng, vector& cxMag, vector& cxTrn) { if (size == cxAng.size() && size == cxMag.size() && @@ -707,9 +707,9 @@ public: /// /// The array of embers /// The size of the embers array - static void AsymmetricRefAngles(Ember* embers, unsigned int count) + static void AsymmetricRefAngles(Ember* embers, size_t count) { - unsigned int k, xfi, col; + size_t k, xfi; T cxang[4][2], c1[2], d; for (xfi = 0; xfi < embers[0].XformCount(); xfi++)//Final xforms don't rotate regardless of their symmetry. @@ -718,7 +718,7 @@ public: { //Establish the angle for each component. //Should potentially functionalize. - for (col = 0; col < 2; col++) + for (glm::length_t col = 0; col < 2; col++) { c1[0] = embers[k].GetXform(xfi)->m_Affine.m_Mat[0][col];//A,D then B,E. c1[1] = embers[k].GetXform(xfi)->m_Affine.m_Mat[1][col]; @@ -729,7 +729,7 @@ public: for (k = 1; k < count; k++) { - for (col = 0; col < 2; col++) + for (size_t col = 0; col < 2; col++) { int sym0, sym1; int padSymFlag; @@ -832,7 +832,7 @@ public: /// The number xforms in the ember /// The index of this xform within the ember /// The stagger coefficient - static inline T GetStaggerCoef(T t, T staggerPercent, int numXforms, int thisXform) + static inline T GetStaggerCoef(T t, T staggerPercent, size_t numXforms, size_t thisXform) { //maxStag is the spacing between xform start times if staggerPercent = 1.0. T maxStag = T(numXforms - 1) / numXforms; diff --git a/Source/Ember/Isaac.h b/Source/Ember/Isaac.h index dba7d41..f1ed2ff 100644 --- a/Source/Ember/Isaac.h +++ b/Source/Ember/Isaac.h @@ -32,10 +32,10 @@ /// #ifndef __ISAAC64 - typedef unsigned long int ISAAC_INT; + typedef unsigned int ISAAC_INT; const ISAAC_INT GOLDEN_RATIO = ISAAC_INT(0x9e3779b9); #else - typedef uint64_t ISAAC_INT; + typedef size_t ISAAC_INT; const ISAAC_INT GOLDEN_RATIO = ISAAC_INT(0x9e3779b97f4a7c13); #endif diff --git a/Source/Ember/Iterator.h b/Source/Ember/Iterator.h index d1a77a8..c1f4db5 100644 --- a/Source/Ember/Iterator.h +++ b/Source/Ember/Iterator.h @@ -58,7 +58,7 @@ public: /// Accessors. /// const unsigned char* XformDistributions() const { return m_XformDistributions.empty() ? nullptr : &m_XformDistributions[0]; } - const unsigned int XformDistributionsSize() const { return (unsigned int)m_XformDistributions.size(); } + const size_t XformDistributionsSize() const { return m_XformDistributions.size(); } /// /// Virtual empty iteration function that will be overidden in derived iterator classes. @@ -69,7 +69,7 @@ public: /// The buffer to store the output points /// The random context to use /// The number of bad values - virtual unsigned int Iterate(Ember& ember, unsigned int count, unsigned int skip, Point* samples, QTIsaac& rand) { return 0; } + virtual size_t Iterate(Ember& ember, size_t count, size_t skip, Point* samples, QTIsaac& rand) { return 0; } /// /// Initialize the xform selection vector by normalizing the weights of all xforms and @@ -85,8 +85,8 @@ public: /// True if success, else false. bool InitDistributions(Ember& ember) { - unsigned int i; - unsigned int distribCount = ember.XaosPresent() ? (unsigned int)ember.XformCount() + 1 : 1; + size_t i; + size_t distribCount = ember.XaosPresent() ? ember.XformCount() + 1 : 1; const Xform* xforms = ember.Xforms(); if (m_XformDistributions.size() < CHOOSE_XFORM_GRAIN * distribCount) @@ -95,7 +95,7 @@ public: if (m_XformDistributions.size() < CHOOSE_XFORM_GRAIN * distribCount) return false; - for (unsigned int distrib = 0; distrib < distribCount; distrib++) + for (size_t distrib = 0; distrib < distribCount; distrib++) { T totalDensity = 0; @@ -115,7 +115,7 @@ public: //only the first xform will get used. //Calculate how much of a fraction of a the total density each element represents. - unsigned int j = 0; + size_t j = 0; T tempDensity = 0, currentDensityLimit = 0, densityPerElement = totalDensity / CHOOSE_XFORM_GRAIN; //Assign xform indices in order to each element of m_XformDistributions. @@ -135,7 +135,7 @@ public: while (tempDensity < currentDensityLimit && j < CHOOSE_XFORM_GRAIN) { //printf("offset = %d, xform = %d, running sum = %f\n", j, i, tempDensity); - m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + j] = i; + m_XformDistributions[(distrib * CHOOSE_XFORM_GRAIN) + j] = (unsigned char)i; tempDensity += densityPerElement; j++; } @@ -181,9 +181,9 @@ protected: /// The point which initially had the bad values and which will store the newly computed values /// The random context this iterator is using /// True if a good value was computed within 5 tries, else false - inline bool DoBadVals(Xform* xforms, unsigned int& badVals, Point* point, QTIsaac& rand) + inline bool DoBadVals(Xform* xforms, size_t& badVals, Point* point, QTIsaac& rand) { - unsigned int xformIndex, consec = 0; + size_t xformIndex, consec = 0; Point firstBadPoint; while (consec < 5) @@ -246,9 +246,9 @@ protected: /// The index to retrieve /// When xaos is prsent, the index of the previous xform used. Default: 0 (xaos not present). /// - unsigned int NextXformFromIndex(unsigned int index, unsigned int distribOffset = 0) + size_t NextXformFromIndex(size_t index, size_t distribOffset = 0) { - return (unsigned int)m_XformDistributions[(index % CHOOSE_XFORM_GRAIN) + (CHOOSE_XFORM_GRAIN * distribOffset)]; + return (size_t)m_XformDistributions[(index % CHOOSE_XFORM_GRAIN) + (CHOOSE_XFORM_GRAIN * distribOffset)]; } vector m_XformDistributions; @@ -278,9 +278,9 @@ public: /// The buffer to store the output points /// The random context to use /// The number of bad values - virtual unsigned int Iterate(Ember& ember, unsigned int count, unsigned int skip, Point* samples, QTIsaac& rand) + virtual size_t Iterate(Ember& ember, size_t count, size_t skip, Point* samples, QTIsaac& rand) { - unsigned int i, badVals = 0; + size_t i, badVals = 0; Point tempPoint, p1; Xform* xforms = ember.NonConstXforms(); @@ -401,9 +401,9 @@ public: /// The point which initially had the bad values and which will store the newly computed values /// The random context this iterator is using /// True if a good value was computed within 5 tries, else false - inline bool DoBadVals(Xform* xforms, unsigned int& xformIndex, unsigned int lastXformUsed, unsigned int& badVals, Point* point, QTIsaac& rand) + inline bool DoBadVals(Xform* xforms, size_t& xformIndex, size_t lastXformUsed, size_t& badVals, Point* point, QTIsaac& rand) { - unsigned int consec = 0; + size_t consec = 0; Point firstBadPoint; while (consec < 5) @@ -442,11 +442,11 @@ public: /// The buffer to store the output points /// The random context to use /// The number of bad values - virtual unsigned int Iterate(Ember& ember, unsigned int count, unsigned int skip, Point* samples, QTIsaac& rand) + virtual size_t Iterate(Ember& ember, size_t count, size_t skip, Point* samples, QTIsaac& rand) { - unsigned int i, xformIndex; - unsigned int lastXformUsed = 0; - unsigned int badVals = 0; + size_t i, xformIndex; + size_t lastXformUsed = 0; + size_t badVals = 0; Point tempPoint, p1; Xform* xforms = ember.NonConstXforms(); diff --git a/Source/Ember/Palette.h b/Source/Ember/Palette.h index 7afcac9..9345a47 100644 --- a/Source/Ember/Palette.h +++ b/Source/Ember/Palette.h @@ -39,7 +39,7 @@ public: /// The index in the palette file /// The size of the palette which should be 256 /// A pointer to 256 color entries - Palette(string name, int index, unsigned int size, v4T* xmlPaletteEntries) + Palette(const string& name, int index, unsigned int size, v4T* xmlPaletteEntries) { m_Name = name; m_Index = index; diff --git a/Source/Ember/PaletteList.h b/Source/Ember/PaletteList.h index d1b1843..5052944 100644 --- a/Source/Ember/PaletteList.h +++ b/Source/Ember/PaletteList.h @@ -32,7 +32,7 @@ public: /// The full path to the file to read /// If true, override the initialization state and force a read, else observe the initialization state. /// The initialization state - bool Init(string filename, bool force = false) + bool Init(const string& filename, bool force = false) { if (!m_Init || force) { @@ -93,7 +93,7 @@ public: /// /// The name of the palette to retrieve /// A pointer to the palette if found, else nullptr - Palette* GetPaletteByName(string& name) + Palette* GetPaletteByName(const string&& name) { for (unsigned int i = 0; i < Count(); i++) if (m_Palettes[i].m_Name == name) diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index 4f47c19..300970d 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -10,33 +10,10 @@ namespace EmberNs template Renderer::Renderer() { - m_Abort = false; - m_LockAccum = false; - m_EarlyClip = false; - m_YAxisUp = false; - m_InsertPalette = false; - m_ReclaimOnResize = false; - m_SubBatchSize = 1024 * 10; - m_NumChannels = 3; - m_BytesPerChannel = 1; - m_SuperSize = 0; m_PixelAspectRatio = 1; - m_Transparency = false; - ThreadCount(Timing::ProcessorCount()); m_StandardIterator = unique_ptr>(new StandardIterator()); m_XaosIterator = unique_ptr>(new XaosIterator()); m_Iterator = m_StandardIterator.get(); - m_Callback = nullptr; - m_ProgressParameter = nullptr; - m_LastPass = 0; - m_LastTemporalSample = 0; - m_LastIter = 0; - m_LastIterPercent = 0; - m_InteractiveFilter = FILTER_LOG; - m_ProcessState = NONE; - m_ProcessAction = FULL_RENDER; - m_InRender = false; - m_InFinalAccum = false; } /// @@ -48,36 +25,8 @@ Renderer::~Renderer() } /// -/// Compute the bounds of the histogram and density filtering buffers. -/// These are affected by the final requested dimensions, spatial and density -/// filter sizes and supersampling. +/// Non-virtual processing functions. /// -template -void Renderer::ComputeBounds() -{ - unsigned int maxDEFilterWidth = 0; - - m_GutterWidth = ClampGte((m_SpatialFilter->FinalFilterWidth() - Supersample()) / 2, 0u); - - //Check the size of the density estimation filter. - //If the radius of the density estimation filter is greater than the - //gutter width, have to pad with more. Otherwise, use the same value. - for (unsigned int i = 0; i < m_Embers.size(); i++) - maxDEFilterWidth = max((unsigned int)(ceil(m_Embers[i].m_MaxRadDE) * m_Ember.m_Supersample), maxDEFilterWidth); - - //Need an extra ss = (int)floor(m_Supersample / 2.0) of pixels so that a local iteration count for DE can be determined.//SMOULDER - if (maxDEFilterWidth > 0) - maxDEFilterWidth += (unsigned int)Floor(m_Ember.m_Supersample / T(2)); - - //To have a fully present set of pixels for the spatial filter, must - //add the DE filter width to the spatial filter width.//SMOULDER - m_DensityFilterOffset = maxDEFilterWidth; - m_GutterWidth += m_DensityFilterOffset; - - m_SuperRasW = (Supersample() * FinalRasW()) + (2 * m_GutterWidth); - m_SuperRasH = (Supersample() * FinalRasH()) + (2 * m_GutterWidth); - m_SuperSize = m_SuperRasW * m_SuperRasH; -} /// /// Compute the camera. @@ -115,83 +64,80 @@ void Renderer::ComputeCamera() } /// -/// Abort the render and call a function to do something, most likely change a value. -/// Then update the current process action to the one specified. -/// The current process action will only be set if it makes sense based -/// on the current process state. If the value specified doesn't make sense -/// the next best choice will be made. If nothing makes sense, a complete -/// re-render will be triggered on the next call to Run(). +/// Add an ember to the end of the embers vector and reset the rendering process. +/// Reset the rendering process. /// -/// The function to execute -/// The desired process action +/// The ember to add template -void Renderer::ChangeVal(std::function func, eProcessAction action) +void Renderer::AddEmber(Ember& ember) { - Abort(); - EnterRender(); - func(); + ChangeVal([&] + { + m_Embers.push_back(ember); - //If they want a full render, don't bother inspecting process state, just start over. - if (action == FULL_RENDER) - { - m_ProcessState = NONE; - m_ProcessAction = FULL_RENDER; - } - //Keep iterating is when rendering has completed and the user increases the quality. - //Rendering can be started where it left off by adding just the difference between the - //new and old quality values. - else if (action == KEEP_ITERATING) - { - if (m_ProcessState == ACCUM_DONE && TemporalSamples() == 1 && Passes() == 1) - { - m_ProcessState = ITER_STARTED; - m_ProcessAction = KEEP_ITERATING; - } - else//Invaid process state to handle KEEP_ITERATING, so just start over. - { - m_ProcessState = NONE; - m_ProcessAction = FULL_RENDER; - } - } - else if (action == FILTER_AND_ACCUM) - { - //If in the middle of a render, cannot skip to filtering or accum, so just start over. - if (m_ProcessState == NONE || m_ProcessState == ITER_STARTED) - { - m_ProcessState = NONE; - m_ProcessAction = FULL_RENDER; - } - //If passes == 1, set the state to ITER_DONE and the next process action to FILTER_AND_ACCUM. - else - { - m_ProcessState = Passes() == 1 ? ITER_DONE : NONE; - m_ProcessAction = Passes() == 1 ? FILTER_AND_ACCUM : FULL_RENDER;//Cannot just filter if passes > 1 because filtering is done with each pass. - } - } - //Run accum only. - else if (action == ACCUM_ONLY) - { - //Doesn't make sense if in the middle of iterating, so just start over. - if (m_ProcessState == NONE || m_ProcessState == ITER_STARTED) - { - m_ProcessAction = FULL_RENDER; - } - else if (m_ProcessState == ITER_DONE)//If iterating is done, can start at density filtering and proceed. - { - m_ProcessAction = FILTER_AND_ACCUM; - } - else if (m_ProcessState == FILTER_DONE)//Density filtering is done, so the process action is assigned as desired. - { - m_ProcessAction = ACCUM_ONLY; - } - else if (m_ProcessState == ACCUM_DONE)//Final accum is done, so back up and run final accum again. - { - m_ProcessState = FILTER_DONE; - m_ProcessAction = ACCUM_ONLY; - } - } + if (m_Embers.size() == 1) + m_Ember = m_Embers[0]; + }, FULL_RENDER); +} - LeaveRender(); +/// +/// Set the m_Iterator member to point to the appropriate +/// iterator based on whether the ember currently being rendered +/// contains xaos. +/// After assigning, initialize the xform selection buffer. +/// +/// True if assignment and distribution initialization succeeded, else false. +template +bool Renderer::AssignIterator() +{ + //Setup iterator and distributions. + //Both iterator types were setup in the constructor (add more in the future if needed). + //So simply assign the pointer to the correct type and re-initialize its distributions + //based on the current ember. + if (XaosPresent()) + m_Iterator = m_XaosIterator.get(); + else + m_Iterator = m_StandardIterator.get(); + + //Timing t; + return m_Iterator->InitDistributions(m_Ember); + //t.Toc("Distrib creation"); +} + +/// +/// Virtual processing functions overriden from RendererBase. +/// + +/// +/// Compute the bounds of the histogram and density filtering buffers. +/// These are affected by the final requested dimensions, spatial and density +/// filter sizes and supersampling. +/// +template +void Renderer::ComputeBounds() +{ + size_t maxDEFilterWidth = 0; + + m_GutterWidth = ClampGte((m_SpatialFilter->FinalFilterWidth() - Supersample()) / 2, 0ULL); + + //Check the size of the density estimation filter. + //If the radius of the density estimation filter is greater than the + //gutter width, have to pad with more. Otherwise, use the same value. + for (size_t i = 0; i < m_Embers.size(); i++) + maxDEFilterWidth = max((size_t)(ceil(m_Embers[i].m_MaxRadDE) * m_Ember.m_Supersample), maxDEFilterWidth); + + //Need an extra ss = (int)floor(m_Supersample / 2.0) of pixels so that a local iteration count for DE can be determined.//SMOULDER + if (maxDEFilterWidth > 0) + maxDEFilterWidth += (size_t)Floor(m_Ember.m_Supersample / T(2)); + + //To have a fully present set of pixels for the spatial filter, must + //add the DE filter width to the spatial filter width.//SMOULDER + m_DensityFilterOffset = maxDEFilterWidth; + m_GutterWidth += m_DensityFilterOffset; + + m_SuperRasW = (Supersample() * FinalRasW()) + (2 * m_GutterWidth); + m_SuperRasH = (Supersample() * FinalRasH()) + (2 * m_GutterWidth); + m_SuperSize = m_SuperRasW * m_SuperRasH; } /// @@ -235,20 +181,73 @@ void Renderer::SetEmber(vector>& embers) } /// -/// Add an ember to the end of the embers vector and reset the rendering process. -/// Reset the rendering process. +/// Create the density filter if the current filter parameters differ +/// from the last density filter created. +/// The filter will be deleted if the max DE radius is 0, in which case regular +/// log scale filtering will be used. /// -/// The ember to add +/// True if a new filter instance was created, else false. +/// True if the filter is not nullptr (whether a new one was created or not) or if max rad is 0, else false. template -void Renderer::AddEmber(Ember& ember) +bool Renderer::CreateDEFilter(bool& newAlloc) { - ChangeVal([&] - { - m_Embers.push_back(ember); + //If they wanted DE, create it if needed, else clear the last DE filter which means we'll do regular log filtering after iters are done. + newAlloc = false; - if (m_Embers.size() == 1) - m_Ember = m_Embers[0]; - }, FULL_RENDER); + if (m_Ember.m_MaxRadDE > 0) + { + //Use intelligent testing so it isn't created every time a new ember is passed in. + if ((!m_DensityFilter.get()) || + (m_Ember.m_MinRadDE != m_DensityFilter->MinRad()) || + (m_Ember.m_MaxRadDE != m_DensityFilter->MaxRad()) || + (m_Ember.m_CurveDE != m_DensityFilter->Curve()) || + (m_Ember.m_Supersample != m_DensityFilter->Supersample())) + { + m_DensityFilter = unique_ptr>(new DensityFilter(m_Ember.m_MinRadDE, m_Ember.m_MaxRadDE, m_Ember.m_CurveDE, m_Ember.m_Supersample)); + newAlloc = true; + } + + if (newAlloc) + { + if (!m_DensityFilter.get()) { return false; }//Did object creation succeed? + if (!m_DensityFilter->Create()) { return false; }//Object creation succeeded, did filter creation succeed? + //cout << m_DensityFilter->ToString() << endl; + } + else + if (!m_DensityFilter->Valid()) { return false; }//Previously created, are values ok? + } + else + { + m_DensityFilter.reset();//They want to do log filtering. Return true because even though the filter is being deleted, nothing went wrong. + } + + return true; +} + +/// +/// Create the spatial filter if the current filter parameters differ +/// from the last spatial filter created. +/// +/// True if a new filter instance was created, else false. +/// True if the filter is not nullptr (whether a new one was created or not), else false. +template +bool Renderer::CreateSpatialFilter(bool& newAlloc) +{ + newAlloc = false; + + //Use intelligent testing so it isn't created every time a new ember is passed in. + if ((!m_SpatialFilter.get()) || + (m_Ember.m_SpatialFilterType != m_SpatialFilter->FilterType()) || + (m_Ember.m_SpatialFilterRadius != m_SpatialFilter->FilterRadius()) || + (m_Ember.m_Supersample != m_SpatialFilter->Supersample()) || + (m_PixelAspectRatio != m_SpatialFilter->PixelAspectRatio())) + { + m_SpatialFilter = unique_ptr>( + SpatialFilterCreator::Create(m_Ember.m_SpatialFilterType, m_Ember.m_SpatialFilterRadius, m_Ember.m_Supersample, m_PixelAspectRatio)); + newAlloc = true; + } + + return m_SpatialFilter.get() != nullptr; } /// @@ -278,40 +277,6 @@ bool Renderer::CreateTemporalFilter(bool& newAlloc) return m_TemporalFilter.get() != nullptr; } -/// -/// Resize the passed in vector to be large enough to handle the output image. -/// If m_ReclaimOnResize is true, and the vector is already larger than needed, -/// it will be shrunk to the needed size. However if m_ReclaimOnResize is false, -/// it will be left alone if already large enough. -/// ComputeBounds() must be called before calling this function. -/// -/// The vector to allocate -/// True if the vector contains enough space to hold the output image -template -bool Renderer::PrepFinalAccumVector(vector& pixels) -{ - EnterResize(); - size_t size = FinalBufferSize(); - - if (m_ReclaimOnResize) - { - if (pixels.size() != size) - { - pixels.resize(size); - pixels.shrink_to_fit(); - } - } - else - { - if (pixels.size() < size) - pixels.resize(size); - } - - LeaveResize(); - - return pixels.size() >= size;//Ensure allocation went ok. -} - /// /// The main render loop. This is the core of the algorithm. /// The processing steps are: Iterating, density filtering, final accumulation. @@ -354,7 +319,7 @@ bool Renderer::PrepFinalAccumVector(vector& pixels) /// Offset in finalImage to store the pixels to. Default: 0. /// True if nothing went wrong, else false. template -eRenderStatus Renderer::Run(vector& finalImage, double time, unsigned int subBatchCountOverride, bool forceOutput, size_t finalOffset) +eRenderStatus Renderer::Run(vector& finalImage, double time, size_t subBatchCountOverride, bool forceOutput, size_t finalOffset) { m_InRender = true; EnterRender(); @@ -363,7 +328,7 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl bool accumOnly = m_ProcessAction == ACCUM_ONLY; bool resume = m_ProcessState != NONE; bool newFilterAlloc; - unsigned int temporalSample = 0, pass; + size_t temporalSample = 0, pass; T deTime; eRenderStatus success = RENDER_OK; //double iterationTime = 0; @@ -408,8 +373,8 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl pass = (resume ? m_LastPass : 0); //Make sure values are within valid range. - ClampGteRef(m_Ember.m_Passes, 1u); - ClampGteRef(m_Ember.m_Supersample, 1u); + ClampGteRef(m_Ember.m_Passes, 1ULL); + ClampGteRef(m_Ember.m_Supersample, 1ULL); //Make sure to get most recent update since loop won't be entered to call Interp(). //Vib, gam and background are normally summed for each temporal sample. However if iteration is skipped, make sure to get the latest. @@ -509,8 +474,8 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl //The actual number of times to iterate. Each thread will get (totalIters / ThreadCount) iters to do. //This is based on zoom and scale calculated in ComputeCamera(). //Note that the iter count is based on the final image dimensions, and not the super sampled dimensions. - uint64_t itersPerTemporalSample = ItersPerTemporalSample();//The total number of iterations for this temporal sample in this pass without overrides. - uint64_t sampleItersToDo;//The number of iterations to actually do in this sample in this pass, considering overrides. + size_t itersPerTemporalSample = ItersPerTemporalSample();//The total number of iterations for this temporal sample in this pass without overrides. + size_t sampleItersToDo;//The number of iterations to actually do in this sample in this pass, considering overrides. if (subBatchCountOverride > 0) sampleItersToDo = subBatchCountOverride * SubBatchSize() * ThreadCount();//Run a specific number of sub batches. @@ -710,339 +675,25 @@ Finish: /// If true, embed a hexadecimal palette instead of Xml Color tags, else use Xml color tags. /// The EmberImageComments object with image comments filled out template -EmberImageComments Renderer::ImageComments(unsigned int printEditDepth, bool intPalette, bool hexPalette) +EmberImageComments Renderer::ImageComments(EmberStats& stats, size_t printEditDepth, bool intPalette, bool hexPalette) { ostringstream ss; EmberImageComments comments; ss.imbue(std::locale("")); comments.m_Genome = m_EmberToXml.ToString(m_Ember, "", printEditDepth, false, intPalette, hexPalette); - ss << ((double)m_Stats.m_Badvals / (double)m_Stats.m_Iters);//Percentage of bad values to iters. + ss << ((double)stats.m_Badvals / (double)stats.m_Iters);//Percentage of bad values to iters. comments.m_Badvals = ss.str(); ss.str(""); - ss << m_Stats.m_Iters; + ss << stats.m_Iters; comments.m_NumIters = ss.str(); ss.str("");//Total iters. - ss << (m_Stats.m_RenderMs / 1000.0); + ss << (stats.m_RenderMs / 1000.0); comments.m_Runtime = ss.str();//Number of seconds for iterating, accumulating and filtering. return comments; } /// -/// Return the amount of memory needed to render the current ember. -/// Optionally include the memory needed for the final output image. -/// -/// If true include the memory needed for the final output image, else don't. -/// The memory required to render the current ember -template -uint64_t Renderer::MemoryRequired(bool includeFinal) -{ - bool newFilterAlloc = false; - - CreateSpatialFilter(newFilterAlloc); - CreateTemporalFilter(newFilterAlloc); - ComputeBounds(); - - //Because ComputeBounds() was called, this includes gutter. - uint64_t histSize = SuperSize() * sizeof(glm::detail::tvec4); - - return (histSize * 2) + (includeFinal ? FinalBufferSize() : 0);//Multiply hist by 2 to account for the density filtering buffer which is the same size as the histogram. -} - -/// -/// Virtual functions to be overriden in derived renderers that use the GPU. -/// - -/// -/// The amount of RAM available to render with. -/// -/// An unsigned 64-bit integer specifying how much memory is available -template -uint64_t Renderer::MemoryAvailable() -{ - uint64_t memAvailable = 0; - -#ifdef WIN32 - - MEMORYSTATUSEX stat; - - stat.dwLength = sizeof(stat); - GlobalMemoryStatusEx(&stat); - memAvailable = stat.ullTotalPhys; - -#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) - - memAvailable = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); - -#elif defined __APPLE__ - - #ifdef __LP64__ - long physmem; - size_t len = sizeof(physmem); - static int mib[2] = { CTL_HW, HW_MEMSIZE }; - #else - unsigned int physmem; - size_t len = sizeof(physmem); - static int mib[2] = { CTL_HW, HW_PHYSMEM }; - #endif - - if (sysctl(mib, 2, &physmem, &len, nullptr, 0) == 0 && len == sizeof(physmem)) - { - memAvailable = physmem; - } - else - { - cout << "Warning: unable to determine physical memory." << endl; - memAvailable = 4e9; - } - -#else - - cout << "Warning: unable to determine physical memory." << endl; - memAvailable = 4e9; - -#endif - - return memAvailable; -} - -/// -/// Stop rendering, ensure all locks are exited and reset the rendering state. -/// -template -void Renderer::Reset() -{ - Abort(); - EnterRender(); - EnterFinalAccum(); - LeaveFinalAccum(); - LeaveRender(); - m_ProcessState = NONE; - m_ProcessAction = FULL_RENDER; -} - -/// -/// Get a status indicating whether this renderer is ok. -/// Return true for this class, derived classes will inspect GPU hardware -/// to determine if they are ok. -/// -/// Always true for this class -template -bool Renderer::Ok() const -{ - return true; -} - -/// -/// Create the density filter if the current filter parameters differ -/// from the last density filter created. -/// The filter will be deleted if the max DE radius is 0, in which case regular -/// log scale filtering will be used. -/// -/// True if a new filter instance was created, else false. -/// True if the filter is not nullptr (whether a new one was created or not) or if max rad is 0, else false. -template -bool Renderer::CreateDEFilter(bool& newAlloc) -{ - //If they wanted DE, create it if needed, else clear the last DE filter which means we'll do regular log filtering after iters are done. - newAlloc = false; - - if (m_Ember.m_MaxRadDE > 0) - { - //Use intelligent testing so it isn't created every time a new ember is passed in. - if ((!m_DensityFilter.get()) || - (m_Ember.m_MinRadDE != m_DensityFilter->MinRad()) || - (m_Ember.m_MaxRadDE != m_DensityFilter->MaxRad()) || - (m_Ember.m_CurveDE != m_DensityFilter->Curve()) || - (m_Ember.m_Supersample != m_DensityFilter->Supersample())) - { - m_DensityFilter = unique_ptr>(new DensityFilter(m_Ember.m_MinRadDE, m_Ember.m_MaxRadDE, m_Ember.m_CurveDE, m_Ember.m_Supersample)); - newAlloc = true; - } - - if (newAlloc) - { - if (!m_DensityFilter.get()) { return false; }//Did object creation succeed? - if (!m_DensityFilter->Create()) { return false; }//Object creation succeeded, did filter creation succeed? - //cout << m_DensityFilter->ToString() << endl; - } - else - if (!m_DensityFilter->Valid()) { return false; }//Previously created, are values ok? - } - else - { - m_DensityFilter.reset();//They want to do log filtering. Return true because even though the filter is being deleted, nothing went wrong. - } - - return true; -} - -/// -/// Create the spatial filter if the current filter parameters differ -/// from the last spatial filter created. -/// -/// True if a new filter instance was created, else false. -/// True if the filter is not nullptr (whether a new one was created or not), else false. -template -bool Renderer::CreateSpatialFilter(bool& newAlloc) -{ - newAlloc = false; - - //Use intelligent testing so it isn't created every time a new ember is passed in. - if ((!m_SpatialFilter.get()) || - (m_Ember.m_SpatialFilterType != m_SpatialFilter->FilterType()) || - (m_Ember.m_SpatialFilterRadius != m_SpatialFilter->FilterRadius()) || - (m_Ember.m_Supersample != m_SpatialFilter->Supersample()) || - (m_PixelAspectRatio != m_SpatialFilter->PixelAspectRatio())) - { - m_SpatialFilter = unique_ptr>( - SpatialFilterCreator::Create(m_Ember.m_SpatialFilterType, m_Ember.m_SpatialFilterRadius, m_Ember.m_Supersample, m_PixelAspectRatio)); - newAlloc = true; - } - - return m_SpatialFilter.get() != nullptr; -} - -/// -/// Get the sub batch size. This is the size of of the chunks that the iteration -/// trajectory will be broken up into. -/// Default: 10k. -/// -/// The sub batch size -template -unsigned int Renderer::SubBatchSize() const { return m_SubBatchSize; } - -/// -/// Set the sub batch size. This is the size of of the chunks that the iteration -/// trajectory will be broken up into. -/// Reset the rendering process. -/// -/// The sub batch size to set -template -void Renderer::SubBatchSize(unsigned int sbs) -{ - ChangeVal([&] { m_SubBatchSize = sbs; }, FULL_RENDER); -} - -/// -/// Get the number of channels per pixel in the output image. 3 for RGB images -/// like Bitmap and Jpeg, 4 for Png. -/// Default is 3. -/// -/// The number of channels per pixel in the output image -template unsigned int Renderer::NumChannels() const { return m_NumChannels; } - -/// -/// Set the number of channels per pixel in the output image. 3 for RGB images -/// like Bitmap and Jpeg, 4 for Png. -/// Default is 3. -/// Set the render state to ACCUM_ONLY. -/// -/// The number of channels per pixel in the output image -template -void Renderer::NumChannels(unsigned int numChannels) -{ - ChangeVal([&] { m_NumChannels = numChannels; }, ACCUM_ONLY); -} - -/// -/// Get the renderer type enum. -/// CPU_RENDERER for this class, other values for derived classes. -/// -/// CPU_RENDERER -template -eRendererType Renderer::RendererType() const { return CPU_RENDERER; } - -/// -/// Get the number of threads used when rendering. -/// Default: use all avaliable cores. -/// -/// The number of threads used when rendering -template -unsigned int Renderer::ThreadCount() const { return m_ThreadsToUse; } - -/// -/// Set the number of threads to use when rendering. -/// This will also reset the vector of random contexts to be the same size -/// as the number of specified threads. -/// Since this is where they get set up, the caller can optionally pass in -/// a seed string, however it's only used if threads is 1. -/// This is useful for debugging since it will run the same point trajectory -/// every time. -/// Reset the rendering process. -/// -/// The number of threads to use -/// The seed string to use if threads is 1. Default: nullptr. -template -void Renderer::ThreadCount(unsigned int threads, const char* seedString) -{ - ChangeVal([&] - { - Timing t; - unsigned int i, size; - const unsigned int isaacSize = 1 << ISAAC_SIZE; - ISAAC_INT seeds[isaacSize]; - m_ThreadsToUse = threads > 0 ? threads : 1; - m_Rand.clear(); - m_SubBatch.clear(); - m_SubBatch.resize(m_ThreadsToUse); - m_BadVals.resize(m_ThreadsToUse); - - if (seedString) - { - memset(seeds, 0, isaacSize * sizeof(ISAAC_INT)); - memcpy((char*)seeds, seedString, min(strlen(seedString), isaacSize * sizeof(ISAAC_INT))); - } - - //This is critical for multithreading, otherwise the threads all happen - //too close to each other in time, resulting in bad randomization. - while (m_Rand.size() < m_ThreadsToUse) - { - size = (unsigned int)m_Rand.size(); - - if (seedString) - { - unsigned int newSize = size + 5 + (unsigned int)(t.Toc() + t.EndTime()); - -#ifdef ISAAC_FLAM3_DEBUG - QTIsaac isaac(0, 0, 0, seeds); -#else - QTIsaac isaac(newSize, newSize * 2, newSize * 3, seeds); -#endif - m_Rand.push_back(isaac); - - for (i = 0; i < (isaacSize * sizeof(ISAAC_INT)); i++) - ((unsigned char*)seeds)[i]++; - } - else - { - for (i = 0; i < isaacSize; i++) - { - t.Toc(); - seeds[i] = (ISAAC_INT)(t.EndTime() * i) + (size + 1); - } - - t.Toc(); - ISAAC_INT r = (size * i) + i + (ISAAC_INT)t.EndTime(); - QTIsaac isaac(r, r * 2, r * 3, seeds); - - m_Rand.push_back(isaac); - } - } - }, FULL_RENDER); -} - -/// -/// Set the callback object. -/// -/// The callback object to set -template -void Renderer::Callback(RenderCallback* callback) -{ - m_Callback = callback; -} - -/// -/// Virtual functions to be overriden in derived renderers that use the GPU, but not accessed outside. +/// New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside. /// /// @@ -1103,7 +754,7 @@ bool Renderer::Alloc() b &= (m_Samples.size() == m_ThreadsToUse); } - for (unsigned int i = 0; i < m_Samples.size(); i++) + for (size_t i = 0; i < m_Samples.size(); i++) { if (m_Samples[i].size() != m_SubBatchSize) { @@ -1134,13 +785,13 @@ bool Renderer::ResetBuckets(bool resetHist, bool resetAccum) //parallel_invoke( //[&] //{ - if (resetHist && !m_HistBuckets.empty()) - memset((void*)m_HistBuckets.data(), 0, m_HistBuckets.size() * sizeof(m_HistBuckets[0])); + if (resetHist && !m_HistBuckets.empty()) + Memset(m_HistBuckets); //}, //[&] //{ - if (resetAccum && !m_AccumulatorBuckets.empty()) - memset(m_AccumulatorBuckets.data(), 0, m_AccumulatorBuckets.size() * sizeof(m_AccumulatorBuckets[0])); + if (resetAccum && !m_AccumulatorBuckets.empty()) + Memset(m_AccumulatorBuckets); //}); return resetHist || resetAccum; @@ -1155,26 +806,26 @@ bool Renderer::ResetBuckets(bool resetHist, bool resetAccum) template eRenderStatus Renderer::LogScaleDensityFilter() { - unsigned int startRow = 0; - unsigned int endRow = m_SuperRasH; - unsigned int startCol = 0; - unsigned int endCol = m_SuperRasW; + size_t startRow = 0; + size_t endRow = m_SuperRasH; + size_t startCol = 0; + size_t endCol = m_SuperRasW; //Timing t(4); //Original didn't parallelize this, doing so gives a 50-75% speedup. //If there is only one pass, the value can be directly assigned, which is quicker than summing. if (Passes() == 1) { - parallel_for(startRow, endRow, [&] (unsigned int j) + parallel_for(startRow, endRow, [&] (size_t j) { - unsigned int row = j * m_SuperRasW; + size_t row = j * m_SuperRasW; //__m128 logm128;//Figure out SSE at some point. //__m128 bucketm128; //__m128 scaledBucket128; - for (unsigned int i = startCol; (i < endCol) && !m_Abort; i++) + for (size_t i = startCol; (i < endCol) && !m_Abort; i++) { - unsigned int index = row + i; + size_t index = row + i; //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. if (m_HistBuckets[index].a != 0) @@ -1190,13 +841,13 @@ eRenderStatus Renderer::LogScaleDensityFilter() } else//Passes > 1, so sum. { - parallel_for(startRow, endRow, [&] (unsigned int j) + parallel_for(startRow, endRow, [&] (size_t j) { - unsigned int row = j * m_SuperRasW; + size_t row = j * m_SuperRasW; - for (unsigned int i = startCol; (i < endCol) && !m_Abort; i++) + for (size_t i = startCol; (i < endCol) && !m_Abort; i++) { - unsigned int index = row + i; + size_t index = row + i; //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. if (m_HistBuckets[index].a != 0) @@ -1229,48 +880,48 @@ template eRenderStatus Renderer::GaussianDensityFilter() { Timing totalTime, localTime; - int scf = !(Supersample() & 1); - unsigned int ss = Floor(Supersample() / T(2)); + bool scf = !(Supersample() & 1); + intmax_t ss = Floor(Supersample() / T(2)); T scfact = pow(Supersample() / (Supersample() + T(1.0)), T(2.0)); - - unsigned int threads = m_ThreadsToUse; - unsigned int startRow = Supersample() - 1; - unsigned int endRow = m_SuperRasH - (Supersample() - 1);//Original did + which is most likely wrong. - unsigned int startCol = Supersample() - 1; - unsigned int endCol = m_SuperRasW - (Supersample() - 1); - unsigned int chunkSize = (unsigned int)ceil(double(endRow - startRow) / double(threads)); - + + size_t threads = m_ThreadsToUse; + size_t startRow = Supersample() - 1; + size_t endRow = m_SuperRasH - (Supersample() - 1);//Original did + which is most likely wrong. + intmax_t startCol = Supersample() - 1; + intmax_t endCol = m_SuperRasW - (Supersample() - 1); + size_t chunkSize = (size_t)ceil(double(endRow - startRow) / double(threads)); + //parallel_for scales very well, dividing the work almost perfectly among all processors. - parallel_for((unsigned int)0, threads, [&] (unsigned int threadIndex) + parallel_for(0ULL, threads, [&] (size_t threadIndex) { - unsigned int pixelNumber = 0; - unsigned int localStartRow = min(startRow + (threadIndex * chunkSize), endRow - 1); - unsigned int localEndRow = min(localStartRow + chunkSize, endRow); - unsigned int pixelsThisThread = (localEndRow - localStartRow) * m_SuperRasW; + size_t pixelNumber = 0; + int localStartRow = (int)min(startRow + (threadIndex * chunkSize), endRow - 1); + int localEndRow = (int)min(localStartRow + chunkSize, endRow); + size_t pixelsThisThread = size_t(localEndRow - localStartRow) * m_SuperRasW; double lastPercent = 0; glm::detail::tvec4 logScaleBucket; - - for (unsigned int j = localStartRow; (j < localEndRow) && !m_Abort; j++) + + for (intmax_t j = localStartRow; (j < localEndRow) && !m_Abort; j++) { - unsigned int bucketRowStart = j * m_SuperRasW;//Pull out of inner loop for optimization. + size_t bucketRowStart = j * m_SuperRasW;//Pull out of inner loop for optimization. const glm::detail::tvec4* bucket; const glm::detail::tvec4* buckets = m_HistBuckets.data(); const T* filterCoefs = m_DensityFilter->Coefs(); const T* filterWidths = m_DensityFilter->Widths(); - - for (unsigned int i = startCol; i < endCol; i++) + + for (intmax_t i = startCol; i < endCol; i++) { - int ii, jj, arrFilterWidth; - unsigned int filterSelectInt, filterCoefIndex; + intmax_t ii, jj, arrFilterWidth; + size_t filterSelectInt, filterCoefIndex; T filterSelect = 0; bucket = buckets + bucketRowStart + i; - + //Don't do anything if there's no hits here. Must also put this first to avoid dividing by zero below. if (bucket->a == 0) continue; - + T cacheLog = (m_K1 * log(T(1.0) + bucket->a * m_K2)) / bucket->a;//Caching this calculation gives a 30% speedup. - + if (ss == 0) { filterSelect = bucket->a; @@ -1280,37 +931,37 @@ eRenderStatus Renderer::GaussianDensityFilter() //The original contained a glaring flaw as it would run past the boundaries of the buffers //when calculating the density for a box centered on the last row or column. //Clamp here to not run over the edge. - int densityBoxLeftX = i - min(i, ss); - int densityBoxRightX = i + min(ss, m_SuperRasW - i - 1); - int densityBoxTopY = j - min(j, ss); - int densityBoxBottomY = j + min(ss, m_SuperRasH - j - 1); - + intmax_t densityBoxLeftX = (i - min(i, ss)); + intmax_t densityBoxRightX = (i + min(ss, (intmax_t)m_SuperRasW - i - 1)); + intmax_t densityBoxTopY = (j - min(j, ss)); + intmax_t densityBoxBottomY = (j + min(ss, (intmax_t)m_SuperRasH - j - 1)); + //Count density in ssxss area. //Original went one col at a time, which is cache inefficient. Go one row at at time here for a slight speedup. for (jj = densityBoxTopY; jj <= densityBoxBottomY; jj++) for (ii = densityBoxLeftX; ii <= densityBoxRightX; ii++) filterSelect += buckets[ii + (jj * m_SuperRasW)].a;//Original divided by 255 in every iteration. Omit here because colors are already in the range of [0..1]. } - + //Scale if supersample > 1 for equal iters. if (scf) filterSelect *= scfact; - + if (filterSelect > m_DensityFilter->MaxFilteredCounts()) filterSelectInt = m_DensityFilter->MaxFilterIndex(); else if (filterSelect <= DE_THRESH) - filterSelectInt = (int)ceil(filterSelect) - 1; + filterSelectInt = (size_t)ceil(filterSelect) - 1; else - filterSelectInt = (int)DE_THRESH + Floor(pow(filterSelect - DE_THRESH, m_DensityFilter->Curve())); - + filterSelectInt = DE_THRESH + (size_t)Floor(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()) filterSelectInt = m_DensityFilter->MaxFilterIndex(); - + //Only have to calculate the values for ~1/8 of the square. filterCoefIndex = filterSelectInt * m_DensityFilter->KernelSize(); - arrFilterWidth = (int)ceil(filterWidths[filterSelectInt]) - 1; - + arrFilterWidth = (intmax_t)ceil(filterWidths[filterSelectInt]) - 1; + for (jj = 0; jj <= arrFilterWidth; jj++) { for (ii = 0; ii <= jj; ii++, filterCoefIndex++) @@ -1318,12 +969,12 @@ eRenderStatus Renderer::GaussianDensityFilter() //Skip if coef is 0. if (filterCoefs[filterCoefIndex] == 0) continue; - + T logScale = filterCoefs[filterCoefIndex] * cacheLog; - + //Original first assigned the fields, then scaled them. Combine into a single step for a 1% optimization. logScaleBucket = (*bucket * bucketT(logScale)); - + if (jj == 0 && ii == 0) { AddToAccum(logScaleBucket, i, ii, j, jj); @@ -1357,28 +1008,28 @@ eRenderStatus Renderer::GaussianDensityFilter() } } } - + if (m_Callback && threadIndex == 0) { pixelNumber += m_SuperRasW; double percent = (double(pixelNumber) / double(pixelsThisThread)) * 100.0; double percentDiff = percent - lastPercent; double toc = localTime.Toc(); - + if (percentDiff >= 10 || (toc > 1000 && percentDiff >= 1)) { double etaMs = ((100.0 - percent) / percent) * totalTime.Toc(); - + if (!m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, percent, 1, etaMs)) Abort(); - + lastPercent = percent; localTime.Tic(); } } } }); - + if (m_Callback && !m_Abort) m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 1, 0); @@ -1416,7 +1067,7 @@ eRenderStatus Renderer::AccumulatorToFinalImage(unsigned char* pixel EnterFinalAccum(); //Timing t(4); - unsigned int filterWidth = m_SpatialFilter->FinalFilterWidth(); + size_t filterWidth = m_SpatialFilter->FinalFilterWidth(); T g, linRange, vibrancy; Color background; @@ -1427,11 +1078,11 @@ eRenderStatus Renderer::AccumulatorToFinalImage(unsigned char* pixel //The original does it this way as well and it's roughly 11 times faster to do it this way than inline below with each pixel. if (EarlyClip()) { - parallel_for((unsigned int)0, m_SuperRasH, [&] (unsigned int j) + parallel_for(0ULL, m_SuperRasH, [&] (size_t j) { - unsigned int rowStart = j * m_SuperRasW;//Pull out of inner loop for optimization. + size_t rowStart = j * m_SuperRasW;//Pull out of inner loop for optimization. - for (unsigned int i = 0; i < m_SuperRasW && !m_Abort; i++) + for (size_t i = 0; i < m_SuperRasW && !m_Abort; i++) { GammaCorrection(m_AccumulatorBuckets[i + rowStart], background, g, linRange, vibrancy, true, false, &(m_AccumulatorBuckets[i + rowStart][0]));//Write back in place. } @@ -1447,26 +1098,26 @@ eRenderStatus Renderer::AccumulatorToFinalImage(unsigned char* pixel //Note that abort is not checked here. The final accumulation must run to completion //otherwise artifacts that resemble page tearing will occur in an interactive run. It's //critical to never exit this loop prematurely. - //for (unsigned int j = 0; j < FinalRasH(); j++)//Keep around for debugging. - parallel_for((unsigned int)0, FinalRasH(), [&] (unsigned int j) + //for (size_t j = 0; j < FinalRasH(); j++)//Keep around for debugging. + parallel_for(0ULL, FinalRasH(), [&](size_t j) { Color newBucket; - int pixelsRowStart = (m_YAxisUp ? ((FinalRasH() - j) - 1) : j) * FinalRowSize();//Pull out of inner loop for optimization. - unsigned int y = m_DensityFilterOffset + (j * Supersample());//Start at the beginning row of each super sample block. + size_t pixelsRowStart = (m_YAxisUp ? ((FinalRasH() - j) - 1) : j) * FinalRowSize();//Pull out of inner loop for optimization. + size_t y = m_DensityFilterOffset + (j * Supersample());//Start at the beginning row of each super sample block. unsigned short* p16; - for (unsigned int i = 0; i < FinalRasW(); i++, pixelsRowStart += PixelSize()) + for (size_t i = 0; i < FinalRasW(); i++, pixelsRowStart += PixelSize()) { - unsigned int ii, jj; - unsigned int x = m_DensityFilterOffset + (i * Supersample());//Start at the beginning column of each super sample block. + size_t ii, jj; + size_t x = m_DensityFilterOffset + (i * Supersample());//Start at the beginning column of each super sample block. newBucket.Clear(); //Original was iterating column-wise, which is slow. //Here, iterate one row at a time, giving a 10% speed increase. for (jj = 0; jj < filterWidth; jj++) { - unsigned int filterKRowIndex = jj * filterWidth; - unsigned int accumRowIndex = (y + jj) * m_SuperRasW;//Pull out of inner loop for optimization. + size_t filterKRowIndex = jj * filterWidth; + size_t accumRowIndex = (y + jj) * m_SuperRasW;//Pull out of inner loop for optimization. for (ii = 0; ii < filterWidth; ii++) { @@ -1527,7 +1178,7 @@ eRenderStatus Renderer::AccumulatorToFinalImage(unsigned char* pixel //Insert the palette into the image for debugging purposes. Only works with 8bpc. if (m_InsertPalette && BytesPerChannel() == 1) { - unsigned int i, j, ph = 100; + size_t i, j, ph = 100; if (ph >= FinalRasH()) ph = FinalRasH(); @@ -1566,28 +1217,28 @@ eRenderStatus Renderer::AccumulatorToFinalImage(unsigned char* pixel /// The temporal sample within the current pass this is running for /// Rendering statistics template -EmberStats Renderer::Iterate(uint64_t iterCount, unsigned int pass, unsigned int temporalSample) +EmberStats Renderer::Iterate(size_t iterCount, size_t pass, size_t temporalSample) { //Timing t2(4); m_IterTimer.Tic(); - unsigned int fuse = EarlyClip() ? 100 : 15;//EarlyClip was one way of detecting a later version of flam3, so it used 100 which is a better value. - uint64_t totalItersPerThread = (uint64_t)ceil((double)iterCount / (double)m_ThreadsToUse); + size_t fuse = EarlyClip() ? 100 : 15;//EarlyClip was one way of detecting a later version of flam3, so it used 100 which is a better value. + size_t totalItersPerThread = (size_t)ceil((double)iterCount / (double)m_ThreadsToUse); double percent, etaMs; EmberStats stats; #ifdef TG - unsigned int threadIndex; + size_t threadIndex; - for (unsigned int i = 0; i < m_ThreadsToUse; i++) + for (size_t i = 0; i < m_ThreadsToUse; i++) { threadIndex = i; m_TaskGroup.run([&, threadIndex] () { #else - parallel_for((unsigned int)0, m_ThreadsToUse, [&] (unsigned int threadIndex) + parallel_for(0ULL, m_ThreadsToUse, [&] (size_t threadIndex) { #endif Timing t; - uint64_t subBatchSize = (unsigned int)min(totalItersPerThread, (uint64_t)m_SubBatchSize); + size_t subBatchSize = (size_t)min(totalItersPerThread, (size_t)m_SubBatchSize); m_BadVals[threadIndex] = 0; @@ -1609,14 +1260,14 @@ EmberStats Renderer::Iterate(uint64_t iterCount, unsigned int pass, //Finally, iterate. //t.Tic(); //Iterating, loop 4. - m_BadVals[threadIndex] += (uint64_t)m_Iterator->Iterate(m_Ember, (uint32_t)subBatchSize, fuse, m_Samples[threadIndex].data(), m_Rand[threadIndex]); + m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, subBatchSize, fuse, m_Samples[threadIndex].data(), m_Rand[threadIndex]); //iterationTime += t.Toc(); if (m_LockAccum) m_AccumCs.Enter(); //t.Tic(); //Map temp buffer samples into the histogram using the palette for color. - Accumulate(m_Samples[threadIndex].data(), (unsigned int)subBatchSize, &m_Dmap); + Accumulate(m_Samples[threadIndex].data(), subBatchSize, &m_Dmap); //accumulationTime += t.Toc(); if (m_LockAccum) m_AccumCs.Leave(); @@ -1670,203 +1321,9 @@ EmberStats Renderer::Iterate(uint64_t iterCount, unsigned int pass, } /// -/// Accessors for render properties. +/// Non-virtual render properties, getters and setters. /// -/// -/// Get a copy of the vector of random contexts. -/// Useful for debugging because the returned vector can be used for future renders to -/// produce the exact same output. -/// -/// The vector of random contexts to assign -template -vector> Renderer::RandVec() { return m_Rand; } - -/// -/// Set the vector of random contexts. -/// Assignment will only take place if the size of the vector matches -/// the number of threads used for rendering. -/// Reset the rendering process. -/// -/// The vector of random contexts to assign -/// True if the size of the vector matched the number of threads used for rendering, else false. -template -bool Renderer::RandVec(vector>& randVec) -{ - bool b = false; - - if (randVec.size() == ThreadCount()) - { - ChangeVal([&] - { - m_Rand = randVec; - b = true; - }, FULL_RENDER); - } - - return b; -} - -/// -/// Get whether the histogram is locked during accumulation. -/// This is to prevent two threads from writing to the same histogram -/// bucket at once. -/// The current implementation matches flam3 and is very innefficient -/// to the point of negating any gains gotten from multi-threading. -/// Future workarounds may be tried in the future. -/// Default: false. -/// -/// True if the histogram is locked during accumulation, else false. -template -bool Renderer::LockAccum() const { return m_LockAccum; } - -/// -/// Set whether the histogram is locked during accumulation. -/// This is to prevent two threads from writing to the same histogram -/// bucket at once. -/// The current implementation matches flam3 and is very innefficient -/// to the point of negating any gains gotten from multi-threading. -/// Different workarounds may be tried in the future. -/// Reset the rendering process. -/// -/// True if the histogram should be locked when accumulating, else false -template -void Renderer::LockAccum(bool lockAccum) -{ - ChangeVal([&] { m_LockAccum = lockAccum; }, FULL_RENDER); -} - -/// -/// Get whether color clipping and gamma correction is done before -/// or after spatial filtering. -/// Default: false. -/// -/// True if early clip, else false. -template -bool Renderer::EarlyClip() const { return m_EarlyClip; } - -/// -/// Set whether color clipping and gamma correction is done before -/// or after spatial filtering. -/// Set the render state to FILTER_AND_ACCUM. -/// -/// True if early clip, else false. -template -void Renderer::EarlyClip(bool earlyClip) -{ - ChangeVal([&] { m_EarlyClip = earlyClip; }, FILTER_AND_ACCUM); -} - -/// -/// Get whether the positive Y coordinate of the final output image is up. -/// Default: false. -/// -/// True if up, else false. -template -bool Renderer::YAxisUp() const { return m_YAxisUp; } - -/// -/// Set whether the positive Y axis of the final output image is up. -/// -/// True if the positive y axis is up, else false. -template -void Renderer::YAxisUp(bool yup) -{ - ChangeVal([&] { m_YAxisUp = yup; }, ACCUM_ONLY); -} - -/// -/// Get whether to insert the palette as a block of colors in the final output image. -/// This is useful for debugging palette issues. -/// Default: 1. -/// -/// True if inserting the palette, else false. -template -bool Renderer::InsertPalette() const { return m_InsertPalette; } - -/// -/// Set whether to insert the palette as a block of colors in the final output image. -/// This is useful for debugging palette issues. -/// Set the render state to ACCUM_ONLY. -/// -/// True if inserting the palette, else false. -template -void Renderer::InsertPalette(bool insertPalette) -{ - ChangeVal([&] { m_InsertPalette = insertPalette; }, ACCUM_ONLY); -} - -/// -/// Get whether to reclaim unused memory in the final output buffer -/// when a smaller size is requested than has been previously allocated. -/// Default: false. -/// -/// True if reclaim, else false. -template -bool Renderer::ReclaimOnResize() const { return m_ReclaimOnResize; } - -/// -/// Set whether to reclaim unused memory in the final output buffer -/// when a smaller size is requested than has been previously allocated. -/// Reset the rendering process. -/// -/// True if reclaim, else false. -template -void Renderer::ReclaimOnResize(bool reclaimOnResize) -{ - ChangeVal([&] { m_ReclaimOnResize = reclaimOnResize; }, FULL_RENDER); -} - -/// -/// Get whether to use transparency in the alpha channel. -/// This only applies when the number of channels is 4 and the output -/// image is Png. -/// Default: false. -/// -/// True if using transparency, else false. -template bool Renderer::Transparency() const { return m_Transparency; } - -/// -/// Set whether to use transparency in the alpha channel. -/// This only applies when the number of channels is 4 and the output -/// image is Png. -/// Set the render state to ACCUM_ONLY. -/// -/// True if using transparency, else false. -template -void Renderer::Transparency(bool transparency) -{ - ChangeVal([&] { m_Transparency = transparency; }, ACCUM_ONLY); -} - -/// -/// Get the bytes per channel of the output image. -/// The only acceptable values are 1 and 2, and 2 is only -/// used when the output is Png. -/// Default: 1. -/// -/// -template unsigned int Renderer::BytesPerChannel() const { return m_BytesPerChannel; } - -/// -/// Set the bytes per channel of the output image. -/// The only acceptable values are 1 and 2, and 2 is only -/// used when the output is Png. -/// Set the render state to ACCUM_ONLY. -/// -/// The bytes per channel. -template -void Renderer::BytesPerChannel(unsigned int bytesPerChannel) -{ - ChangeVal([&] - { - if (bytesPerChannel == 0 || bytesPerChannel > 2) - m_BytesPerChannel = 1; - else - m_BytesPerChannel = bytesPerChannel; - }, ACCUM_ONLY); -} - /// /// Get the pixel aspect ratio of the output image. /// Default: 1. @@ -1886,28 +1343,78 @@ void Renderer::PixelAspectRatio(T pixelAspectRatio) } /// -/// Get the type of filter to use for preview renders during interactive rendering. -/// Using basic log scaling is quicker, but doesn't provide any bluring. -/// Full DE is much slower, but provides a more realistic preview of what the final image -/// will look like. -/// Default: FILTER_LOG. +/// Non-virtual renderer properties, getters only. /// -/// The type of filter to use -template eInteractiveFilter Renderer::InteractiveFilter() const { return m_InteractiveFilter; } + +template T Renderer::Scale() const { return m_Scale; } +template T Renderer::PixelsPerUnitX() const { return m_PixelsPerUnitX; } +template T Renderer::PixelsPerUnitY() const { return m_PixelsPerUnitY; } +template T Renderer::K1() const { return m_K1; } +template T Renderer::K2() const { return m_K2; } +template const CarToRas* Renderer::CoordMap() const { return &m_CarToRas; } +template glm::detail::tvec4* Renderer::HistBuckets() { return m_HistBuckets.data(); } +template glm::detail::tvec4* Renderer::AccumulatorBuckets() { return m_AccumulatorBuckets.data(); } +template SpatialFilter* Renderer::GetSpatialFilter() { return m_SpatialFilter.get(); } +template TemporalFilter* Renderer::GetTemporalFilter() { return m_TemporalFilter.get(); } /// -/// Set the type of filter to use for preview renders during interactive rendering. -/// Using basic log scaling is quicker, but doesn't provide any bluring. -/// Full DE is much slower, but provides a more realistic preview of what the final image -/// will look like. -/// Reset the rendering process. +/// Virtual renderer properties overridden from RendererBase, getters only. /// -/// The filter. -template -void Renderer::InteractiveFilter(eInteractiveFilter filter) -{ - ChangeVal([&] { m_InteractiveFilter = filter; }, FULL_RENDER); -} + +template double Renderer::ScaledQuality() const { return (double)m_ScaledQuality; } +template double Renderer::LowerLeftX(bool gutter) const { return (double)(gutter ? m_CarToRas.CarLlX() : m_LowerLeftX); } +template double Renderer::LowerLeftY(bool gutter) const { return (double)(gutter ? m_CarToRas.CarLlY() : m_LowerLeftY); } +template double Renderer::UpperRightX(bool gutter) const { return (double)(gutter ? m_CarToRas.CarUrX() : m_UpperRightX); } +template double Renderer::UpperRightY(bool gutter) const { return (double)(gutter ? m_CarToRas.CarUrY() : m_UpperRightY); } +template DensityFilterBase* Renderer::GetDensityFilter() { return m_DensityFilter.get(); } + +/// +/// Non-virtual ember wrappers, getters only. +/// + +template bool Renderer::XaosPresent() const { return m_Ember.XaosPresent(); } +template size_t Renderer::Supersample() const { return m_Ember.m_Supersample; } +template size_t Renderer::PaletteIndex() const { return m_Ember.PaletteIndex(); } +template T Renderer::Time() const { return m_Ember.m_Time; } +template T Renderer::Quality() const { return m_Ember.m_Quality; } +template T Renderer::SpatialFilterRadius() const { return m_Ember.m_SpatialFilterRadius; } +template T Renderer::PixelsPerUnit() const { return m_Ember.m_PixelsPerUnit; } +template T Renderer::Zoom() const { return m_Ember.m_Zoom; } +template T Renderer::CenterX() const { return m_Ember.m_CenterX; } +template T Renderer::CenterY() const { return m_Ember.m_CenterY; } +template T Renderer::Rotate() const { return m_Ember.m_Rotate; } +template T Renderer::Hue() const { return m_Ember.m_Hue; } +template T Renderer::Brightness() const { return m_Ember.m_Brightness; } +template T Renderer::Gamma() const { return m_Ember.m_Gamma; } +template T Renderer::Vibrancy() const { return m_Ember.m_Vibrancy; } +template T Renderer::GammaThresh() const { return m_Ember.m_GammaThresh; } +template T Renderer::HighlightPower() const { return m_Ember.m_HighlightPower; } +template Color Renderer::Background() const { return m_Ember.m_Background; } +template const Xform* Renderer::Xforms() const { return m_Ember.Xforms(); } +template Xform* Renderer::NonConstXforms() { return m_Ember.NonConstXforms(); } +template size_t Renderer::XformCount() const { return m_Ember.XformCount(); } +template const Xform* Renderer::FinalXform() const { return m_Ember.FinalXform(); } +template Xform* Renderer::NonConstFinalXform() { return m_Ember.NonConstFinalXform(); } +template bool Renderer::UseFinalXform() const { return m_Ember.UseFinalXform(); } +template const Palette* Renderer::GetPalette() const { return &m_Ember.m_Palette; } +template ePaletteMode Renderer::PaletteMode() const { return m_Ember.m_PaletteMode; } + +/// +/// Virtual ember wrappers overridden from RendererBase, getters only. +/// + +template size_t Renderer::Passes() const { return m_Ember.m_Passes; } +template size_t Renderer::TemporalSamples() const { return m_Ember.m_TemporalSamples; } +template size_t Renderer::FinalRasW() const { return m_Ember.m_FinalRasW; } +template size_t Renderer::FinalRasH() const { return m_Ember.m_FinalRasH; } + +/// +/// Non-virtual iterator wrappers. +/// + +template const unsigned char* Renderer::XformDistributions() const { return m_Iterator != nullptr ? m_Iterator->XformDistributions() : nullptr; } +template const size_t Renderer::XformDistributionsSize() const { return m_Iterator != nullptr ? m_Iterator->XformDistributionsSize() : 0; } +template Point* Renderer::Samples(size_t threadIndex) const { return threadIndex < m_Samples.size() ? (Point*)m_Samples[threadIndex].data() : nullptr; } /// /// Non-virtual functions that might be needed by a derived class. @@ -1926,7 +1433,7 @@ void Renderer::PrepFinalAccumVals(Color& background, T& g, T& lin //If they are doing incremental rendering, they can get here without doing a full temporal //sample, which means the values will be zero. vibrancy = m_Vibrancy == 0 ? m_Ember.m_Vibrancy : m_Vibrancy; - unsigned int vibGamCount = m_VibGamCount == 0 ? 1 : m_VibGamCount; + size_t vibGamCount = m_VibGamCount == 0 ? 1 : m_VibGamCount; T gamma = m_Gamma == 0 ? m_Ember.m_Gamma : m_Gamma; g = T(1.0) / ClampGte(gamma / vibGamCount, T(0.01));//Ensure a divide by zero doesn't occur. linRange = GammaThresh(); @@ -1938,7 +1445,7 @@ void Renderer::PrepFinalAccumVals(Color& background, T& g, T& lin } /// -/// Miscellaneous functions used only in this class. +/// Miscellaneous non-virtual functions used only in this class. /// /// @@ -1949,9 +1456,9 @@ void Renderer::PrepFinalAccumVals(Color& background, T& g, T& lin /// The number of samples /// The palette to use template -void Renderer::Accumulate(Point* samples, unsigned int sampleCount, const Palette* palette) +void Renderer::Accumulate(Point* samples, size_t sampleCount, const Palette* palette) { - unsigned int histIndex, intColorIndex, histSize = (unsigned int)m_HistBuckets.size(); + size_t histIndex, intColorIndex, histSize = m_HistBuckets.size(); bucketT colorIndex, colorIndexFrac; const glm::detail::tvec4* dmap = &(palette->m_Entries[0]); @@ -1964,7 +1471,7 @@ void Renderer::Accumulate(Point* samples, unsigned int sampleCoun //Original used a function called bump_no_overflow(). Just do a straight add because the type will always be float or double. //Doing so gives a 25% speed increase. //Splitting these conditionals into separate loops makes no speed difference. - for (unsigned int i = 0; i < sampleCount && !m_Abort; i++) + for (size_t i = 0; i < sampleCount && !m_Abort; i++) { if (Rotate() != 0) { @@ -1999,7 +1506,7 @@ void Renderer::Accumulate(Point* samples, unsigned int sampleCoun if (PaletteMode() == PALETTE_LINEAR) { colorIndex = (bucketT)samples[i].m_ColorX * COLORMAP_LENGTH; - intColorIndex = (unsigned int)colorIndex; + intColorIndex = (size_t)colorIndex; if (intColorIndex < 0) { @@ -2023,7 +1530,7 @@ void Renderer::Accumulate(Point* samples, unsigned int sampleCoun } else if (PaletteMode() == PALETTE_STEP) { - intColorIndex = Clamp((unsigned int)(samples[i].m_ColorX * COLORMAP_LENGTH), 0, COLORMAP_LENGTH_MINUS_1); + intColorIndex = Clamp((size_t)(samples[i].m_ColorX * COLORMAP_LENGTH), 0, COLORMAP_LENGTH_MINUS_1); if (samples[i].m_VizAdjusted == 1) m_HistBuckets[histIndex] += dmap[intColorIndex]; @@ -2045,9 +1552,9 @@ void Renderer::Accumulate(Point* samples, unsigned int sampleCoun /// The row of the bucket /// The offset to add to the row template -void Renderer::AddToAccum(const glm::detail::tvec4& bucket, int i, int ii, int j, int jj) +void Renderer::AddToAccum(const glm::detail::tvec4& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj) { - if (j + jj >= 0 && j + jj < (int)m_SuperRasH && i + ii >= 0 && i + ii < (int)m_SuperRasW) + if (j + jj >= 0 && j + jj < (intmax_t)m_SuperRasH && i + ii >= 0 && i + ii < (intmax_t)m_SuperRasW) m_AccumulatorBuckets[(i + ii) + ((j + jj) * m_SuperRasW)] += bucket; } @@ -2089,7 +1596,7 @@ void Renderer::GammaCorrection(glm::detail::tvec4::template CalcNewRgb(&bucket[0], ls, HighlightPower(), newRgb); - for (unsigned int rgbi = 0; rgbi < 3; rgbi++) + for (glm::length_t rgbi = 0; rgbi < 3; rgbi++) { a = newRgb[rgbi] + ((T(1.0) - vibrancy) * T(255) * pow(T(bucket[rgbi]), g)); @@ -2121,125 +1628,4 @@ void Renderer::GammaCorrection(glm::detail::tvec4::max();//Final accum, 4 channels, but not using transparency. 255 for 8 bpc, 65535 for 16 bpc. } } - -/// -/// Set the m_Iterator member to point to the appropriate -/// iterator based on whether the ember currently being rendered -/// contains xaos. -/// After assigning, initialize the xform selection buffer. -/// -/// True if assignment and distribution initialization succeeded, else false. -template -bool Renderer::AssignIterator() -{ - //Setup iterator and distributions. - //Both iterator types were setup in the constructor (add more in the future if needed). - //So simply assign the pointer to the correct type and re-initialize its distributions - //based on the current ember. - if (XaosPresent()) - m_Iterator = m_XaosIterator.get(); - else - m_Iterator = m_StandardIterator.get(); - - //Timing t; - return m_Iterator->InitDistributions(m_Ember); - //t.Toc("Distrib creation"); -} - -/// -/// Threading control. -/// - -template void Renderer::EnterRender() { m_RenderingCs.Enter(); } -template void Renderer::LeaveRender() { m_RenderingCs.Leave(); } - -template void Renderer::EnterFinalAccum() { m_FinalAccumCs.Enter(); m_InFinalAccum = true; } -template void Renderer::LeaveFinalAccum() { m_FinalAccumCs.Leave(); m_InFinalAccum = false; } - -template void Renderer::EnterResize() { m_ResizeCs.Enter(); } -template void Renderer::LeaveResize() { m_ResizeCs.Leave(); } - -template void Renderer::Abort() { m_Abort = true; } -template bool Renderer::Aborted() { return m_Abort; } - -template bool Renderer::InRender() { return m_InRender; } -template bool Renderer::InFinalAccum() { return m_InFinalAccum; } - -/// -/// Renderer properties, getters only. -/// - -template unsigned int Renderer::SuperRasW() const { return m_SuperRasW; } -template unsigned int Renderer::SuperRasH() const { return m_SuperRasH; } -template unsigned int Renderer::SuperSize() const { return m_SuperSize; } -template unsigned int Renderer::FinalBufferSize() const { return FinalRowSize() * FinalRasH(); } -template unsigned int Renderer::FinalRowSize() const { return FinalRasW() * PixelSize(); } -template unsigned int Renderer::FinalDimensions() const { return FinalRasW() * FinalRasH(); } -template unsigned int Renderer::PixelSize() const { return NumChannels() * BytesPerChannel(); } -template unsigned int Renderer::GutterWidth() const { return m_GutterWidth; } -template unsigned int Renderer::DensityFilterOffset() const { return m_DensityFilterOffset; } -template double Renderer::ScaledQuality() const { return m_ScaledQuality; } -template T Renderer::Scale() const { return m_Scale; } -template T Renderer::PixelsPerUnitX() const { return m_PixelsPerUnitX; } -template T Renderer::PixelsPerUnitY() const { return m_PixelsPerUnitY; } -template double Renderer::LowerLeftX(bool gutter) const { return gutter ? m_CarToRas.CarLlX() : m_LowerLeftX; } -template double Renderer::LowerLeftY(bool gutter) const { return gutter ? m_CarToRas.CarLlY() : m_LowerLeftY; } -template double Renderer::UpperRightX(bool gutter) const { return gutter ? m_CarToRas.CarUrX() : m_UpperRightX; } -template double Renderer::UpperRightY(bool gutter) const { return gutter ? m_CarToRas.CarUrY() : m_UpperRightY; } -template T Renderer::K1() const { return m_K1; } -template T Renderer::K2() const { return m_K2; } -template uint64_t Renderer::TotalIterCount() const { return (uint64_t)((uint64_t)Round(m_ScaledQuality) * (uint64_t)FinalRasW() * (uint64_t)FinalRasH()); }//Use Round() because there can be some roundoff error when interpolating. -template uint64_t Renderer::ItersPerTemporalSample() const { return (uint64_t)ceil(double(TotalIterCount()) / double(Passes() * TemporalSamples())); } -template eProcessState Renderer::ProcessState() const { return m_ProcessState; } -template eProcessAction Renderer::ProcessAction() const { return m_ProcessAction; } -template EmberStats Renderer::Stats() const { return m_Stats; } -template const CarToRas* Renderer::CoordMap() const { return &m_CarToRas; } -template glm::detail::tvec4* Renderer::HistBuckets() { return m_HistBuckets.data(); } -template glm::detail::tvec4* Renderer::AccumulatorBuckets() { return m_AccumulatorBuckets.data(); } -template SpatialFilter* Renderer::GetSpatialFilter() { return m_SpatialFilter.get(); } -template TemporalFilter* Renderer::GetTemporalFilter() { return m_TemporalFilter.get(); } -template DensityFilter* Renderer::GetDensityFilter() { return m_DensityFilter.get(); } - -/// -/// Ember wrappers, getters only. -/// - -template bool Renderer::XaosPresent() { return m_Ember.XaosPresent(); } -template unsigned int Renderer::FinalRasW() const { return m_Ember.m_FinalRasW; } -template unsigned int Renderer::FinalRasH() const { return m_Ember.m_FinalRasH; } -template unsigned int Renderer::Supersample() const { return m_Ember.m_Supersample; } -template unsigned int Renderer::Passes() const { return m_Ember.m_Passes; } -template unsigned int Renderer::TemporalSamples() const { return m_Ember.m_TemporalSamples; } -template unsigned int Renderer::PaletteIndex() const { return m_Ember.PaletteIndex(); } -template T Renderer::Time() const { return m_Ember.m_Time; } -template T Renderer::Quality() const { return m_Ember.m_Quality; } -template T Renderer::SpatialFilterRadius() const { return m_Ember.m_SpatialFilterRadius; } -template T Renderer::PixelsPerUnit() const { return m_Ember.m_PixelsPerUnit; } -template T Renderer::Zoom() const { return m_Ember.m_Zoom; } -template T Renderer::CenterX() const { return m_Ember.m_CenterX; } -template T Renderer::CenterY() const { return m_Ember.m_CenterY; } -template T Renderer::Rotate() const { return m_Ember.m_Rotate; } -template T Renderer::Hue() const { return m_Ember.m_Hue; } -template T Renderer::Brightness() const { return m_Ember.m_Brightness; } -template T Renderer::Gamma() const { return m_Ember.m_Gamma; } -template T Renderer::Vibrancy() const { return m_Ember.m_Vibrancy; } -template T Renderer::GammaThresh() const { return m_Ember.m_GammaThresh; } -template T Renderer::HighlightPower() const { return m_Ember.m_HighlightPower; } -template Color Renderer::Background() const { return m_Ember.m_Background; } -template const Xform* Renderer::Xforms() const { return m_Ember.Xforms(); } -template Xform* Renderer::NonConstXforms() { return m_Ember.NonConstXforms(); } -template unsigned int Renderer::XformCount() const { return m_Ember.XformCount(); } -template const Xform* Renderer::FinalXform() const { return m_Ember.FinalXform(); } -template Xform* Renderer::NonConstFinalXform() { return m_Ember.NonConstFinalXform(); } -template bool Renderer::UseFinalXform() const { return m_Ember.UseFinalXform(); } -template const Palette* Renderer::GetPalette() const { return &m_Ember.m_Palette; } -template ePaletteMode Renderer::PaletteMode() const { return m_Ember.m_PaletteMode; } - -/// -/// Iterator wrappers. -/// - -template const unsigned char* Renderer::XformDistributions() const { return m_Iterator != nullptr ? m_Iterator->XformDistributions() : nullptr; } -template const unsigned int Renderer::XformDistributionsSize() const { return m_Iterator != nullptr ? m_Iterator->XformDistributionsSize() : 0; } -template Point* Renderer::Samples(unsigned int threadIndex) const { return threadIndex < m_Samples.size() ? (Point*)m_Samples[threadIndex].data() : nullptr; } } diff --git a/Source/Ember/Renderer.h b/Source/Ember/Renderer.h index 6b6fb32..8c0a6e3 100644 --- a/Source/Ember/Renderer.h +++ b/Source/Ember/Renderer.h @@ -1,149 +1,19 @@ #pragma once -#include "Ember.h" +#include "RendererBase.h" #include "Iterator.h" -#include "Utils.h" #include "SpatialFilter.h" -#include "DensityFilter.h" #include "TemporalFilter.h" #include "Interpolate.h" #include "CarToRas.h" #include "EmberToXml.h" /// -/// Renderer, RenderCallback and EmberStats classes. +/// Renderer. /// namespace EmberNs { -/// -/// Function pointers present a major restriction when dealing -/// with member functions, and that is they can only point to -/// static ones. So instead of a straight function pointer, use -/// a callback class with a single virtual callback -/// member function. -/// Template argument expected to be float or double. -/// -class EMBER_API RenderCallback -{ -public: - /// - /// Virtual destructor to ensure anything declared in derived classes gets cleaned up. - /// - virtual ~RenderCallback() { } - - /// - /// Empty progress function to be implemented in derived classes to take action on progress updates. - /// - /// The ember currently being rendered - /// An extra dummy parameter - /// The progress fraction from 0-100 - /// The stage of iteration. 1 is iterating, 2 is density filtering, 2 is final accumulation. - /// The estimated milliseconds to completion of the current stage - /// Override should return 0 if an abort is requested, else 1 to continue rendering - virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) { return 0; } - virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) { return 0; } -}; - -/// -/// Render statistics for the number of iterations ran, -/// number of bad values calculated during iteration, and -/// the total time for the entire render from the start of -/// iteration to the end of final accumulation. -/// -class EMBER_API EmberStats -{ -public: - /// - /// Constructor which sets all values to 0. - /// - EmberStats() - { - Clear(); - } - - void Clear() - { - m_Iters = 0; - m_Badvals = 0; - m_IterMs = 0; - m_RenderMs = 0; - } - - uint64_t m_Iters, m_Badvals; - double m_IterMs, m_RenderMs; -}; - -/// -/// The types of available renderers. -/// Add more in the future as different rendering methods are experimented with. -/// Possible values might be: CPU+OpenGL, Particle, Inverse. -/// -enum eRendererType { CPU_RENDERER, OPENCL_RENDERER }; - -/// -/// A base class with virtual functions to allow both templating and polymorphism to work together. -/// Derived classes will implement all of these functions. -/// Note that functions which return a decimal number use the most precise type, double. -/// -class EMBER_API RendererBase : public EmberReport -{ -public: - RendererBase() { } - virtual ~RendererBase() { } - virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER) { } - virtual void SetEmber(vector>& embers) { } - virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER) { } - virtual void SetEmber(vector>& embers) { } - virtual void Callback(RenderCallback* callback) { } - virtual bool CreateSpatialFilter(bool& newAlloc) { return false; } - virtual bool CreateTemporalFilter(bool& newAlloc) { return false; } - virtual void ComputeBounds() { } - virtual bool Ok() const { return false; } - virtual void Reset() { } - virtual void EnterRender() { } - virtual void LeaveRender() { } - virtual void EnterFinalAccum() { } - virtual void LeaveFinalAccum() { } - virtual void EnterResize() { } - virtual void LeaveResize() { } - virtual void Abort() { } - virtual bool Aborted() { return false; } - virtual bool InRender() { return false; } - virtual bool InFinalAccum() { return false; } - virtual unsigned int NumChannels() const { return 0; } - virtual void NumChannels(unsigned int numChannels) { } - virtual eRendererType RendererType() const { return CPU_RENDERER; } - virtual void ReclaimOnResize(bool reclaimOnResize) { } - virtual bool EarlyClip() const { return false; } - virtual void EarlyClip(bool earlyClip) { } - virtual bool YAxisUp() const { return false; } - virtual void YAxisUp(bool yup) { } - virtual void ThreadCount(unsigned int threads, const char* seedString = nullptr) { } - virtual void Transparency(bool transparency) { } - virtual void InteractiveFilter(eInteractiveFilter filter) { } - virtual unsigned int FinalRasW() const { return 0; } - virtual unsigned int FinalRasH() const { return 0; } - virtual unsigned int SuperRasW() const { return 0; } - virtual unsigned int SuperRasH() const { return 0; } - virtual unsigned int FinalBufferSize() const { return 0; } - virtual unsigned int GutterWidth() const { return 0; } - virtual double ScaledQuality() const { return 0; } - virtual double LowerLeftX(bool gutter = true) const { return 0; } - virtual double LowerLeftY(bool gutter = true) const { return 0; } - virtual double UpperRightX(bool gutter = true) const { return 0; } - virtual double UpperRightY(bool gutter = true) const { return 0; } - virtual uint64_t MemoryRequired(bool includeFinal) { return 0; } - virtual uint64_t MemoryAvailable() { return 0; } - virtual bool PrepFinalAccumVector(vector& pixels) { return false; } - virtual eProcessState ProcessState() const { return NONE; } - virtual eProcessAction ProcessAction() const { return NOTHING; } - virtual EmberStats Stats() const { EmberStats stats; return stats; } - virtual eRenderStatus Run(vector& finalImage, double time = 0, unsigned int subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) { return RENDER_ERROR; } - virtual EmberImageComments ImageComments(unsigned int printEditDepth = 0, bool intPalette = false, bool hexPalette = true) { EmberImageComments comments; return comments; } - virtual DensityFilterBase* GetDensityFilter() { return nullptr; } -}; - /// /// Renderer is the main class where all of the execution takes place. /// It is intended that the program have one instance of it that it @@ -154,7 +24,7 @@ public: /// The final image output vector is also passed in because the calling code has more /// use for it than this class does. /// Several functions are made virtual and have a default CPU-based implementation -/// that roughly matches what flam3 did. However they can be overriden in derived classes +/// that roughly matches what flam3 did. However they can be overridden in derived classes /// to provide alternative rendering implementations, such as using the GPU. /// Since this is a templated class, it's supposed to be entirely implemented in this .h file. /// However, VC++ 2010 has very crippled support for lambdas, which Renderer makes use of. @@ -179,36 +49,24 @@ public: Renderer(); virtual ~Renderer(); - virtual void ComputeBounds(); + //Non-virtual processing functions. void ComputeCamera(); - void ChangeVal(std::function func, eProcessAction action); - virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER); - virtual void SetEmber(vector>& embers); void AddEmber(Ember& ember); - bool CreateTemporalFilter(bool& newAlloc); bool AssignIterator(); - virtual bool PrepFinalAccumVector(vector& pixels); - virtual eRenderStatus Run(vector& finalImage, double time = 0, unsigned int subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0); - virtual EmberImageComments ImageComments(unsigned int printEditDepth = 0, bool intPalette = false, bool hexPalette = true); - virtual uint64_t MemoryRequired(bool includeFinal); - //Virtual functions to be overriden in derived renderers that use the GPU. - virtual uint64_t MemoryAvailable(); - virtual void Reset(); - virtual bool Ok() const; - virtual bool CreateDEFilter(bool& newAlloc); - virtual bool CreateSpatialFilter(bool& newAlloc); - virtual unsigned int SubBatchSize() const; - virtual void SubBatchSize(unsigned int sbs); - virtual unsigned int NumChannels() const; - virtual void NumChannels(unsigned int numChannels); - virtual eRendererType RendererType() const; - virtual unsigned int ThreadCount() const; - virtual void ThreadCount(unsigned int threads, const char* seedString = nullptr); - virtual void Callback(RenderCallback* callback); + //Virtual processing functions overriden from RendererBase. + virtual void ComputeBounds() override; + virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER) override; + virtual void SetEmber(vector>& embers) override; + virtual bool CreateDEFilter(bool& newAlloc) override; + virtual bool CreateSpatialFilter(bool& newAlloc) override; + virtual bool CreateTemporalFilter(bool& newAlloc) override; + virtual size_t HistBucketSize() const override { return sizeof(glm::detail::tvec4); } + virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) override; + virtual EmberImageComments ImageComments(EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) override; protected: - //Virtual functions to be overriden in derived renderers that use the GPU, but not accessed outside. + //New virtual functions to be overridden in derived renderers that use the GPU, but not accessed outside. virtual void MakeDmap(T colorScalar); virtual bool Alloc(); virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true); @@ -216,148 +74,84 @@ protected: virtual eRenderStatus GaussianDensityFilter(); virtual eRenderStatus AccumulatorToFinalImage(vector& pixels, size_t finalOffset); virtual eRenderStatus AccumulatorToFinalImage(unsigned char* pixels, size_t finalOffset); - virtual EmberStats Iterate(uint64_t iterCount, unsigned int pass, unsigned int temporalSample); + virtual EmberStats Iterate(size_t iterCount, size_t pass, size_t temporalSample); public: - //Accessors for render properties. - vector> RandVec(); - bool RandVec(vector>& randVec); - - inline bool LockAccum() const; - void LockAccum(bool lockAccum); - - virtual bool EarlyClip() const; - virtual void EarlyClip(bool earlyClip); - - virtual bool YAxisUp() const; - virtual void YAxisUp(bool yup); - - inline bool InsertPalette() const; - void InsertPalette(bool insertPalette); - - inline bool ReclaimOnResize() const; - virtual void ReclaimOnResize(bool reclaimOnResize); - - inline bool Transparency() const; - virtual void Transparency(bool transparency); - - inline unsigned int BytesPerChannel() const; - void BytesPerChannel(unsigned int bytesPerChannel); - + //Non-virtual render properties, getters and setters. inline T PixelAspectRatio() const; void PixelAspectRatio(T pixelAspectRatio); - inline eInteractiveFilter InteractiveFilter() const; - virtual void InteractiveFilter(eInteractiveFilter filter); - - //Threading control. - virtual void EnterRender(); - virtual void LeaveRender(); - virtual void EnterFinalAccum(); - virtual void LeaveFinalAccum(); - virtual void EnterResize(); - virtual void LeaveResize(); - virtual void Abort(); - virtual bool Aborted(); - virtual bool InRender(); - virtual bool InFinalAccum(); - - //Renderer properties, getters only. - virtual unsigned int SuperRasW() const; - virtual unsigned int SuperRasH() const; - inline unsigned int SuperSize() const; - virtual unsigned int FinalBufferSize() const; - inline unsigned int FinalRowSize() const; - unsigned int FinalDimensions() const; - inline unsigned int PixelSize() const; - virtual unsigned int GutterWidth() const; - inline unsigned int DensityFilterOffset() const; - virtual double ScaledQuality() const; + //Non-virtual renderer properties, getters only. inline T Scale() const; inline T PixelsPerUnitX() const; inline T PixelsPerUnitY() const; - virtual double LowerLeftX(bool gutter = true) const; - virtual double LowerLeftY(bool gutter = true) const; - virtual double UpperRightX(bool gutter = true) const; - virtual double UpperRightY(bool gutter = true) const; inline T K1() const; inline T K2() const; - inline uint64_t TotalIterCount() const; - inline uint64_t ItersPerTemporalSample() const; - virtual eProcessState ProcessState() const; - virtual eProcessAction ProcessAction() const; - virtual EmberStats Stats() const; inline const CarToRas* CoordMap() const; inline glm::detail::tvec4* HistBuckets(); inline glm::detail::tvec4* AccumulatorBuckets(); inline SpatialFilter* GetSpatialFilter(); inline TemporalFilter* GetTemporalFilter(); - virtual DensityFilter* GetDensityFilter(); - //Ember wrappers, getters only. - inline bool XaosPresent(); - unsigned int FinalRasW() const; - unsigned int FinalRasH() const; - inline unsigned int Supersample() const; - inline unsigned int Passes() const; - inline unsigned int TemporalSamples() const; - inline unsigned int PaletteIndex() const; - inline T Time() const; - inline T Quality() const; - inline T SpatialFilterRadius() const; - inline T PixelsPerUnit() const; - inline T Zoom() const; - inline T CenterX() const; - inline T CenterY() const; - inline T Rotate() const; - inline T Hue() const; - inline T Brightness() const; - inline T Contrast() const; - inline T Gamma() const; - inline T Vibrancy() const; - inline T GammaThresh() const; - inline T HighlightPower() const; - inline Color Background() const; - inline const Xform* Xforms() const; - inline Xform* NonConstXforms(); - inline unsigned int XformCount() const; - inline const Xform* FinalXform() const; - inline Xform* NonConstFinalXform(); - inline bool UseFinalXform() const; - inline const Palette* GetPalette() const; - inline ePaletteMode PaletteMode() const; + //Virtual renderer properties overridden from RendererBase, getters only. + virtual double ScaledQuality() const override; + virtual double LowerLeftX(bool gutter = true) const override; + virtual double LowerLeftY(bool gutter = true) const override; + virtual double UpperRightX(bool gutter = true) const override; + virtual double UpperRightY(bool gutter = true) const override; + virtual DensityFilterBase* GetDensityFilter() override; - //Iterator wrappers. - const unsigned char* XformDistributions() const; - const unsigned int XformDistributionsSize() const; - Point* Samples(unsigned int threadIndex) const; + //Non-virtual ember wrappers, getters only. + inline bool XaosPresent() const; + inline size_t Supersample() const; + inline size_t PaletteIndex() const; + inline T Time() const; + inline T Quality() const; + inline T SpatialFilterRadius() const; + inline T PixelsPerUnit() const; + inline T Zoom() const; + inline T CenterX() const; + inline T CenterY() const; + inline T Rotate() const; + inline T Hue() const; + inline T Brightness() const; + inline T Contrast() const; + inline T Gamma() const; + inline T Vibrancy() const; + inline T GammaThresh() const; + inline T HighlightPower() const; + inline Color Background() const; + inline const Xform* Xforms() const; + inline Xform* NonConstXforms(); + inline size_t XformCount() const; + inline const Xform* FinalXform() const; + inline Xform* NonConstFinalXform(); + inline bool UseFinalXform() const; + inline const Palette* GetPalette() const; + inline ePaletteMode PaletteMode() const; - void* m_ProgressParameter; + //Virtual ember wrappers overridden from RendererBase, getters only. + virtual size_t Passes() const override; + virtual size_t TemporalSamples() const override; + virtual size_t FinalRasW() const override; + virtual size_t FinalRasH() const override; + + //Non-virtual iterator wrappers. + const unsigned char* XformDistributions() const; + const size_t XformDistributionsSize() const; + Point* Samples(size_t threadIndex) const; protected: //Non-virtual functions that might be needed by a derived class. void PrepFinalAccumVals(Color& background, T& g, T& linRange, T& vibrancy); private: - //Miscellaneous functions used only in this class. - void Accumulate(Point* samples, unsigned int sampleCount, const Palette* palette); - /*inline*/ void AddToAccum(const glm::detail::tvec4& bucket, int i, int ii, int j, int jj); + //Miscellaneous non-virtual functions used only in this class. + void Accumulate(Point* samples, size_t sampleCount, const Palette* palette); + /*inline*/ void AddToAccum(const glm::detail::tvec4& bucket, intmax_t i, intmax_t ii, intmax_t j, intmax_t jj); template void GammaCorrection(glm::detail::tvec4& bucket, Color& background, T g, T linRange, T vibrancy, bool doAlpha, bool scale, accumT* correctedChannels); protected: - bool m_EarlyClip; - bool m_YAxisUp; - bool m_Transparency; - unsigned int m_SuperRasW; - unsigned int m_SuperRasH; - unsigned int m_SuperSize; - unsigned int m_GutterWidth; - unsigned int m_DensityFilterOffset; - unsigned int m_NumChannels; - unsigned int m_BytesPerChannel; - unsigned int m_SubBatchSize; - unsigned int m_ThreadsToUse; - T m_ScaledQuality; T m_Scale; T m_PixelsPerUnitX; T m_PixelsPerUnitY; @@ -370,30 +164,14 @@ protected: T m_K2; T m_Vibrancy;//Accumulate these after each temporal sample. T m_Gamma; + T m_ScaledQuality; Color m_Background; Affine2D m_RotMat; - - volatile bool m_Abort; - bool m_LockAccum; - bool m_InRender; - bool m_InFinalAccum; - bool m_InsertPalette; - bool m_ReclaimOnResize; - unsigned int m_VibGamCount; - unsigned int m_LastPass; - unsigned int m_LastTemporalSample; - uint64_t m_LastIter; - double m_LastIterPercent; - eProcessAction m_ProcessAction; - eProcessState m_ProcessState; - eInteractiveFilter m_InteractiveFilter; - EmberStats m_Stats; Ember m_Ember; Ember m_TempEmber; Ember m_LastEmber; vector> m_Embers; CarToRas m_CarToRas; - RenderCallback* m_Callback; Iterator* m_Iterator; unique_ptr> m_StandardIterator; unique_ptr> m_XaosIterator; @@ -404,12 +182,6 @@ protected: unique_ptr> m_TemporalFilter; unique_ptr> m_DensityFilter; vector>> m_Samples; - vector m_SubBatch; - vector m_BadVals; - vector> m_Rand; - tbb::task_group m_TaskGroup; - CriticalSection m_RenderingCs, m_AccumCs, m_FinalAccumCs, m_ResizeCs; - Timing m_RenderTimer, m_IterTimer, m_ProgressTimer; EmberToXml m_EmberToXml; }; diff --git a/Source/Ember/RendererBase.cpp b/Source/Ember/RendererBase.cpp new file mode 100644 index 0000000..9d82832 --- /dev/null +++ b/Source/Ember/RendererBase.cpp @@ -0,0 +1,635 @@ +#include "EmberPch.h" +#include "RendererBase.h" + +namespace EmberNs +{ +/// +/// Constructor that sets default values. +/// The thread count is set to the number of cores detected on the system. +/// +RendererBase::RendererBase() +{ + m_Abort = false; + m_LockAccum = false; + m_EarlyClip = false; + m_YAxisUp = false; + m_InsertPalette = false; + m_ReclaimOnResize = false; + m_SubBatchSize = 1024 * 10; + m_NumChannels = 3; + m_BytesPerChannel = 1; + m_SuperSize = 0; + m_Transparency = false; + ThreadCount(Timing::ProcessorCount()); + m_Callback = nullptr; + m_ProgressParameter = nullptr; + m_LastPass = 0; + m_LastTemporalSample = 0; + m_LastIter = 0; + m_LastIterPercent = 0; + m_InteractiveFilter = FILTER_LOG; + m_ProcessState = NONE; + m_ProcessAction = FULL_RENDER; + m_InRender = false; + m_InFinalAccum = false; +} + +/// +/// Non-virtual processing functions. +/// + +/// +/// Abort the render and call a function to do something, most likely change a value. +/// Then update the current process action to the one specified. +/// The current process action will only be set if it makes sense based +/// on the current process state. If the value specified doesn't make sense +/// the next best choice will be made. If nothing makes sense, a complete +/// re-render will be triggered on the next call to Run(). +/// +/// The function to execute +/// The desired process action +void RendererBase::ChangeVal(std::function func, eProcessAction action) +{ + Abort(); + EnterRender(); + func(); + + //If they want a full render, don't bother inspecting process state, just start over. + if (action == FULL_RENDER) + { + m_ProcessState = NONE; + m_ProcessAction = FULL_RENDER; + } + //Keep iterating is when rendering has completed and the user increases the quality. + //Rendering can be started where it left off by adding just the difference between the + //new and old quality values. + else if (action == KEEP_ITERATING) + { + if (m_ProcessState == ACCUM_DONE && TemporalSamples() == 1 && Passes() == 1) + { + m_ProcessState = ITER_STARTED; + m_ProcessAction = KEEP_ITERATING; + } + else//Invaid process state to handle KEEP_ITERATING, so just start over. + { + m_ProcessState = NONE; + m_ProcessAction = FULL_RENDER; + } + } + else if (action == FILTER_AND_ACCUM) + { + //If in the middle of a render, cannot skip to filtering or accum, so just start over. + if (m_ProcessState == NONE || m_ProcessState == ITER_STARTED) + { + m_ProcessState = NONE; + m_ProcessAction = FULL_RENDER; + } + //If passes == 1, set the state to ITER_DONE and the next process action to FILTER_AND_ACCUM. + else + { + m_ProcessState = Passes() == 1 ? ITER_DONE : NONE; + m_ProcessAction = Passes() == 1 ? FILTER_AND_ACCUM : FULL_RENDER;//Cannot just filter if passes > 1 because filtering is done with each pass. + } + } + //Run accum only. + else if (action == ACCUM_ONLY) + { + //Doesn't make sense if in the middle of iterating, so just start over. + if (m_ProcessState == NONE || m_ProcessState == ITER_STARTED) + { + m_ProcessAction = FULL_RENDER; + } + else if (m_ProcessState == ITER_DONE)//If iterating is done, can start at density filtering and proceed. + { + m_ProcessAction = FILTER_AND_ACCUM; + } + else if (m_ProcessState == FILTER_DONE)//Density filtering is done, so the process action is assigned as desired. + { + m_ProcessAction = ACCUM_ONLY; + } + else if (m_ProcessState == ACCUM_DONE)//Final accum is done, so back up and run final accum again. + { + m_ProcessState = FILTER_DONE; + m_ProcessAction = ACCUM_ONLY; + } + } + + LeaveRender(); +} + +/// +/// Return the amount of memory needed to render the current ember. +/// Optionally include the memory needed for the final output image. +/// +/// If true include the memory needed for the final output image, else don't. +/// The memory required to render the current ember +size_t RendererBase::MemoryRequired(size_t strips, bool includeFinal) +{ + bool newFilterAlloc = false; + + CreateSpatialFilter(newFilterAlloc); + CreateTemporalFilter(newFilterAlloc); + ComputeBounds(); + + //Because ComputeBounds() was called, this includes gutter. + size_t histSize = (SuperSize() * HistBucketSize()) / strips; + + return (histSize * 2) + (includeFinal ? FinalBufferSize() : 0);//Multiply hist by 2 to account for the density filtering buffer which is the same size as the histogram. +} + +/// +/// Get a copy of the vector of random contexts. +/// Useful for debugging because the returned vector can be used for future renders to +/// produce the exact same output. +/// +/// The vector of random contexts to assign +vector> RendererBase::RandVec() { return m_Rand; } + +/// +/// Set the vector of random contexts. +/// Assignment will only take place if the size of the vector matches +/// the number of threads used for rendering. +/// Reset the rendering process. +/// +/// The vector of random contexts to assign +/// True if the size of the vector matched the number of threads used for rendering, else false. +bool RendererBase::RandVec(vector>& randVec) +{ + bool b = false; + + if (randVec.size() == ThreadCount()) + { + ChangeVal([&] + { + m_Rand = randVec; + b = true; + }, FULL_RENDER); + } + + return b; +} + +/// +/// Resize the passed in vector to be large enough to handle the output image. +/// If m_ReclaimOnResize is true, and the vector is already larger than needed, +/// it will be shrunk to the needed size. However if m_ReclaimOnResize is false, +/// it will be left alone if already large enough. +/// ComputeBounds() must be called before calling this function. +/// +/// The vector to allocate +/// True if the vector contains enough space to hold the output image +bool RendererBase::PrepFinalAccumVector(vector& pixels) +{ + EnterResize(); + size_t size = FinalBufferSize(); + + if (m_ReclaimOnResize) + { + if (pixels.size() != size) + { + pixels.resize(size); + pixels.shrink_to_fit(); + } + } + else + { + if (pixels.size() < size) + pixels.resize(size); + } + + LeaveResize(); + + return pixels.size() >= size;//Ensure allocation went ok. +} + +/// +/// Virtual processing functions. +/// + +/// +/// Get a status indicating whether this renderer is ok. +/// Return true for this class, derived classes will inspect GPU hardware +/// to determine if they are ok. +/// +/// Always true for this class +bool RendererBase::Ok() const +{ + return true; +} + +/// +/// The amount of RAM available to render with. +/// +/// An unsigned 64-bit integer specifying how much memory is available +size_t RendererBase::MemoryAvailable() +{ + size_t memAvailable = 0; + +#ifdef WIN32 + + MEMORYSTATUSEX stat; + + stat.dwLength = sizeof(stat); + GlobalMemoryStatusEx(&stat); + memAvailable = stat.ullTotalPhys; + +#elif defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) + + memAvailable = sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE); + +#elif defined __APPLE__ + +#ifdef __LP64__ + long physmem; + size_t len = sizeof(physmem); + static int mib[2] = { CTL_HW, HW_MEMSIZE }; +#else + size_t physmem; + size_t len = sizeof(physmem); + static int mib[2] = { CTL_HW, HW_PHYSMEM }; +#endif + + if (sysctl(mib, 2, &physmem, &len, nullptr, 0) == 0 && len == sizeof(physmem)) + { + memAvailable = physmem; + } + else + { + cout << "Warning: unable to determine physical memory." << endl; + memAvailable = 4e9; + } + +#else + + cout << "Warning: unable to determine physical memory." << endl; + memAvailable = 4e9; + +#endif + + return memAvailable; +} + +/// +/// Non-virtual renderer properties, getters only. +/// + +size_t RendererBase::SuperRasW() const { return m_SuperRasW; } +size_t RendererBase::SuperRasH() const { return m_SuperRasH; } +size_t RendererBase::SuperSize() const { return m_SuperSize; } +size_t RendererBase::FinalRowSize() const { return FinalRasW() * PixelSize(); } +size_t RendererBase::FinalDimensions() const { return FinalRasW() * FinalRasH(); } +size_t RendererBase::FinalBufferSize() const { return FinalRowSize() * FinalRasH(); } +size_t RendererBase::PixelSize() const { return NumChannels() * BytesPerChannel(); } +size_t RendererBase::GutterWidth() const { return m_GutterWidth; } +size_t RendererBase::DensityFilterOffset() const { return m_DensityFilterOffset; } +size_t RendererBase::TotalIterCount() const { return (size_t)((size_t)Round(ScaledQuality()) * FinalRasW() * FinalRasH()); }//Use Round() because there can be some roundoff error when interpolating. +size_t RendererBase::ItersPerTemporalSample() const { return (size_t)ceil(double(TotalIterCount()) / double(Passes() * TemporalSamples())); } +eProcessState RendererBase::ProcessState() const { return m_ProcessState; } +eProcessAction RendererBase::ProcessAction() const { return m_ProcessAction; } +EmberStats RendererBase::Stats() const { return m_Stats; } + +/// +/// Non-virtual render properties, getters and setters. +/// + +/// +/// Get whether the histogram is locked during accumulation. +/// This is to prevent two threads from writing to the same histogram +/// bucket at once. +/// The current implementation matches flam3 and is very innefficient +/// to the point of negating any gains gotten from multi-threading. +/// Future workarounds may be tried in the future. +/// Default: false. +/// +/// True if the histogram is locked during accumulation, else false. +bool RendererBase::LockAccum() const { return m_LockAccum; } + +/// +/// Set whether the histogram is locked during accumulation. +/// This is to prevent two threads from writing to the same histogram +/// bucket at once. +/// The current implementation matches flam3 and is very innefficient +/// to the point of negating any gains gotten from multi-threading. +/// Different workarounds may be tried in the future. +/// Reset the rendering process. +/// +/// True if the histogram should be locked when accumulating, else false +void RendererBase::LockAccum(bool lockAccum) +{ + ChangeVal([&] { m_LockAccum = lockAccum; }, FULL_RENDER); +} + +/// +/// Get whether color clipping and gamma correction is done before +/// or after spatial filtering. +/// Default: false. +/// +/// True if early clip, else false. +bool RendererBase::EarlyClip() const { return m_EarlyClip; } + +/// +/// Set whether color clipping and gamma correction is done before +/// or after spatial filtering. +/// Set the render state to FILTER_AND_ACCUM. +/// +/// True if early clip, else false. +void RendererBase::EarlyClip(bool earlyClip) +{ + ChangeVal([&] { m_EarlyClip = earlyClip; }, FILTER_AND_ACCUM); +} + +/// +/// Get whether the positive Y coordinate of the final output image is up. +/// Default: false. +/// +/// True if up, else false. +bool RendererBase::YAxisUp() const { return m_YAxisUp; } + +/// +/// Set whether the positive Y axis of the final output image is up. +/// +/// True if the positive y axis is up, else false. +void RendererBase::YAxisUp(bool yup) +{ + ChangeVal([&] { m_YAxisUp = yup; }, ACCUM_ONLY); +} + +/// +/// Get whether to insert the palette as a block of colors in the final output image. +/// This is useful for debugging palette issues. +/// Default: 1. +/// +/// True if inserting the palette, else false. +bool RendererBase::InsertPalette() const { return m_InsertPalette; } + +/// +/// Set whether to insert the palette as a block of colors in the final output image. +/// This is useful for debugging palette issues. +/// Set the render state to ACCUM_ONLY. +/// +/// True if inserting the palette, else false. +void RendererBase::InsertPalette(bool insertPalette) +{ + ChangeVal([&] { m_InsertPalette = insertPalette; }, ACCUM_ONLY); +} + +/// +/// Get whether to reclaim unused memory in the final output buffer +/// when a smaller size is requested than has been previously allocated. +/// Default: false. +/// +/// True if reclaim, else false. +bool RendererBase::ReclaimOnResize() const { return m_ReclaimOnResize; } + +/// +/// Set whether to reclaim unused memory in the final output buffer +/// when a smaller size is requested than has been previously allocated. +/// Reset the rendering process. +/// +/// True if reclaim, else false. +void RendererBase::ReclaimOnResize(bool reclaimOnResize) +{ + ChangeVal([&] { m_ReclaimOnResize = reclaimOnResize; }, FULL_RENDER); +} + +/// +/// Get whether to use transparency in the alpha channel. +/// This only applies when the number of channels is 4 and the output +/// image is Png. +/// Default: false. +/// +/// True if using transparency, else false. +bool RendererBase::Transparency() const { return m_Transparency; } + +/// +/// Set whether to use transparency in the alpha channel. +/// This only applies when the number of channels is 4 and the output +/// image is Png. +/// Set the render state to ACCUM_ONLY. +/// +/// True if using transparency, else false. +void RendererBase::Transparency(bool transparency) +{ + ChangeVal([&] { m_Transparency = transparency; }, ACCUM_ONLY); +} + +/// +/// Set the sub batch size. This is the size of of the chunks that the iteration +/// trajectory will be broken up into. +/// Reset the rendering process. +/// +/// The sub batch size to set +void RendererBase::SubBatchSize(size_t sbs) +{ + ChangeVal([&] { m_SubBatchSize = sbs; }, FULL_RENDER); +} + +/// +/// Set the callback object. +/// +/// The callback object to set +void RendererBase::Callback(RenderCallback* callback) +{ + m_Callback = callback; +} + +/// +/// Set the number of threads to use when rendering. +/// This will also reset the vector of random contexts to be the same size +/// as the number of specified threads. +/// Since this is where they get set up, the caller can optionally pass in +/// a seed string, however it's only used if threads is 1. +/// This is useful for debugging since it will run the same point trajectory +/// every time. +/// Reset the rendering process. +/// +/// The number of threads to use +/// The seed string to use if threads is 1. Default: nullptr. +void RendererBase::ThreadCount(size_t threads, const char* seedString) +{ + ChangeVal([&] + { + Timing t; + size_t i, size; + const size_t isaacSize = 1 << ISAAC_SIZE; + ISAAC_INT seeds[isaacSize]; + m_ThreadsToUse = threads > 0 ? threads : 1; + m_Rand.clear(); + m_SubBatch.clear(); + m_SubBatch.resize(m_ThreadsToUse); + m_BadVals.resize(m_ThreadsToUse); + + if (seedString) + { + memset(seeds, 0, isaacSize * sizeof(ISAAC_INT)); + memcpy((char*)seeds, seedString, min(strlen(seedString), isaacSize * sizeof(ISAAC_INT))); + } + + //This is critical for multithreading, otherwise the threads all happen + //too close to each other in time, resulting in bad randomization. + while (m_Rand.size() < m_ThreadsToUse) + { + size = m_Rand.size(); + + if (seedString) + { + ISAAC_INT newSize = (ISAAC_INT)(size + 5 + (t.Toc() + t.EndTime())); + +#ifdef ISAAC_FLAM3_DEBUG + QTIsaac isaac(0, 0, 0, seeds); +#else + QTIsaac isaac(newSize, newSize * 2, newSize * 3, seeds); +#endif + m_Rand.push_back(isaac); + + for (i = 0; i < (isaacSize * sizeof(ISAAC_INT)); i++) + ((unsigned char*)seeds)[i]++; + } + else + { + for (i = 0; i < isaacSize; i++) + { + t.Toc(); + seeds[i] = (ISAAC_INT)((t.EndTime() * i) + (size + 1)); + } + + t.Toc(); + ISAAC_INT r = (ISAAC_INT)((size * i) + i + t.EndTime()); + QTIsaac isaac(r, r * 2, r * 3, seeds); + + m_Rand.push_back(isaac); + } + } + }, FULL_RENDER); +} + +/// +/// Get the bytes per channel of the output image. +/// The only acceptable values are 1 and 2, and 2 is only +/// used when the output is Png. +/// Default: 1. +/// +/// +size_t RendererBase::BytesPerChannel() const { return m_BytesPerChannel; } + +/// +/// Set the bytes per channel of the output image. +/// The only acceptable values are 1 and 2, and 2 is only +/// used when the output is Png. +/// Set the render state to ACCUM_ONLY. +/// +/// The bytes per channel. +void RendererBase::BytesPerChannel(size_t bytesPerChannel) +{ + ChangeVal([&] + { + if (bytesPerChannel == 0 || bytesPerChannel > 2) + m_BytesPerChannel = 1; + else + m_BytesPerChannel = bytesPerChannel; + }, ACCUM_ONLY); +} + +/// +/// Get the number of channels per pixel in the output image. 3 for RGB images +/// like Bitmap and Jpeg, 4 for Png. +/// Default is 3. +/// +/// The number of channels per pixel in the output image +size_t RendererBase::NumChannels() const { return m_NumChannels; } + +/// +/// Get the type of filter to use for preview renders during interactive rendering. +/// Using basic log scaling is quicker, but doesn't provide any bluring. +/// Full DE is much slower, but provides a more realistic preview of what the final image +/// will look like. +/// Default: FILTER_LOG. +/// +/// The type of filter to use +eInteractiveFilter RendererBase::InteractiveFilter() const { return m_InteractiveFilter; } + +/// +/// Set the type of filter to use for preview renders during interactive rendering. +/// Using basic log scaling is quicker, but doesn't provide any bluring. +/// Full DE is much slower, but provides a more realistic preview of what the final image +/// will look like. +/// Reset the rendering process. +/// +/// The filter. +void RendererBase::InteractiveFilter(eInteractiveFilter filter) +{ + ChangeVal([&] { m_InteractiveFilter = filter; }, FULL_RENDER); +} + +/// +/// Virtual render properties, getters and setters. +/// + +/// +/// Set the number of channels per pixel in the output image. 3 for RGB images +/// like Bitmap and Jpeg, 4 for Png. +/// Default is 3. +/// Set the render state to ACCUM_ONLY. +/// +/// The number of channels per pixel in the output image +void RendererBase::NumChannels(size_t numChannels) +{ + ChangeVal([&] { m_NumChannels = numChannels; }, ACCUM_ONLY); +} + +/// +/// Get the number of threads used when rendering. +/// Default: use all avaliable cores. +/// +/// The number of threads used when rendering +size_t RendererBase::ThreadCount() const { return m_ThreadsToUse; } + +/// +/// Get the sub batch size. This is the size of of the chunks that the iteration +/// trajectory will be broken up into. +/// Default: 10k. +/// +/// The sub batch size +size_t RendererBase::SubBatchSize() const { return m_SubBatchSize; } + +/// +/// Get the renderer type enum. +/// CPU_RENDERER for this class, other values for derived classes. +/// +/// CPU_RENDERER +eRendererType RendererBase::RendererType() const { return CPU_RENDERER; } + +/// +/// //Non-virtual threading control. +/// + +/// +/// Stop rendering, ensure all locks are exited and reset the rendering state. +/// +void RendererBase::Reset() +{ + Abort(); + EnterRender(); + EnterFinalAccum(); + LeaveFinalAccum(); + LeaveRender(); + m_ProcessState = NONE; + m_ProcessAction = FULL_RENDER; +} + +void RendererBase::EnterRender() { m_RenderingCs.Enter(); } +void RendererBase::LeaveRender() { m_RenderingCs.Leave(); } + +void RendererBase::EnterFinalAccum() { m_FinalAccumCs.Enter(); m_InFinalAccum = true; } +void RendererBase::LeaveFinalAccum() { m_FinalAccumCs.Leave(); m_InFinalAccum = false; } + +void RendererBase::EnterResize() { m_ResizeCs.Enter(); } +void RendererBase::LeaveResize() { m_ResizeCs.Leave(); } + +void RendererBase::Abort() { m_Abort = true; } +bool RendererBase::Aborted() { return m_Abort; } + +bool RendererBase::InRender() { return m_InRender; } +bool RendererBase::InFinalAccum() { return m_InFinalAccum; } + +} \ No newline at end of file diff --git a/Source/Ember/RendererBase.h b/Source/Ember/RendererBase.h new file mode 100644 index 0000000..27c6c40 --- /dev/null +++ b/Source/Ember/RendererBase.h @@ -0,0 +1,229 @@ +#pragma once + +#include "Utils.h" +#include "Ember.h" +#include "DensityFilter.h" + +/// +/// RendererBase, RenderCallback and EmberStats classes. +/// + +namespace EmberNs +{ +/// +/// Function pointers present a major restriction when dealing +/// with member functions, and that is they can only point to +/// static ones. So instead of a straight function pointer, use +/// a callback class with a single virtual callback +/// member function. +/// Template argument expected to be float or double. +/// +class EMBER_API RenderCallback +{ +public: + /// + /// Virtual destructor to ensure anything declared in derived classes gets cleaned up. + /// + virtual ~RenderCallback() { } + + /// + /// Empty progress function to be implemented in derived classes to take action on progress updates. + /// + /// The ember currently being rendered + /// An extra dummy parameter + /// The progress fraction from 0-100 + /// The stage of iteration. 1 is iterating, 2 is density filtering, 2 is final accumulation. + /// The estimated milliseconds to completion of the current stage + /// Override should return 0 if an abort is requested, else 1 to continue rendering + virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) { return 0; } + virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) { return 0; } +}; + +/// +/// Render statistics for the number of iterations ran, +/// number of bad values calculated during iteration, and +/// the total time for the entire render from the start of +/// iteration to the end of final accumulation. +/// +class EMBER_API EmberStats +{ +public: + /// + /// Constructor which sets all values to 0. + /// + EmberStats() + { + Clear(); + } + + void Clear() + { + m_Iters = 0; + m_Badvals = 0; + m_IterMs = 0; + m_RenderMs = 0; + } + + EmberStats& operator += (const EmberStats& stats) + { + m_Iters += stats.m_Iters; + m_Badvals += stats.m_Badvals; + m_IterMs += stats.m_IterMs; + m_RenderMs += stats.m_RenderMs; + return *this; + } + + size_t m_Iters, m_Badvals; + double m_IterMs, m_RenderMs; +}; + +/// +/// The types of available renderers. +/// Add more in the future as different rendering methods are experimented with. +/// Possible values might be: CPU+OpenGL, Particle, Inverse. +/// +enum eRendererType { CPU_RENDERER, OPENCL_RENDERER }; + +/// +/// A base class with virtual functions to allow both templating and polymorphism to work together. +/// Derived classes will implement all of these functions. +/// Note that functions which return a decimal number use the most precise type, double. +/// +class EMBER_API RendererBase : public EmberReport +{ +public: + RendererBase(); + virtual ~RendererBase() { } + + //Non-virtual processing functions. + void ChangeVal(std::function func, eProcessAction action); + size_t MemoryRequired(size_t strips, bool includeFinal); + vector> RandVec(); + bool RandVec(vector>& randVec); + bool PrepFinalAccumVector(vector& pixels); + + //Virtual processing functions. + virtual bool Ok() const; + virtual size_t MemoryAvailable(); + virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER) { } + virtual void SetEmber(vector>& embers) { } + virtual void SetEmber(Ember& ember, eProcessAction action = FULL_RENDER) { } + virtual void SetEmber(vector>& embers) { } + + //Abstract processing functions. + virtual bool CreateDEFilter(bool& newAlloc) = 0; + virtual bool CreateSpatialFilter(bool& newAlloc) = 0; + virtual bool CreateTemporalFilter(bool& newAlloc) = 0; + virtual void ComputeBounds() = 0; + virtual eRenderStatus Run(vector& finalImage, double time = 0, size_t subBatchCountOverride = 0, bool forceOutput = false, size_t finalOffset = 0) = 0; + virtual EmberImageComments ImageComments(EmberStats& stats, size_t printEditDepth = 0, bool intPalette = false, bool hexPalette = true) = 0; + virtual DensityFilterBase* GetDensityFilter() = 0; + + //Non-virtual renderer properties, getters only. + size_t SuperRasW() const; + size_t SuperRasH() const; + size_t SuperSize() const; + size_t FinalRowSize() const; + size_t FinalDimensions() const; + size_t FinalBufferSize() const; + size_t PixelSize() const; + size_t GutterWidth() const; + size_t DensityFilterOffset() const; + size_t TotalIterCount() const; + size_t ItersPerTemporalSample() const; + eProcessState ProcessState() const; + eProcessAction ProcessAction() const; + EmberStats Stats() const; + + //Non-virtual render getters and setters. + bool LockAccum() const; + void LockAccum(bool lockAccum); + bool EarlyClip() const; + void EarlyClip(bool earlyClip); + bool YAxisUp() const; + void YAxisUp(bool yup); + bool InsertPalette() const; + void InsertPalette(bool insertPalette); + bool ReclaimOnResize() const; + void ReclaimOnResize(bool reclaimOnResize); + bool Transparency() const; + void Transparency(bool transparency); + void SubBatchSize(size_t subBatchSize); + void Callback(RenderCallback* callback); + void ThreadCount(size_t threads, const char* seedString = nullptr); + size_t BytesPerChannel() const; + void BytesPerChannel(size_t bytesPerChannel); + size_t NumChannels() const; + eInteractiveFilter InteractiveFilter() const; + void InteractiveFilter(eInteractiveFilter filter); + + //Virtual render properties, getters and setters. + virtual void NumChannels(size_t numChannels); + virtual size_t ThreadCount() const; + virtual size_t SubBatchSize() const; + virtual eRendererType RendererType() const; + + //Abstract render properties, getters only. + virtual size_t Passes() const = 0; + virtual size_t TemporalSamples() const = 0; + virtual size_t HistBucketSize() const = 0; + virtual size_t FinalRasW() const = 0; + virtual size_t FinalRasH() const = 0; + virtual double ScaledQuality() const = 0; + virtual double LowerLeftX(bool gutter = true) const = 0; + virtual double LowerLeftY(bool gutter = true) const = 0; + virtual double UpperRightX(bool gutter = true) const = 0; + virtual double UpperRightY(bool gutter = true) const = 0; + + //Non-virtual threading control. + void Reset(); + void EnterRender(); + void LeaveRender(); + void EnterFinalAccum(); + void LeaveFinalAccum(); + void EnterResize(); + void LeaveResize(); + void Abort(); + bool Aborted(); + bool InRender(); + bool InFinalAccum(); + + void* m_ProgressParameter; + +protected: + bool m_EarlyClip; + bool m_YAxisUp; + bool m_Transparency; + bool m_LockAccum; + bool m_InRender; + bool m_InFinalAccum; + bool m_InsertPalette; + bool m_ReclaimOnResize; + volatile bool m_Abort; + size_t m_SuperRasW; + size_t m_SuperRasH; + size_t m_SuperSize; + size_t m_GutterWidth; + size_t m_DensityFilterOffset; + size_t m_NumChannels; + size_t m_BytesPerChannel; + size_t m_SubBatchSize; + size_t m_ThreadsToUse; + size_t m_VibGamCount; + size_t m_LastPass; + size_t m_LastTemporalSample; + double m_LastIterPercent; + size_t m_LastIter; + eProcessAction m_ProcessAction; + eProcessState m_ProcessState; + eInteractiveFilter m_InteractiveFilter; + EmberStats m_Stats; + RenderCallback* m_Callback; + vector m_SubBatch; + vector m_BadVals; + vector> m_Rand; + tbb::task_group m_TaskGroup; + CriticalSection m_RenderingCs, m_AccumCs, m_FinalAccumCs, m_ResizeCs; + Timing m_RenderTimer, m_IterTimer, m_ProgressTimer; +}; +} diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h index e79e323..f869474 100644 --- a/Source/Ember/SheepTools.h +++ b/Source/Ember/SheepTools.h @@ -61,7 +61,7 @@ public: /// /// The full path and filename of the palette file /// A pre-constructed renderer to use. The caller should not delete this. - SheepTools(string palettePath, Renderer* renderer) + SheepTools(const string& palettePath, Renderer* renderer) { Timing t; @@ -113,10 +113,10 @@ public: /// The ember whose xforms will be truncated /// The maximum number of variations each xform can have /// A string describing what was done - string TruncateVariations(Ember& ember, unsigned int maxVars) + string TruncateVariations(Ember& ember, size_t maxVars) { - int smallest; - unsigned int i, j, numVars; + intmax_t smallest; + size_t i, j, numVars; T sv = 0; ostringstream os; @@ -188,7 +188,8 @@ public: /// A string describing what was done string Mutate(Ember& ember, eMutateMode mode, vector& useVars, int sym, T speed) { - unsigned int i, j, k, x, done, modXform; + bool done = false; + size_t modXform; char ministr[32]; T randSelect; ostringstream os; @@ -226,14 +227,14 @@ public: //Create a random flame, and use the variations to replace those in the original. Random(mutation, useVars, sym, ember.TotalXformCount()); - for (i = 0; i < ember.TotalXformCount(); i++) + for (size_t i = 0; i < ember.TotalXformCount(); i++) { Xform* xform1 = ember.GetTotalXform(i); Xform* xform2 = mutation.GetTotalXform(i); if (xform1 && xform2) { - for (j = 0; j < xform1->TotalVariationCount(); j++) + for (size_t j = 0; j < xform1->TotalVariationCount(); j++) { Variation* var1 = xform1->GetVariation(j); Variation* var2 = xform2->GetVariationById(var1->VariationId()); @@ -242,10 +243,10 @@ public: { xform1->ClearAndDeleteVariations(); - for (k = 0; k < xform2->TotalVariationCount(); k++) + for (size_t k = 0; k < xform2->TotalVariationCount(); k++) xform1->AddVariation(xform2->GetVariation(k)->Copy()); - done = 1; + done = true; } } } @@ -271,8 +272,8 @@ public: } else { - for (i = 0; i < 2; i++) - for (j = 0; j < 3; j++) + for (glm::length_t i = 0; i < 2; i++) + for (glm::length_t j = 0; j < 3; j++) xform1->m_Affine.m_Mat[i][j] = xform2->m_Affine.m_Mat[i][j]; } } @@ -283,13 +284,13 @@ public: } else if (mode == MUTATE_POST_XFORMS) { + bool same = (m_Rand.Rand() & 3) > 0;//25% chance of using the same post for all of them. unsigned int b = 1 + m_Rand.Rand() % 6; - unsigned int same = m_Rand.Rand() & 3;//25% chance of using the same post for all of them. - sprintf_s(ministr, 32, "(%d%s)", b, (same > 0) ? " same" : ""); + sprintf_s(ministr, 32, "(%d%s)", b, same ? " same" : ""); os << "mutate post xforms " << ministr; - for (i = 0; i < ember.TotalXformCount(); i++) + for (size_t i = 0; i < ember.TotalXformCount(); i++) { int copy = (i > 0) && same; Xform* xform = ember.GetTotalXform(i); @@ -405,7 +406,7 @@ public: } else if (mode == MUTATE_DELETE_XFORM) { - unsigned int nx = m_Rand.Rand() % ember.TotalXformCount(); + size_t nx = m_Rand.Rand() % ember.TotalXformCount(); os << "mutate delete xform " << nx; if (ember.TotalXformCount() > 1) @@ -417,13 +418,13 @@ public: Random(mutation, useVars, sym, ember.TotalXformCount()); //Change all the coefs by a fraction of the random. - for (x = 0; x < ember.TotalXformCount(); x++) + for (size_t x = 0; x < ember.TotalXformCount(); x++) { Xform* xform1 = ember.GetTotalXform(x); Xform* xform2 = mutation.GetTotalXform(x); - for (i = 0; i < 2; i++) - for (j = 0; j < 3; j++) + for (glm::length_t i = 0; i < 2; i++) + for (glm::length_t j = 0; j < 3; j++) xform1->m_Affine.m_Mat[i][j] += speed * xform2->m_Affine.m_Mat[i][j]; //Eventually, mutate the parametric variation parameters here. @@ -443,7 +444,8 @@ public: /// A string describing what was done string Cross(Ember& ember0, Ember& ember1, Ember& emberOut, int crossMode) { - unsigned int i, rb; + unsigned int rb; + size_t i; T t; ostringstream os; char ministr[32]; @@ -579,7 +581,8 @@ public: if (m_Rand.Frand01() < T(0.4)) { //Select the starting parent. - unsigned int ci, startParent = m_Rand.RandBit(); + size_t ci; + unsigned int startParent = m_Rand.RandBit(); os << " cmap_cross " << startParent << ":"; @@ -617,14 +620,15 @@ 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, int sym, int specXforms) + void Random(Ember& ember, vector& useVars, int sym, size_t specXforms) { bool postid, addfinal = false; int var, samed, multid, samepost; - unsigned int i, j, k, n, varCount = (unsigned int)m_VariationList.Size(); + glm::length_t i, j, k, n; + size_t varCount = m_VariationList.Size(); Palette palette; - static unsigned int xformDistrib[] = + static size_t xformDistrib[] = { 2, 2, 2, 2, 3, 3, 3, 3, @@ -853,8 +857,8 @@ public: T TryColors(Ember& ember, int colorResolution) { unsigned char* p; - unsigned int i, hits = 0, res = colorResolution; - unsigned int pixTotal, res3 = res * res * res; + size_t i, hits = 0, res = colorResolution; + size_t pixTotal, res3 = res * res * res; T scalar; Ember adjustedEmber = ember; @@ -865,8 +869,8 @@ public: //Scale the image so that the total number of pixels is ~10,000. pixTotal = ember.m_FinalRasW * ember.m_FinalRasH; scalar = sqrt(T(10000) / pixTotal); - adjustedEmber.m_FinalRasW = (unsigned int)(ember.m_FinalRasW * scalar); - adjustedEmber.m_FinalRasH = (unsigned int)(ember.m_FinalRasH * scalar); + adjustedEmber.m_FinalRasW = (size_t)(ember.m_FinalRasW * scalar); + adjustedEmber.m_FinalRasH = (size_t)(ember.m_FinalRasH * scalar); adjustedEmber.m_PixelsPerUnit *= scalar; adjustedEmber.m_Passes = 1; adjustedEmber.m_TemporalSamples = 1; @@ -887,6 +891,7 @@ public: m_Hist.resize(res3); memset(m_Hist.data(), 0, res3); + p = m_FinalImage.data(); for (i = 0; i < m_Renderer->FinalDimensions(); i++) @@ -913,7 +918,7 @@ public: /// Change palette if true, else don't void ChangeColors(Ember& ember, bool changePalette) { - unsigned int i; + size_t i; Xform* xform0; Xform* xform1; @@ -966,13 +971,13 @@ public: /// The ember to get a random xform from /// Optionally exclude an xform. Pass -1 to include all for consideration. /// The random xform if successful, else nullptr. - Xform* RandomXform(Ember& ember, int excluded) + Xform* RandomXform(Ember& ember, intmax_t excluded) { - int ntries = 0; + size_t ntries = 0; while (ntries++ < 100) { - int i = m_Rand.Rand() % ember.TotalXformCount(); + size_t i = m_Rand.Rand() % ember.TotalXformCount(); if (i != excluded) { @@ -1000,7 +1005,7 @@ public: //Insert motion magic here : //If there are motion elements, modify the contents of //the result xforms before rotate is called. - for (unsigned int i = 0; i < ember.TotalXformCount(); i++) + for (size_t i = 0; i < ember.TotalXformCount(); i++) { Xform* xform1 = ember.GetTotalXform(i); Xform* xform2 = rotated.GetTotalXform(i); @@ -1024,7 +1029,7 @@ public: /// True if embers points to the first or last ember in the entire sequence, else false. void Edge(Ember* embers, Ember& result, T blend, bool seqFlag) { - unsigned int i, si; + size_t i, si; Ember spun[2], prealign[2]; //Insert motion magic here : @@ -1160,7 +1165,7 @@ public: void ApplyTemplate(Ember& ember, Ember& templ) { //Check for invalid values - only replace those with valid ones. - for (unsigned int i = 0; i < 3; i++) + for (glm::length_t i = 0; i < 3; i++) if (templ.m_Background[i] >= 0) ember.m_Background[i] = templ.m_Background[i]; @@ -1280,9 +1285,9 @@ public: /// The bmin[0] and bmin[1] will be the minimum x and y values. /// The bmax[0] and bmax[1] will be the maximum x and y values. /// The number of iterations ran - uint64_t EstimateBoundingBox(Ember& ember, T eps, unsigned int samples, T* bmin, T* bmax) + size_t EstimateBoundingBox(Ember& ember, T eps, size_t samples, T* bmin, T* bmax) { - unsigned int i, lowTarget, highTarget; + size_t i, lowTarget, highTarget; T min[2], max[2]; if (ember.XaosPresent()) @@ -1293,7 +1298,7 @@ public: m_Iterator->InitDistributions(ember); m_Samples.resize(samples); - uint64_t bv = m_Iterator->Iterate(ember, samples, 20, m_Samples.data(), m_Rand);//Use a special fuse of 20, all other calls to this will use 15, or 100. + size_t bv = m_Iterator->Iterate(ember, samples, 20, m_Samples.data(), m_Rand);//Use a special fuse of 20, all other calls to this will use 15, or 100. if (bv / T(samples) > eps) eps = 3 * bv / T(samples); @@ -1301,7 +1306,7 @@ public: if (eps > T(0.3)) eps = T(0.3); - lowTarget = (int)(samples * eps); + lowTarget = (size_t)(samples * eps); highTarget = samples - lowTarget; min[0] = min[1] = 1e10; diff --git a/Source/Ember/SpatialFilter.h b/Source/Ember/SpatialFilter.h index e4cd30f..d21082b 100644 --- a/Source/Ember/SpatialFilter.h +++ b/Source/Ember/SpatialFilter.h @@ -51,7 +51,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - SpatialFilter(eSpatialFilterType filterType, T support, T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + SpatialFilter(eSpatialFilterType filterType, T support, T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) { m_FilterType = filterType; m_Support = support; @@ -152,7 +152,7 @@ public: /// The string representation of this filter string ToString() const { - unsigned int i; + size_t i; stringstream ss; ss @@ -179,9 +179,9 @@ public: /// void Apply() { } inline int FinalFilterWidth() const { return m_FinalFilterWidth; } - inline unsigned int Supersample() const { return m_Supersample; } - inline unsigned int BufferSize() const { return (unsigned int)m_Filter.size(); } - inline unsigned int BufferSizeBytes() const { return BufferSize() * sizeof(T); } + inline size_t Supersample() const { return m_Supersample; } + inline size_t BufferSize() const { return m_Filter.size(); } + inline size_t BufferSizeBytes() const { return BufferSize() * sizeof(T); } inline T Support() const { return m_Support; } inline T FilterRadius() const { return m_FilterRadius; } inline T PixelAspectRatio() const { return m_PixelAspectRatio; } @@ -231,7 +231,7 @@ private: } int m_FinalFilterWidth;//The final width that the filter ends up being. - unsigned int m_Supersample;//The supersample value of the ember using this filter to render. + size_t m_Supersample;//The supersample value of the ember using this filter to render. T m_Support;//Extra value. T m_FilterRadius;//The requested filter radius. T m_PixelAspectRatio;//The aspect ratio of the ember using this filter to render, usually 1. @@ -253,7 +253,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - GaussianFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + GaussianFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(GAUSSIAN_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { } /// @@ -281,7 +281,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - HermiteFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + HermiteFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(HERMITE_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -316,7 +316,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - BoxFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + BoxFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(BOX_SPATIAL_FILTER, T(0.5), filterRadius, superSample, pixelAspectRatio) { } /// @@ -347,7 +347,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - TriangleFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + TriangleFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(TRIANGLE_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -381,7 +381,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - BellFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + BellFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(BELL_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { } /// @@ -422,7 +422,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - BsplineFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + BsplineFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(BSPLINE_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -467,7 +467,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - Lanczos3Filter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + Lanczos3Filter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(LANCZOS3_SPATIAL_FILTER, T(3.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -501,7 +501,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - Lanczos2Filter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + Lanczos2Filter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(LANCZOS2_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -535,7 +535,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - MitchellFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + MitchellFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(MITCHELL_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -588,7 +588,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - BlackmanFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + BlackmanFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(BLACKMAN_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -616,7 +616,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - CatromFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + CatromFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(CATROM_SPATIAL_FILTER, T(2.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -659,7 +659,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - HammingFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + HammingFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(HAMMING_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -687,7 +687,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - HanningFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + HanningFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(HANNING_SPATIAL_FILTER, T(1.0), filterRadius, superSample, pixelAspectRatio) { } /// @@ -715,7 +715,7 @@ public: /// The filter radius /// The supersample of the ember being rendered /// The pixel aspect ratio being used to render. Default: 1. - QuadraticFilter(T filterRadius, unsigned int superSample, T pixelAspectRatio = T(1.0)) + QuadraticFilter(T filterRadius, size_t superSample, T pixelAspectRatio = T(1.0)) : SpatialFilter(QUADRATIC_SPATIAL_FILTER, T(1.5), filterRadius, superSample, pixelAspectRatio) { } /// @@ -756,7 +756,7 @@ public: /// The supersample value of the ember using this filter to render /// The aspect ratio of the ember using this filter to render. Default: 1. /// A pointer to the newly created filter object - static SpatialFilter* Create(eSpatialFilterType filterType, T filterRadius, unsigned int superSample, T pixelAspectRatio = 1) + static SpatialFilter* Create(eSpatialFilterType filterType, T filterRadius, size_t superSample, T pixelAspectRatio = 1) { SpatialFilter* filter = nullptr; @@ -829,7 +829,7 @@ public: /// /// The string name of the filter /// The filter type enum - static eSpatialFilterType FromString(string filterType) + static eSpatialFilterType FromString(const string& filterType) { if (!_stricmp(filterType.c_str(), "Gaussian")) return GAUSSIAN_SPATIAL_FILTER; diff --git a/Source/Ember/TemporalFilter.h b/Source/Ember/TemporalFilter.h index 03ba26b..693ae71 100644 --- a/Source/Ember/TemporalFilter.h +++ b/Source/Ember/TemporalFilter.h @@ -47,9 +47,9 @@ public: /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. - TemporalFilter(eTemporalFilterType filterType, unsigned int passes, unsigned int temporalSamples, T filterWidth) + TemporalFilter(eTemporalFilterType filterType, size_t passes, size_t temporalSamples, T filterWidth) { - unsigned int i, steps = passes * temporalSamples; + size_t i, steps = passes * temporalSamples; m_Passes = passes; m_TemporalSamples = temporalSamples; @@ -117,7 +117,7 @@ public: /// The string representation of this filter string ToString() const { - unsigned int i; + size_t i; stringstream ss; ss << "Temporal Filter:" << endl @@ -146,8 +146,8 @@ public: /// Accessors. /// size_t Size() const { return m_Filter.size(); } - unsigned int Passes() const { return m_Passes; } - unsigned int TemporalSamples() const { return m_TemporalSamples; } + size_t Passes() const { return m_Passes; } + size_t TemporalSamples() const { return m_TemporalSamples; } T FilterWidth() const { return m_FilterWidth; } T FilterExp() const { return m_FilterExp; } T SumFilt() const { return m_SumFilt; } @@ -164,7 +164,7 @@ protected: { m_SumFilt = 0; - for (unsigned int i = 0; i < Size(); i++) + for (size_t i = 0; i < Size(); i++) { m_Filter[i] /= maxFilt; m_SumFilt += m_Filter[i]; @@ -176,8 +176,8 @@ protected: T m_SumFilt;//The sum of all filter values. T m_FilterWidth; T m_FilterExp; - unsigned int m_Passes; - unsigned int m_TemporalSamples; + size_t m_Passes; + size_t m_TemporalSamples; vector m_Deltas;//Delta vector. vector m_Filter;//Filter vector. eTemporalFilterType m_FilterType;//The type of filter this is. @@ -198,14 +198,14 @@ public: /// The number of temporal samples in the ember being rendered /// The width of the filter. /// The filter exp. - ExpTemporalFilter(unsigned int passes, unsigned int temporalSamples, T filterWidth, T filterExp) + ExpTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth, T filterExp) : TemporalFilter(BOX_TEMPORAL_FILTER, passes, temporalSamples, filterWidth) { if (Size() > 1) { T slpx, maxFilt = 0; - for (unsigned int i = 0; i < Size(); i++) + for (size_t i = 0; i < Size(); i++) { if (filterExp >= 0) slpx = (T(i) + 1) / Size(); @@ -240,7 +240,7 @@ public: /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. - GaussianTemporalFilter(unsigned int passes, unsigned int temporalSamples, T filterWidth) + GaussianTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth) : TemporalFilter(GAUSSIAN_TEMPORAL_FILTER, passes, temporalSamples, filterWidth) { if (Size() > 1) @@ -248,7 +248,7 @@ public: T maxFilt = 0, halfSteps = T(Size()) / T(2); GaussianFilter gaussian(1, 1);//Just pass dummy values, they are unused in this case. - for (unsigned int i = 0; i < Size(); i++) + for (size_t i = 0; i < Size(); i++) { m_Filter[i] = gaussian.Filter(gaussian.Support() * fabs(i - halfSteps) / halfSteps); @@ -276,12 +276,12 @@ public: /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. - BoxTemporalFilter(unsigned int passes, unsigned int temporalSamples, T filterWidth) + BoxTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth) : TemporalFilter(BOX_TEMPORAL_FILTER, passes, temporalSamples, filterWidth) { if (Size() > 1) { - for (unsigned int i = 0; i < Size(); i++) + for (size_t i = 0; i < Size(); i++) m_Filter[i] = 1; FinishFilter(1); @@ -305,7 +305,7 @@ public: /// The width of the filter /// The filter exp, only used with Exp filter, otherwise ignored. /// A pointer to the newly created filter object - static TemporalFilter* Create(eTemporalFilterType filterType, unsigned int passes, unsigned int temporalSamples, T filterWidth, T filterExp = 1) + static TemporalFilter* Create(eTemporalFilterType filterType, size_t passes, size_t temporalSamples, T filterWidth, T filterExp = 1) { TemporalFilter* filter = nullptr; @@ -342,7 +342,7 @@ public: /// /// The string name of the filter /// The filter type enum - static eTemporalFilterType FromString(string filterType) + static eTemporalFilterType FromString(const string& filterType) { if (!_stricmp(filterType.c_str(), "box")) return BOX_TEMPORAL_FILTER; diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index 18dcd9b..79061d8 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -115,7 +115,7 @@ public: /// Add string to report. /// /// The string to add - virtual void AddToReport(string s) { m_ErrorReport.push_back(s); } + virtual void AddToReport(const string& s) { m_ErrorReport.push_back(s); } /// /// Add a vector of strings to report. @@ -138,7 +138,7 @@ public: { stringstream ss; - ForEach(errorReport, [&](string s) { ss << s << endl; }); + ForEach(errorReport, [&](const string& s) { ss << s << endl; }); return ss.str(); } @@ -218,7 +218,28 @@ static void CopyVec(vector& dest, const vector& source) dest.resize(source.size()); for (size_t i = 0; i < source.size(); i++) - dest[i] = T(source[i]);//Valid assignment operator between T and U types must be defined somewhere. + dest[i] = (T)source[i];//Valid assignment operator between T and U types must be defined somewhere. +} + +/// +/// Clear dest and copy all of the elements of vector source with elements of type U to the vector +/// dest with elements of type T. +/// Call a function on each element after it's been copied. +/// +/// The vector of type T to copy to +/// The vector of type U to copy from +/// A function to call on each element after it's copied +template +static void CopyVec(vector& dest, const vector& source, std::function perElementOperation) +{ + dest.clear(); + dest.resize(source.size()); + + for (size_t i = 0; i < source.size(); i++) + { + dest[i] = (T)source[i];//Valid assignment operator between T and U types must be defined somewhere. + perElementOperation(dest[i]); + } } /// @@ -246,6 +267,18 @@ static void ClearVec(vector& vec, bool arrayDelete = false) vec.clear(); } +/// +/// Thin wrapper around passing a vector to memset() to relieve +/// the caller of having to pass the size. +/// +/// The vector to memset +/// The value to set each element to, default 0. +template +static inline void Memset(vector& vec, int val = 0) +{ + memset((void*)vec.data(), val, vec.size() * sizeof(vec[0])); +} + /// /// System floor() extremely slow because it accounts for various error conditions. /// This is a much faster version that works on data that is not NaN. @@ -761,7 +794,7 @@ static string ToUpper(const string& str) /// The string to trim /// The character to trim. Default: space. /// The trimmed string -static string Trim(string& str, char ch = ' ') +static string Trim(const string& str, char ch = ' ') { string ret; diff --git a/Source/Ember/Variation.h b/Source/Ember/Variation.h index 3a41b20..df70e86 100644 --- a/Source/Ember/Variation.h +++ b/Source/Ember/Variation.h @@ -1336,8 +1336,8 @@ public: eVariationAssignType AssignType() const { return m_AssignType; } const Xform* ParentXform() const { return m_Xform; } void ParentXform(Xform* xform) { m_Xform = xform; } - int IndexInXform() { return m_Xform ? m_Xform->GetVariationIndex(this) : -1; } - int XformIndexInEmber() { return m_Xform ? m_Xform->IndexInParentEmber() : -1; } + intmax_t IndexInXform() { return m_Xform ? m_Xform->GetVariationIndex(this) : -1; } + intmax_t XformIndexInEmber() { return m_Xform ? m_Xform->IndexInParentEmber() : -1; } T m_Weight;//The weight of the variation. @@ -1822,7 +1822,7 @@ public: /// Accessors. /// ParamWithName* Params() { return &m_Params[0]; } - unsigned int ParamCount() { return (unsigned int)m_Params.size(); } + size_t ParamCount() { return m_Params.size(); } const vector>& ParamsVec() const { return m_Params; } protected: diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h index 01042c5..fdde0fe 100644 --- a/Source/Ember/VariationList.h +++ b/Source/Ember/VariationList.h @@ -433,7 +433,7 @@ public: /// /// The name to search for /// A pointer to the variation if found, else nullptr. - Variation* GetVariation(string& name) + Variation* GetVariation(const string& name) { for (unsigned int i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++) if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str())) @@ -449,7 +449,7 @@ public: /// The name of the variation in the list to make a copy of /// The weight to assign the new copy. Default: 1 /// A pointer to the variation with a matching name, else nullptr. - Variation* GetVariationCopy(string name, T weight = 1) { return MakeCopyWithWeight(GetVariation(name), weight); } + Variation* GetVariationCopy(const string& name, T weight = 1) { return MakeCopyWithWeight(GetVariation(name), weight); } /// /// Get a parametric variation at the specified index. @@ -464,7 +464,7 @@ public: /// /// The name of the variation in the parametric variations list to retrieve /// The parametric variation with a matching name, else nullptr. - ParametricVariation* GetParametricVariation(string name) + ParametricVariation* GetParametricVariation(const string& name) { for (unsigned int i = 0; i < m_ParametricVariations.size() && m_ParametricVariations[i] != nullptr; i++) if (!_stricmp(name.c_str(), m_ParametricVariations[i]->Name().c_str())) @@ -478,7 +478,7 @@ public: /// /// The name of the variation whose index is returned /// The index of the variation with the matching name, else -1 - int GetVariationIndex(string name) + int GetVariationIndex(const string& name) { for (unsigned int i = 0; i < m_Variations.size() && m_Variations[i] != nullptr; i++) if (!_stricmp(name.c_str(), m_Variations[i]->Name().c_str())) diff --git a/Source/Ember/Variations01.h b/Source/Ember/Variations01.h index 6b0f0d4..b464288 100644 --- a/Source/Ember/Variations01.h +++ b/Source/Ember/Variations01.h @@ -29,7 +29,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -66,7 +66,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n" @@ -106,7 +106,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares);\n" @@ -151,7 +151,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t c1 = sin(precalcSumSquares);\n" @@ -196,7 +196,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSqrtSumSquares);\n" @@ -235,7 +235,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (precalcAtanxy * M_1_PI);\n" @@ -272,7 +272,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares * sin(precalcAtanxy + precalcSqrtSumSquares);\n" @@ -313,7 +313,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = precalcSqrtSumSquares * precalcAtanxy;\n" @@ -361,7 +361,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weightByPI = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -424,7 +424,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n" @@ -466,7 +466,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = Zeps(precalcSqrtSumSquares);\n" @@ -505,7 +505,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * precalcSina * cos(precalcSqrtSumSquares);\n" @@ -553,7 +553,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = precalcAtanxy;\n" @@ -606,7 +606,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * sqrt(precalcSqrtSumSquares);\n" @@ -654,7 +654,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t nx = vIn.x < 0.0 ? (vIn.x * 2.0) : vIn.x;\n" @@ -705,7 +705,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string dx2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -782,7 +782,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = 2 * xform->m_VariationWeights[" << varIndex << "] / (precalcSqrtSumSquares + 1);\n" @@ -828,7 +828,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t dx = tan(3 * vIn.y);\n" @@ -875,7 +875,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t dx = xform->m_VariationWeights[" << varIndex << "] * exp(vIn.x - 1.0);\n" @@ -921,7 +921,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * pow(precalcSqrtSumSquares, precalcSina);\n" @@ -964,7 +964,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = vIn.x * M_PI;\n" @@ -1014,7 +1014,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t dx = Zeps(xform->m_C * xform->m_C);\n" @@ -1069,7 +1069,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t dx = M_PI * Zeps(xform->m_C * xform->m_C);\n" @@ -1121,7 +1121,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string blobLow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1207,7 +1207,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string pdjA = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1308,7 +1308,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string fan2X = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1399,7 +1399,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string rings2Val = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1468,7 +1468,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = (xform->m_VariationWeights[" << varIndex << "] * 2.0) / (precalcSqrtSumSquares + 1.0);\n" @@ -1506,7 +1506,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t denom = 0.25 * precalcSumSquares + 1;\n" @@ -1542,7 +1542,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n" @@ -1581,7 +1581,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -1658,7 +1658,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tempr = MwcNext01(mwc) * M_2PI;\n" @@ -1700,7 +1700,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -1798,7 +1798,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -1900,7 +1900,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tmpr = MwcNext01(mwc) * M_2PI;\n" @@ -1939,7 +1939,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n" @@ -1987,7 +1987,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -2062,7 +2062,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2144,7 +2144,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string sides = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2249,7 +2249,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string c1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2329,7 +2329,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2398,7 +2398,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * M_PI;\n" @@ -2435,7 +2435,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) / cos(vIn.y);\n" @@ -2468,7 +2468,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (MwcNext01(mwc) - 0.5);\n" @@ -2505,7 +2505,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t ang = xform->m_VariationWeights[" << varIndex << "] * MwcNext01(mwc) * M_PI;\n" @@ -2546,7 +2546,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -2592,7 +2592,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -2643,7 +2643,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -2686,7 +2686,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "] /Zeps(fabs((vIn.x - vIn.y) * (vIn.x + vIn.y)));\n" @@ -2729,7 +2729,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string rot = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -2837,7 +2837,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string m = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -2935,7 +2935,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string petals = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3002,7 +3002,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string eccentricity = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3068,7 +3068,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string height = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3139,7 +3139,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3250,7 +3250,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3408,7 +3408,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t roundX = Rint(vIn.x);\n" @@ -3483,7 +3483,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t wx = xform->m_VariationWeights[" << varIndex << "] * 1.3029400317411197908970256609023;\n" @@ -3563,7 +3563,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string size = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3663,7 +3663,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string powerR = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3748,7 +3748,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string xAmp = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3851,7 +3851,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tmp = precalcSumSquares + 1.0;\n" @@ -3926,7 +3926,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weightDivPiDiv2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4010,7 +4010,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string beta = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4101,7 +4101,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t expx = exp(vIn.x) * 0.5;\n" @@ -4162,7 +4162,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string spin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4274,7 +4274,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string w2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4352,7 +4352,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4452,7 +4452,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string separation = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4544,7 +4544,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string vvar = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4604,7 +4604,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4741,7 +4741,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4837,7 +4837,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string xSize = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4925,7 +4925,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4996,7 +4996,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string space = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5065,7 +5065,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5153,7 +5153,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -5250,7 +5250,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5332,7 +5332,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string inside = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5400,7 +5400,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string freqX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5475,7 +5475,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t expe = xform->m_VariationWeights[" << varIndex << "] * exp(vIn.x);\n" @@ -5513,7 +5513,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string base = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5569,7 +5569,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) * cosh(vIn.y);\n" @@ -5603,7 +5603,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * cos(vIn.x) * cosh(vIn.y);\n" @@ -5642,7 +5642,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tansin = sin(2.0 * vIn.x);\n" @@ -5687,7 +5687,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t secsin = sin(vIn.x);\n" @@ -5732,7 +5732,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cscsin = sin(vIn.x);\n" @@ -5777,7 +5777,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cotsin = sin(2.0 * vIn.x);\n" @@ -5821,7 +5821,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sinhsin = sin(vIn.y);\n" @@ -5864,7 +5864,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t coshsin = sin(vIn.y);\n" @@ -5908,7 +5908,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t tanhsin = sin(2.0 * vIn.y);\n" @@ -5953,7 +5953,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sechsin = sin(vIn.y);\n" @@ -5998,7 +5998,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cschsin = sin(vIn.y);\n" @@ -6043,7 +6043,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t cothsin = sin(2.0 * vIn.y);\n" @@ -6090,7 +6090,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string symmetry = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -6175,7 +6175,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string spread = "parVars[" + ToUpper(m_Params[i++].Name()) + index; diff --git a/Source/Ember/Variations02.h b/Source/Ember/Variations02.h index be0843f..3fc825f 100644 --- a/Source/Ember/Variations02.h +++ b/Source/Ember/Variations02.h @@ -27,7 +27,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t t = xform->m_VariationWeights[" << varIndex << "] / sqrt(precalcSumSquares + 1.0);\n" @@ -77,7 +77,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string n = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -187,7 +187,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string bwrapsCellsize = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -347,7 +347,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); @@ -423,7 +423,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string blurZoomLength = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -485,7 +485,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string blurPixelizeSize = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -575,7 +575,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -731,7 +731,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -819,7 +819,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string blurLinearLength = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -886,7 +886,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string v = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -992,7 +992,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = vOut.y = 0;\n" @@ -1024,7 +1024,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = vOut.y = 0;\n" @@ -1056,7 +1056,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = vOut.y = 0;\n" @@ -1097,7 +1097,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n"; @@ -1147,7 +1147,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t angle = MwcNext01(mwc) * M_2PI;\n" @@ -1190,7 +1190,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r2 = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSumSquares + SQR(vIn.z));\n" @@ -1231,7 +1231,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string cx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1317,7 +1317,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string pi = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1412,7 +1412,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1529,7 +1529,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1599,7 +1599,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1727,7 +1727,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string hole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1840,7 +1840,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string hole = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2028,7 +2028,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t avgr = xform->m_VariationWeights[" << varIndex << "] * (sqrt(SQR(vIn.y) + SQR(vIn.x + 1)) / sqrt(SQR(vIn.y) + SQR(vIn.x - 1)));\n" @@ -2074,7 +2074,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string real = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2161,7 +2161,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string rootFace = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2232,7 +2232,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = M_2PI / (precalcSqrtSumSquares + 1);\n" @@ -2283,7 +2283,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string five = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -2362,7 +2362,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2470,7 +2470,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string v2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -2616,7 +2616,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t x = LRint(vIn.x);\n" @@ -2719,7 +2719,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2786,7 +2786,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2882,7 +2882,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2977,7 +2977,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3066,7 +3066,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3190,7 +3190,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3292,7 +3292,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3401,7 +3401,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string v = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -3469,7 +3469,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3568,7 +3568,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3651,7 +3651,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3749,7 +3749,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string c = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3852,7 +3852,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string parity = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4019,7 +4019,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string in = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4158,7 +4158,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string c1r = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4257,7 +4257,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string r = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4371,7 +4371,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string powx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4528,7 +4528,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string t3 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4640,7 +4640,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string frequency = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4770,7 +4770,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string shiftX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4892,7 +4892,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string ampX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4996,7 +4996,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string distort = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5064,7 +5064,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = xform->m_VariationWeights[" << varIndex << "];\n" @@ -5109,7 +5109,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string vvar2 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Precalcs only, no params. @@ -5180,7 +5180,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string freqX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5295,7 +5295,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string angle = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5404,7 +5404,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5475,7 +5475,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string weight01 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5528,7 +5528,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x) * (cosh(vIn.y) + 1.0) * Sqr(sin(vIn.x));\n" @@ -5563,7 +5563,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t d = xform->m_VariationWeights[" << varIndex << "] / precalcSumSquares;\n" @@ -5616,7 +5616,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string r = "parVars[" + ToUpper(m_Params[i++].Name()) + index; diff --git a/Source/Ember/Variations03.h b/Source/Ember/Variations03.h index 4f50bb3..5c92a90 100644 --- a/Source/Ember/Variations03.h +++ b/Source/Ember/Variations03.h @@ -30,7 +30,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string effect = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -80,7 +80,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -119,7 +119,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string numerator = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -195,7 +195,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -248,7 +248,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (vIn.x - ((SQR(vIn.x) * vIn.x) / 3)) + vIn.x * SQR(vIn.y);\n" @@ -290,7 +290,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -359,7 +359,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string pull = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -466,7 +466,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -634,7 +634,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -792,7 +792,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -947,7 +947,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1036,7 +1036,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1092,7 +1092,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t rad = sqrt(MwcNext01(mwc));\n" @@ -1136,7 +1136,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1217,7 +1217,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1320,7 +1320,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string n = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1404,7 +1404,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string mode = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1505,7 +1505,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string n = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1584,7 +1584,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string n = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1658,7 +1658,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string powx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1712,7 +1712,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string powx = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1771,7 +1771,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1829,7 +1829,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1893,7 +1893,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1976,7 +1976,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sinX = sin(vIn.x);\n" @@ -2018,7 +2018,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t e = 1 / precalcSumSquares + SQR(M_2_PI);\n" @@ -2092,7 +2092,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t inZ, otherZ, tempTz, tempPz;\n" @@ -2178,7 +2178,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t d = Zeps(precalcSumSquares);\n" @@ -2246,7 +2246,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = precalcAtanyx;\n" @@ -2327,7 +2327,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2414,7 +2414,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2501,7 +2501,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string reA = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2600,7 +2600,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string reA = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2754,7 +2754,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2886,7 +2886,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string min = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2966,7 +2966,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string n = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3036,7 +3036,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string even = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3120,7 +3120,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string r = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3225,7 +3225,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3331,7 +3331,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3400,7 +3400,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string in = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3473,7 +3473,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string rotate = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3556,7 +3556,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3667,7 +3667,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string shift = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3749,7 +3749,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string ww = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3812,7 +3812,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -3884,7 +3884,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4016,7 +4016,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4126,7 +4126,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4226,7 +4226,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string move = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4322,7 +4322,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string push = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4410,7 +4410,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string rotate = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4496,7 +4496,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; diff --git a/Source/Ember/Variations04.h b/Source/Ember/Variations04.h index bc7ba18..d6c9b43 100644 --- a/Source/Ember/Variations04.h +++ b/Source/Ember/Variations04.h @@ -42,7 +42,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string in = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -211,7 +211,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string spinIn = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -430,7 +430,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -546,7 +546,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -611,7 +611,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t d = Zeps(precalcSumSquares);\n" @@ -648,7 +648,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t d = Zeps(precalcSumSquares);\n" @@ -1162,7 +1162,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string strength = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1242,7 +1242,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string n = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1325,7 +1325,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string w = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1414,7 +1414,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string m_k = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1658,7 +1658,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (MwcNext01(mwc) - 0.5);\n" @@ -1730,7 +1730,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string rho = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1918,7 +1918,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string stretchX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2027,7 +2027,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2145,7 +2145,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2286,7 +2286,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string spin = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2436,7 +2436,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string at = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2567,7 +2567,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string radius = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2634,7 +2634,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2721,7 +2721,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3011,7 +3011,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string a1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3173,7 +3173,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3220,7 +3220,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3268,7 +3268,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3317,7 +3317,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3371,7 +3371,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3430,7 +3430,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3483,7 +3483,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3530,7 +3530,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3583,7 +3583,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3642,7 +3642,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t sysz = SQR(vIn.y) + SQR(vIn.z);\n" @@ -3696,7 +3696,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3745,7 +3745,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3792,7 +3792,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t absV = Hypot(vIn.y, vIn.z);\n" @@ -3837,7 +3837,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string base = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -3896,7 +3896,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] / Zeps(precalcSqrtSumSquares);\n" @@ -3938,7 +3938,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string q01 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4048,7 +4048,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string p = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4461,7 +4461,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string deltaX = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4645,7 +4645,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4782,7 +4782,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string r1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4898,7 +4898,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string re = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -4973,7 +4973,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t r = MwcNext01(mwc) * xform->m_VariationWeights[" << varIndex << "] * precalcSqrtSumSquares;\n" @@ -5015,7 +5015,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string blobLow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5103,7 +5103,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -5242,7 +5242,7 @@ MAKEPREPOSTPARVAR(Blocky, blocky, BLOCKY) // virtual string OpenCLString() override // { // ostringstream ss; -// int varIndex = IndexInXform(); +// intmax_t varIndex = IndexInXform(); // // ss << "\t{\n" // << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * vIn.x;\n" @@ -5273,7 +5273,7 @@ MAKEPREPOSTPARVAR(Blocky, blocky, BLOCKY) // virtual string OpenCLString() override // { // ostringstream ss; -// int varIndex = IndexInXform(); +// intmax_t varIndex = IndexInXform(); // // ss << "\t{\n" // << "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * vIn.y;\n" diff --git a/Source/Ember/Variations05.h b/Source/Ember/Variations05.h index d3232dc..35c3b09 100644 --- a/Source/Ember/Variations05.h +++ b/Source/Ember/Variations05.h @@ -37,7 +37,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -145,7 +145,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -303,7 +303,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -431,7 +431,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string sc = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -669,7 +669,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -900,7 +900,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string xpand = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1042,7 +1042,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t expx = exp(vIn.x) * 0.5;\n" @@ -1098,7 +1098,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string xpow = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1178,7 +1178,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1262,7 +1262,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string delta = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1357,7 +1357,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string vv = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1433,7 +1433,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1503,7 +1503,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string freq = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1563,7 +1563,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string slices = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1738,7 +1738,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * sin(vIn.x);\n" @@ -1845,7 +1845,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string xdist = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -1974,7 +1974,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2081,7 +2081,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t a = M_PI / (precalcSqrtSumSquares + 1);\n" @@ -2160,7 +2160,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string scatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index; @@ -2742,7 +2742,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string power = "parVars[" + ToUpper(m_Params[i++].Name()) + index; diff --git a/Source/Ember/VariationsDC.h b/Source/Ember/VariationsDC.h index 1bb7ede..c65fb18 100644 --- a/Source/Ember/VariationsDC.h +++ b/Source/Ember/VariationsDC.h @@ -39,7 +39,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string scale = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -121,7 +121,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string origin = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -232,7 +232,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string cubeC1 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -390,7 +390,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -551,7 +551,7 @@ public: virtual string OpenCLString() override { ostringstream ss; - int varIndex = IndexInXform(); + intmax_t varIndex = IndexInXform(); ss << "\t{\n" << "\t\treal_t x = LRint(vIn.x);\n" @@ -664,7 +664,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string offset = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -825,7 +825,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string scatterArea = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. @@ -970,7 +970,7 @@ public: virtual string OpenCLString() override { ostringstream ss, ss2; - int i = 0, varIndex = IndexInXform(); + intmax_t i = 0, varIndex = IndexInXform(); ss2 << "_" << XformIndexInEmber() << "]"; string index = ss2.str(); string x0 = "parVars[" + ToUpper(m_Params[i++].Name()) + index;//Params. diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index 0be6d64..1a3e34c 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -169,7 +169,7 @@ public: //Must manually add them via the AddVariation() function so that //the variation's m_IndexInXform member gets properly set to this. - for (unsigned int i = 0; i < xform.TotalVariationCount(); i++) + for (size_t i = 0; i < xform.TotalVariationCount(); i++) { Variation* var = nullptr; @@ -199,7 +199,7 @@ public: /// void Init() { - static unsigned int count = 0; + static size_t count = 0; m_Weight = 0; m_ColorSpeed = T(0.5); @@ -302,7 +302,7 @@ public: const_cast*>(this)->AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { - for (unsigned int i = 0; i < variations.size(); i++, count++) + for (size_t i = 0; i < variations.size(); i++, count++) { if (count == index) { @@ -327,7 +327,7 @@ public: const_cast*>(this)->AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { - for (unsigned int i = 0; i < variations.size(); i++) + for (size_t i = 0; i < variations.size(); i++) { if (variations[i] != nullptr && variations[i]->VariationId() == id) { @@ -346,13 +346,13 @@ public: /// /// The name to search for /// A pointer to the variation if found, else nullptr. - Variation* GetVariationByName(string name) const + Variation* GetVariationByName(const string& name) const { Variation* var = nullptr; const_cast*>(this)->AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { - for (unsigned int i = 0; i < variations.size(); i++) + for (size_t i = 0; i < variations.size(); i++) { if (variations[i] != nullptr && variations[i]->Name() == name) { @@ -372,13 +372,13 @@ public: /// /// A pointer to the variation to search for /// The index of the variation if found, else -1 - int GetVariationIndex(Variation* var) const + intmax_t GetVariationIndex(Variation* var) const { - int count = 0, index = -1; + intmax_t count = 0, index = -1; const_cast*>(this)->AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { - for (unsigned int i = 0; i < variations.size(); i++, count++) + for (size_t i = 0; i < variations.size(); i++, count++) { if (variations[i] == var) { @@ -404,7 +404,7 @@ public: AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { - for (unsigned int i = 0; i < variations.size(); i++) + for (size_t i = 0; i < variations.size(); i++) { if (variations[i] != nullptr && variations[i]->VariationId() == id) { @@ -497,7 +497,7 @@ public: /// /// The index to set /// The xaos value to set it to - void SetXaos(unsigned int i, T val) + void SetXaos(size_t i, T val) { if (i < m_Xaos.size()) { @@ -520,7 +520,7 @@ public: bool XaosPresent() const { if (m_ParentEmber) - for (unsigned int i = 0; i < m_Xaos.size(); i++) + for (size_t i = 0; i < m_Xaos.size(); i++) if (i < m_ParentEmber->XformCount()) if (!IsClose(m_Xaos[i], 1)) return true;//If at least one entry is not equal to 1, then xaos is present. @@ -683,15 +683,14 @@ public: /// The time blending value 0-1 void ApplyMotion(Xform& xform, T blend) { - unsigned int i, j, k; Xform* mot = xform.m_Motion.data(); //Loop over the motion elements and add their contribution to the original vals. - for (i = 0; i < xform.m_Motion.size(); i++) + for (size_t i = 0; i < xform.m_Motion.size(); i++) { //Original only pulls these from the first motion xform which is a bug. Want to pull it from each one. Xform* currentMot = &xform.m_Motion[i]; - int freq = currentMot->m_MotionFreq; + intmax_t freq = currentMot->m_MotionFreq; eMotion func = currentMot->m_MotionFunc; //Clamp these to the appropriate range after all are applied. @@ -703,7 +702,7 @@ public: APPMOT(m_ColorSpeed); APPMOT(m_Animate); - for (j = 0; j < currentMot->TotalVariationCount(); j++)//For each variation in the motion xform. + for (size_t j = 0; j < currentMot->TotalVariationCount(); j++)//For each variation in the motion xform. { Variation* motVar = currentMot->GetVariation(j);//Get the variation, which may or may not be present in this xform. ParametricVariation* motParVar = dynamic_cast*>(motVar); @@ -730,7 +729,7 @@ public: ParamWithName* params = parVar->Params(); ParamWithName* motParams = motParVar->Params(); - for (k = 0; k < motParVar->ParamCount(); k++) + for (size_t k = 0; k < motParVar->ParamCount(); k++) { if (!motParams[k].IsPrecalc()) *(params[k].Param()) += motParams[k].ParamVal() * Interpolater::MotionFuncs(func, freq * blend); @@ -738,9 +737,9 @@ public: } } - for (j = 0; j < 2; j++) + for (glm::length_t j = 0; j < 2; j++) { - for (k = 0; k < 3; k++) + for (glm::length_t k = 0; k < 3; k++) { APPMOT(m_Affine.m_Mat[j][k]); APPMOT(m_Post.m_Mat[j][k]); @@ -762,17 +761,17 @@ public: /// The precalc flags are duplicated in each variation. Each value here /// is true if any of the variations need it precalculated. /// - inline bool NeedPrecalcSumSquares() const { return m_NeedPrecalcSumSquares; } + inline bool NeedPrecalcSumSquares() const { return m_NeedPrecalcSumSquares; } inline bool NeedPrecalcSqrtSumSquares() const { return m_NeedPrecalcSqrtSumSquares; } - inline bool NeedPrecalcAngles() const { return m_NeedPrecalcAngles; } - inline bool NeedPrecalcAtanXY() const { return m_NeedPrecalcAtanXY; } - inline bool NeedPrecalcAtanYX() const { return m_NeedPrecalcAtanYX; } + inline bool NeedPrecalcAngles() const { return m_NeedPrecalcAngles; } + inline bool NeedPrecalcAtanXY() const { return m_NeedPrecalcAtanXY; } + inline bool NeedPrecalcAtanYX() const { return m_NeedPrecalcAtanYX; } inline bool NeedAnyPrecalc() const { return NeedPrecalcSumSquares() || NeedPrecalcSqrtSumSquares() || NeedPrecalcAngles() || NeedPrecalcAtanXY() || NeedPrecalcAtanYX(); } bool HasPost() const { return m_HasPost; } - unsigned int PreVariationCount() const { return (unsigned int)m_PreVariations.size(); } - unsigned int VariationCount() const { return (unsigned int)m_Variations.size(); } - unsigned int PostVariationCount() const { return (unsigned int)m_PostVariations.size(); } - unsigned int TotalVariationCount() const { return PreVariationCount() + VariationCount() + PostVariationCount(); } + size_t PreVariationCount() const { return m_PreVariations.size(); } + size_t VariationCount() const { return m_Variations.size(); } + size_t PostVariationCount() const { return m_PostVariations.size(); } + size_t TotalVariationCount() const { return PreVariationCount() + VariationCount() + PostVariationCount(); } bool Empty() const { return TotalVariationCount() == 0 && m_Affine.IsID(); }//Use this instead of padding like the original did. T VizAdjusted() const { return m_VizAdjusted; } T ColorSpeedCache() const { return m_ColorSpeedCache; } @@ -780,7 +779,7 @@ public: const vector& XaosVec() const { return m_Xaos; } Ember* ParentEmber() const { return m_ParentEmber; } void ParentEmber(Ember* ember) { m_ParentEmber = ember; } - int IndexInParentEmber() { return m_ParentEmber ? m_ParentEmber->GetTotalXformIndex(this) : -1; } + intmax_t IndexInParentEmber() { return m_ParentEmber ? m_ParentEmber->GetTotalXformIndex(this) : -1; } /// /// Set the precalc flags based on whether any variation in the vector needs them. @@ -1135,7 +1134,7 @@ public: const_cast*>(this)->AllVarsFunc([&] (vector*>& variations, bool& keepGoing) { - for (unsigned int i = 0; i < variations.size(); i++) + for (size_t i = 0; i < variations.size(); i++) ss << variations[i]->ToString() << endl; ss << endl; @@ -1143,7 +1142,7 @@ public: if (XaosPresent()) { - for (unsigned int i = 0; i < m_Xaos.size(); i++) + for (size_t i = 0; i < m_Xaos.size(); i++) ss << m_Xaos[i] << " "; ss << endl; @@ -1207,7 +1206,7 @@ public: T m_Animate;//Whether or not this xform rotates during animation. 0 means stationary, > 0 means rotate. Use T instead of bool so it can be interpolated. T m_Wind[2]; eMotion m_MotionFunc; - int m_MotionFreq; + intmax_t m_MotionFreq; vector> m_Motion; string m_Name; diff --git a/Source/Ember/XmlToEmber.h b/Source/Ember/XmlToEmber.h index a7f89ae..2a054bf 100644 --- a/Source/Ember/XmlToEmber.h +++ b/Source/Ember/XmlToEmber.h @@ -252,11 +252,12 @@ public: char* bn; const char* xmlPtr; const char* loc = __FUNCTION__; - unsigned int emberSize; + size_t emberSize; size_t bufSize; xmlDocPtr doc;//Parsed XML document tree. xmlNodePtr rootnode; Locale locale;//Sets and restores on exit. + //Timing t; m_ErrorReport.clear(); //Parse XML string into internal document. @@ -264,6 +265,7 @@ public: bufSize = strlen(xmlPtr); embers.reserve(bufSize / 2500);//The Xml text for an ember is around 2500 bytes, but can be much more. Pre-allocate to aovid unnecessary resizing. doc = xmlReadMemory(xmlPtr, (int)bufSize, filename, nullptr, XML_PARSE_NONET);//Forbid network access during read. + //t.Toc("xmlReadMemory"); if (doc == nullptr) { @@ -275,10 +277,12 @@ public: rootnode = xmlDocGetRootElement(doc); //Scan for nodes, starting with this node. + //t.Tic(); bn = basename((char*)filename); ScanForEmberNodes(rootnode, bn, embers); xmlFreeDoc(doc); - emberSize = (unsigned int)embers.size(); + emberSize = embers.size(); + //t.Toc("ScanForEmberNodes"); //Check to see if the first control point or the second-to-last //control point has interpolation="smooth". This is invalid @@ -322,6 +326,7 @@ public: /// /// Parse the specified file and place the results in the vector of embers passed in. + /// This will strip out ampersands because the Xml parser can't handle them. /// /// Full path and filename /// The newly constructed embers based on what was parsed @@ -330,7 +335,7 @@ public: { const char* loc = __FUNCTION__; string buf; - + //Ensure palette list is setup first. if (!m_PaletteList.Init()) { @@ -340,11 +345,7 @@ public: if (ReadFile(filename, buf)) { - if (buf.find_first_of('&') != std::string::npos) - { - FindAndReplace(buf, "&", "&"); - } - + std::replace(buf.begin(), buf.end(), '&', '+'); return Parse((unsigned char*)buf.data(), filename, embers); } else @@ -459,7 +460,7 @@ public: /// The unsigned 64-bit integer to convert /// The radix of the integer. Default: 10. /// The converted string - static string Itos64(uint64_t i, int radix = 10) + static string Itos64(size_t i, int radix = 10) { char ch[64]; @@ -517,7 +518,7 @@ private: // m_ErrorReport.push_back(string(loc) + " : Error interpolating missing palette colors"); currentEmber.CacheXforms(); - currentEmber.m_Index = (int)embers.size(); + currentEmber.m_Index = embers.size(); currentEmber.m_ParentFilename = parentFileString; embers.push_back(currentEmber); } @@ -562,7 +563,7 @@ private: //First parse out simple float reads. if (ParseAndAssignFloat(curAtt->name, attStr, "time", currentEmber.m_Time, ret)) { } - else if (ParseAndAssignFloat(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { } + else if (ParseAndAssignFloat(curAtt->name, attStr, "scale", currentEmber.m_PixelsPerUnit, ret)) { currentEmber.m_OrigPixPerUnit = currentEmber.m_PixelsPerUnit; } else if (ParseAndAssignFloat(curAtt->name, attStr, "rotate", currentEmber.m_Rotate, ret)) { } else if (ParseAndAssignFloat(curAtt->name, attStr, "zoom", currentEmber.m_Zoom, ret)) { } else if (ParseAndAssignFloat(curAtt->name, attStr, "filter", currentEmber.m_SpatialFilterRadius, ret)) { } @@ -1481,7 +1482,7 @@ private: } /// - /// Wrapper to parse an unsigned int Xml value and convert it to unsigned int. + /// Wrapper to parse an int Xml string value and convert it to an int. /// /// The xml tag to parse /// The name of the Xml attribute @@ -1489,21 +1490,8 @@ private: /// The parsed value /// Bitwise ANDed with true if name matched str and the call to Atoi() succeeded, else false. Used for keeping a running value between successive calls. /// True if the tag was matched, else false - bool ParseAndAssignInt(const xmlChar* name, const char* attStr, const char* str, unsigned int& val, bool& b) - { - return ParseAndAssignInt(name, attStr, str, (int&)val, b); - } - - /// - /// Wrapper to parse an int Xml value and convert it to int. - /// - /// The xml tag to parse - /// The name of the Xml attribute - /// The name of the Xml tag - /// The parsed value - /// Bitwise ANDed with true if name matched str and the call to Atoi() succeeded, else false. Used for keeping a running value between successive calls. - /// True if the tag was matched, else false - bool ParseAndAssignInt(const xmlChar* name, const char* attStr, const char* str, int& val, bool& b) + template + bool ParseAndAssignInt(const xmlChar* name, const char* attStr, const char* str, intT& val, bool& b) { bool ret = false; T fval = 0; @@ -1511,7 +1499,7 @@ private: if (!Compare(name, str)) { b &= Atof(attStr, fval); - val = (int)fval; + val = (intT)fval; ret = true;//Means the strcmp() was right, but doesn't necessarily mean the conversion went ok. } diff --git a/Source/EmberAnimate/EmberAnimate.cpp b/Source/EmberAnimate/EmberAnimate.cpp index 8e4fbcc..a5745f6 100644 --- a/Source/EmberAnimate/EmberAnimate.cpp +++ b/Source/EmberAnimate/EmberAnimate.cpp @@ -297,8 +297,8 @@ bool EmberAnimate(EmberOptions& opt) } writeSuccess = false; - comments = renderer->ImageComments(opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette()); stats = renderer->Stats(); + comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette()); os.str(""); os << comments.m_NumIters << " / " << renderer->TotalIterCount() << " (" << std::fixed << std::setprecision(2) << ((double)stats.m_Iters/(double)renderer->TotalIterCount() * 100) << "%)"; diff --git a/Source/EmberCL/DEOpenCLKernelCreator.cpp b/Source/EmberCL/DEOpenCLKernelCreator.cpp index 7eb965b..fb5b677 100644 --- a/Source/EmberCL/DEOpenCLKernelCreator.cpp +++ b/Source/EmberCL/DEOpenCLKernelCreator.cpp @@ -85,7 +85,7 @@ template string DEOpenCLKernelCreator::LogScaleAssignDEEntryPoin /// Filter width /// The kernel source template -string DEOpenCLKernelCreator::GaussianDEKernel(unsigned int ss, unsigned int filterWidth) +string DEOpenCLKernelCreator::GaussianDEKernel(size_t ss, unsigned int filterWidth) { if ((typeid(T) == typeid(double)) || (filterWidth > MaxDEFilterSize()))//Type double does not use cache. { @@ -120,7 +120,7 @@ string DEOpenCLKernelCreator::GaussianDEKernel(unsigned int ss, unsigned int /// Filter width /// The name of the density estimation filtering entry point kernel function template -string DEOpenCLKernelCreator::GaussianDEEntryPoint(unsigned int ss, unsigned int filterWidth) +string DEOpenCLKernelCreator::GaussianDEEntryPoint(size_t ss, unsigned int filterWidth) { if ((typeid(T) == typeid(double)) || (filterWidth > MaxDEFilterSize()))//Type double does not use cache. { @@ -292,7 +292,7 @@ string DEOpenCLKernelCreator::CreateLogScaleAssignDEKernelString() /// The supersample being used /// The kernel string template -string DEOpenCLKernelCreator::CreateGaussianDEKernel(unsigned int ss) +string DEOpenCLKernelCreator::CreateGaussianDEKernel(size_t ss) { bool doSS = ss > 1; bool doScf = !(ss & 1); @@ -552,7 +552,7 @@ string DEOpenCLKernelCreator::CreateGaussianDEKernel(unsigned int ss) /// The supersample being used /// The kernel string template -string DEOpenCLKernelCreator::CreateGaussianDEKernelNoLocalCache(unsigned int ss) +string DEOpenCLKernelCreator::CreateGaussianDEKernelNoLocalCache(size_t ss) { bool doSS = ss > 1; bool doScf = !(ss & 1); diff --git a/Source/EmberCL/DEOpenCLKernelCreator.h b/Source/EmberCL/DEOpenCLKernelCreator.h index de65e7a..802ddd6 100644 --- a/Source/EmberCL/DEOpenCLKernelCreator.h +++ b/Source/EmberCL/DEOpenCLKernelCreator.h @@ -39,8 +39,8 @@ public: string LogScaleSumDEEntryPoint(); string LogScaleAssignDEKernel(); string LogScaleAssignDEEntryPoint(); - string GaussianDEKernel(unsigned int ss, unsigned int filterWidth); - string GaussianDEEntryPoint(unsigned int ss, unsigned int filterWidth); + string GaussianDEKernel(size_t ss, unsigned int filterWidth); + string GaussianDEEntryPoint(size_t ss, unsigned int filterWidth); //Miscellaneous static functions. static unsigned int MaxDEFilterSize(); @@ -51,8 +51,8 @@ private: //Kernel creators. string CreateLogScaleSumDEKernelString(); string CreateLogScaleAssignDEKernelString(); - string CreateGaussianDEKernel(unsigned int ss); - string CreateGaussianDEKernelNoLocalCache(unsigned int ss); + string CreateGaussianDEKernel(size_t ss); + string CreateGaussianDEKernelNoLocalCache(size_t ss); string m_LogScaleSumDEKernel; string m_LogScaleSumDEEntryPoint; diff --git a/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp b/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp index f785c66..c0d5c5d 100644 --- a/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp +++ b/Source/EmberCL/FinalAccumOpenCLKernelCreator.cpp @@ -63,7 +63,7 @@ template string FinalAccumOpenCLKernelCreator::FinalAccumLateCli /// True if channels equals 4 and using transparency, else false. /// The name of the gamma correction entry point kernel function template -string FinalAccumOpenCLKernelCreator::GammaCorrectionEntryPoint(unsigned int channels, bool transparency) +string FinalAccumOpenCLKernelCreator::GammaCorrectionEntryPoint(size_t channels, bool transparency) { bool alphaCalc = ((channels > 3) && transparency); return alphaCalc ? m_GammaCorrectionWithAlphaCalcEntryPoint : m_GammaCorrectionWithoutAlphaCalcEntryPoint; @@ -76,7 +76,7 @@ string FinalAccumOpenCLKernelCreator::GammaCorrectionEntryPoint(unsigned int /// True if channels equals 4 and using transparency, else false. /// The gamma correction kernel string template -string FinalAccumOpenCLKernelCreator::GammaCorrectionKernel(unsigned int channels, bool transparency) +string FinalAccumOpenCLKernelCreator::GammaCorrectionKernel(size_t channels, bool transparency) { bool alphaCalc = ((channels > 3) && transparency); return alphaCalc ? m_GammaCorrectionWithAlphaCalcKernel : m_GammaCorrectionWithoutAlphaCalcKernel; @@ -92,7 +92,7 @@ string FinalAccumOpenCLKernelCreator::GammaCorrectionKernel(unsigned int chan /// Storage for the alpha scale value used in the kernel. 255 if transparency is true, else 0. /// The name of the final accumulation entry point kernel function template -string FinalAccumOpenCLKernelCreator::FinalAccumEntryPoint(bool earlyClip, unsigned int channels, bool transparency, T& alphaBase, T& alphaScale) +string FinalAccumOpenCLKernelCreator::FinalAccumEntryPoint(bool earlyClip, size_t channels, bool transparency, T& alphaBase, T& alphaScale) { bool alphaCalc = ((channels > 3) && transparency); bool alphaAccum = channels > 3; @@ -135,7 +135,7 @@ string FinalAccumOpenCLKernelCreator::FinalAccumEntryPoint(bool earlyClip, un /// True if channels equals 4 and using transparency, else false. /// The final accumulation kernel string template -string FinalAccumOpenCLKernelCreator::FinalAccumKernel(bool earlyClip, unsigned int channels, bool transparency) +string FinalAccumOpenCLKernelCreator::FinalAccumKernel(bool earlyClip, size_t channels, bool transparency) { bool alphaCalc = (channels > 3 && transparency); bool alphaAccum = channels > 3; @@ -172,7 +172,7 @@ string FinalAccumOpenCLKernelCreator::FinalAccumKernel(bool earlyClip, unsign /// True if channels equals 4 and using transparency, else false. /// The final accumulation kernel string template -string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyClip, unsigned int channels, bool transparency) +string FinalAccumOpenCLKernelCreator::CreateFinalAccumKernelString(bool earlyClip, size_t channels, bool transparency) { return CreateFinalAccumKernelString(earlyClip, (channels > 3 && transparency), channels > 3); } diff --git a/Source/EmberCL/FinalAccumOpenCLKernelCreator.h b/Source/EmberCL/FinalAccumOpenCLKernelCreator.h index 5ded6ec..426b0d3 100644 --- a/Source/EmberCL/FinalAccumOpenCLKernelCreator.h +++ b/Source/EmberCL/FinalAccumOpenCLKernelCreator.h @@ -46,13 +46,13 @@ public: string FinalAccumLateClipWithAlphaCalcWithAlphaAccumEntryPoint(); string FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumKernel(); string FinalAccumLateClipWithoutAlphaCalcWithAlphaAccumEntryPoint(); - string GammaCorrectionEntryPoint(unsigned int channels, bool transparency); - string GammaCorrectionKernel(unsigned int channels, bool transparency); - string FinalAccumEntryPoint(bool earlyClip, unsigned int channels, bool transparency, T& alphaBase, T& alphaScale); - string FinalAccumKernel(bool earlyClip, unsigned int channels, bool transparency); + string GammaCorrectionEntryPoint(size_t channels, bool transparency); + string GammaCorrectionKernel(size_t channels, bool transparency); + string FinalAccumEntryPoint(bool earlyClip, size_t channels, bool transparency, T& alphaBase, T& alphaScale); + string FinalAccumKernel(bool earlyClip, size_t channels, bool transparency); private: - string CreateFinalAccumKernelString(bool earlyClip, unsigned int channels, bool transparency); + string CreateFinalAccumKernelString(bool earlyClip, size_t channels, bool transparency); string CreateGammaCorrectionKernelString(bool alphaCalc); string CreateFinalAccumKernelString(bool earlyClip, bool alphaCalc, bool alphaAccum); diff --git a/Source/EmberCL/IterOpenCLKernelCreator.cpp b/Source/EmberCL/IterOpenCLKernelCreator.cpp index 7542f22..6c944e6 100644 --- a/Source/EmberCL/IterOpenCLKernelCreator.cpp +++ b/Source/EmberCL/IterOpenCLKernelCreator.cpp @@ -46,7 +46,7 @@ template string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, string& parVarDefines, bool lockAccum, bool doAccum) { bool doublePrecision = typeid(T) == typeid(double); - unsigned int i, v, varIndex, varCount, totalXformCount = ember.TotalXformCount(); + size_t i, v, varIndex, varCount, totalXformCount = ember.TotalXformCount(); ostringstream kernelIterBody, xformFuncs, os; vector*> variations; @@ -57,7 +57,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin for (i = 0; i < totalXformCount; i++) { Xform* xform = ember.GetTotalXform(i); - unsigned int totalVarCount = xform->TotalVariationCount(); + size_t totalVarCount = xform->TotalVariationCount(); bool needPrecalcSumSquares = false; bool needPrecalcSqrtSumSquares = false; bool needPrecalcAngles = false; @@ -395,7 +395,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin if (ember.UseFinalXform()) { - unsigned int finalIndex = ember.TotalXformCount() - 1; + size_t finalIndex = ember.TotalXformCount() - 1; //CPU takes an extra step here to preserve the opacity of the randomly selected xform, rather than the final xform's opacity. //The same thing takes place here automatically because secondPoint.m_LastXfUsed is used below to retrieve the opacity when accumulating. @@ -564,7 +564,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin /// /// The variations the 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 overriden OpenCLString() functions. +/// in their overridden OpenCLString() functions. /// Template argument expected to be float or double. /// /// The ember to create the values from @@ -574,7 +574,7 @@ string IterOpenCLKernelCreator::CreateIterKernelString(Ember& ember, strin template void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pair>& params, bool doVals, bool doString) { - unsigned int i, j, k, size = 0, xformCount = ember.TotalXformCount(); + size_t i, j, k, size = 0, xformCount = ember.TotalXformCount(); Xform* xform; ostringstream os; @@ -585,7 +585,7 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pairTotalVariationCount(); + size_t varCount = xform->TotalVariationCount(); for (j = 0; j < varCount; j++) { @@ -632,7 +632,7 @@ void IterOpenCLKernelCreator::ParVarIndexDefines(Ember& ember, pair bool IterOpenCLKernelCreator::IsBuildRequired(Ember& ember1, Ember& ember2) { - unsigned int i, j, xformCount = ember1.TotalXformCount(); + size_t i, j, xformCount = ember1.TotalXformCount(); if (xformCount != ember2.TotalXformCount()) return true; @@ -653,7 +653,7 @@ bool IterOpenCLKernelCreator::IsBuildRequired(Ember& ember1, Ember& emb { Xform* xform1 = ember1.GetTotalXform(i); Xform* xform2 = ember2.GetTotalXform(i); - unsigned int varCount = xform1->TotalVariationCount(); + size_t varCount = xform1->TotalVariationCount(); if (xform1->HasPost() != xform2->HasPost()) return true; @@ -706,7 +706,7 @@ string IterOpenCLKernelCreator::CreateZeroizeKernelString() template string IterOpenCLKernelCreator::CreateProjectionString(Ember& ember) { - unsigned int projBits = ember.ProjBits(); + size_t projBits = ember.ProjBits(); ostringstream os; if (projBits) diff --git a/Source/EmberCL/OpenCLWrapper.cpp b/Source/EmberCL/OpenCLWrapper.cpp index 92cbf01..0a043c5 100644 --- a/Source/EmberCL/OpenCLWrapper.cpp +++ b/Source/EmberCL/OpenCLWrapper.cpp @@ -132,7 +132,7 @@ void OpenCLWrapper::ClearPrograms() /// The size in bytes of the buffer /// The buffer flags. Default: CL_MEM_READ_WRITE. /// True if success, else false. -bool OpenCLWrapper::AddBuffer(string name, size_t size, cl_mem_flags flags) +bool OpenCLWrapper::AddBuffer(const string& name, size_t size, cl_mem_flags flags) { cl_int err; @@ -153,16 +153,16 @@ bool OpenCLWrapper::AddBuffer(string name, size_t size, cl_mem_flags flags) } else if (GetBufferSize(bufferIndex) != size)//If it did exist, only create and add if the sizes were different. { - m_Buffers[bufferIndex] = NamedBuffer(cl::Buffer(m_Context, flags, 0, NULL, &err), "emptybuffer"); + m_Buffers[bufferIndex] = NamedBuffer(cl::Buffer(m_Context, flags, 0, NULL, &err), "emptybuffer");//First clear out the original so the two don't exist in memory at once. - cl::Buffer buff(m_Context, flags, size, NULL, &err); + cl::Buffer buff(m_Context, flags, size, NULL, &err);//Create the new buffer. if (!CheckCL(err, "cl::Buffer()")) return false; - NamedBuffer nb(buff, name); + NamedBuffer nb(buff, name);//Make a named buffer out of the new buffer. - m_Buffers[bufferIndex] = nb; + m_Buffers[bufferIndex] = nb;//Finally, assign. } //If the buffer existed and the sizes were the same, take no action. @@ -182,49 +182,14 @@ bool OpenCLWrapper::AddBuffer(string name, size_t size, cl_mem_flags flags) /// The name of the buffer /// A pointer to the buffer /// The size in bytes of the buffer +/// The buffer flags. Default: CL_MEM_READ_WRITE. /// True if success, else false. -bool OpenCLWrapper::AddAndWriteBuffer(string name, void* data, size_t size) +bool OpenCLWrapper::AddAndWriteBuffer(const string& name, void* data, size_t size, cl_mem_flags flags) { - cl_int err; bool b = false; - if (m_Init) - { - int bufferIndex = FindBufferIndex(name); - - //Easy case: totally new buffer, so just create and add. - if (bufferIndex == -1) - { - cl::Buffer buff(m_Context, CL_MEM_READ_WRITE, size, NULL, &err); - - if (!CheckCL(err, "cl::Buffer()")) - return b; - - NamedBuffer nb(buff, name); - - m_Buffers.push_back(nb); - b = WriteBuffer((unsigned int)m_Buffers.size() - 1, data, size); - } - else//Harder case: the buffer already exists. Replace or overwrite? - { - if (GetBufferSize(bufferIndex) == size)//Size was equal, so just copy data without creating a new buffer. - { - b = WriteBuffer(bufferIndex, data, size); - } - else//Size was not equal, so create entirely new buffer, replace, and copy data. - { - cl::Buffer buff(m_Context, CL_MEM_READ_WRITE, size, NULL, &err); - - if (!CheckCL(err, "cl::Buffer()")) - return b; - - NamedBuffer nb(buff, name); - - m_Buffers[bufferIndex] = nb; - b = WriteBuffer(bufferIndex, data, size); - } - } - } + if (AddBuffer(name, size, flags)) + b = WriteBuffer(name, data, size); return b; } @@ -236,7 +201,7 @@ bool OpenCLWrapper::AddAndWriteBuffer(string name, void* data, size_t size) /// A pointer to the buffer /// The size in bytes of the buffer /// True if success, else false. -bool OpenCLWrapper::WriteBuffer(string name, void* data, size_t size) +bool OpenCLWrapper::WriteBuffer(const string& name, void* data, size_t size) { int bufferIndex = FindBufferIndex(name); @@ -274,7 +239,7 @@ bool OpenCLWrapper::WriteBuffer(unsigned int bufferIndex, void* data, size_t siz /// A pointer to a buffer to copy the data to /// The size in bytes of the buffer /// True if success, else false. -bool OpenCLWrapper::ReadBuffer(string name, void* data, size_t size) +bool OpenCLWrapper::ReadBuffer(const string& name, void* data, size_t size) { int bufferIndex = FindBufferIndex(name); @@ -310,7 +275,7 @@ bool OpenCLWrapper::ReadBuffer(unsigned int bufferIndex, void* data, size_t size /// /// The name of the buffer to search for /// The index if found, else -1. -int OpenCLWrapper::FindBufferIndex(string name) +int OpenCLWrapper::FindBufferIndex(const string& name) { for (unsigned int i = 0; i < m_Buffers.size(); i++) if (m_Buffers[i].m_Name == name) @@ -324,7 +289,7 @@ int OpenCLWrapper::FindBufferIndex(string name) /// /// The name of the buffer to search for /// The size of the buffer if found, else 0. -unsigned int OpenCLWrapper::GetBufferSize(string name) +unsigned int OpenCLWrapper::GetBufferSize(const string& name) { unsigned int bufferIndex = FindBufferIndex(name); @@ -369,7 +334,7 @@ void OpenCLWrapper::ClearBuffers() /// True if shared with an OpenGL texture, else false. Default: false. /// The texture ID of the shared OpenGL texture if shared. Default: 0. /// True if success, else false. -bool OpenCLWrapper::AddAndWriteImage(string name, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch, void* data, bool shared, GLuint texName) +bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch, void* data, bool shared, GLuint texName) { cl_int err; @@ -432,10 +397,10 @@ bool OpenCLWrapper::AddAndWriteImage(string name, cl_mem_flags flags, const cl:: } else { - NamedImage2D namedImage = m_Images[imageIndex]; - - if (!CompareImageParams(namedImage.m_Image, flags, format, width, height, row_pitch)) + if (!CompareImageParams(m_Images[imageIndex].m_Image, flags, format, width, height, row_pitch)) { + m_Images[imageIndex] = NamedImage2D();//First clear out the original so the two don't exist in memory at once. + NamedImage2D namedImage(cl::Image2D(m_Context, flags, format, width, height, row_pitch, data, &err), name); if (CheckCL(err, "cl::Image2D()")) @@ -517,7 +482,7 @@ bool OpenCLWrapper::WriteImage2D(unsigned int index, bool shared, ::size_t width /// True if shared with an OpenGL texture, else false. /// A pointer to a buffer to copy the data to /// True if success, else false. -bool OpenCLWrapper::ReadImage(string name, ::size_t width, ::size_t height, ::size_t row_pitch, bool shared, void* data) +bool OpenCLWrapper::ReadImage(const string& name, ::size_t width, ::size_t height, ::size_t row_pitch, bool shared, void* data) { if (m_Init) { @@ -583,7 +548,7 @@ bool OpenCLWrapper::ReadImage(unsigned int imageIndex, ::size_t width, ::size_t /// The name of the image to search for /// True if shared with an OpenGL texture, else false. /// The index if found, else -1. -int OpenCLWrapper::FindImageIndex(string name, bool shared) +int OpenCLWrapper::FindImageIndex(const string& name, bool shared) { if (shared) { @@ -607,7 +572,7 @@ int OpenCLWrapper::FindImageIndex(string name, bool shared) /// The name of the image to search for /// True if shared with an OpenGL texture, else false. /// The size of the 2D image if found, else 0. -unsigned int OpenCLWrapper::GetImageSize(string name, bool shared) +unsigned int OpenCLWrapper::GetImageSize(const string& name, bool shared) { int imageIndex = FindImageIndex(name, shared); return GetImageSize(imageIndex, shared); @@ -745,7 +710,7 @@ bool OpenCLWrapper::CreateImage2DGL(IMAGEGL2D& image2DGL, cl_mem_flags flags, GL /// /// The name of the image to acquire /// True if success, else false. -bool OpenCLWrapper::EnqueueAcquireGLObjects(string name) +bool OpenCLWrapper::EnqueueAcquireGLObjects(const string& name) { int index = FindImageIndex(name, true); @@ -780,7 +745,7 @@ bool OpenCLWrapper::EnqueueAcquireGLObjects(IMAGEGL2D& image) /// /// The name of the image to release /// True if success, else false. -bool OpenCLWrapper::EnqueueReleaseGLObjects(string name) +bool OpenCLWrapper::EnqueueReleaseGLObjects(const string& name) { int index = FindImageIndex(name, true); @@ -953,7 +918,7 @@ bool OpenCLWrapper::SetImageArg(unsigned int kernelIndex, unsigned int argIndex, /// /// The name of the kernel to search for /// The index if found, else -1. -int OpenCLWrapper::FindKernelIndex(string name) +int OpenCLWrapper::FindKernelIndex(const string& name) { for (unsigned int i = 0; i < m_Programs.size(); i++) if (m_Programs[i].m_Name == name) diff --git a/Source/EmberCL/OpenCLWrapper.h b/Source/EmberCL/OpenCLWrapper.h index 4fd438e..e060d01 100644 --- a/Source/EmberCL/OpenCLWrapper.h +++ b/Source/EmberCL/OpenCLWrapper.h @@ -111,32 +111,32 @@ public: void ClearPrograms(); //Buffers. - bool AddBuffer(string name, size_t size, cl_mem_flags flags = CL_MEM_READ_WRITE); - bool AddAndWriteBuffer(string name, void* data, size_t size); - bool WriteBuffer(string name, void* data, size_t size); + bool AddBuffer(const string& name, size_t size, cl_mem_flags flags = CL_MEM_READ_WRITE); + bool AddAndWriteBuffer(const string& name, void* data, size_t size, cl_mem_flags flags = CL_MEM_READ_WRITE); + bool WriteBuffer(const string& name, void* data, size_t size); bool WriteBuffer(unsigned int bufferIndex, void* data, size_t size); - bool ReadBuffer(string name, void* data, size_t size); + bool ReadBuffer(const string& name, void* data, size_t size); bool ReadBuffer(unsigned int bufferIndex, void* data, size_t size); - int FindBufferIndex(string name); - unsigned int GetBufferSize(string name); + int FindBufferIndex(const string& name); + unsigned int GetBufferSize(const string& name); unsigned int GetBufferSize(unsigned int bufferIndex); void ClearBuffers(); //Images. - bool AddAndWriteImage(string name, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch, void* data = NULL, bool shared = false, GLuint texName = 0); + bool AddAndWriteImage(const string& name, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch, void* data = NULL, bool shared = false, GLuint texName = 0); bool WriteImage2D(unsigned int index, bool shared, ::size_t width, ::size_t height, ::size_t row_pitch, void* data); - bool ReadImage(string name, ::size_t width, ::size_t height, ::size_t row_pitch, bool shared, void* data); + bool ReadImage(const string& name, ::size_t width, ::size_t height, ::size_t row_pitch, bool shared, void* data); bool ReadImage(unsigned int imageIndex, ::size_t width, ::size_t height, ::size_t row_pitch, bool shared, void* data); - int FindImageIndex(string name, bool shared); - unsigned int GetImageSize(string name, bool shared); + int FindImageIndex(const string& name, bool shared); + unsigned int GetImageSize(const string& name, bool shared); unsigned int GetImageSize(unsigned int imageIndex, bool shared); bool CompareImageParams(cl::Image& image, cl_mem_flags flags, const cl::ImageFormat& format, ::size_t width, ::size_t height, ::size_t row_pitch); void ClearImages(bool shared); bool CreateImage2D(cl::Image2D& image2D, cl_mem_flags flags, cl::ImageFormat format, ::size_t width, ::size_t height, ::size_t row_pitch = 0, void* data = NULL); bool CreateImage2DGL(IMAGEGL2D& image2DGL, cl_mem_flags flags, GLenum target, GLint miplevel, GLuint texobj); - bool EnqueueAcquireGLObjects(string name); + bool EnqueueAcquireGLObjects(const string& name); bool EnqueueAcquireGLObjects(IMAGEGL2D& image); - bool EnqueueReleaseGLObjects(string name); + bool EnqueueReleaseGLObjects(const string& name); bool EnqueueReleaseGLObjects(IMAGEGL2D& image); bool EnqueueAcquireGLObjects(const VECTOR_CLASS* memObjects = NULL); bool EnqueueReleaseGLObjects(const VECTOR_CLASS* memObjects = NULL); @@ -170,7 +170,7 @@ public: } //Kernels. - int FindKernelIndex(string name); + int FindKernelIndex(const string& name); bool RunKernel(unsigned int kernelIndex, unsigned int totalGridWidth, unsigned int totalGridHeight, unsigned int totalGridDepth, unsigned int blockWidth, unsigned int blockHeight, unsigned int blockDepth); //Info. diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index 8871e8e..bc7a889 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -63,7 +63,7 @@ RendererCL::~RendererCL() } /// -/// Ordinary member functions for OpenCL specific tasks. +/// Non-virtual member functions for OpenCL specific tasks. /// /// @@ -82,16 +82,17 @@ template bool RendererCL::Init(unsigned int platform, unsigned int device, bool shared, GLuint outputTexID) { //Timing t; + bool b = true; m_OutputTexID = outputTexID; const char* loc = __FUNCTION__; if (!m_Wrapper.Ok() || PlatformIndex() != platform || DeviceIndex() != device) { m_Init = false; - m_Wrapper.Init(platform, device, shared); + b = m_Wrapper.Init(platform, device, shared); } - if (m_Wrapper.Ok() && !m_Init) + if (b && m_Wrapper.Ok() && !m_Init) { m_NVidia = ToLower(m_Wrapper.DeviceAndPlatformNames()).find_first_of("nvidia") != string::npos && m_Wrapper.LocalMemSize() > (32 * 1024); m_WarpSize = m_NVidia ? 32 : 64; @@ -102,11 +103,11 @@ bool RendererCL::Init(unsigned int platform, unsigned int device, bool shared string logAssignProgram = m_DEOpenCLKernelCreator.LogScaleAssignDEKernel(); string logSumProgram = m_DEOpenCLKernelCreator.LogScaleSumDEKernel();//Build a couple of simple programs to ensure OpenCL is working right. - if (!m_Wrapper.AddProgram(m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), zeroizeProgram, m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), m_DoublePrecision)) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddProgram(m_DEOpenCLKernelCreator.LogScaleAssignDEEntryPoint(), logAssignProgram, m_DEOpenCLKernelCreator.LogScaleAssignDEEntryPoint(), m_DoublePrecision)) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddProgram(m_DEOpenCLKernelCreator.LogScaleSumDEEntryPoint(), logSumProgram, m_DEOpenCLKernelCreator.LogScaleSumDEEntryPoint(), m_DoublePrecision)) { m_ErrorReport.push_back(loc); return false; } + if (b && !(b = m_Wrapper.AddProgram(m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), zeroizeProgram, m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), m_DoublePrecision))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddProgram(m_DEOpenCLKernelCreator.LogScaleAssignDEEntryPoint(), logAssignProgram, m_DEOpenCLKernelCreator.LogScaleAssignDEEntryPoint(), m_DoublePrecision))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddProgram(m_DEOpenCLKernelCreator.LogScaleSumDEEntryPoint(), logSumProgram, m_DEOpenCLKernelCreator.LogScaleSumDEEntryPoint(), m_DoublePrecision))) { m_ErrorReport.push_back(loc); } - if (!m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, 256, 1, 0, NULL)) { m_ErrorReport.push_back(loc); return false; } + if (b && !(b = m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, 256, 1, 0, NULL))) { m_ErrorReport.push_back(loc); } //This is the maximum box dimension for density filtering which consists of (blockSize * blockSize) + (2 * filterWidth). //These blocks must be square, and ideally, 32x32. @@ -119,7 +120,29 @@ bool RendererCL::Init(unsigned int platform, unsigned int device, bool shared //t.Toc(loc); } - return m_Init; + return b; +} + +template +bool RendererCL::SetOutputTexture(GLuint outputTexID) +{ + bool success = true; + const char* loc = __FUNCTION__; + + if (!m_Wrapper.Ok()) + return false; + + m_OutputTexID = outputTexID; + EnterResize(); + + if (!m_Wrapper.AddAndWriteImage(m_FinalImageName, CL_MEM_WRITE_ONLY, m_FinalFormat, FinalRasW(), FinalRasH(), 0, NULL, m_Wrapper.Shared(), m_OutputTexID)) + { + m_ErrorReport.push_back(loc); + success = false; + } + + LeaveResize(); + return success; } /// @@ -182,6 +205,49 @@ bool RendererCL::ReadPoints(vector>& vec) return false; } +/// +/// Clear the histogram buffer with all zeroes. +/// +/// True if success, else false. +template +bool RendererCL::ClearHist() +{ + return ClearBuffer(m_HistBufferName, (unsigned int)SuperRasW(), (unsigned int)SuperRasH(), sizeof(v4T)); +} + +/// +/// Clear the desnity filtering buffer with all zeroes. +/// +/// True if success, else false. +template +bool RendererCL::ClearAccum() +{ + return ClearBuffer(m_AccumBufferName, (unsigned int)SuperRasW(), (unsigned int)SuperRasH(), sizeof(v4T)); +} + +/// +/// Write values from a host side CPU buffer into the temporary points buffer. +/// Used for debugging. +/// +/// The host side buffer whose values to write +/// True if success, else false. +template +bool RendererCL::WritePoints(vector>& vec) +{ + return m_Wrapper.WriteBuffer(m_PointsBufferName, (void*)vec.data(), vec.size() * sizeof(vec[0])); +} + +/// +/// Get the kernel string for the last built iter program. +/// +/// The string representation of the kernel for the last built iter program. +template +string RendererCL::IterKernel() { return m_IterKernel; } + +/// +/// Virtual functions overridden from RendererCLBase. +/// + /// /// Read the final image buffer buffer into the host side CPU buffer. /// This must be called before saving the final output image to file. @@ -214,7 +280,7 @@ bool RendererCL::ClearFinal() if (!b) m_ErrorReport.push_back(__FUNCTION__); - + return b; } else @@ -222,46 +288,7 @@ bool RendererCL::ClearFinal() } /// -/// Clear the histogram buffer with all zeroes. -/// -/// True if success, else false. -template -bool RendererCL::ClearHist() -{ - return ClearBuffer(m_HistBufferName, SuperRasW(), SuperRasH(), sizeof(v4T)); -} - -/// -/// Clear the desnity filtering buffer with all zeroes. -/// -/// True if success, else false. -template -bool RendererCL::ClearAccum() -{ - return ClearBuffer(m_AccumBufferName, SuperRasW(), SuperRasH(), sizeof(v4T)); -} - -/// -/// Write values from a host side CPU buffer into the temporary points buffer. -/// Used for debugging. -/// -/// The host side buffer whose values to write -/// True if success, else false. -template -bool RendererCL::WritePoints(vector>& vec) -{ - return m_Wrapper.WriteBuffer(m_PointsBufferName, (void*)vec.data(), vec.size() * sizeof(vec[0])); -} - -/// -/// Get the kernel string for the last built iter program. -/// -/// The string representation of the kernel for the last built iter program. -template -string RendererCL::IterKernel() { return m_IterKernel; } - -/// -/// Public virtual functions overriden from Renderer. +/// Public virtual functions overridden from Renderer or RendererBase. /// /// @@ -269,7 +296,7 @@ string RendererCL::IterKernel() { return m_IterKernel; } /// /// An unsigned 64-bit integer specifying how much video memory is available template -unsigned __int64 RendererCL::MemoryAvailable() +size_t RendererCL::MemoryAvailable() { return Ok() ? m_Wrapper.GetInfo(PlatformIndex(), DeviceIndex(), CL_DEVICE_GLOBAL_MEM_SIZE) : 0ULL; } @@ -290,7 +317,7 @@ bool RendererCL::Ok() const /// /// The number of channels, ignored. template -void RendererCL::NumChannels(unsigned int numChannels) +void RendererCL::NumChannels(size_t numChannels) { m_NumChannels = 4; } @@ -322,7 +349,7 @@ void RendererCL::ClearErrorReport() /// /// The number of iterations ran in a single kernel call template -unsigned int RendererCL::SubBatchSize() const +size_t RendererCL::SubBatchSize() const { return m_IterBlocksWide * m_IterBlocksHigh * SQR(m_IterCountPerKernel); } @@ -333,24 +360,11 @@ unsigned int RendererCL::SubBatchSize() const /// /// 1 template -unsigned int RendererCL::ThreadCount() const +size_t RendererCL::ThreadCount() const { return 1; } -/// -/// Override to always set the thread count to 1 for OpenCL. -/// Specific seeds can't be used for OpenCL. If a repeatable trajectory -/// is needed for debugging, use the base class. -/// -/// The number of threads to use, ignored. -/// The seed string to use if threads is 1, ignored. Default: NULL. -template -void RendererCL::ThreadCount(unsigned int threads, const char* seedString) -{ - Renderer::ThreadCount(threads, seedString); -} - /// /// Create the density filter in the base class and copy the filter values /// to the corresponding OpenCL buffers. @@ -360,22 +374,25 @@ void RendererCL::ThreadCount(unsigned int threads, const char* seedString) template bool RendererCL::CreateDEFilter(bool& newAlloc) { + bool b = true; + if (Renderer::CreateDEFilter(newAlloc)) { //Copy coefs and widths here. Convert and copy the other filter params right before calling the filtering kernel. if (newAlloc) { - DensityFilter* filter = GetDensityFilter(); + const char* loc = __FUNCTION__; + DensityFilter* filter = dynamic_cast*>(GetDensityFilter()); - if (!m_Wrapper.AddAndWriteBuffer(m_DECoefsBufferName, (void*)filter->Coefs(), filter->CoefsSizeBytes())) { m_ErrorReport.push_back(__FUNCTION__); return false; } - if (!m_Wrapper.AddAndWriteBuffer(m_DEWidthsBufferName, (void*)filter->Widths(), filter->WidthsSizeBytes())) { m_ErrorReport.push_back(__FUNCTION__); return false; } - if (!m_Wrapper.AddAndWriteBuffer(m_DECoefIndicesBufferName, (void*)filter->CoefIndices(), filter->CoefsIndicesSizeBytes())) { m_ErrorReport.push_back(__FUNCTION__); return false; } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_DECoefsBufferName, (void*)filter->Coefs(), filter->CoefsSizeBytes()))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_DEWidthsBufferName, (void*)filter->Widths(), filter->WidthsSizeBytes()))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_DECoefIndicesBufferName, (void*)filter->CoefIndices(), filter->CoefsIndicesSizeBytes()))) { m_ErrorReport.push_back(loc); } } - - return true; } + else + b = false; - return false; + return b; } /// @@ -387,15 +404,18 @@ bool RendererCL::CreateDEFilter(bool& newAlloc) template bool RendererCL::CreateSpatialFilter(bool& newAlloc) { + bool b = true; + if (Renderer::CreateSpatialFilter(newAlloc)) { if (newAlloc) - if (!m_Wrapper.AddAndWriteBuffer(m_SpatialFilterCoefsBufferName, (void*)GetSpatialFilter()->Filter(), GetSpatialFilter()->BufferSizeBytes())) { m_ErrorReport.push_back(__FUNCTION__); return false; } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_SpatialFilterCoefsBufferName, (void*)GetSpatialFilter()->Filter(), GetSpatialFilter()->BufferSizeBytes()))) { m_ErrorReport.push_back(__FUNCTION__); } - return true; } + else + b = false; - return false; + return b; } /// @@ -435,7 +455,7 @@ vector RendererCL::ErrorReport() } /// -/// Protected virtual functions overriden from Renderer. +/// Protected virtual functions overridden from Renderer. /// /// @@ -469,26 +489,21 @@ bool RendererCL::Alloc() size_t accumLength = SuperSize() * sizeof(v4T); const char* loc = __FUNCTION__; - if (!m_Wrapper.AddBuffer(m_EmberBufferName, sizeof(m_EmberCL))) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddBuffer(m_ParVarsBufferName, 128 * sizeof(T))) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddBuffer(m_DistBufferName, CHOOSE_XFORM_GRAIN)) { m_ErrorReport.push_back(loc); return false; }//Will be resized for xaos. - if (!m_Wrapper.AddBuffer(m_CarToRasBufferName, sizeof(m_CarToRasCL))) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddBuffer(m_DEFilterParamsBufferName, sizeof(m_DensityFilterCL))) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddBuffer(m_SpatialFilterParamsBufferName, sizeof(m_SpatialFilterCL))) { m_ErrorReport.push_back(loc); return false; } + if (b && !(b = m_Wrapper.AddBuffer(m_EmberBufferName, sizeof(m_EmberCL)))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddBuffer(m_ParVarsBufferName, 128 * sizeof(T)))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddBuffer(m_DistBufferName, CHOOSE_XFORM_GRAIN))) { m_ErrorReport.push_back(loc); }//Will be resized for xaos. + if (b && !(b = m_Wrapper.AddBuffer(m_CarToRasBufferName, sizeof(m_CarToRasCL)))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddBuffer(m_DEFilterParamsBufferName, sizeof(m_DensityFilterCL)))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddBuffer(m_SpatialFilterParamsBufferName, sizeof(m_SpatialFilterCL)))) { m_ErrorReport.push_back(loc); } - if (!m_Wrapper.AddBuffer(m_HistBufferName, histLength)) { m_ErrorReport.push_back(loc); return false; }//Histogram. Will memset to zero later. - if (!m_Wrapper.AddBuffer(m_AccumBufferName, accumLength)) { m_ErrorReport.push_back(loc); return false; }//Accum buffer. - if (!m_Wrapper.AddBuffer(m_PointsBufferName, TotalIterKernelCount() * sizeof(PointCL))) { m_ErrorReport.push_back(loc); return false; }//Points between iter calls. - - if (!m_Wrapper.AddAndWriteImage(m_FinalImageName, CL_MEM_WRITE_ONLY, m_FinalFormat, FinalRasW(), FinalRasH(), 0, NULL, m_Wrapper.Shared(), m_OutputTexID)) - { - m_ErrorReport.push_back(loc); - LeaveResize(); - return false; - } + if (b && !(b = m_Wrapper.AddBuffer(m_HistBufferName, histLength))) { m_ErrorReport.push_back(loc); }//Histogram. Will memset to zero later. + if (b && !(b = m_Wrapper.AddBuffer(m_AccumBufferName, accumLength))) { m_ErrorReport.push_back(loc); }//Accum buffer. + if (b && !(b = m_Wrapper.AddBuffer(m_PointsBufferName, TotalIterKernelCount() * sizeof(PointCL)))) { m_ErrorReport.push_back(loc); }//Points between iter calls. + if (b && !(b = SetOutputTexture(m_OutputTexID))) { m_ErrorReport.push_back(loc); } + LeaveResize(); - return true; + return b; } /// @@ -590,7 +605,7 @@ eRenderStatus RendererCL::AccumulatorToFinalImage(unsigned char* pixels, size /// The temporal sample within the current pass this is running for /// Rendering statistics template -EmberStats RendererCL::Iterate(unsigned __int64 iterCount, unsigned int pass, unsigned int temporalSample) +EmberStats RendererCL::Iterate(size_t iterCount, size_t pass, size_t temporalSample) { bool b = true; EmberStats stats;//Do not record bad vals with with GPU. If the user needs to investigate bad vals, use the CPU. @@ -685,17 +700,17 @@ bool RendererCL::BuildIterProgramForEmber(bool doAccum) /// The storage for the number of iterations ran /// True if success, else false. template -bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsigned int temporalSample, unsigned __int64& itersRan) +bool RendererCL::RunIter(size_t iterCount, size_t pass, size_t temporalSample, size_t& itersRan) { Timing t;//, t2(4); - bool b = false; - unsigned int fuse, argIndex; + bool b = true; + unsigned int seed, fuse, argIndex; unsigned int iterCountPerKernel = m_IterCountPerKernel; unsigned int iterCountPerBlock = iterCountPerKernel * m_IterBlockWidth * m_IterBlockHeight; - unsigned int seed; - unsigned int fuseFreq = m_SubBatchSize / m_IterCountPerKernel; - unsigned __int64 itersRemaining, localIterCount = 0; + unsigned int supersize = (unsigned int)SuperSize(); int kernelIndex = m_Wrapper.FindKernelIndex(m_IterOpenCLKernelCreator.IterEntryPoint()); + size_t fuseFreq = m_SubBatchSize / m_IterCountPerKernel; + size_t itersRemaining, localIterCount = 0; double percent, etaMs; const char* loc = __FUNCTION__; @@ -706,21 +721,20 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig if (kernelIndex != -1) { - b = true; m_EmberCL = ConvertEmber(m_Ember); m_CarToRasCL = ConvertCarToRas(*CoordMap()); - if (!m_Wrapper.WriteBuffer (m_EmberBufferName, (void*)&m_EmberCL, sizeof(m_EmberCL))) { m_ErrorReport.push_back(loc); return false; } - if (!m_Wrapper.AddAndWriteBuffer(m_DistBufferName, (void*)XformDistributions(), XformDistributionsSize())) { m_ErrorReport.push_back(loc); return false; }//Will be resized for xaos. - if (!m_Wrapper.WriteBuffer (m_CarToRasBufferName, (void*)&m_CarToRasCL, sizeof(m_CarToRasCL))) { m_ErrorReport.push_back(loc); return false; } + if (b && !(b = m_Wrapper.WriteBuffer (m_EmberBufferName, (void*)&m_EmberCL, sizeof(m_EmberCL)))) { m_ErrorReport.push_back(loc); } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_DistBufferName, (void*)XformDistributions(), XformDistributionsSize()))) { m_ErrorReport.push_back(loc); }//Will be resized for xaos. + if (b && !(b = m_Wrapper.WriteBuffer (m_CarToRasBufferName, (void*)&m_CarToRasCL, sizeof(m_CarToRasCL)))) { m_ErrorReport.push_back(loc); } - if (!m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Dmap.m_Entries.size(), 1, 0, m_Dmap.m_Entries.data())) { m_ErrorReport.push_back(loc); return false; } + if (b && !(b = m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Dmap.m_Entries.size(), 1, 0, m_Dmap.m_Entries.data()))) { m_ErrorReport.push_back(loc); } //If animating, treat each temporal sample as a newly started render for fusing purposes. if (temporalSample > 0) m_Calls = 0; - while (itersRan < iterCount && !m_Abort) + while (b && itersRan < iterCount && !m_Abort) { argIndex = 0; seed = m_Rand[0].Rand(); @@ -744,27 +758,26 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig iterCountThisLaunch = iterCountPerKernel * (gridW * gridH * m_IterBlockWidth * m_IterBlockHeight); } - if (!m_Wrapper.SetArg (kernelIndex, argIndex++, iterCountPerKernel)) { m_ErrorReport.push_back(loc); return false; }//Number of iters for each thread to run. - if (!m_Wrapper.SetArg (kernelIndex, argIndex++, fuse)) { m_ErrorReport.push_back(loc); return false; }//Number of iters to fuse. - if (!m_Wrapper.SetArg (kernelIndex, argIndex++, seed)) { m_ErrorReport.push_back(loc); return false; }//Seed. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_EmberBufferName)) { m_ErrorReport.push_back(loc); return false; }//Flame. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_ParVarsBufferName)) { m_ErrorReport.push_back(loc); return false; }//Parametric variation parameters. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_DistBufferName)) { m_ErrorReport.push_back(loc); return false; }//Xform distributions. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_CarToRasBufferName)) { m_ErrorReport.push_back(loc); return false; }//Coordinate converter. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_HistBufferName)) { m_ErrorReport.push_back(loc); return false; }//Histogram. - if (!m_Wrapper.SetArg (kernelIndex, argIndex++, SuperSize())) { m_ErrorReport.push_back(loc); return false; }//Histogram size. - if (!m_Wrapper.SetImageArg (kernelIndex, argIndex++, false, "Palette")) { m_ErrorReport.push_back(loc); return false; }//Palette. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_PointsBufferName)) { m_ErrorReport.push_back(loc); return false; }//Random start points. + if (b && !(b = m_Wrapper.SetArg (kernelIndex, argIndex++, iterCountPerKernel))) { m_ErrorReport.push_back(loc); }//Number of iters for each thread to run. + if (b && !(b = m_Wrapper.SetArg (kernelIndex, argIndex++, fuse))) { m_ErrorReport.push_back(loc); }//Number of iters to fuse. + if (b && !(b = m_Wrapper.SetArg (kernelIndex, argIndex++, seed))) { m_ErrorReport.push_back(loc); }//Seed. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_EmberBufferName))) { m_ErrorReport.push_back(loc); }//Flame. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_ParVarsBufferName))) { m_ErrorReport.push_back(loc); }//Parametric variation parameters. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_DistBufferName))) { m_ErrorReport.push_back(loc); }//Xform distributions. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_CarToRasBufferName))) { m_ErrorReport.push_back(loc); }//Coordinate converter. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_HistBufferName))) { m_ErrorReport.push_back(loc); }//Histogram. + if (b && !(b = m_Wrapper.SetArg (kernelIndex, argIndex++, supersize))) { m_ErrorReport.push_back(loc); }//Histogram size. + if (b && !(b = m_Wrapper.SetImageArg (kernelIndex, argIndex++, false, "Palette"))) { m_ErrorReport.push_back(loc); }//Palette. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_PointsBufferName))) { m_ErrorReport.push_back(loc); }//Random start points. - if (!m_Wrapper.RunKernel(kernelIndex, + if (b && !(b = m_Wrapper.RunKernel(kernelIndex, gridW * IterBlockWidth(),//Total grid dims. gridH * IterBlockHeight(), 1, IterBlockWidth(),//Individual block dims. IterBlockHeight(), - 1)) + 1))) { - b = false; m_Abort = true; m_ErrorReport.push_back(loc); break; @@ -808,6 +821,7 @@ bool RendererCL::RunIter(unsigned __int64 iterCount, unsigned int pass, unsig } else { + b = false; m_ErrorReport.push_back(loc); } @@ -823,6 +837,7 @@ template eRenderStatus RendererCL::RunLogScaleFilter() { //Timing t(4); + bool b = true; int kernelIndex; const char* loc = __FUNCTION__; eRenderStatus status = RENDER_OK; @@ -843,23 +858,23 @@ eRenderStatus RendererCL::RunLogScaleFilter() OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.AddAndWriteBuffer(m_DEFilterParamsBufferName, (void*)&m_DensityFilterCL, sizeof(m_DensityFilterCL))) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_DEFilterParamsBufferName, (void*)&m_DensityFilterCL, sizeof(m_DensityFilterCL)))) { m_ErrorReport.push_back(loc); } - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_HistBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Histogram. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Accumulator. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_DEFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//DensityFilterCL. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_HistBufferName))) { m_ErrorReport.push_back(loc); }//Histogram. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_AccumBufferName))) { m_ErrorReport.push_back(loc); }//Accumulator. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, m_DEFilterParamsBufferName))) { m_ErrorReport.push_back(loc); }//DensityFilterCL. //t.Tic(); - if (!m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1))) { m_ErrorReport.push_back(loc); } //t.Toc(loc); } else { - status = RENDER_ERROR; + b = false; m_ErrorReport.push_back(loc); } - return status; + return b ? RENDER_OK : RENDER_ERROR; } /// @@ -870,11 +885,11 @@ eRenderStatus RendererCL::RunLogScaleFilter() template eRenderStatus RendererCL::RunDensityFilter() { + bool b = true; Timing t(4);//, t2(4); m_DensityFilterCL = ConvertDensityFilter(); int kernelIndex = MakeAndGetDensityFilterProgram(Supersample(), m_DensityFilterCL.m_FilterWidth); const char* loc = __FUNCTION__; - eRenderStatus status = RENDER_OK; if (kernelIndex != -1) { @@ -909,17 +924,17 @@ eRenderStatus RendererCL::RunDensityFilter() double totalChunks = chunkSizeW * chunkSizeH; - if (!m_Wrapper.AddAndWriteBuffer(m_DEFilterParamsBufferName, (void*)&m_DensityFilterCL, sizeof(m_DensityFilterCL))) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_DEFilterParamsBufferName, (void*)&m_DensityFilterCL, sizeof(m_DensityFilterCL)))) { m_ErrorReport.push_back(loc); } - for (unsigned int row = 0; row < chunkSizeH; row++) + for (unsigned int row = 0; b && !m_Abort && row < chunkSizeH; row++) { - for (unsigned int col = 0; col < chunkSizeW; col++) + for (unsigned int col = 0; b && !m_Abort && col < chunkSizeW; col++) { //t2.Tic(); - if (!RunDensityFilterPrivate(kernelIndex, gridW, gridH, blockSizeW, blockSizeH, chunkSizeW, chunkSizeH, row, col)) { m_Abort = true; m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = RunDensityFilterPrivate(kernelIndex, gridW, gridH, blockSizeW, blockSizeH, chunkSizeW, chunkSizeH, row, col))) { m_Abort = true; m_ErrorReport.push_back(loc); } //t2.Toc(loc); - if (m_Callback) + if (b && m_Callback) { double percent = (double((row * chunkSizeW) + (col + 1)) / totalChunks) * 100.0; double etaMs = ((100.0 - percent) / percent) * t.Toc(); @@ -927,24 +942,21 @@ eRenderStatus RendererCL::RunDensityFilter() if (!m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, percent, 1, etaMs)) Abort(); } - - if (m_Abort) - return RENDER_ABORT; } } - if (m_Callback) + if (b && m_Callback) m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 1, 0.0); //t2.Toc(__FUNCTION__ " all passes"); } else { - status = RENDER_ERROR; + b = false; m_ErrorReport.push_back(loc); } - return status; + return m_Abort ? RENDER_ABORT : (b ? RENDER_OK : RENDER_ERROR); } /// @@ -955,6 +967,7 @@ template eRenderStatus RendererCL::RunFinalAccum() { //Timing t(4); + bool b = true; T alphaBase; T alphaScale; int accumKernelIndex = MakeAndGetFinalAccumProgram(alphaBase, alphaScale); @@ -964,19 +977,18 @@ eRenderStatus RendererCL::RunFinalAccum() unsigned int blockW; unsigned int blockH; const char* loc = __FUNCTION__; - eRenderStatus status = RENDER_OK; if (!m_Abort && accumKernelIndex != -1) { //This is needed with or without early clip. m_SpatialFilterCL = ConvertSpatialFilter(); - if (!m_Wrapper.AddAndWriteBuffer(m_SpatialFilterParamsBufferName, (void*)&m_SpatialFilterCL, sizeof(m_SpatialFilterCL))) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = m_Wrapper.AddAndWriteBuffer(m_SpatialFilterParamsBufferName, (void*)&m_SpatialFilterCL, sizeof(m_SpatialFilterCL)))) { m_ErrorReport.push_back(loc); } //Since early clip requires gamma correcting the entire accumulator first, //it can't be done inside of the normal final accumulation kernel, so //an additional kernel must be launched first. - if (EarlyClip()) + if (b && EarlyClip()) { int gammaCorrectKernelIndex = MakeAndGetGammaCorrectionProgram(); @@ -989,15 +1001,15 @@ eRenderStatus RendererCL::RunFinalAccum() gridH = m_SpatialFilterCL.m_SuperRasH; OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex++, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Accumulator. - if (!m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex++, m_SpatialFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//SpatialFilterCL. + if (b && !(b = m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex++, m_AccumBufferName))) { m_ErrorReport.push_back(loc); }//Accumulator. + if (b && !(b = m_Wrapper.SetBufferArg(gammaCorrectKernelIndex, argIndex++, m_SpatialFilterParamsBufferName))) { m_ErrorReport.push_back(loc); }//SpatialFilterCL. - if (!m_Wrapper.RunKernel(gammaCorrectKernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = m_Wrapper.RunKernel(gammaCorrectKernelIndex, gridW, gridH, 1, blockW, blockH, 1))) { m_ErrorReport.push_back(loc); } } else { + b = false; m_ErrorReport.push_back(loc); - return RENDER_ERROR; } } @@ -1008,30 +1020,30 @@ eRenderStatus RendererCL::RunFinalAccum() gridH = m_SpatialFilterCL.m_FinalRasH; OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Accumulator. - if (!m_Wrapper.SetImageArg(accumKernelIndex, argIndex++, m_Wrapper.Shared(), m_FinalImageName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Final image. - if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//SpatialFilterCL. - if (!m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterCoefsBufferName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Filter coefs. - if (!m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaBase)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Alpha base. - if (!m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaScale)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; }//Alpha scale. + if (b && !(b = m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_AccumBufferName))) { m_ErrorReport.push_back(loc); }//Accumulator. + if (b && !(b = m_Wrapper.SetImageArg (accumKernelIndex, argIndex++, m_Wrapper.Shared(), m_FinalImageName))) { m_ErrorReport.push_back(loc); }//Final image. + if (b && !(b = m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterParamsBufferName))) { m_ErrorReport.push_back(loc); }//SpatialFilterCL. + if (b && !(b = m_Wrapper.SetBufferArg(accumKernelIndex, argIndex++, m_SpatialFilterCoefsBufferName))) { m_ErrorReport.push_back(loc); }//Filter coefs. + if (b && !(b = m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaBase))) { m_ErrorReport.push_back(loc); }//Alpha base. + if (b && !(b = m_Wrapper.SetArg (accumKernelIndex, argIndex++, alphaScale))) { m_ErrorReport.push_back(loc); }//Alpha scale. - if (m_Wrapper.Shared()) - if (!m_Wrapper.EnqueueAcquireGLObjects(m_FinalImageName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && m_Wrapper.Shared()) + if (b && !(b = m_Wrapper.EnqueueAcquireGLObjects(m_FinalImageName))) { m_ErrorReport.push_back(loc); } - if (!m_Wrapper.RunKernel(accumKernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && !(b = m_Wrapper.RunKernel(accumKernelIndex, gridW, gridH, 1, blockW, blockH, 1))) { m_ErrorReport.push_back(loc); } - if (m_Wrapper.Shared()) - if (!m_Wrapper.EnqueueReleaseGLObjects(m_FinalImageName)) { m_ErrorReport.push_back(loc); return RENDER_ERROR; } + if (b && m_Wrapper.Shared()) + if (b && !(b = m_Wrapper.EnqueueReleaseGLObjects(m_FinalImageName))) { m_ErrorReport.push_back(loc); } //t.Toc((char*)loc); } else { - status = RENDER_ERROR; + b = false; m_ErrorReport.push_back(loc); } - return status; + return b ? RENDER_OK : RENDER_ERROR; } /// @@ -1043,8 +1055,9 @@ eRenderStatus RendererCL::RunFinalAccum() /// Size of each element /// True if success, else false. template -bool RendererCL::ClearBuffer(string bufferName, unsigned int width, unsigned int height, unsigned int elementSize) +bool RendererCL::ClearBuffer(const string& bufferName, unsigned int width, unsigned int height, unsigned int elementSize) { + bool b = true; int kernelIndex = m_Wrapper.FindKernelIndex(m_IterOpenCLKernelCreator.ZeroizeEntryPoint()); unsigned int argIndex = 0; const char* loc = __FUNCTION__; @@ -1058,17 +1071,18 @@ bool RendererCL::ClearBuffer(string bufferName, unsigned int width, unsigned OpenCLWrapper::MakeEvenGridDims(blockW, blockH, gridW, gridH); - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex++, bufferName)) { m_ErrorReport.push_back(loc); return false; }//Buffer of unsigned char. - if (!m_Wrapper.SetArg (kernelIndex, argIndex++, width * elementSize)) { m_ErrorReport.push_back(loc); return false; }//Width. - if (!m_Wrapper.SetArg (kernelIndex, argIndex++, height)) { m_ErrorReport.push_back(loc); return false; }//Height. - if (!m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return false; } - - return true; + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex++, bufferName))) { m_ErrorReport.push_back(loc); }//Buffer of unsigned char. + if (b && !(b = m_Wrapper.SetArg (kernelIndex, argIndex++, width * elementSize))) { m_ErrorReport.push_back(loc); }//Width. + if (b && !(b = m_Wrapper.SetArg (kernelIndex, argIndex++, height))) { m_ErrorReport.push_back(loc); }//Height. + if (b && !(b = m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1))) { m_ErrorReport.push_back(loc); } } else + { + b = false; m_ErrorReport.push_back(loc); + } - return false; + return b; } /// @@ -1092,23 +1106,23 @@ bool RendererCL::RunDensityFilterPrivate(unsigned int kernelIndex, unsigned i unsigned int argIndex = 0; const char* loc = __FUNCTION__; - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_HistBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Histogram. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_AccumBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Accumulator. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DEFilterParamsBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//FlameDensityFilterCL. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DECoefsBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Coefs. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DEWidthsBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Widths. - if (!m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DECoefIndicesBufferName)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Coef indices. - if (!m_Wrapper.SetArg( kernelIndex, argIndex, chunkSizeW)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Chunk size width (gapW + 1). - if (!m_Wrapper.SetArg( kernelIndex, argIndex, chunkSizeH)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Chunk size height (gapH + 1). - if (!m_Wrapper.SetArg( kernelIndex, argIndex, rowParity)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Row parity. - if (!m_Wrapper.SetArg( kernelIndex, argIndex, colParity)) { m_ErrorReport.push_back(loc); return false; } argIndex++;//Col parity. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_HistBufferName))) { m_ErrorReport.push_back(loc); } argIndex++;//Histogram. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_AccumBufferName))) { m_ErrorReport.push_back(loc); } argIndex++;//Accumulator. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DEFilterParamsBufferName))) { m_ErrorReport.push_back(loc); } argIndex++;//FlameDensityFilterCL. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DECoefsBufferName))) { m_ErrorReport.push_back(loc); } argIndex++;//Coefs. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DEWidthsBufferName))) { m_ErrorReport.push_back(loc); } argIndex++;//Widths. + if (b && !(b = m_Wrapper.SetBufferArg(kernelIndex, argIndex, m_DECoefIndicesBufferName))) { m_ErrorReport.push_back(loc); } argIndex++;//Coef indices. + if (b && !(b = m_Wrapper.SetArg( kernelIndex, argIndex, chunkSizeW))) { m_ErrorReport.push_back(loc); } argIndex++;//Chunk size width (gapW + 1). + if (b && !(b = m_Wrapper.SetArg( kernelIndex, argIndex, chunkSizeH))) { m_ErrorReport.push_back(loc); } argIndex++;//Chunk size height (gapH + 1). + if (b && !(b = m_Wrapper.SetArg( kernelIndex, argIndex, rowParity))) { m_ErrorReport.push_back(loc); } argIndex++;//Row parity. + if (b && !(b = m_Wrapper.SetArg( kernelIndex, argIndex, colParity))) { m_ErrorReport.push_back(loc); } argIndex++;//Col parity. //t.Toc(__FUNCTION__ " set args"); //t.Tic(); - if (!m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1)) { m_ErrorReport.push_back(loc); return false; }//Method 7, accumulating to temp box area. + if (b && !(b = m_Wrapper.RunKernel(kernelIndex, gridW, gridH, 1, blockW, blockH, 1))) { m_ErrorReport.push_back(loc); }//Method 7, accumulating to temp box area. //t.Toc(__FUNCTION__ " RunKernel()"); - return true; + return b; } /// @@ -1118,7 +1132,7 @@ bool RendererCL::RunDensityFilterPrivate(unsigned int kernelIndex, unsigned i /// Width of the gaussian filter /// The kernel index if successful, else -1. template -int RendererCL::MakeAndGetDensityFilterProgram(unsigned int ss, unsigned int filterWidth) +int RendererCL::MakeAndGetDensityFilterProgram(size_t ss, unsigned int filterWidth) { string deEntryPoint = m_DEOpenCLKernelCreator.GaussianDEEntryPoint(ss, filterWidth); int kernelIndex = m_Wrapper.FindKernelIndex(deEntryPoint); @@ -1210,21 +1224,21 @@ template DensityFilterCL RendererCL::ConvertDensityFilter() { DensityFilterCL filterCL; - DensityFilter* densityFilter = GetDensityFilter(); + DensityFilter* densityFilter = dynamic_cast*>(GetDensityFilter()); - filterCL.m_Supersample = Supersample(); - filterCL.m_SuperRasW = SuperRasW(); - filterCL.m_SuperRasH = SuperRasH(); + filterCL.m_Supersample = (unsigned int)Supersample(); + filterCL.m_SuperRasW = (unsigned int)SuperRasW(); + filterCL.m_SuperRasH = (unsigned int)SuperRasH(); filterCL.m_K1 = K1(); filterCL.m_K2 = K2(); if (densityFilter) { filterCL.m_Curve = densityFilter->Curve(); - filterCL.m_KernelSize = densityFilter->KernelSize(); - filterCL.m_MaxFilterIndex = densityFilter->MaxFilterIndex(); - filterCL.m_MaxFilteredCounts = densityFilter->MaxFilteredCounts(); - filterCL.m_FilterWidth = densityFilter->FilterWidth(); + filterCL.m_KernelSize = (unsigned int)densityFilter->KernelSize(); + filterCL.m_MaxFilterIndex = (unsigned int)densityFilter->MaxFilterIndex(); + filterCL.m_MaxFilteredCounts = (unsigned int)densityFilter->MaxFilteredCounts(); + filterCL.m_FilterWidth = (unsigned int)densityFilter->FilterWidth(); } return filterCL; @@ -1244,15 +1258,15 @@ SpatialFilterCL RendererCL::ConvertSpatialFilter() PrepFinalAccumVals(background, g, linRange, vibrancy); - filterCL.m_SuperRasW = SuperRasW(); - filterCL.m_SuperRasH = SuperRasH(); - filterCL.m_FinalRasW = FinalRasW(); - filterCL.m_FinalRasH = FinalRasH(); - filterCL.m_Supersample = Supersample(); - filterCL.m_FilterWidth = GetSpatialFilter()->FinalFilterWidth(); - filterCL.m_NumChannels = Renderer::NumChannels(); - filterCL.m_BytesPerChannel = BytesPerChannel(); - filterCL.m_DensityFilterOffset = DensityFilterOffset(); + filterCL.m_SuperRasW = (unsigned int)SuperRasW(); + filterCL.m_SuperRasH = (unsigned int)SuperRasH(); + filterCL.m_FinalRasW = (unsigned int)FinalRasW(); + filterCL.m_FinalRasH = (unsigned int)FinalRasH(); + filterCL.m_Supersample = (unsigned int)Supersample(); + filterCL.m_FilterWidth = (unsigned int)GetSpatialFilter()->FinalFilterWidth(); + filterCL.m_NumChannels = (unsigned int)Renderer::NumChannels(); + filterCL.m_BytesPerChannel = (unsigned int)BytesPerChannel(); + filterCL.m_DensityFilterOffset = (unsigned int)DensityFilterOffset(); filterCL.m_Transparency = Transparency(); filterCL.m_YAxisUp = (unsigned int)m_YAxisUp; filterCL.m_Vibrancy = vibrancy; @@ -1333,7 +1347,7 @@ CarToRasCL RendererCL::ConvertCarToRas(const CarToRas& carToRas) { CarToRasCL carToRasCL; - carToRasCL.m_RasWidth = carToRas.RasWidth(); + carToRasCL.m_RasWidth = (unsigned int)carToRas.RasWidth(); carToRasCL.m_PixPerImageUnitW = carToRas.PixPerImageUnitW(); carToRasCL.m_RasLlX = carToRas.RasLlX(); carToRasCL.m_PixPerImageUnitH = carToRas.PixPerImageUnitH(); diff --git a/Source/EmberCL/RendererCL.h b/Source/EmberCL/RendererCL.h index 06d96b3..927d142 100644 --- a/Source/EmberCL/RendererCL.h +++ b/Source/EmberCL/RendererCL.h @@ -15,8 +15,8 @@ namespace EmberCLns class EMBERCL_API RendererCLBase { public: - virtual bool ReadFinal(unsigned char* pixels) { return false; } - virtual bool ClearFinal() { return false; } + virtual bool ReadFinal(unsigned char* pixels) = 0; + virtual bool ClearFinal() = 0; }; /// @@ -36,8 +36,9 @@ public: RendererCL(unsigned int platform = 0, unsigned int device = 0, bool shared = false, GLuint outputTexID = 0); ~RendererCL(); - //Ordinary member functions for OpenCL specific tasks. + //Non-virtual member functions for OpenCL specific tasks. bool Init(unsigned int platform, unsigned int device, bool shared, GLuint outputTexID); + bool SetOutputTexture(GLuint outputTexID); inline unsigned int IterCountPerKernel(); inline unsigned int IterBlocksWide(); inline unsigned int IterBlocksHigh(); @@ -51,50 +52,51 @@ public: bool ReadHist(); bool ReadAccum(); bool ReadPoints(vector>& vec); - virtual bool ReadFinal(unsigned char* pixels); - virtual bool ClearFinal(); bool ClearHist(); bool ClearAccum(); bool WritePoints(vector>& vec); string IterKernel(); - //Public virtual functions overriden from Renderer. - virtual unsigned __int64 MemoryAvailable(); - virtual bool Ok() const; - virtual void NumChannels(unsigned int numChannels); - virtual void DumpErrorReport(); - virtual void ClearErrorReport(); - virtual unsigned int SubBatchSize() const; - virtual unsigned int ThreadCount() const; - virtual void ThreadCount(unsigned int threads, const char* seedString = NULL); - virtual bool CreateDEFilter(bool& newAlloc); - virtual bool CreateSpatialFilter(bool& newAlloc); - virtual eRendererType RendererType() const; - virtual string ErrorReportString(); - virtual vector ErrorReport(); + //Virtual functions overridden from RendererCLBase. + virtual bool ReadFinal(unsigned char* pixels); + virtual bool ClearFinal(); + + //Public virtual functions overridden from Renderer or RendererBase. + virtual size_t MemoryAvailable() override; + virtual bool Ok() const override; + virtual void NumChannels(size_t numChannels) override; + virtual void DumpErrorReport() override; + virtual void ClearErrorReport() override; + virtual size_t SubBatchSize() const override; + virtual size_t ThreadCount() const override; + virtual bool CreateDEFilter(bool& newAlloc) override; + virtual bool CreateSpatialFilter(bool& newAlloc) override; + virtual eRendererType RendererType() const override; + virtual string ErrorReportString() override; + virtual vector ErrorReport() override; #ifndef TEST_CL protected: #endif - //Protected virtual functions overriden from Renderer. - virtual void MakeDmap(T colorScalar); - virtual bool Alloc(); - virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true); - virtual eRenderStatus LogScaleDensityFilter(); - virtual eRenderStatus GaussianDensityFilter(); - virtual eRenderStatus AccumulatorToFinalImage(unsigned char* pixels, size_t finalOffset); - virtual EmberStats Iterate(unsigned __int64 iterCount, unsigned int pass, unsigned int temporalSample); + //Protected virtual functions overridden from Renderer. + virtual void MakeDmap(T colorScalar) override; + virtual bool Alloc() override; + virtual bool ResetBuckets(bool resetHist = true, bool resetAccum = true) override; + virtual eRenderStatus LogScaleDensityFilter() override; + virtual eRenderStatus GaussianDensityFilter() override; + virtual eRenderStatus AccumulatorToFinalImage(unsigned char* pixels, size_t finalOffset) override; + virtual EmberStats Iterate(size_t iterCount, size_t pass, size_t temporalSample) override; private: //Private functions for making and running OpenCL programs. bool BuildIterProgramForEmber(bool doAccum = true); - bool RunIter(unsigned __int64 iterCount, unsigned int pass, unsigned int temporalSample, unsigned __int64& itersRan); + bool RunIter(size_t iterCount, size_t pass, size_t temporalSample, size_t& itersRan); eRenderStatus RunLogScaleFilter(); eRenderStatus RunDensityFilter(); eRenderStatus RunFinalAccum(); - bool ClearBuffer(string bufferName, unsigned int width, unsigned int height, unsigned int elementSize); + bool ClearBuffer(const string& bufferName, unsigned int width, unsigned int height, unsigned int elementSize); bool RunDensityFilterPrivate(unsigned int kernelIndex, unsigned int gridW, unsigned int gridH, unsigned int blockW, unsigned int blockH, unsigned int chunkSizeW, unsigned int chunkSizeH, unsigned int rowParity, unsigned int colParity); - int MakeAndGetDensityFilterProgram(unsigned int ss, unsigned int filterWidth); + int MakeAndGetDensityFilterProgram(size_t ss, unsigned int filterWidth); int MakeAndGetFinalAccumProgram(T& alphaBase, T& alphaScale); int MakeAndGetGammaCorrectionProgram(); @@ -113,8 +115,9 @@ private: unsigned int m_MaxDEBlockSizeW; unsigned int m_MaxDEBlockSizeH; unsigned int m_WarpSize; - unsigned int m_Calls; + size_t m_Calls; + //Buffer names. string m_EmberBufferName; string m_ParVarsBufferName; string m_DistBufferName; @@ -130,6 +133,7 @@ private: string m_FinalImageName; string m_PointsBufferName; + //Kernels. string m_IterKernel; OpenCLWrapper m_Wrapper; diff --git a/Source/EmberCommon/EmberCommon.h b/Source/EmberCommon/EmberCommon.h index 2e204d5..97fc416 100644 --- a/Source/EmberCommon/EmberCommon.h +++ b/Source/EmberCommon/EmberCommon.h @@ -108,7 +108,7 @@ static bool ParseEmberFile(XmlToEmber& parser, string filename, vectorThe full path and name of the file /// True if success, else false. template -static bool InitPaletteList(string filename) +static bool InitPaletteList(const string& filename) { PaletteList paletteList;//Even though this is local, the members are static so they will remain. @@ -129,7 +129,7 @@ static bool InitPaletteList(string filename) /// The RGB buffer /// The width of the image in pixels /// The height of the image in pixels -static void RgbaToRgb(vector& rgba, vector& rgb, unsigned int width, unsigned int height) +static void RgbaToRgb(vector& rgba, vector& rgb, size_t width, size_t height) { rgb.resize(width * height * 3); @@ -143,23 +143,21 @@ static void RgbaToRgb(vector& rgba, vector& rgb, u /// /// Calculate the number of strips required if the needed amount of memory -/// is greater than the system memory, or greater than what the user want to allow. +/// is greater than the system memory, or greater than what the user wants to allow. /// /// Amount of memory required +/// Amount of memory available on the system /// The maximum amount of memory to use. Use max if 0. /// The number of strips to use -static unsigned int CalcStrips(double mem, double memAvailable, double useMem) +static unsigned int CalcStrips(double memRequired, double memAvailable, double useMem) { unsigned int strips; - double memRequired; if (useMem > 0) memAvailable = useMem; else memAvailable *= 0.8; - memRequired = mem; - if (memAvailable >= memRequired) return 1; @@ -175,10 +173,11 @@ static unsigned int CalcStrips(double mem, double memAvailable, double useMem) /// The numerator /// The denominator /// The next highest divisor if found, else 1. -static unsigned int NextHighestEvenDiv(unsigned int numerator, unsigned int denominator) +template +static T NextHighestEvenDiv(T numerator, T denominator) { - unsigned int result = 1; - unsigned int numDiv2 = numerator / 2; + T result = 1; + T numDiv2 = numerator / 2; do { @@ -202,10 +201,11 @@ static unsigned int NextHighestEvenDiv(unsigned int numerator, unsigned int deno /// The numerator /// The denominator /// The next lowest divisor if found, else 1. -static unsigned int NextLowestEvenDiv(unsigned int numerator, unsigned int denominator) +template +static T NextLowestEvenDiv(T numerator, T denominator) { - unsigned int result = 1; - unsigned int numDiv2 = numerator / 2; + T result = 1; + T numDiv2 = numerator / 2; denominator--; @@ -242,19 +242,19 @@ template static Renderer* CreateRenderer(eRendererType renderType, unsigned int platform, unsigned int device, bool shared, GLuint texId, EmberReport& errorReport) { string s; - auto_ptr> renderer; + unique_ptr> renderer; try { if (renderType == CPU_RENDERER) { s = "CPU"; - renderer = auto_ptr>(new Renderer()); + renderer = unique_ptr>(new Renderer()); } else if (renderType == OPENCL_RENDERER) { s = "OpenCL"; - renderer = auto_ptr>(new RendererCL(platform, device, shared, texId)); + renderer = unique_ptr>(new RendererCL(platform, device, shared, texId)); if (!renderer.get() || !renderer->Ok()) { @@ -262,7 +262,7 @@ static Renderer* CreateRenderer(eRendererType renderType, unsigned i errorReport.AddToReport(renderer->ErrorReport()); errorReport.AddToReport("Error initializing OpenCL renderer, using CPU renderer instead."); - renderer = auto_ptr>(new Renderer()); + renderer = unique_ptr>(new Renderer()); } } } @@ -274,6 +274,116 @@ static Renderer* CreateRenderer(eRendererType renderType, unsigned i return renderer.release(); } +template +static bool StripsRender(RendererBase* renderer, Ember& ember, vector& finalImage, double time, size_t strips, bool yAxisUp, + std::function perStripStart, + std::function perStripFinish, + std::function perStripError, + std::function& finalEmber)> allStripsFinished) +{ + bool success = true; + size_t origHeight, realHeight = ember.m_FinalRasH; + T centerY = ember.m_CenterY; + T floatStripH = T(ember.m_FinalRasH) / T(strips); + T zoomScale = pow(T(2), ember.m_Zoom); + T centerBase = centerY - ((strips - 1) * floatStripH) / (2 * ember.m_PixelsPerUnit * zoomScale); + vector> randVec; + + ember.m_Quality *= strips; + ember.m_FinalRasH = (size_t)ceil(floatStripH); + + if (strips > 1) + randVec = renderer->RandVec(); + + for (size_t strip = 0; strip < strips; strip++) + { + size_t stripOffset; + + if (yAxisUp) + stripOffset = ember.m_FinalRasH * ((strips - strip) - 1) * renderer->FinalRowSize(); + else + stripOffset = ember.m_FinalRasH * strip * renderer->FinalRowSize(); + + ember.m_CenterY = centerBase + ember.m_FinalRasH * T(strip) / (ember.m_PixelsPerUnit * zoomScale); + + if ((ember.m_FinalRasH * (strip + 1)) > realHeight) + { + origHeight = ember.m_FinalRasH; + ember.m_FinalRasH = realHeight - origHeight * strip; + ember.m_CenterY -= (origHeight - ember.m_FinalRasH) * T(0.5) / (ember.m_PixelsPerUnit * zoomScale); + } + + ember.m_CenterY; + perStripStart(strip); + + if (strips > 1) + { + renderer->RandVec(randVec);//Use the same vector of ISAAC rands for each strip. + renderer->SetEmber(ember);//Set one final time after modifications for strips. + } + + if ((renderer->Run(finalImage, time, 0, false, stripOffset) != RENDER_OK) || renderer->Aborted() || finalImage.empty()) + { + perStripError(strip); + success = false; + break; + } + else + { + perStripFinish(strip); + } + + if (strip == strips - 1) + { + //Restore the ember values to their original values. + if (strips > 1) + { + ember.m_Quality /= strips; + ember.m_FinalRasH = realHeight; + ember.m_CenterY = centerY; + renderer->SetEmber(ember);//Further processing will require the dimensions to match the original ember, so re-assign. + } + + allStripsFinished(ember); + } + } + + Memset(finalImage); + + return success; +} + +static size_t VerifyStrips(size_t height, size_t strips, + std::function stripError1, + std::function stripError2, + std::function stripError3) +{ + ostringstream os; + + if (strips > height) + { + os << "Cannot have more strips than rows: " << strips << " > " << height << ". Setting strips = rows."; + stripError1(os.str()); os.str(""); + strips = height; + } + + if (height % strips != 0) + { + os << "A strips value of " << strips << " does not divide evenly into a height of " << height << "."; + stripError2(os.str()); os.str(""); + + strips = NextHighestEvenDiv(height, strips); + + if (strips == 1)//No higher divisor, check for a lower one. + strips = NextLowestEvenDiv(height, strips); + + os << "Setting strips to " << strips << "."; + stripError3(os.str()); os.str(""); + } + + return strips; +} + /// /// Simple macro to print a string if the --verbose options has been specified. /// diff --git a/Source/EmberCommon/JpegUtils.h b/Source/EmberCommon/JpegUtils.h index a0e974c..d342fe0 100644 --- a/Source/EmberCommon/JpegUtils.h +++ b/Source/EmberCommon/JpegUtils.h @@ -12,10 +12,10 @@ /// Width of the image in pixels /// Height of the image in pixels /// True if success, else false -static bool WritePpm(const char* filename, unsigned char* image, int width, int height) +static bool WritePpm(const char* filename, unsigned char* image, size_t width, size_t height) { bool b = false; - unsigned int size = width * height * 3; + size_t size = width * height * 3; FILE* file; if (fopen_s(&file, filename, "wb") == 0) @@ -44,7 +44,7 @@ static bool WritePpm(const char* filename, unsigned char* image, int width, int /// Url of the author /// Nickname of the author /// True if success, else false -static bool WriteJpeg(const char* filename, unsigned char* image, unsigned int width, unsigned int height, int quality, bool enableComments, EmberImageComments& comments, string id, string url, string nick) +static bool WriteJpeg(const char* filename, unsigned char* image, size_t width, size_t height, int quality, bool enableComments, EmberImageComments& comments, string id, string url, string nick) { bool b = false; FILE* file; @@ -70,8 +70,8 @@ static bool WriteJpeg(const char* filename, unsigned char* image, unsigned int w jpeg_stdio_dest(&info, file); info.in_color_space = JCS_RGB; info.input_components = 3; - info.image_width = width; - info.image_height = height; + info.image_width = (JDIMENSION)width; + info.image_height = (JDIMENSION)height; jpeg_set_defaults(&info); jpeg_set_quality(&info, quality, TRUE); jpeg_start_compress(&info, TRUE); @@ -135,7 +135,7 @@ static bool WriteJpeg(const char* filename, unsigned char* image, unsigned int w /// Url of the author /// Nickname of the author /// True if success, else false -static bool WritePng(const char* filename, unsigned char* image, unsigned int width, unsigned int height, int bytesPerChannel, bool enableComments, EmberImageComments& comments, string id, string url, string nick) +static bool WritePng(const char* filename, unsigned char* image, size_t width, size_t height, size_t bytesPerChannel, bool enableComments, EmberImageComments& comments, string id, string url, string nick) { bool b = false; FILE* file; @@ -197,7 +197,7 @@ static bool WritePng(const char* filename, unsigned char* image, unsigned int wi png_init_io(png_ptr, file); - png_set_IHDR(png_ptr, info_ptr, width, height, 8 * bytesPerChannel, + png_set_IHDR(png_ptr, info_ptr, (png_uint_32)width, (png_uint_32)height, 8 * (png_uint_32)bytesPerChannel, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, @@ -232,17 +232,17 @@ static bool WritePng(const char* filename, unsigned char* image, unsigned int wi /// The height. /// The size of the new buffer created /// The converted buffer if successful, else NULL. -static BYTE* ConvertRGBToBMPBuffer(BYTE* buffer, int width, int height, long& newSize) +static BYTE* ConvertRGBToBMPBuffer(BYTE* buffer, size_t width, size_t height, size_t& newSize) { if (NULL == buffer || width == 0 || height == 0) return NULL; - int padding = 0; - int scanlinebytes = width * 3; + size_t padding = 0; + size_t scanlinebytes = width * 3; while ((scanlinebytes + padding ) % 4 != 0) padding++; - int psw = scanlinebytes + padding; + size_t psw = scanlinebytes + padding; newSize = height * psw; BYTE* newBuf = new BYTE[newSize]; @@ -251,12 +251,12 @@ static BYTE* ConvertRGBToBMPBuffer(BYTE* buffer, int width, int height, long& ne { memset (newBuf, 0, newSize); - long bufpos = 0; - long newpos = 0; + size_t bufpos = 0; + size_t newpos = 0; - for (int y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { - for (int x = 0; x < 3 * width; x += 3) + for (size_t x = 0; x < 3 * width; x += 3) { bufpos = y * 3 * width + x; // position in original buffer newpos = (height - y - 1) * psw + x; // position in padded buffer @@ -286,11 +286,11 @@ static BYTE* ConvertRGBToBMPBuffer(BYTE* buffer, int width, int height, long& ne /// Height of the image in pixels /// Padded size, greater than or equal to total image size. /// True if success, else false -static bool SaveBmp(const char* filename, BYTE* image, int width, int height, long paddedSize) +static bool SaveBmp(const char* filename, BYTE* image, size_t width, size_t height, size_t paddedSize) { BITMAPFILEHEADER bmfh; BITMAPINFOHEADER info; - unsigned long bwritten; + DWORD bwritten; HANDLE file; memset (&bmfh, 0, sizeof (BITMAPFILEHEADER)); memset (&info, 0, sizeof (BITMAPINFOHEADER)); @@ -298,12 +298,12 @@ static bool SaveBmp(const char* filename, BYTE* image, int width, int height, lo bmfh.bfType = 0x4d42; // 0x4d42 = 'BM' bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; - bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + paddedSize; + bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (DWORD)paddedSize; bmfh.bfOffBits = 0x36; info.biSize = sizeof(BITMAPINFOHEADER); - info.biWidth = width; - info.biHeight = height; + info.biWidth = (LONG)width; + info.biHeight = (LONG)height; info.biPlanes = 1; info.biBitCount = 24; info.biCompression = BI_RGB; @@ -331,7 +331,7 @@ static bool SaveBmp(const char* filename, BYTE* image, int width, int height, lo return false; } - if (WriteFile(file, image, paddedSize, &bwritten, NULL) == false) + if (WriteFile(file, image, (DWORD)paddedSize, &bwritten, NULL) == false) { CloseHandle(file); return false; @@ -349,10 +349,10 @@ static bool SaveBmp(const char* filename, BYTE* image, int width, int height, lo /// Width of the image in pixels /// Height of the image in pixels /// True if success, else false -static bool WriteBmp(const char* filename, unsigned char* image, int width, int height) +static bool WriteBmp(const char* filename, unsigned char* image, size_t width, size_t height) { bool b = false; - long newSize; + size_t newSize; auto_ptr bgrBuf(ConvertRGBToBMPBuffer(image, width, height, newSize)); if (bgrBuf.get()) diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index 98cba97..8764cd6 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -61,7 +61,7 @@ bool EmberGenome(EmberOptions& opt) bool exactTimeMatch, randomMode, didColor, seqFlag; unsigned int i, j, i0, i1, rep, val, frame, frameCount, count = 0; unsigned int ftime, firstFrame, lastFrame; - unsigned int n, tot, totb, totw; + size_t n, tot, totb, totw; T avgPix, fractionBlack, fractionWhite, blend, spread, mix0, mix1; string token, filename; ostringstream os, os2; diff --git a/Source/EmberRender/EmberRender.cpp b/Source/EmberRender/EmberRender.cpp index 16746ca..c2e7e05 100644 --- a/Source/EmberRender/EmberRender.cpp +++ b/Source/EmberRender/EmberRender.cpp @@ -28,9 +28,9 @@ bool EmberRender(EmberOptions& opt) Timing t; bool writeSuccess = false; unsigned char* finalImagep; - unsigned int i, channels, strip, strips, realHeight, origHeight; - size_t stripOffset; - T centerY, centerBase, zoomScale, floatStripH; + size_t i, channels; + size_t strips; + size_t iterCount; string filename; ostringstream os; vector> embers; @@ -188,6 +188,7 @@ bool EmberRender(EmberOptions& opt) embers[i].m_FinalRasH = 1080; } + stats.Clear(); renderer->SetEmber(embers[i]); renderer->PrepFinalAccumVector(finalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). @@ -197,40 +198,17 @@ bool EmberRender(EmberOptions& opt) } else { - strips = CalcStrips((double)renderer->MemoryRequired(false), (double)renderer->MemoryAvailable(), opt.UseMem()); + strips = CalcStrips((double)renderer->MemoryRequired(1, true), (double)renderer->MemoryAvailable(), opt.UseMem()); if (strips > 1) VerbosePrint("Setting strips to " << strips << " with specified memory usage of " << opt.UseMem()); } - if (strips > embers[i].m_FinalRasH) - { - cout << "Cannot have more strips than rows: " << opt.Strips() << " > " << embers[i].m_FinalRasH << ". Setting strips = rows." << endl; - opt.Strips(strips = embers[i].m_FinalRasH); - } + strips = VerifyStrips(embers[i].m_FinalRasH, strips, + [&](const string& s) { cout << s << endl; },//Greater than height. + [&](const string& s) { cout << s << endl; },//Mod height != 0. + [&](const string& s) { cout << s << endl; });//Final strips value to be set. - if (embers[i].m_FinalRasH % strips != 0) - { - cout << "A strips value of " << strips << " does not divide evenly into a height of " << embers[i].m_FinalRasH; - - strips = NextHighestEvenDiv(embers[i].m_FinalRasH, strips); - - if (strips == 1)//No higher divisor, check for a lower one. - strips = NextLowestEvenDiv(embers[i].m_FinalRasH, strips); - - cout << ". Setting strips to " << strips << "." << endl; - } - - embers[i].m_Quality *= strips; - realHeight = embers[i].m_FinalRasH; - floatStripH = T(embers[i].m_FinalRasH) / T(strips); - embers[i].m_FinalRasH = (unsigned int)ceil(floatStripH); - centerY = embers[i].m_CenterY; - zoomScale = pow(T(2), embers[i].m_Zoom); - centerBase = centerY - ((strips - 1) * floatStripH) / (2 * embers[i].m_PixelsPerUnit * zoomScale); - - if (strips > 1) - randVec = renderer->RandVec(); //For testing incremental renderer. //int sb = 1; //bool resume = false, success = false; @@ -242,104 +220,84 @@ bool EmberRender(EmberOptions& opt) //} //while (success && renderer->ProcessState() != ACCUM_DONE); - for (strip = 0; strip < strips; strip++) + StripsRender(renderer.get(), embers[i], finalImage, 0, strips, opt.YAxisUp(), + [&](size_t strip)//Pre strip. { - stripOffset = (size_t)embers[i].m_FinalRasH * strip * renderer->FinalRowSize(); - embers[i].m_CenterY = centerBase + embers[i].m_FinalRasH * T(strip) / (embers[i].m_PixelsPerUnit * zoomScale); - - if ((embers[i].m_FinalRasH * (strip + 1)) > realHeight) - { - origHeight = embers[i].m_FinalRasH; - embers[i].m_FinalRasH = realHeight - origHeight * strip; - embers[i].m_CenterY -= (origHeight - embers[i].m_FinalRasH) * T(0.5) / (embers[i].m_PixelsPerUnit * zoomScale); - } + if (opt.Verbose() && (strips > 1) && strip > 0) + cout << endl; if (strips > 1) - { - renderer->RandVec(randVec);//Use the same vector of ISAAC rands for each strip. - renderer->SetEmber(embers[i]);//Set one final time after modifications for strips. - - if (opt.Verbose() && (strips > 1) && strip > 0) - cout << endl; - VerbosePrint("Strip = " << (strip + 1) << "/" << strips); - } - - if ((renderer->Run(finalImage, 0, 0, false, stripOffset) != RENDER_OK) || renderer->Aborted() || finalImage.empty()) - { - cout << "Error: image rendering failed, skipping to next image." << endl; - renderer->DumpErrorReport();//Something went wrong, print errors. - break;//Exit strips loop, resume next iter in embers loop. - } - - progress->Clear(); - - //Original wrote every strip as a full image which could be very slow with many large images. - //Only write once all strips for this image are finished. - if (strip == strips - 1) - { - if (!opt.Out().empty()) - { - filename = opt.Out(); - } - else if (opt.NameEnable() && !embers[i].m_Name.empty()) - { - filename = opt.Prefix() + embers[i].m_Name + opt.Suffix() + "." + opt.Format(); - } - else - { - ostringstream ssLocal; - - ssLocal << opt.Prefix() << setfill('0') << setw(5) << i << opt.Suffix() << "." << opt.Format(); - filename = ssLocal.str(); - } - - writeSuccess = false; - comments = renderer->ImageComments(opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette()); - stats = renderer->Stats(); - os.str(""); - os << comments.m_NumIters << " / " << renderer->TotalIterCount() << " (" << std::fixed << std::setprecision(2) << ((double)stats.m_Iters/(double)renderer->TotalIterCount() * 100) << "%)"; - - VerbosePrint("\nIters ran/requested: " + os.str()); - VerbosePrint("Bad values: " << stats.m_Badvals); - VerbosePrint("Render time: " + t.Format(stats.m_RenderMs)); - VerbosePrint("Pure iter time: " + t.Format(stats.m_IterMs)); - VerbosePrint("Iters/sec: " << unsigned __int64(stats.m_Iters / (stats.m_IterMs / 1000.0)) << endl); - VerbosePrint("Writing " + filename); - - if ((opt.Format() == "jpg" || opt.Format() == "bmp") && renderer->NumChannels() == 4) - { - RgbaToRgb(finalImage, vecRgb, renderer->FinalRasW(), realHeight); - - finalImagep = vecRgb.data(); - } - else - { - finalImagep = finalImage.data(); - } - - if (opt.Format() == "png") - writeSuccess = WritePng(filename.c_str(), finalImagep, renderer->FinalRasW(), realHeight, opt.BitsPerChannel() / 8, opt.PngComments(), comments, opt.Id(), opt.Url(), opt.Nick()); - else if (opt.Format() == "jpg") - writeSuccess = WriteJpeg(filename.c_str(), finalImagep, renderer->FinalRasW(), realHeight, opt.JpegQuality(), opt.JpegComments(), comments, opt.Id(), opt.Url(), opt.Nick()); - else if (opt.Format() == "ppm") - writeSuccess = WritePpm(filename.c_str(), finalImagep, renderer->FinalRasW(), realHeight); - else if (opt.Format() == "bmp") - writeSuccess = WriteBmp(filename.c_str(), finalImagep, renderer->FinalRasW(), realHeight); - - if (!writeSuccess) - cout << "Error writing " << filename << endl; - } - } - - //Restore the ember values to their original values. - if (strips > 1) + }, + [&](size_t strip)//Post strip. { - embers[i].m_Quality /= strips; - embers[i].m_FinalRasH = realHeight; - embers[i].m_CenterY = centerY; - memset(finalImage.data(), 0, finalImage.size()); - } + progress->Clear(); + stats += renderer->Stats(); + }, + [&](size_t strip)//Error. + { + cout << "Error: image rendering failed, skipping to next image." << endl; + renderer->DumpErrorReport();//Something went wrong, print errors. + }, + //Final strip. + //Original wrote every strip as a full image which could be very slow with many large images. + //Only write once all strips for this image are finished. + [&](Ember& finalEmber) + { + if (!opt.Out().empty()) + { + filename = opt.Out(); + } + else if (opt.NameEnable() && !finalEmber.m_Name.empty()) + { + filename = opt.Prefix() + finalEmber.m_Name + opt.Suffix() + "." + opt.Format(); + } + else + { + ostringstream ssLocal; + + ssLocal << opt.Prefix() << setfill('0') << setw(5) << i << opt.Suffix() << "." << opt.Format(); + filename = ssLocal.str(); + } + + //TotalIterCount() is actually using ScaledQuality() which does not get reset upon ember assignment, + //so it ends up using the correct value for quality * strips. + writeSuccess = false; + iterCount = renderer->TotalIterCount(); + comments = renderer->ImageComments(stats, opt.PrintEditDepth(), opt.IntPalette(), opt.HexPalette()); + os.str(""); + os << comments.m_NumIters << " / " << iterCount << " (" << std::fixed << std::setprecision(2) << (((double)stats.m_Iters / (double)iterCount) * 100) << "%)"; + + VerbosePrint("\nIters ran/requested: " + os.str()); + VerbosePrint("Bad values: " << stats.m_Badvals); + VerbosePrint("Render time: " + t.Format(stats.m_RenderMs)); + VerbosePrint("Pure iter time: " + t.Format(stats.m_IterMs)); + VerbosePrint("Iters/sec: " << unsigned __int64(stats.m_Iters / (stats.m_IterMs / 1000.0)) << endl); + VerbosePrint("Writing " + filename); + + if ((opt.Format() == "jpg" || opt.Format() == "bmp") && renderer->NumChannels() == 4) + { + RgbaToRgb(finalImage, vecRgb, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH); + + finalImagep = vecRgb.data(); + } + else + { + finalImagep = finalImage.data(); + } + + if (opt.Format() == "png") + writeSuccess = WritePng(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.BitsPerChannel() / 8, opt.PngComments(), comments, opt.Id(), opt.Url(), opt.Nick()); + else if (opt.Format() == "jpg") + writeSuccess = WriteJpeg(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, opt.JpegQuality(), opt.JpegComments(), comments, opt.Id(), opt.Url(), opt.Nick()); + else if (opt.Format() == "ppm") + writeSuccess = WritePpm(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH); + else if (opt.Format() == "bmp") + writeSuccess = WriteBmp(filename.c_str(), finalImagep, finalEmber.m_FinalRasW, finalEmber.m_FinalRasH); + + if (!writeSuccess) + cout << "Error writing " << filename << endl; + }); if (opt.EmberCL() && opt.DumpKernel()) cout << "Iteration kernel: \n" << ((RendererCL*)renderer.get())->IterKernel() << endl; diff --git a/Source/EmberTester/EmberTester.cpp b/Source/EmberTester/EmberTester.cpp index 388886e..d42bded 100644 --- a/Source/EmberTester/EmberTester.cpp +++ b/Source/EmberTester/EmberTester.cpp @@ -94,7 +94,7 @@ string GetEmberCLKernelString(Ember& ember, bool iter, bool log, bool de, return os.str(); } -void MakeTestAllVarsRegPrePostComboFile(string filename) +void MakeTestAllVarsRegPrePostComboFile(const string& filename) { EmberToXml writer; vector> embers; @@ -1322,7 +1322,7 @@ void TestOperations() vector*> varVec; //stringVec.push_back("%"); - //varVec = FindVarsWith(stringVec); + //varVec = FindVarsWith(Vec); // //for (size_t i = 0; i < varVec.size(); i++) //{ diff --git a/Source/Fractorium/EmberFile.h b/Source/Fractorium/EmberFile.h index 4bd6e02..caa17ce 100644 --- a/Source/Fractorium/EmberFile.h +++ b/Source/Fractorium/EmberFile.h @@ -76,6 +76,14 @@ public: m_Embers.clear(); } + /// + /// Thin wrapper to get the size of the vector of embers. + /// + size_t Size() + { + return m_Embers.size(); + } + /// /// Ensure all ember names are unique. /// @@ -89,7 +97,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 + "_" + QString::number(++x).toStdString(); + m_Embers[j].m_Name = m_Embers[j].m_Name + "_" + ToString(++x).toStdString(); j = 0; } } @@ -109,7 +117,7 @@ public: /// Ensures a given input filename is unique by appending a count to the end. /// /// The passed in name if it was unique, else a uniquely made name. - static QString UniqueFilename(QString& filename) + static QString UniqueFilename(const QString& filename) { if (!QFile::exists(filename)) return filename; @@ -117,13 +125,13 @@ public: int counter = 2; QString newPath; QFileInfo original(filename); - QString path = original.absolutePath() + QDir::separator(); + QString path = original.absolutePath() + '/'; QString base = original.completeBaseName(); QString extension = original.suffix(); do { - newPath = path + base + "_" + QString::number(counter++) + "." + extension; + newPath = path + base + "_" + ToString(counter++) + "." + extension; } while (QFile::exists(newPath)); @@ -138,7 +146,7 @@ public: /// The default ember name static QString DefaultEmberName(unsigned int i) { - return DefaultFilename() + "-" + QString::number(i); + return DefaultFilename() + "-" + ToString(i); } QString m_Filename; diff --git a/Source/Fractorium/FinalRenderDialog.cpp b/Source/Fractorium/FinalRenderDialog.cpp index f6095d0..cdb19be 100644 --- a/Source/Fractorium/FinalRenderDialog.cpp +++ b/Source/Fractorium/FinalRenderDialog.cpp @@ -18,7 +18,7 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set int row = 0, spinHeight = 20; unsigned int i; double dmax = numeric_limits::max(); - QTableWidget* table = ui.FinalRenderGeometryTable; + QTableWidget* table = ui.FinalRenderParamsTable; QTableWidgetItem* item = NULL; m_Fractorium = (Fractorium*)parent; @@ -31,30 +31,51 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set connect(ui.FinalRenderDoublePrecisionCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoublePrecisionCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.FinalRenderPlatformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnPlatformComboCurrentIndexChanged(int)), Qt::QueuedConnection); connect(ui.FinalRenderDoAllCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoAllCheckBoxStateChanged(int)), Qt::QueuedConnection); + connect(ui.FinalRenderDoSequenceCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnDoSequenceCheckBoxStateChanged(int)), Qt::QueuedConnection); + connect(ui.FinalRenderCurrentSpin, SIGNAL(valueChanged(int)), this, SLOT(OnFinalRenderCurrentSpinChanged(int)), Qt::QueuedConnection); + connect(ui.FinalRenderApplyToAllCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnApplyAllCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.FinalRenderKeepAspectCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnKeepAspectCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.FinalRenderScaleNoneRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection); connect(ui.FinalRenderScaleWidthRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection); connect(ui.FinalRenderScaleHeightRadioButton, SIGNAL(toggled(bool)), this, SLOT(OnScaleRadioButtonChanged(bool)), Qt::QueuedConnection); + + SetupSpinner(ui.FinalRenderSizeTable, this, row, 1, m_WidthScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnFinalRenderWidthScaleChanged(double)), true, 1.0, 1.0, 1.0); + SetupSpinner(ui.FinalRenderSizeTable, this, row, 1, m_HeightScaleSpin, spinHeight, 0.001, 99.99, 0.1, SIGNAL(valueChanged(double)), SLOT(OnFinalRenderHeightScaleChanged(double)), true, 1.0, 1.0, 1.0); + m_WidthScaleSpin->setDecimals(3); + m_HeightScaleSpin->setDecimals(3); + m_WidthScaleSpin->setSuffix(" ( )"); + m_HeightScaleSpin->setSuffix(" ( )"); + m_WidthScaleSpin->SmallStep(0.001); + m_HeightScaleSpin->SmallStep(0.001); - SetupSpinner (table, this, row, 1, m_WidthSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)), true, 1980); - SetupSpinner (table, this, row, 1, m_HeightSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, 1080); - SetupSpinner(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 1000); - 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_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 2); + row = 0; + SetupSpinner(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 1000, 1000, 1000); + SetupSpinner (table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 50, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000, 1000, 1000); + SetupSpinner (table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 2, 1, 1); + SetupSpinner (table, this, row, 1, m_StripsSpin, spinHeight, 1, 64, 1, SIGNAL(valueChanged(int)), SLOT(OnStripsChanged(int)), true, 1, 1, 1); - row++;//Memory usage. + m_MemoryCellIndex = row++;//Memory usage. + m_PathCellIndex = row; - TwoButtonWidget* tbw = new TwoButtonWidget("...", "Open", 22, 40, 22, table); - table->setCellWidget(row, 1, tbw); + QStringList comboList; + + comboList.append("jpg"); + comboList.append("png"); + + m_Tbcw = new TwoButtonComboWidget("...", "Open", comboList, 22, 40, 22, table); + table->setCellWidget(row, 1, m_Tbcw); table->item(row++, 1)->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); - connect(tbw->m_Button1, SIGNAL(clicked(bool)), this, SLOT(OnFileButtonClicked(bool)), Qt::QueuedConnection); - connect(tbw->m_Button2, SIGNAL(clicked(bool)), this, SLOT(OnShowFolderButtonClicked(bool)), Qt::QueuedConnection); + connect(m_Tbcw->m_Button1, SIGNAL(clicked(bool)), this, SLOT(OnFileButtonClicked(bool)), Qt::QueuedConnection); + connect(m_Tbcw->m_Button2, SIGNAL(clicked(bool)), this, SLOT(OnShowFolderButtonClicked(bool)), Qt::QueuedConnection); + connect(m_Tbcw->m_Combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFinalRenderExtIndexChanged(int)), Qt::QueuedConnection); m_PrefixEdit = new QLineEdit(table); table->setCellWidget(row++, 1, m_PrefixEdit); m_SuffixEdit = new QLineEdit(table); table->setCellWidget(row++, 1, m_SuffixEdit); + connect(m_PrefixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnFinalRenderPrefixChanged(const QString&)), Qt::QueuedConnection); + connect(m_SuffixEdit, SIGNAL(textChanged(const QString&)), this, SLOT(OnFinalRenderSuffixChanged(const QString&)), Qt::QueuedConnection); ui.StartRenderButton->disconnect(SIGNAL(clicked(bool))); connect(ui.StartRenderButton, SIGNAL(clicked(bool)), this, SLOT(OnRenderClicked(bool)), Qt::QueuedConnection); @@ -97,22 +118,22 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set ui.FinalRenderKeepAspectCheckBox->setChecked( m_Settings->FinalKeepAspect()); ui.FinalRenderThreadCountSpin->setValue( m_Settings->FinalThreadCount()); - m_WidthSpin->setValue(m_Settings->FinalWidth()); - m_HeightSpin->setValue(m_Settings->FinalHeight()); m_QualitySpin->setValue(m_Settings->FinalQuality()); m_TemporalSamplesSpin->setValue(m_Settings->FinalTemporalSamples()); m_SupersampleSpin->setValue(m_Settings->FinalSupersample()); + m_StripsSpin->setValue(m_Settings->FinalStrips()); Scale((eScaleType)m_Settings->FinalScale()); - if (m_Settings->FinalDoAllExt() == "jpg") - ui.FinalRenderJpgRadioButton->setChecked(true); + if (m_Settings->FinalExt() == "jpg") + m_Tbcw->m_Combo->setCurrentIndex(0); else - ui.FinalRenderPngRadioButton->setChecked(true); + m_Tbcw->m_Combo->setCurrentIndex(1); //Explicitly call these to enable/disable the appropriate controls. OnOpenCLCheckBoxStateChanged(ui.FinalRenderOpenCLCheckBox->isChecked()); OnDoAllCheckBoxStateChanged(ui.FinalRenderDoAllCheckBox->isChecked()); + OnDoSequenceCheckBoxStateChanged(ui.FinalRenderDoSequenceCheckBox->isChecked()); QSize s = size(); int desktopHeight = qApp->desktop()->availableGeometry().height(); @@ -122,29 +143,32 @@ FractoriumFinalRenderDialog::FractoriumFinalRenderDialog(FractoriumSettings* set QWidget* w = SetTabOrder(this, ui.FinalRenderEarlyClipCheckBox, ui.FinalRenderYAxisUpCheckBox); + //Update these with new controls. w = SetTabOrder(this, w, ui.FinalRenderTransparencyCheckBox); w = SetTabOrder(this, w, ui.FinalRenderOpenCLCheckBox); w = SetTabOrder(this, w, ui.FinalRenderDoublePrecisionCheckBox); w = SetTabOrder(this, w, ui.FinalRenderSaveXmlCheckBox); w = SetTabOrder(this, w, ui.FinalRenderDoAllCheckBox); w = SetTabOrder(this, w, ui.FinalRenderDoSequenceCheckBox); - w = SetTabOrder(this, w, ui.FinalRenderKeepAspectCheckBox); - w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton); - w = SetTabOrder(this, w, ui.FinalRenderScaleWidthRadioButton); - w = SetTabOrder(this, w, ui.FinalRenderScaleHeightRadioButton); - w = SetTabOrder(this, w, ui.FinalRenderJpgRadioButton); - w = SetTabOrder(this, w, ui.FinalRenderPngRadioButton); + w = SetTabOrder(this, w, ui.FinalRenderCurrentSpin); w = SetTabOrder(this, w, ui.FinalRenderPlatformCombo); w = SetTabOrder(this, w, ui.FinalRenderDeviceCombo); w = SetTabOrder(this, w, ui.FinalRenderThreadCountSpin); - w = SetTabOrder(this, w, m_WidthSpin); - w = SetTabOrder(this, w, m_HeightSpin); + w = SetTabOrder(this, w, ui.FinalRenderApplyToAllCheckBox); + w = SetTabOrder(this, w, m_WidthScaleSpin); + w = SetTabOrder(this, w, m_HeightScaleSpin); + w = SetTabOrder(this, w, ui.FinalRenderScaleNoneRadioButton); + w = SetTabOrder(this, w, ui.FinalRenderScaleWidthRadioButton); + w = SetTabOrder(this, w, ui.FinalRenderScaleHeightRadioButton); + w = SetTabOrder(this, w, ui.FinalRenderKeepAspectCheckBox); w = SetTabOrder(this, w, m_QualitySpin); w = SetTabOrder(this, w, m_TemporalSamplesSpin); w = SetTabOrder(this, w, m_SupersampleSpin); - w = SetTabOrder(this, w, tbw); - w = SetTabOrder(this, w, tbw->m_Button1); - w = SetTabOrder(this, w, tbw->m_Button2); + w = SetTabOrder(this, w, m_StripsSpin); + w = SetTabOrder(this, w, m_Tbcw); + w = SetTabOrder(this, w, m_Tbcw->m_Combo); + w = SetTabOrder(this, w, m_Tbcw->m_Button1); + w = SetTabOrder(this, w, m_Tbcw->m_Button2); w = SetTabOrder(this, w, m_PrefixEdit); w = SetTabOrder(this, w, m_SuffixEdit); w = SetTabOrder(this, w, ui.FinalRenderTextOutput); @@ -166,19 +190,22 @@ bool FractoriumFinalRenderDialog::SaveXml() { return ui.FinalRenderSaveXmlCheckB bool FractoriumFinalRenderDialog::DoAll() { return ui.FinalRenderDoAllCheckBox->isChecked(); } bool FractoriumFinalRenderDialog::DoSequence() { return ui.FinalRenderDoSequenceCheckBox->isChecked(); } bool FractoriumFinalRenderDialog::KeepAspect() { return ui.FinalRenderKeepAspectCheckBox->isChecked(); } -QString FractoriumFinalRenderDialog::DoAllExt() { return ui.FinalRenderJpgRadioButton->isChecked() ? "jpg" : "png"; } -QString FractoriumFinalRenderDialog::Path() { return ui.FinalRenderGeometryTable->item(6, 1)->text(); } -void FractoriumFinalRenderDialog::Path(QString s) { ui.FinalRenderGeometryTable->item(6, 1)->setText(s); } +bool FractoriumFinalRenderDialog::ApplyToAll() { return ui.FinalRenderApplyToAllCheckBox->isChecked(); } +QString FractoriumFinalRenderDialog::Ext() { return m_Tbcw->m_Combo->currentIndex() == 0 ? "jpg" : "png"; } +QString FractoriumFinalRenderDialog::Path() { return ui.FinalRenderParamsTable->item(m_PathCellIndex, 1)->text(); } +void FractoriumFinalRenderDialog::Path(const QString& s) { ui.FinalRenderParamsTable->item(m_PathCellIndex, 1)->setText(s); } QString FractoriumFinalRenderDialog::Prefix() { return m_PrefixEdit->text(); } QString FractoriumFinalRenderDialog::Suffix() { return m_SuffixEdit->text(); } +unsigned int FractoriumFinalRenderDialog::Current() { return ui.FinalRenderCurrentSpin->value(); } unsigned int FractoriumFinalRenderDialog::PlatformIndex() { return ui.FinalRenderPlatformCombo->currentIndex(); } unsigned int FractoriumFinalRenderDialog::DeviceIndex() { return ui.FinalRenderDeviceCombo->currentIndex(); } unsigned int FractoriumFinalRenderDialog::ThreadCount() { return ui.FinalRenderThreadCountSpin->value(); } -unsigned int FractoriumFinalRenderDialog::Width() { return m_WidthSpin->value(); } -unsigned int FractoriumFinalRenderDialog::Height() { return m_HeightSpin->value(); } +double FractoriumFinalRenderDialog::WidthScale() { return m_WidthScaleSpin->value(); } +double FractoriumFinalRenderDialog::HeightScale() { return m_HeightScaleSpin->value(); } double FractoriumFinalRenderDialog::Quality() { return m_QualitySpin->value(); } unsigned int FractoriumFinalRenderDialog::TemporalSamples() { return m_TemporalSamplesSpin->value(); } unsigned int FractoriumFinalRenderDialog::Supersample() { return m_SupersampleSpin->value(); } +unsigned int FractoriumFinalRenderDialog::Strips() { return m_StripsSpin->value(); } /// /// Capture the current state of the Gui. @@ -200,17 +227,18 @@ FinalRenderGuiState FractoriumFinalRenderDialog::State() state.m_KeepAspect = KeepAspect(); state.m_Scale = Scale(); state.m_Path = Path(); - state.m_DoAllExt = DoAllExt(); + state.m_Ext = Ext(); state.m_Prefix = Prefix(); state.m_Suffix = Suffix(); state.m_PlatformIndex = PlatformIndex(); state.m_DeviceIndex = DeviceIndex(); state.m_ThreadCount = ThreadCount(); - state.m_Width = Width(); - state.m_Height = Height(); + state.m_WidthScale = WidthScale(); + state.m_HeightScale = HeightScale(); state.m_Quality = Quality(); state.m_TemporalSamples = TemporalSamples(); state.m_Supersample = Supersample(); + state.m_Strips = Strips(); return state; } @@ -237,6 +265,8 @@ eScaleType FractoriumFinalRenderDialog::Scale() /// The type of scaling to use void FractoriumFinalRenderDialog::Scale(eScaleType scale) { + ui.FinalRenderScaleNoneRadioButton->blockSignals(true); + if (scale == SCALE_NONE) ui.FinalRenderScaleNoneRadioButton->setChecked(true); else if (scale == SCALE_WIDTH) @@ -245,6 +275,8 @@ void FractoriumFinalRenderDialog::Scale(eScaleType scale) ui.FinalRenderScaleHeightRadioButton->setChecked(true); else ui.FinalRenderScaleNoneRadioButton->setChecked(true); + + ui.FinalRenderScaleNoneRadioButton->blockSignals(false); } /// @@ -307,6 +339,39 @@ void FractoriumFinalRenderDialog::OnDoublePrecisionCheckBoxStateChanged(int stat SetMemory(); } +/// +/// The do all checkbox was changed. +/// If checked, render all embers available in the currently opened file, else +/// only render the current ember. +/// +/// The state of the checkbox +void FractoriumFinalRenderDialog::OnDoAllCheckBoxStateChanged(int state) +{ + ui.FinalRenderDoSequenceCheckBox->setEnabled(ui.FinalRenderDoAllCheckBox->isChecked()); +} + +/// +/// The do sequence checkbox was changed. +/// If checked, render all embers available in the currently opened file as an animation sequence, else +/// render them individually. +/// +/// The state of the checkbox +void FractoriumFinalRenderDialog::OnDoSequenceCheckBoxStateChanged(int state) +{ + m_TemporalSamplesSpin->setEnabled(ui.FinalRenderDoSequenceCheckBox->isChecked()); +} + +/// +/// The current ember spinner was changed, update fields. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnFinalRenderCurrentSpinChanged(int d) +{ + m_Controller->SetEmber(d - 1); + m_Controller->SyncCurrentToGui(); + SetMemory(); +} + /// /// Populate the the device combo box with all available /// OpenCL devices for the selected platform. @@ -324,15 +389,44 @@ void FractoriumFinalRenderDialog::OnPlatformComboCurrentIndexChanged(int index) } /// -/// The do all checkbox was changed. -/// If checked, render all embers available in the currently opened file, else -/// only render the current ember. +/// The apply all checkbox was changed. +/// If checked, set values for all embers in the file to the values specified in the GUI. /// /// The state of the checkbox -void FractoriumFinalRenderDialog::OnDoAllCheckBoxStateChanged(int state) +void FractoriumFinalRenderDialog::OnApplyAllCheckBoxStateChanged(int state) { - ui.FinalRenderDoSequenceCheckBox->setEnabled(ui.FinalRenderDoAllCheckBox->isChecked()); - ui.FinalRenderExtensionGroupBox->setEnabled(ui.FinalRenderDoAllCheckBox->isChecked()); + if (state && m_Controller.get()) + m_Controller->SyncGuiToEmbers(); +} + +/// +/// The width spinner was changed, recompute required memory. +/// If the aspect ratio checkbox is checked, set the value of +/// the height spinner as well to be in proportion. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnFinalRenderWidthScaleChanged(double d) +{ + if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get()) + m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value()); + + if (SetMemory()) + m_Controller->SyncCurrentToSizeSpinners(false, true); +} + +/// +/// The height spinner was changed, recompute required memory. +/// If the aspect ratio checkbox is checked, set the value of +/// the width spinner as well to be in proportion. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnFinalRenderHeightScaleChanged(double d) +{ + if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get()) + m_WidthScaleSpin->SetValueStealth(m_HeightScaleSpin->value()); + + if (SetMemory()) + m_Controller->SyncCurrentToSizeSpinners(false, true); } /// @@ -343,7 +437,7 @@ void FractoriumFinalRenderDialog::OnDoAllCheckBoxStateChanged(int state) void FractoriumFinalRenderDialog::OnKeepAspectCheckBoxStateChanged(int state) { if (state && m_Controller.get()) - m_HeightSpin->SetValueStealth(m_WidthSpin->value() / m_Controller->OriginalAspect()); + m_HeightScaleSpin->SetValueStealth(m_WidthScaleSpin->value()); SetMemory(); } @@ -358,34 +452,6 @@ void FractoriumFinalRenderDialog::OnScaleRadioButtonChanged(bool checked) SetMemory(); } -/// -/// The width spinner was changed, recompute required memory. -/// If the aspect ratio checkbox is checked, set the value of -/// the height spinner as well to be in proportion. -/// -/// Ignored -void FractoriumFinalRenderDialog::OnWidthChanged(int d) -{ - if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get()) - m_HeightSpin->SetValueStealth(m_WidthSpin->value() / m_Controller->OriginalAspect()); - - SetMemory(); -} - -/// -/// The height spinner was changed, recompute required memory. -/// If the aspect ratio checkbox is checked, set the value of -/// the width spinner as well to be in proportion. -/// -/// Ignored -void FractoriumFinalRenderDialog::OnHeightChanged(int d) -{ - if (ui.FinalRenderKeepAspectCheckBox->isChecked() && m_Controller.get()) - m_WidthSpin->SetValueStealth(m_HeightSpin->value() * m_Controller->OriginalAspect()); - - SetMemory(); -} - /// /// The quality spinner was changed, recompute required memory. /// @@ -413,6 +479,15 @@ void FractoriumFinalRenderDialog::OnSupersampleChanged(int d) SetMemory(); } +/// +/// The supersample spinner was changed, recompute required memory. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnStripsChanged(int d) +{ + SetMemory(); +} + /// /// If a single ember is being rendered, show the save file dialog. /// If a more than one is being rendered, show the save folder dialog. @@ -422,26 +497,12 @@ void FractoriumFinalRenderDialog::OnSupersampleChanged(int d) void FractoriumFinalRenderDialog::OnFileButtonClicked(bool checked) { bool doAll = ui.FinalRenderDoAllCheckBox->isChecked(); - QString filename; - - if (doAll) - filename = m_Fractorium->SetupSaveFolderDialog(); - else - filename = m_Fractorium->SetupSaveImageDialog(m_Controller->Name()); + QString s = m_Fractorium->SetupSaveFolderDialog(); - if (filename != "") + if (Exists(s)) { - if (doAll) - { - if (!filename.endsWith(QDir::separator())) - filename += "/"; - } - - QFileInfo fileInfo(filename); - QString path = fileInfo.absolutePath(); - - m_Settings->SaveFolder(path);//Any time they exit the box with a valid value, preserve it in the settings. - Path(filename); + m_Settings->SaveFolder(s);//Any time they exit the box with a valid value, preserve it in the settings. + Path(m_Controller->ComposePath(m_Controller->Name()));//And update the GUI. SetMemory(); } } @@ -452,17 +513,41 @@ void FractoriumFinalRenderDialog::OnFileButtonClicked(bool checked) /// Ignored void FractoriumFinalRenderDialog::OnShowFolderButtonClicked(bool checked) { - QString text = Path(); + QString s = m_Settings->SaveFolder(); - if (text != "") - { - QFileInfo fileInfo(text); - QString path = fileInfo.absolutePath(); - QDir dir(path); + if (Exists(s)) + QDesktopServices::openUrl(QUrl::fromLocalFile(s)); + else + QDesktopServices::openUrl(QStandardPaths::standardLocations(QStandardPaths::DesktopLocation)[0]); +} - if (dir.exists()) - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); - } +/// +/// Change the extension of the output image, which also may change the +/// number of channels used in the final output buffer. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnFinalRenderExtIndexChanged(int d) +{ + if (SetMemory()) + Path(m_Controller->ComposePath(m_Controller->Name())); +} + +/// +/// Change the prefix prepended to the output file name. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnFinalRenderPrefixChanged(const QString& s) +{ + Path(m_Controller->ComposePath(m_Controller->Name())); +} + +/// +/// Change the suffix appended to the output file name. +/// +/// Ignored +void FractoriumFinalRenderDialog::OnFinalRenderSuffixChanged(const QString& s) +{ + Path(m_Controller->ComposePath(m_Controller->Name())); } /// @@ -492,27 +577,41 @@ void FractoriumFinalRenderDialog::OnCancelRenderClicked(bool checked) /// The event void FractoriumFinalRenderDialog::showEvent(QShowEvent* e) { -#ifdef DO_DOUBLE - Ember ed; -#else - Ember ed; -#endif - if (CreateControllerFromGUI(true)) { - m_Fractorium->m_Controller->CopyEmber(ed);//Copy the current ember from the main window out in to a temp. - m_Controller->SetEmber(ed);//Copy the temp into the final render controller. - m_Controller->SetOriginalEmber(ed); +#ifdef DO_DOUBLE + Ember ed; + EmberFile efi; + m_Fractorium->m_Controller->CopyEmberFile(efi, [&](Ember& ember) + { + ember.SyncSize(); + ember.m_Quality = m_Settings->FinalQuality(); + ember.m_Supersample = m_Settings->FinalSupersample(); + });//Copy the whole file, will take about 0.2ms per ember in the file. +#else + Ember ed; + EmberFile efi; + m_Fractorium->m_Controller->CopyEmberFile(efi, [&](Ember& ember) + { + ember.SyncSize(); + ember.m_Quality = m_Settings->FinalQuality(); + ember.m_Supersample = m_Settings->FinalSupersample(); + ember.m_TemporalSamples = m_Settings->FinalTemporalSamples(); + });//Copy the whole file, will take about 0.2ms per ember in the file. +#endif + m_Controller->SetEmberFile(efi);//Copy the temp file into the final render controller. + m_Controller->SetEmber(m_Fractorium->m_Controller->Index());//Set the currently selected ember to the one that was being edited. + ui.FinalRenderCurrentSpin->setMaximum(efi.Size()); + m_Controller->m_ImageCount = 0; SetMemory(); m_Controller->ResetProgress(); + + QString s = m_Settings->SaveFolder(); + + if (Exists(s)) + Path(m_Controller->ComposePath(m_Controller->Name()));//Update the GUI. } - QDir dir(m_Settings->SaveFolder()); - QString name = m_Controller->Name(); - - if (dir.exists() && name != "") - Path(dir.absolutePath() + "/" + name + ".png"); - ui.FinalRenderTextOutput->clear(); QDialog::showEvent(e); } @@ -542,23 +641,28 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer) bool ok = true; #ifdef DO_DOUBLE size_t size = Double() ? sizeof(double) : sizeof(float); - Ember ed; - Ember orig; - EmberFile efd; #else size_t size = sizeof(float); - Ember ed; - Ember orig; - EmberFile efd; #endif if (!m_Controller.get() || (m_Controller->SizeOfT() != size)) { +#ifdef DO_DOUBLE + size_t size = Double() ? sizeof(double) : sizeof(float); + Ember ed; + Ember orig; + EmberFile efd; +#else + size_t size = sizeof(float); + Ember ed; + Ember orig; + EmberFile efd; +#endif + //First check if a controller has already been created, and if so, save its embers and gracefully shut it down. if (m_Controller.get()) - { - m_Controller->CopyEmber(ed);//Convert float to double or save double verbatim; - m_Controller->CopyEmberFile(efd); + { + m_Controller->CopyEmberFile(efd);//Convert float to double or save double verbatim; m_Controller->Shutdown(); } @@ -572,12 +676,7 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer) //Restore the ember and ember file. if (m_Controller.get()) - { - m_Controller->SetEmber(ed);//Convert float to double or set double verbatim; - m_Controller->SetEmberFile(efd); - m_Fractorium->m_Controller->CopyEmber(orig);//Copy the current ember from the main window out in to a temp. - m_Controller->SetOriginalEmber(orig); - } + m_Controller->SetEmberFile(efd);//Convert float to double or set double verbatim; } if (m_Controller.get()) @@ -595,8 +694,13 @@ bool FractoriumFinalRenderDialog::CreateControllerFromGUI(bool createRenderer) /// Compute the amount of memory needed via call to SyncAndComputeMemory(), then /// assign the result to the table cell as text. /// -void FractoriumFinalRenderDialog::SetMemory() +bool FractoriumFinalRenderDialog::SetMemory() { if (isVisible() && CreateControllerFromGUI(true)) - ui.FinalRenderGeometryTable->item(5, 1)->setText(QLocale(QLocale::English).toString(m_Controller->SyncAndComputeMemory())); + { + ui.FinalRenderParamsTable->item(m_MemoryCellIndex, 1)->setText(ToString(m_Controller->SyncAndComputeMemory())); + return true; + } + + return false; } diff --git a/Source/Fractorium/FinalRenderDialog.h b/Source/Fractorium/FinalRenderDialog.h index d188b7f..6d5d1a8 100644 --- a/Source/Fractorium/FinalRenderDialog.h +++ b/Source/Fractorium/FinalRenderDialog.h @@ -3,7 +3,7 @@ #include "ui_FinalRenderDialog.h" #include "SpinBox.h" #include "DoubleSpinBox.h" -#include "TwoButtonWidget.h" +#include "TwoButtonComboWidget.h" #include "FractoriumSettings.h" #include "FinalRenderEmberController.h" @@ -53,21 +53,24 @@ public: bool DoAll(); bool DoSequence(); bool KeepAspect(); + bool ApplyToAll(); eScaleType Scale(); void Scale(eScaleType scale); - QString DoAllExt(); + QString Ext(); QString Path(); - void Path(QString s); + void Path(const QString& s); QString Prefix(); QString Suffix(); + unsigned int Current(); unsigned int PlatformIndex(); unsigned int DeviceIndex(); unsigned int ThreadCount(); - unsigned int Width(); - unsigned int Height(); + double WidthScale(); + double HeightScale(); double Quality(); unsigned int TemporalSamples(); unsigned int Supersample(); + unsigned int Strips(); FinalRenderGuiState State(); public Q_SLOTS: @@ -77,17 +80,24 @@ public Q_SLOTS: void OnTransparencyCheckBoxStateChanged(int state); void OnOpenCLCheckBoxStateChanged(int state); void OnDoublePrecisionCheckBoxStateChanged(int state); - void OnPlatformComboCurrentIndexChanged(int index); void OnDoAllCheckBoxStateChanged(int state); + void OnDoSequenceCheckBoxStateChanged(int state); + void OnFinalRenderCurrentSpinChanged(int d); + void OnPlatformComboCurrentIndexChanged(int index); + void OnApplyAllCheckBoxStateChanged(int state); + void OnFinalRenderWidthScaleChanged(double d); + void OnFinalRenderHeightScaleChanged(double d); void OnKeepAspectCheckBoxStateChanged(int state); void OnScaleRadioButtonChanged(bool checked); - void OnWidthChanged(int d); - void OnHeightChanged(int d); void OnQualityChanged(double d); void OnTemporalSamplesChanged(int d); void OnSupersampleChanged(int d); + void OnStripsChanged(int d); void OnFileButtonClicked(bool checked); void OnShowFolderButtonClicked(bool checked); + void OnFinalRenderExtIndexChanged(int d); + void OnFinalRenderPrefixChanged(const QString& s); + void OnFinalRenderSuffixChanged(const QString& s); void OnRenderClicked(bool checked); void OnCancelRenderClicked(bool checked); @@ -97,15 +107,19 @@ protected: private: bool CreateControllerFromGUI(bool createRenderer); - void SetMemory(); + bool SetMemory(); + int m_MemoryCellIndex; + int m_PathCellIndex; OpenCLWrapper m_Wrapper; Timing m_RenderTimer; - SpinBox* m_WidthSpin; - SpinBox* m_HeightSpin; + DoubleSpinBox* m_WidthScaleSpin; + DoubleSpinBox* m_HeightScaleSpin; DoubleSpinBox* m_QualitySpin; SpinBox* m_TemporalSamplesSpin; SpinBox* m_SupersampleSpin; + SpinBox* m_StripsSpin; + TwoButtonComboWidget* m_Tbcw; QLineEdit* m_PrefixEdit; QLineEdit* m_SuffixEdit; FractoriumSettings* m_Settings; diff --git a/Source/Fractorium/FinalRenderDialog.ui b/Source/Fractorium/FinalRenderDialog.ui index ee5c5ee..c82d260 100644 --- a/Source/Fractorium/FinalRenderDialog.ui +++ b/Source/Fractorium/FinalRenderDialog.ui @@ -7,7 +7,7 @@ 0 0 519 - 813 + 862 @@ -64,7 +64,7 @@ 0 0 507 - 801 + 850 @@ -85,137 +85,6 @@ - - - - - 0 - 40 - - - - - 16777215 - 40 - - - - The scaling to perform from the editor to the final rendered image - - - Scale - - - - 6 - - - 4 - - - 4 - - - 6 - - - - - None - - - true - - - - - - - Width - - - - - - - Height - - - - - - - - - - - 0 - 0 - - - - - 110 - 40 - - - - - 16777215 - 40 - - - - The image type to save the final output as when rendering all open flames - - - Render All Extension - - - - 6 - - - 4 - - - 4 - - - 6 - - - - - - 0 - 0 - - - - Jpg - - - true - - - - - - - - 0 - 0 - - - - Png - - - - - - @@ -226,49 +95,6 @@ - - - - Save an Xml parameter file for each flame rendered - - - Save Xml - - - - - - - Maintain the aspect ratio between width and height to be equal to base width and base height - - - Keep Aspect Ratio - - - false - - - - - - - Use temporal samples value to achieve motion blur effect between flames - - - Render as Animation Sequence - - - - - - - Render all open flames instead of just the current one - - - Render All - - - @@ -279,16 +105,6 @@ - - - - <html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html> - - - Use Double Precision - - - @@ -309,50 +125,119 @@ + + + + <html><head/><body><p>Checked: use 64-bit double precision numbers (slower, but better image quality).</p><p>Unchecked: use 32-bit single precision numbers (faster, but worse image quality).</p></body></html> + + + Use Double Precision + + + + + + + Save an Xml parameter file for each flame rendered + + + Save Xml + + + + + + + Render all open flames instead of just the current one + + + Render All + + + + + + + Use temporal samples value to achieve motion blur effect between flames + + + Render as Animation Sequence + + + - - - - 0 - 0 - + + + QLayout::SetNoConstraint - - - 100 - 100 - - - - - 100 - 100 - - - - - 1 - 1 - - - - QFrame::NoFrame - - - 0 - - - - - - Qt::PlainText - - - Qt::AlignCenter - - + + + + + 0 + 0 + + + + + 100 + 100 + + + + + 100 + 100 + + + + + 1 + 1 + + + + QFrame::NoFrame + + + 0 + + + + + + Qt::PlainText + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + + + 1 + + + 999999999 + + + 1 + + + + @@ -421,7 +306,256 @@ - + + + Apply current operation to all flames + + + Apply Parameters to All + + + + + + + + 0 + 91 + + + + Size + + + + 6 + + + 0 + + + 6 + + + 4 + + + 6 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 44 + + + + + 16777215 + 44 + + + + Qt::NoFocus + + + QFrame::Panel + + + QFrame::Plain + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + false + + + QAbstractItemView::NoSelection + + + QAbstractItemView::ScrollPerPixel + + + QAbstractItemView::ScrollPerPixel + + + true + + + false + + + 2 + + + 2 + + + false + + + 85 + + + false + + + 35 + + + true + + + false + + + 22 + + + false + + + 22 + + + + Width Scale + + + + + Height Scale + + + + + Field + + + + + + Width Scale + + + + + + + + + + Height Scale + + + + + + + + + + + + + + 0 + 45 + + + + + 16777215 + 45 + + + + The scaling to perform from the editor to the final rendered image + + + Scale Type + + + false + + + + 4 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + Width + + + + + + + Height + + + + + + + None + + + true + + + + + + + + + + Maintain the aspect ratio between width and height to be equal to base width and base height + + + Keep Aspect Ratio + + + false + + + + + + + + 0 @@ -431,13 +565,13 @@ 0 - 200 + 178 16777215 - 200 + 178 @@ -521,19 +655,6 @@ false - - - Width - - - - - - - - Height - - Quality @@ -549,6 +670,11 @@ Supersample + + + Strips + + Memory Usage @@ -581,10 +707,10 @@ - Width + Quality - The width in pixels of the final output image + The quality in iterations per pixel of the final output image @@ -594,10 +720,10 @@ - Height + Temporal Samples - The height in pixels of the final output image + The number of interpolated renders to do for each flame when rendering as an animation sequence @@ -607,10 +733,10 @@ - Quality + Supersample - The quality in iterations per pixel of the final output image + <html><head/><body><p>The number to multiply the dimensions of the histogram and density filtering buffer by to achieve anti-aliasing.</p><p>Use this very sparingly as it increases the required memory by n squared.</p></body></html> @@ -620,10 +746,7 @@ - Temporal Samples - - - The number of interpolated renders to do for each flame when rendering as an animation sequence + Strips @@ -633,10 +756,10 @@ - Supersample + Memory Usage - <html><head/><body><p>The number to multiply the dimensions of the histogram and density filtering buffer by to achieve anti-aliasing.</p><p>Use this very sparingly as it increases the required memory by n squared.</p></body></html> + The amount of memory including the final output image required to perform this render @@ -645,19 +768,6 @@ - - Memory Usage - - - The amount of memory including the final output image required to perform this render - - - - - 0 - - - Output @@ -665,25 +775,25 @@ The output file path for rendering a single flame, or folder location for rendering multiple flames + + + + + + + + Prefix + + + The prefix to attach to all image filenames + + - - Prefix - - - The prefix to attach to all image filenames - - - - - - - - Suffix @@ -691,7 +801,7 @@ The suffix to attach to all image filenames - + @@ -933,20 +1043,10 @@ FinalRenderYAxisUpCheckBox FinalRenderTransparencyCheckBox FinalRenderOpenCLCheckBox - FinalRenderDoublePrecisionCheckBox - FinalRenderSaveXmlCheckBox - FinalRenderDoAllCheckBox - FinalRenderDoSequenceCheckBox - FinalRenderKeepAspectCheckBox - FinalRenderScaleNoneRadioButton - FinalRenderScaleWidthRadioButton - FinalRenderScaleHeightRadioButton - FinalRenderJpgRadioButton - FinalRenderPngRadioButton FinalRenderPlatformCombo FinalRenderDeviceCombo FinalRenderThreadCountSpin - FinalRenderGeometryTable + FinalRenderParamsTable FinalRenderTextOutput StartRenderButton StopRenderButton diff --git a/Source/Fractorium/FinalRenderEmberController.cpp b/Source/Fractorium/FinalRenderEmberController.cpp index 7628741..c293651 100644 --- a/Source/Fractorium/FinalRenderEmberController.cpp +++ b/Source/Fractorium/FinalRenderEmberController.cpp @@ -9,14 +9,14 @@ /// It passes a pointer to the main window to the base and initializes members. /// /// Pointer to the final render dialog -FinalRenderEmberControllerBase::FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRender) - : FractoriumEmberControllerBase(finalRender->m_Fractorium) +FinalRenderEmberControllerBase::FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRenderDialog) + : FractoriumEmberControllerBase(finalRenderDialog->m_Fractorium) { m_Run = false; m_PreviewRun = false; m_ImageCount = 0; m_FinishedImageCount = 0; - m_FinalRender = finalRender; + m_FinalRenderDialog = finalRenderDialog; m_Settings = m_Fractorium->m_Settings; } @@ -55,7 +55,7 @@ void FinalRenderEmberControllerBase::CancelRender() while (m_Result.isRunning()) QApplication::processEvents(); - m_FinalRender->ui.FinalRenderTextOutput->append("Render canceled."); + m_FinalRenderDialog->ui.FinalRenderTextOutput->append("Render canceled."); } } @@ -66,14 +66,23 @@ void FinalRenderEmberControllerBase::CancelRender() /// True if a valid renderer is created or if no action is taken, else false. bool FinalRenderEmberControllerBase::CreateRendererFromGUI() { - bool useOpenCL = m_Wrapper.CheckOpenCL() && m_FinalRender->OpenCL(); + bool useOpenCL = m_Wrapper.CheckOpenCL() && m_FinalRenderDialog->OpenCL(); return CreateRenderer(useOpenCL ? OPENCL_RENDERER : CPU_RENDERER, - m_FinalRender->PlatformIndex(), - m_FinalRender->DeviceIndex(), + m_FinalRenderDialog->PlatformIndex(), + m_FinalRenderDialog->DeviceIndex(), false);//Not shared. } +/// +/// Thin wrapper around invoking a call to append text to the output. +/// +/// The string to append +void FinalRenderEmberControllerBase::Output(const QString& s) +{ + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(const QString&, s)); +} + /// /// Constructor which accepts a pointer to the final render dialog and passes it to the base. /// The main final rendering lambda function is constructed here. @@ -86,7 +95,6 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD m_FinalPreviewRenderer = auto_ptr>(new EmberNs::Renderer()); m_FinalPreviewRenderer->Callback(NULL); m_FinalPreviewRenderer->NumChannels(4); - m_FinalPreviewRenderer->ReclaimOnResize(true); m_FinalPreviewRenderFunc = [&]() { @@ -94,38 +102,43 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD m_PreviewRun = true; m_FinalPreviewRenderer->Abort(); - QLabel* widget = m_FinalRender->ui.FinalRenderPreviewLabel; - unsigned int maxDim = 100u; + QLabel* widget = m_FinalRenderDialog->ui.FinalRenderPreviewLabel; + size_t maxDim = 100; T scalePercentage; //Determine how to scale the scaled ember to fit in the label with a max of 100x100. - if (m_Ember.m_FinalRasW >= m_Ember.m_FinalRasH) - scalePercentage = T(maxDim) / m_Ember.m_FinalRasW; + if (m_Ember->m_FinalRasW >= m_Ember->m_FinalRasH) + scalePercentage = T(maxDim) / m_Ember->m_FinalRasW; else - scalePercentage = T(maxDim) / m_Ember.m_FinalRasH; + scalePercentage = T(maxDim) / m_Ember->m_FinalRasH; - m_PreviewEmber = m_Ember; + m_PreviewEmber = *m_Ember; m_PreviewEmber.m_Quality = 100; m_PreviewEmber.m_TemporalSamples = 1; - m_PreviewEmber.m_FinalRasW = min(maxDim, unsigned int(scalePercentage * m_Ember.m_FinalRasW)); - m_PreviewEmber.m_FinalRasH = min(maxDim, unsigned int(scalePercentage * m_Ember.m_FinalRasH)); - m_PreviewEmber.m_PixelsPerUnit = scalePercentage * m_Ember.m_PixelsPerUnit; + m_PreviewEmber.m_FinalRasW = max(1, min(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasW)));//Ensure neither is zero. + m_PreviewEmber.m_FinalRasH = max(1, min(maxDim, size_t(scalePercentage * m_Ember->m_FinalRasH))); + m_PreviewEmber.m_PixelsPerUnit = scalePercentage * m_Ember->m_PixelsPerUnit; - while (!m_FinalPreviewRenderer->Aborted() || m_FinalPreviewRenderer->InRender()) - QApplication::processEvents(); - - m_FinalPreviewRenderer->EarlyClip(m_FinalRender->EarlyClip()); - m_FinalPreviewRenderer->YAxisUp(m_FinalRender->YAxisUp()); - m_FinalPreviewRenderer->Transparency(m_FinalRender->Transparency()); + m_FinalPreviewRenderer->EarlyClip(m_FinalRenderDialog->EarlyClip()); + m_FinalPreviewRenderer->YAxisUp(m_FinalRenderDialog->YAxisUp()); + m_FinalPreviewRenderer->Transparency(m_FinalRenderDialog->Transparency()); m_FinalPreviewRenderer->SetEmber(m_PreviewEmber); + m_FinalPreviewRenderer->PrepFinalAccumVector(m_PreviewFinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). - if (m_FinalPreviewRenderer->Run(m_PreviewFinalImage) == RENDER_OK) - { - QImage image(m_PreviewEmber.m_FinalRasW, m_PreviewEmber.m_FinalRasH, QImage::Format_RGBA8888);//The label wants RGBA. - memcpy(image.scanLine(0), m_PreviewFinalImage.data(), m_PreviewFinalImage.size() * sizeof(m_PreviewFinalImage[0]));//Memcpy the data in. - QPixmap pixmap = QPixmap::fromImage(image); - QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap)); - } + unsigned int strips = VerifyStrips(m_PreviewEmber.m_FinalRasH, m_FinalRenderDialog->Strips(), + [&](const string& s) { }, [&](const string& s) { }, [&](const string& s) { }); + + StripsRender(m_FinalPreviewRenderer.get(), m_PreviewEmber, m_PreviewFinalImage, 0, strips, m_FinalRenderDialog->YAxisUp(), + [&](size_t strip) { },//Pre strip. + [&](size_t strip) { },//Post strip. + [&](size_t strip) { },//Error. + [&](Ember& finalEmber)//Final strip. + { + QImage image(finalEmber.m_FinalRasW, finalEmber.m_FinalRasH, QImage::Format_RGBA8888);//The label wants RGBA. + memcpy(image.scanLine(0), m_PreviewFinalImage.data(), finalEmber.m_FinalRasW * finalEmber.m_FinalRasH * 4);//Memcpy the data in. + QPixmap pixmap = QPixmap::fromImage(image); + QMetaObject::invokeMethod(widget, "setPixmap", Qt::QueuedConnection, Q_ARG(QPixmap, pixmap)); + }); m_PreviewRun = false; m_PreviewCs.Leave(); @@ -136,50 +149,53 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD //If it finishes successfully, delete the backup file. m_FinalRenderFunc = [&]() { - size_t i; - m_Run = true; - m_TotalTimer.Tic();//Begin timing for progress. - m_GuiState = m_FinalRender->State();//Cache render settings from the GUI before running. - m_FinishedImageCount = 0; - - QFileInfo original(m_GuiState.m_Path); - QString backup = original.absolutePath() + QDir::separator() + m_GuiState.m_Prefix + original.completeBaseName() + m_GuiState.m_Suffix + "_backup.flame"; - - QMetaObject::invokeMethod(m_Fractorium, "OnActionSaveCurrentToOpenedFile", Qt::QueuedConnection, Q_ARG(bool, true));//First, save the current ember back to its opened file. - m_Fractorium->m_Controller->CopyEmber(m_Ember); - m_Fractorium->m_Controller->CopyEmberFile(m_EmberFile);//Copy the whole file, will take about 0.2ms per ember in the file. + m_TotalTimer.Tic();//Begin timing for progress of all operations. + size_t i; + m_GuiState = m_FinalRenderDialog->State();//Cache render settings from the GUI before running. + bool doAll = m_GuiState.m_DoAll && m_EmberFile.Size() > 1; + unsigned int currentStripForProgress = 0;//Sort of a hack to get the strip value to the progress function. + QString path = doAll ? ComposePath(QString::fromStdString(m_EmberFile.m_Embers[0].m_Name)) : ComposePath(Name()); + QString backup = path + "_backup.flame"; //Save backup Xml. - if (m_GuiState.m_DoAll && m_EmberFile.m_Embers.size() > 1) + if (doAll) m_XmlWriter.Save(backup.toStdString().c_str(), m_EmberFile.m_Embers, 0, true, false, true); else - m_XmlWriter.Save(backup.toStdString().c_str(), m_Ember, 0, true, false, true); + m_XmlWriter.Save(backup.toStdString().c_str(), *m_Ember, 0, true, false, true); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "setText", Qt::QueuedConnection, Q_ARG(QString, "Begin rendering...")); + m_FinishedImageCount = 0; m_Renderer->EarlyClip(m_GuiState.m_EarlyClip); m_Renderer->YAxisUp(m_GuiState.m_YAxisUp); m_Renderer->ThreadCount(m_GuiState.m_ThreadCount); m_Renderer->Transparency(m_GuiState.m_Transparency); + m_Renderer->m_ProgressParameter = (void*)¤tStripForProgress; - if (m_GuiState.m_Path.endsWith(".png", Qt::CaseInsensitive) || m_Renderer->RendererType() == OPENCL_RENDERER) + if (path.endsWith(".png", Qt::CaseInsensitive) || m_Renderer->RendererType() == OPENCL_RENDERER)//This is creating the wrong thing.//TODO m_Renderer->NumChannels(4); else m_Renderer->NumChannels(3); + m_GuiState.m_Strips = VerifyStrips(m_Ember->m_FinalRasH, m_GuiState.m_Strips, + [&](const string& s) { Output(QString::fromStdString(s)); },//Greater than height. + [&](const string& s) { Output(QString::fromStdString(s)); },//Mod height != 0. + [&](const string& s) { Output(QString::fromStdString(s) + "\n"); });//Final strips value to be set. + //The rendering process is different between doing a single image, and doing multiple. - if (m_GuiState.m_DoAll && m_EmberFile.m_Embers.size() > 1) + if (doAll) { - m_ImageCount = m_EmberFile.m_Embers.size(); + m_ImageCount = m_EmberFile.Size(); ResetProgress(); //Different action required for rendering as animation or not. if (m_GuiState.m_DoSequence) { + Ember* firstEmber = &m_EmberFile.m_Embers[0]; + //Need to loop through and set all w, h, q, ts, ss and t vals. - for (i = 0; i < m_EmberFile.m_Embers.size() && m_Run; i++) + for (i = 0; i < m_EmberFile.Size() && m_Run; i++) { - Sync(m_EmberFile.m_Embers[i]); + SyncGuiToEmber(m_EmberFile.m_Embers[i], firstEmber->m_FinalRasW, firstEmber->m_FinalRasH); if (i > 0) { @@ -194,184 +210,145 @@ FinalRenderEmberController::FinalRenderEmberController(FractoriumFinalRenderD m_EmberFile.m_Embers[i].m_TemporalSamples = m_GuiState.m_TemporalSamples; } + //Not supporting strips with motion blur. + //Shouldn't be a problem because animations will be at max 4k x 4k which will take about 1.1GB + //even when using double precision, which most cards at the time of this writing already exceed. + m_GuiState.m_Strips = 1; m_Renderer->SetEmber(m_EmberFile.m_Embers);//Copy all embers to the local storage inside the renderer. //Render each image, cancelling if m_Run ever gets set to false. - for (i = 0; i < m_EmberFile.m_Embers.size() && m_Run; i++) + for (i = 0; i < m_EmberFile.Size() && m_Run; i++) { + Output("Image " + ToString(m_FinishedImageCount) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name))); m_Renderer->Reset();//Have to manually set this since the ember is not set each time through. - m_RenderTimer.Tic();//Toc() is called in the progress function. + m_RenderTimer.Tic();//Toc() is called in RenderComplete(). - if (m_Renderer->Run(m_FinalImage, i) != RENDER_OK) + StripsRender(m_Renderer.get(), m_EmberFile.m_Embers[i], m_FinalImage, i, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, + [&](size_t strip) { currentStripForProgress = strip; },//Pre strip. + [&](size_t strip) { m_Stats = m_Renderer->Stats(); },//Post strip. + [&](size_t strip)//Error. { - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, "Renderering failed.\n")); - m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRender->ui.FinalRenderTextOutput, false); - } + Output("Renderering failed.\n"); + m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke. + }, + [&](Ember& finalEmber) { RenderComplete(finalEmber); });//Final strip. } } else//Render all images, but not as an animation sequence (without temporal samples motion blur). { - //Copy widget values to all embers - for (i = 0; i < m_EmberFile.m_Embers.size() && m_Run; i++) + for (i = 0; i < m_EmberFile.Size() && m_Run; i++) { - Sync(m_EmberFile.m_Embers[i]); m_EmberFile.m_Embers[i].m_TemporalSamples = 1;//No temporal sampling. } //Render each image, cancelling if m_Run ever gets set to false. - for (i = 0; i < m_EmberFile.m_Embers.size() && m_Run; i++) + for (i = 0; i < m_EmberFile.Size() && m_Run; i++) { + Output("Image " + ToString(m_FinishedImageCount) + ":\n" + ComposePath(QString::fromStdString(m_EmberFile.m_Embers[i].m_Name))); m_Renderer->SetEmber(m_EmberFile.m_Embers[i]); - m_RenderTimer.Tic();//Toc() is called in the progress function. + m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). + m_Stats.Clear(); + Memset(m_FinalImage); + m_RenderTimer.Tic();//Toc() is called in RenderComplete(). - if (m_Renderer->Run(m_FinalImage) != RENDER_OK) + StripsRender(m_Renderer.get(), m_EmberFile.m_Embers[i], m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, + [&](size_t strip) { currentStripForProgress = strip; },//Pre strip. + [&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip. + [&](size_t strip)//Error. { - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, "Renderering failed.\n")); - m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRender->ui.FinalRenderTextOutput, false); - } + Output("Renderering failed.\n"); + m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke. + }, + [&](Ember& finalEmber) { RenderComplete(finalEmber); });//Final strip. } } } else//Render a single image. { m_ImageCount = 1; - Sync(m_Ember); ResetProgress(); - m_Ember.m_TemporalSamples = 1; - m_Renderer->SetEmber(m_Ember); - memset(m_FinalImage.data(), 0, m_FinalImage.size() * sizeof(m_FinalImage[0])); - m_RenderTimer.Tic();//Toc() is called in the progress function. - - if (m_Renderer->Run(m_FinalImage) != RENDER_OK) + m_Ember->m_TemporalSamples = 1; + m_Renderer->SetEmber(*m_Ember); + m_Renderer->PrepFinalAccumVector(m_FinalImage);//Must manually call this first because it could be erroneously made smaller due to strips if called inside Renderer::Run(). + m_Stats.Clear(); + Memset(m_FinalImage); + Output(ComposePath(QString::fromStdString(m_Ember->m_Name))); + m_RenderTimer.Tic();//Toc() is called in RenderComplete(). + + StripsRender(m_Renderer.get(), *m_Ember, m_FinalImage, 0, m_GuiState.m_Strips, m_GuiState.m_YAxisUp, + [&](size_t strip) { currentStripForProgress = strip; },//Pre strip. + [&](size_t strip) { m_Stats += m_Renderer->Stats(); },//Post strip. + [&](size_t strip)//Error. { - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, "Renderering failed.\n")); - m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRender->ui.FinalRenderTextOutput, false); - } + Output("Renderering failed.\n"); + m_Fractorium->ErrorReportToQTextEdit(m_Renderer->ErrorReport(), m_FinalRenderDialog->ui.FinalRenderTextOutput, false);//Internally calls invoke. + }, + [&](Ember& finalEmber) { RenderComplete(finalEmber); });//Final strip. } + QString totalTimeString = "All renders completed in: " + QString::fromStdString(m_TotalTimer.Format(m_TotalTimer.Toc())) + "."; + Output(totalTimeString); + QFile::remove(backup); m_Run = false; }; } +/// +/// Virtual functions overridden from FractoriumEmberControllerBase. +/// + /// /// Setters for embers and ember files which convert between float and double types. /// These are used to preserve the current ember/file when switching between renderers. /// Note that some precision will be lost when going from double to float. /// -template void FinalRenderEmberController::SetEmber(const Ember& ember, bool verbatim) { m_Ember = ember; } -template void FinalRenderEmberController::CopyEmber(Ember& ember) { ember = m_Ember; } -template void FinalRenderEmberController::SetEmberFile(const EmberFile& emberFile) { m_EmberFile = emberFile; } -template void FinalRenderEmberController::CopyEmberFile(EmberFile& emberFile) { emberFile = m_EmberFile; } -template void FinalRenderEmberController::SetOriginalEmber(Ember& ember) { m_OriginalEmber = ember; } -template double FinalRenderEmberController::OriginalAspect() { return double(m_OriginalEmber.m_OrigFinalRasW) / m_OriginalEmber.m_OrigFinalRasH; } +template void FinalRenderEmberController::SetEmberFile(const EmberFile& emberFile) +{ + m_EmberFile = emberFile; + + if (m_EmberFile.Size()) + m_Ember = &(m_EmberFile.m_Embers[0]); +} +template void FinalRenderEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) +{ + emberFile.m_Filename = m_EmberFile.m_Filename; + CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); +} + #ifdef DO_DOUBLE -template void FinalRenderEmberController::SetEmber(const Ember& ember, bool verbatim) { m_Ember = ember; } -template void FinalRenderEmberController::CopyEmber(Ember& ember) { ember = m_Ember; } -template void FinalRenderEmberController::SetEmberFile(const EmberFile& emberFile) { m_EmberFile = emberFile; } -template void FinalRenderEmberController::CopyEmberFile(EmberFile& emberFile) { emberFile = m_EmberFile; } -template void FinalRenderEmberController::SetOriginalEmber(Ember& ember) { m_OriginalEmber = ember; } +template void FinalRenderEmberController::SetEmberFile(const EmberFile& emberFile) +{ + m_EmberFile = emberFile; + + if (m_EmberFile.Size()) + m_Ember = &(m_EmberFile.m_Embers[0]); +} +template void FinalRenderEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) +{ + emberFile.m_Filename = m_EmberFile.m_Filename; + CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); +} #endif /// -/// Progress function. -/// Take special action to sync options upon finishing. +/// Set the ember at the specified index from the currently opened file as the current Ember. +/// Clears the undo state. +/// Resets the rendering process. /// -/// The ember currently being rendered -/// An extra dummy parameter -/// The progress fraction from 0-100 -/// The stage of iteration. 1 is iterating, 2 is density filtering, 2 is final accumulation. -/// The estimated milliseconds to completion of the current stage -/// 0 if the user has clicked cancel, else 1 to continue rendering. +/// The index in the file from which to retrieve the ember template -int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) +void FinalRenderEmberController::SetEmber(size_t index) { - static int count = 0; - int intFract = (int)fraction; - - if (stage == 0) - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract)); - else if (stage == 1) - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract)); - else if (stage == 2) - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract)); - - //Finished, so take special action. - if (stage == 2 && intFract == 100) + if (index < m_EmberFile.Size()) { - string renderTimeString = m_RenderTimer.Format(m_RenderTimer.Toc()), totalTimeString; - QString status, filename = m_GuiState.m_Path; - QFileInfo original(filename); - EmberStats stats = m_Renderer->Stats(); - QString iters = QLocale(QLocale::English).toString(stats.m_Iters); - QString itersPerSec = QLocale(QLocale::English).toString(unsigned __int64(stats.m_Iters / (stats.m_IterMs / 1000.0))); - - if (m_GuiState.m_DoAll && m_EmberFile.m_Embers.size() > 1) - filename = original.absolutePath() + QDir::separator() + m_GuiState.m_Prefix + QString::fromStdString(m_EmberFile.m_Embers[m_FinishedImageCount].m_Name) + m_GuiState.m_Suffix + "." + m_GuiState.m_DoAllExt; - else - filename = original.absolutePath() + QDir::separator() + m_GuiState.m_Prefix + original.completeBaseName() + m_GuiState.m_Suffix + "." + original.suffix(); - - filename = EmberFile::UniqueFilename(filename); - - //Save whatever options were specified on the GUI to the settings. - m_Settings->FinalEarlyClip(m_GuiState.m_EarlyClip); - m_Settings->FinalYAxisUp(m_GuiState.m_YAxisUp); - m_Settings->FinalTransparency(m_GuiState.m_Transparency); - m_Settings->FinalOpenCL(m_GuiState.m_OpenCL); - m_Settings->FinalDouble(m_GuiState.m_Double); - m_Settings->FinalPlatformIndex(m_GuiState.m_PlatformIndex); - m_Settings->FinalDeviceIndex(m_GuiState.m_DeviceIndex); - m_Settings->FinalSaveXml(m_GuiState.m_SaveXml); - m_Settings->FinalDoAll(m_GuiState.m_DoAll); - m_Settings->FinalDoSequence(m_GuiState.m_DoSequence); - m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect); - m_Settings->FinalScale(m_GuiState.m_Scale); - m_Settings->FinalDoAllExt(m_GuiState.m_DoAllExt); - m_Settings->FinalThreadCount(m_GuiState.m_ThreadCount); - m_Settings->FinalWidth(m_GuiState.m_Width); - m_Settings->FinalHeight(m_GuiState.m_Height); - m_Settings->FinalQuality(m_GuiState.m_Quality); - m_Settings->FinalTemporalSamples(m_GuiState.m_TemporalSamples); - m_Settings->FinalSupersample(m_GuiState.m_Supersample); - SaveCurrentRender(filename); - - if (m_GuiState.m_SaveXml) - { - QFileInfo xmlFileInfo(filename);//Create another one in case it was modified for batch rendering. - QString newPath = xmlFileInfo.absolutePath() + QDir::separator() + xmlFileInfo.completeBaseName() + ".flame"; - xmlDocPtr tempEdit = ember.m_Edits; - - ember.m_Edits = m_XmlWriter.CreateNewEditdoc(&ember, NULL, "edit", m_Settings->Nick().toStdString(), m_Settings->Url().toStdString(), m_Settings->Id().toStdString(), "", 0, 0); - m_XmlWriter.Save(newPath.toStdString().c_str(), ember, 0, true, false, true);//Note that the ember passed is used, rather than m_Ember because it's what was actually rendered. - - if (tempEdit != NULL) - xmlFreeDoc(tempEdit); - } - - m_FinishedImageCount++; - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100));//Just to be safe. - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100)); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100)); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(((float)m_FinishedImageCount / (float)m_ImageCount) * 100))); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(QString, QString::number(m_FinishedImageCount) + " / " + QString::number(m_ImageCount))); - - status = "Image " + QString::number(m_FinishedImageCount) + ":\nPure render time: " + QString::fromStdString(renderTimeString); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, status)); - - totalTimeString = m_TotalTimer.Format(m_TotalTimer.Toc()); - status = "Total render time: " + QString::fromStdString(totalTimeString) + "\nTotal iters: " + iters + "\nIters/second: " + itersPerSec + "\n"; - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "append", Qt::QueuedConnection, Q_ARG(QString, status)); - QMetaObject::invokeMethod(m_FinalRender, "MoveCursorToEnd", Qt::QueuedConnection); - - if (m_FinishedImageCount != m_ImageCount) - { - ResetProgress(false); - } + m_Ember = &(m_EmberFile.m_Embers[index]); + SyncCurrentToGui(); + } + else + { + m_Ember = &(m_EmberFile.m_Embers[0]);//Should never happen. } - - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection); - QApplication::processEvents(); - return m_Run ? 1 : 0; } /// @@ -382,17 +359,17 @@ int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, doub template bool FinalRenderEmberController::Render() { - QString filename = m_FinalRender->Path(); + QString filename = m_FinalRenderDialog->Path(); if (filename == "") { - QMessageBox::critical(m_FinalRender, "File Error", "Please enter a valid path and filename for the output."); + m_Fractorium->ShowCritical("File Error", "Please enter a valid path and filename for the output."); return false; } if (CreateRendererFromGUI()) { - m_FinalRender->ui.FinalRenderTextOutput->clear(); + m_FinalRenderDialog->ui.FinalRenderTextOutput->setText("Preparing all parameters.\n"); //Note that a Qt thread must be used, rather than a tbb task. //This is because tbb does a very poor job of allocating thread resources @@ -422,8 +399,7 @@ bool FinalRenderEmberController::CreateRenderer(eRendererType renderType, uns { bool ok = true; vector errorReport; - QString filename = m_FinalRender->Path(); - unsigned int channels = filename.endsWith(".png", Qt::CaseInsensitive) ? 4 : 3; + unsigned int channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3; CancelRender(); @@ -441,14 +417,14 @@ bool FinalRenderEmberController::CreateRenderer(eRendererType renderType, uns m_Device = device; m_OutputTexID = 0;//Don't care about tex ID when doing final render. m_Shared = shared; - + m_Renderer = auto_ptr(::CreateRenderer(renderType, platform, device, shared, m_OutputTexID, emberReport)); errorReport = emberReport.ErrorReport(); if (!errorReport.empty()) { ok = false; - QMessageBox::critical(m_Fractorium, "Renderer Creation Error", "Could not create requested renderer, fallback CPU renderer created. See info tab for details."); + m_Fractorium->ShowCritical("Renderer Creation Error", "Could not create requested renderer, fallback CPU renderer created. See info tab for details."); m_Fractorium->ErrorReportToQTextEdit(errorReport, m_Fractorium->ui.InfoRenderingTextEdit); } } @@ -460,50 +436,109 @@ bool FinalRenderEmberController::CreateRenderer(eRendererType renderType, uns m_Renderer->Callback(this); m_Renderer->NumChannels(channels); - m_Renderer->ReclaimOnResize(true); - m_Renderer->EarlyClip(m_FinalRender->EarlyClip()); - m_Renderer->YAxisUp(m_FinalRender->YAxisUp()); - m_Renderer->ThreadCount(m_FinalRender->ThreadCount()); - m_Renderer->Transparency(m_FinalRender->Transparency()); + m_Renderer->EarlyClip(m_FinalRenderDialog->EarlyClip()); + m_Renderer->YAxisUp(m_FinalRenderDialog->YAxisUp()); + m_Renderer->ThreadCount(m_FinalRenderDialog->ThreadCount()); + m_Renderer->Transparency(m_FinalRenderDialog->Transparency()); } else { ok = false; - QMessageBox::critical(m_FinalRender, "Renderer Creation Error", "Could not create renderer, aborting. See info tab for details."); + m_Fractorium->ShowCritical("Renderer Creation Error", "Could not create renderer, aborting. See info tab for details."); } return ok; } /// -/// Set various parameters in the renderer and current ember with the values -/// specified in the widgets and compute the amount of memory required to render. -/// This includes the memory needed for the final output image. +/// Progress function. +/// Take special action to sync options upon finishing. /// -/// If successful, memory required in bytes, else zero. +/// The ember currently being rendered +/// An extra dummy parameter +/// The progress fraction from 0-100 +/// The stage of iteration. 1 is iterating, 2 is density filtering, 2 is final accumulation. +/// The estimated milliseconds to completion of the current stage +/// 0 if the user has clicked cancel, else 1 to continue rendering. template -unsigned __int64 FinalRenderEmberController::SyncAndComputeMemory() +int FinalRenderEmberController::ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) { - if (m_Renderer.get()) - { - bool b = false; - QString filename = m_FinalRender->Path(); - unsigned int channels = filename.endsWith(".png", Qt::CaseInsensitive) ? 4 : 3;//4 channels for Png, else 3. + static int count = 0; + unsigned int strip = *((unsigned int*)m_Renderer->m_ProgressParameter); + double fracPerStrip = ceil(100.0 / m_GuiState.m_Strips); + double stripsfrac = ceil(fracPerStrip * strip) + ceil(fraction / m_GuiState.m_Strips); + int intFract = (int)stripsfrac; - Sync(m_Ember); - m_Renderer->SetEmber(m_Ember); - m_Renderer->CreateSpatialFilter(b); - m_Renderer->CreateTemporalFilter(b); - m_Renderer->NumChannels(channels); - m_Renderer->ComputeBounds(); - CancelPreviewRender(); - //m_FinalPreviewResult = QtConcurrent::run(m_PreviewRenderFunc); - //while (!m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); }//Wait for it to start up. - m_FinalPreviewRenderFunc(); - return m_Renderer->MemoryRequired(true); + if (stage == 0) + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract)); + else if (stage == 1) + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract)); + else if (stage == 2) + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, intFract)); + + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection); + //QApplication::processEvents(); + return m_Run ? 1 : 0; +} + +/// +/// Virtual functions overridden from FinalRenderEmberControllerBase. +/// + +/// +/// Copy current ember values to widgets. +/// +template +void FinalRenderEmberController::SyncCurrentToGui() +{ + SyncCurrentToSizeSpinners(true, true); + m_FinalRenderDialog->ui.FinalRenderCurrentSpin->setSuffix(" " + Name()); + m_FinalRenderDialog->Scale(m_Ember->ScaleType()); + m_FinalRenderDialog->m_QualitySpin->SetValueStealth(m_Ember->m_Quality); + m_FinalRenderDialog->m_SupersampleSpin->SetValueStealth(m_Ember->m_Supersample); + m_FinalRenderDialog->Path(ComposePath(EmberFile::UniqueFilename(Name()))); +} + +/// +/// Copy GUI values to either the current ember, or all embers in the file +/// depending on whether Render All is checked. +/// +/// Width override to use instead of scaling the original width +/// Height override to use instead of scaling the original height +template +void FinalRenderEmberController::SyncGuiToEmbers(size_t widthOverride, size_t heightOverride) +{ + if (m_FinalRenderDialog->ApplyToAll()) + { + for (size_t i = 0; i < m_EmberFile.Size(); i++) + SyncGuiToEmber(m_EmberFile.m_Embers[i], widthOverride, heightOverride); + } + else + { + SyncGuiToEmber(*m_Ember, widthOverride, heightOverride); + } +} + +/// +/// Set values for scale spinners based on the ratio of the original dimensions to the current dimensions +/// of the current ember. Also update the size suffix text. +/// +/// Whether to update the scale values +/// Whether to update the size suffix text +template +void FinalRenderEmberController::SyncCurrentToSizeSpinners(bool scale, bool size) +{ + if (scale) + { + m_FinalRenderDialog->m_WidthScaleSpin->SetValueStealth((double)m_Ember->m_FinalRasW / m_Ember->m_OrigFinalRasW);//Work backward to determine the scale. + m_FinalRenderDialog->m_HeightScaleSpin->SetValueStealth((double)m_Ember->m_FinalRasH / m_Ember->m_OrigFinalRasH); } - return 0; + if (size) + { + m_FinalRenderDialog->m_WidthScaleSpin->setSuffix(" (" + ToString(m_Ember->m_FinalRasW) + ")"); + m_FinalRenderDialog->m_HeightScaleSpin->setSuffix(" (" + ToString(m_Ember->m_FinalRasH) + ")"); + } } /// @@ -515,15 +550,67 @@ void FinalRenderEmberController::ResetProgress(bool total) { if (total) { - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(QString, "0 / " + QString::number(m_ImageCount))); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, "0 / " + ToString(m_ImageCount))); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); } - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); - QMetaObject::invokeMethod(m_FinalRender->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 0)); } +/// +/// Set various parameters in the renderer and current ember with the values +/// specified in the widgets and compute the amount of memory required to render. +/// This includes the memory needed for the final output image. +/// +/// If successful, memory required in bytes, else zero. +template +size_t FinalRenderEmberController::SyncAndComputeMemory() +{ + if (m_Renderer.get()) + { + bool b = false; + unsigned int channels = m_FinalRenderDialog->Ext() == "png" ? 4 : 3;//4 channels for Png, else 3. + + SyncGuiToEmbers(); + m_Renderer->SetEmber(*m_Ember); + m_Renderer->CreateSpatialFilter(b); + m_Renderer->CreateTemporalFilter(b); + m_Renderer->NumChannels(channels); + m_Renderer->ComputeBounds(); + CancelPreviewRender(); + m_FinalPreviewRenderFunc(); + return m_Renderer->MemoryRequired(m_FinalRenderDialog->Strips(), true); + } + + return 0; +} + +/// +/// Compose a final output path given a base name. +/// This includes the base path, the prefix, the name, the suffix and the +/// extension. +/// +/// The base filename to compose a full path for +/// The fully composed path +template +QString FinalRenderEmberController::ComposePath(const QString& name) +{ + QString path = MakeEnd(m_Settings->SaveFolder(), '/');//Base path. + QString full = path + m_FinalRenderDialog->Prefix() + name + m_FinalRenderDialog->Suffix() + "." + m_FinalRenderDialog->Ext(); + + return full; +} + +/// +/// Non-virtual functions declared in FinalRenderEmberController. +/// + +/// +/// Stop the preview renderer. +/// This is meant to only be called programatically and never by the user. +/// template void FinalRenderEmberController::CancelPreviewRender() { @@ -534,23 +621,105 @@ void FinalRenderEmberController::CancelPreviewRender() while (m_FinalPreviewResult.isRunning()) { QApplication::processEvents(); } } +/// +/// Action to take when rendering an image completes. +/// +/// The ember currently being rendered +template +void FinalRenderEmberController::RenderComplete(Ember& ember) +{ + string renderTimeString = m_RenderTimer.Format(m_RenderTimer.Toc()), totalTimeString; + QString status, filename = ComposePath(EmberFile::UniqueFilename(QString::fromStdString(ember.m_Name))); + QString itersString = ToString(m_Stats.m_Iters); + QString itersPerSecString = ToString(size_t(m_Stats.m_Iters / (m_Stats.m_IterMs / 1000.0))); + + //Save whatever options were specified on the GUI to the settings. + m_Settings->FinalEarlyClip(m_GuiState.m_EarlyClip); + m_Settings->FinalYAxisUp(m_GuiState.m_YAxisUp); + m_Settings->FinalTransparency(m_GuiState.m_Transparency); + m_Settings->FinalOpenCL(m_GuiState.m_OpenCL); + m_Settings->FinalDouble(m_GuiState.m_Double); + m_Settings->FinalPlatformIndex(m_GuiState.m_PlatformIndex); + m_Settings->FinalDeviceIndex(m_GuiState.m_DeviceIndex); + m_Settings->FinalSaveXml(m_GuiState.m_SaveXml); + m_Settings->FinalDoAll(m_GuiState.m_DoAll); + m_Settings->FinalDoSequence(m_GuiState.m_DoSequence); + m_Settings->FinalKeepAspect(m_GuiState.m_KeepAspect); + m_Settings->FinalScale(m_GuiState.m_Scale); + m_Settings->FinalExt(m_GuiState.m_Ext); + m_Settings->FinalThreadCount(m_GuiState.m_ThreadCount); + m_Settings->FinalQuality(m_GuiState.m_Quality); + m_Settings->FinalTemporalSamples(m_GuiState.m_TemporalSamples); + m_Settings->FinalSupersample(m_GuiState.m_Supersample); + m_Settings->FinalStrips(m_GuiState.m_Strips); + SaveCurrentRender(filename, false);//Don't pull from the card, the rendering process already did it. + + if (m_GuiState.m_SaveXml) + { + QFileInfo xmlFileInfo(filename);//Create another one in case it was modified for batch rendering. + QString newPath = xmlFileInfo.absolutePath() + '/' + xmlFileInfo.completeBaseName() + ".flame"; + xmlDocPtr tempEdit = ember.m_Edits; + + ember.m_Edits = m_XmlWriter.CreateNewEditdoc(&ember, NULL, "edit", m_Settings->Nick().toStdString(), m_Settings->Url().toStdString(), m_Settings->Id().toStdString(), "", 0, 0); + m_XmlWriter.Save(newPath.toStdString().c_str(), ember, 0, true, false, true);//Note that the ember passed is used, rather than m_Ember because it's what was actually rendered. + + if (tempEdit != NULL) + xmlFreeDoc(tempEdit); + } + + m_FinishedImageCount++; + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderIterationProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100));//Just to be safe. + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderFilteringProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderAccumProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, 100)); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTotalProgress, "setValue", Qt::QueuedConnection, Q_ARG(int, int(((float)m_FinishedImageCount / (float)m_ImageCount) * 100))); + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderImageCountLabel, "setText", Qt::QueuedConnection, Q_ARG(const QString&, ToString(m_FinishedImageCount) + " / " + ToString(m_ImageCount))); + + status = "Pure render time: " + QString::fromStdString(renderTimeString); + Output(status); + + totalTimeString = m_RenderTimer.Format(m_RenderTimer.Toc()); + status = "Total time: " + QString::fromStdString(totalTimeString) + "\nTotal iters: " + itersString + "\nIters/second: " + itersPerSecString + "\n"; + Output(status); + QMetaObject::invokeMethod(m_FinalRenderDialog, "MoveCursorToEnd", Qt::QueuedConnection); + + if (m_FinishedImageCount != m_ImageCount) + { + ResetProgress(false); + } + + QMetaObject::invokeMethod(m_FinalRenderDialog->ui.FinalRenderTextOutput, "update", Qt::QueuedConnection); +} + /// /// Copy widget values to the ember passed in. /// /// The ember whose values will be modified +/// Width override to use instead of scaling the original width +/// Height override to use instead of scaling the original height template -void FinalRenderEmberController::Sync(Ember& ember) +void FinalRenderEmberController::SyncGuiToEmber(Ember& ember, size_t widthOverride, size_t heightOverride) { - int w = m_FinalRender->m_WidthSpin->value(); - int h = m_FinalRender->m_HeightSpin->value(); + size_t w; + size_t h; - ember.m_FinalRasW = m_OriginalEmber.m_OrigFinalRasW;//Scale is always in terms of the original dimensions of the ember in the editor. - ember.m_FinalRasH = m_OriginalEmber.m_OrigFinalRasH; - ember.m_PixelsPerUnit = m_OriginalEmber.m_PixelsPerUnit; - ember.SetSizeAndAdjustScale(w, h, false, m_FinalRender->Scale()); - ember.m_Quality = m_FinalRender->m_QualitySpin->value(); - ember.m_Supersample = m_FinalRender->m_SupersampleSpin->value(); + if (widthOverride && heightOverride) + { + w = widthOverride; + h = heightOverride; + } + else + { + double wScale = m_FinalRenderDialog->m_WidthScaleSpin->value(); + double hScale = m_FinalRenderDialog->m_HeightScaleSpin->value(); - if (m_FinalRender->ui.FinalRenderDoSequenceCheckBox->isChecked()) - ember.m_TemporalSamples = m_FinalRender->m_TemporalSamplesSpin->value(); + w = ember.m_OrigFinalRasW * wScale; + h = ember.m_OrigFinalRasH * hScale; + } + + w = max(w, 10); + h = max(h, 10); + + ember.SetSizeAndAdjustScale(w, h, false, m_FinalRenderDialog->Scale()); + ember.m_Quality = m_FinalRenderDialog->m_QualitySpin->value(); + ember.m_Supersample = m_FinalRenderDialog->m_SupersampleSpin->value(); } diff --git a/Source/Fractorium/FinalRenderEmberController.h b/Source/Fractorium/FinalRenderEmberController.h index dedaf29..7743a4d 100644 --- a/Source/Fractorium/FinalRenderEmberController.h +++ b/Source/Fractorium/FinalRenderEmberController.h @@ -31,17 +31,18 @@ struct FinalRenderGuiState bool m_KeepAspect; eScaleType m_Scale; QString m_Path; - QString m_DoAllExt; + QString m_Ext; QString m_Prefix; QString m_Suffix; unsigned int m_PlatformIndex; unsigned int m_DeviceIndex; unsigned int m_ThreadCount; - unsigned int m_Width; - unsigned int m_Height; + double m_WidthScale; + double m_HeightScale; double m_Quality; unsigned int m_TemporalSamples; unsigned int m_Supersample; + unsigned int m_Strips; }; /// @@ -55,20 +56,20 @@ class FinalRenderEmberControllerBase : public FractoriumEmberControllerBase friend FractoriumFinalRenderDialog; public: - FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRender); + FinalRenderEmberControllerBase(FractoriumFinalRenderDialog* finalRenderDialog); virtual ~FinalRenderEmberControllerBase() { } - virtual unsigned __int64 SyncAndComputeMemory() { return 0; } - virtual QString Name() const { return ""; } + virtual void SyncCurrentToGui() { } + virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0) { } + virtual void SyncCurrentToSizeSpinners(bool scale, bool size) { } virtual void ResetProgress(bool total = true) { } - virtual void SetOriginalEmber(Ember& ember) { } -#ifdef DO_DOUBLE - virtual void SetOriginalEmber(Ember& ember) { } -#endif + virtual size_t SyncAndComputeMemory() { return 0; } virtual double OriginalAspect() { return 1; } + virtual QString ComposePath(const QString& name) { return ""; } void CancelRender(); bool CreateRendererFromGUI(); + void Output(const QString& s); protected: bool m_Run; @@ -82,7 +83,7 @@ protected: std::function m_FinalPreviewRenderFunc; FractoriumSettings* m_Settings; - FractoriumFinalRenderDialog* m_FinalRender; + FractoriumFinalRenderDialog* m_FinalRenderDialog; FinalRenderGuiState m_GuiState; OpenCLWrapper m_Wrapper; CriticalSection m_PreviewCs; @@ -101,33 +102,36 @@ public: FinalRenderEmberController(FractoriumFinalRenderDialog* finalRender); virtual ~FinalRenderEmberController() { } - virtual void SetEmber(const Ember& ember, bool verbatim = false); - virtual void CopyEmber(Ember& ember); - virtual void SetEmberFile(const EmberFile& emberFile); - virtual void CopyEmberFile(EmberFile& emberFile); - virtual void SetOriginalEmber(Ember& ember); + //Virtual functions overridden from FractoriumEmberControllerBase. + virtual void SetEmberFile(const EmberFile& emberFile) override; + virtual void CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) override; #ifdef DO_DOUBLE - virtual void SetEmber(const Ember& ember, bool verbatim = false); - virtual void CopyEmber(Ember& ember); - virtual void SetEmberFile(const EmberFile& emberFile); - virtual void CopyEmberFile(EmberFile& emberFile); - virtual void SetOriginalEmber(Ember& ember); + virtual void SetEmberFile(const EmberFile& emberFile) override; + virtual void CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) override; #endif - virtual double OriginalAspect(); - virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs); - virtual bool Render(); - virtual bool CreateRenderer(eRendererType renderType, unsigned int platform, unsigned int device, bool shared = true); - virtual unsigned int SizeOfT() { return sizeof(T); } - virtual unsigned __int64 SyncAndComputeMemory(); - virtual QString Name() const { return QString::fromStdString(m_Ember.m_Name); } - virtual void ResetProgress(bool total = true); - void CancelPreviewRender(); + virtual void SetEmber(size_t index) override; + virtual bool Render() override; + virtual bool CreateRenderer(eRendererType renderType, unsigned int platform, unsigned int device, bool shared = true) override; + virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) override; + virtual size_t Index() const override { return m_Ember->m_Index; } + virtual unsigned int SizeOfT() const override { return sizeof(T); } + //Virtual functions overridden from FinalRenderEmberControllerBase. + virtual void SyncCurrentToGui() override; + virtual void SyncGuiToEmbers(size_t widthOverride = 0, size_t heightOverride = 0) override; + virtual void SyncCurrentToSizeSpinners(bool scale, bool size) override; + virtual void ResetProgress(bool total = true) override; + virtual size_t SyncAndComputeMemory() override; + virtual double OriginalAspect() override { return double(m_Ember->m_OrigFinalRasW) / m_Ember->m_OrigFinalRasH; } + virtual QString Name() const override { return QString::fromStdString(m_Ember->m_Name); } + virtual QString ComposePath(const QString& name) override; + protected: - void Sync(Ember& ember); + void CancelPreviewRender(); + void RenderComplete(Ember& ember); + void SyncGuiToEmber(Ember& ember, size_t widthOverride = 0, size_t heightOverride = 0); - Ember m_Ember; - Ember m_OriginalEmber; + Ember* m_Ember; Ember m_PreviewEmber; EmberFile m_EmberFile; EmberToXml m_XmlWriter; diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index 44a1db5..7907c52 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -165,18 +165,6 @@ Fractorium::~Fractorium() m_Settings->sync(); } -/// -/// Stop the render timer and start the delayed restart timer. -/// This is a massive hack because Qt has no way of detecting when a resize event -/// is started and stopped. Detecting if mouse buttons down is also not an option -/// because the documentation says it gives the wrong result. -/// -void Fractorium::Resize() -{ - if (!QCoreApplication::closingDown()) - m_Controller->DelayedStartRenderTimer(); -} - /// /// Set the coordinate text in the status bar. /// @@ -198,11 +186,9 @@ void Fractorium::SetCoordinateStatus(int x, int y, float worldX, float worldY) template void FractoriumEmberController::ApplyXmlSavingTemplate(Ember& ember) { - ember.m_FinalRasW = m_Fractorium->m_Settings->XmlWidth(); - ember.m_FinalRasH = m_Fractorium->m_Settings->XmlHeight(); - ember.m_TemporalSamples = m_Fractorium->m_Settings->XmlTemporalSamples(); ember.m_Quality = m_Fractorium->m_Settings->XmlQuality(); ember.m_Supersample = m_Fractorium->m_Settings->XmlSupersample(); + ember.m_TemporalSamples = m_Fractorium->m_Settings->XmlTemporalSamples(); } /// @@ -260,11 +246,13 @@ void Fractorium::dockLocationChanged(Qt::DockWidgetArea area) /// /// -/// Resize event, just pass to base. +/// Resize event, change width and height double click values to match the window size. /// /// The event void Fractorium::resizeEvent(QResizeEvent* e) { + m_WidthSpin->DoubleClickNonZero(ui.GLParentScrollArea->width()); + m_HeightSpin->DoubleClickNonZero(ui.GLParentScrollArea->height()); QMainWindow::resizeEvent(e); } @@ -362,7 +350,7 @@ void Fractorium::dropEvent(QDropEvent* e) void Fractorium::SetupCombo(QTableWidget* table, const QObject* receiver, int& row, int col, StealthComboBox*& comboBox, vector& vals, const char* signal, const char* slot, Qt::ConnectionType connectionType) { comboBox = new StealthComboBox(table); - ForEach(vals, [&](string s) { comboBox->addItem(s.c_str()); }); + ForEach(vals, [&](const string& s) { comboBox->addItem(s.c_str()); }); table->setCellWidget(row, col, comboBox); connect(comboBox, signal, receiver, slot, connectionType); row++; @@ -425,7 +413,7 @@ QStringList Fractorium::SetupOpenXmlDialog() /// /// The default filename to populate the text box with /// The filename selected -QString Fractorium::SetupSaveXmlDialog(QString defaultFilename) +QString Fractorium::SetupSaveXmlDialog(const QString& defaultFilename) { //Lazy instantiate since it takes a long time. if (!m_FileDialog) @@ -463,7 +451,7 @@ QString Fractorium::SetupSaveXmlDialog(QString defaultFilename) /// /// The default filename to populate the text box with /// The filename selected -QString Fractorium::SetupSaveImageDialog(QString defaultFilename) +QString Fractorium::SetupSaveImageDialog(const QString& defaultFilename) { //Lazy instantiate since it takes a long time. if (!m_FileDialog) @@ -502,7 +490,7 @@ QString Fractorium::SetupSaveImageDialog(QString defaultFilename) /// Setup and show the save folder dialog. /// This will perform lazy instantiation. /// -/// The folder selected +/// The folder selected, with '/' appended to the end QString Fractorium::SetupSaveFolderDialog() { //Lazy instantiate since it takes a long time. @@ -528,11 +516,28 @@ QString Fractorium::SetupSaveFolderDialog() m_FolderDialog->setDirectory(m_Settings->SaveFolder()); if (m_FolderDialog->exec() == QDialog::Accepted) - filename = m_FolderDialog->selectedFiles().value(0); + { + filename = MakeEnd(m_FolderDialog->selectedFiles().value(0), '/'); + } return filename; } +/// +/// Thin wrapper around QMessageBox::critical() to allow it to be invoked from another thread. +/// +void Fractorium::ShowCritical(const QString& title, const QString& text, bool invokeRequired) +{ + if (!invokeRequired) + { + QMessageBox::critical(this, title, text); + } + else + { + QMetaObject::invokeMethod(this, "ShowCritical", Qt::QueuedConnection, Q_ARG(const QString&, title), Q_ARG(const QString&, text), Q_ARG(bool, false)); + } +} + /// /// Explicitly set the tab orders for the entire program. /// Qt has a facility to do this, but it fails when using custom widgets in diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index 5cbb6f5..eb6065d 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -71,7 +71,6 @@ public: void SetCenter(float x, float y); void SetRotation(double rot, bool stealth); void SetScale(double scale); - void Resize(); void SetCoordinateStatus(int x, int y, float worldX, float worldY); //Xforms. @@ -230,6 +229,7 @@ public slots: void StartRenderTimer(); void IdleTimer(); bool ControllersOk(); + void ShowCritical(const QString& title, const QString& text, bool invokeRequired = false); //Can't have a template function be a slot. void SetLibraryTreeItemData(EmberTreeWidgetItemBase* item, vector& v, unsigned int width, unsigned int height); @@ -243,11 +243,11 @@ public: static int FlipDet(Affine2D& affine); protected: - virtual void resizeEvent(QResizeEvent* e); - virtual void closeEvent(QCloseEvent* e); - virtual void dragEnterEvent(QDragEnterEvent* e); - virtual void dragMoveEvent(QDragMoveEvent* e); - virtual void dropEvent(QDropEvent* e); + virtual void resizeEvent(QResizeEvent* e) override; + virtual void closeEvent(QCloseEvent* e) override; + virtual void dragEnterEvent(QDragEnterEvent* e) override; + virtual void dragMoveEvent(QDragMoveEvent* e) override; + virtual void dropEvent(QDropEvent* e) override; private: void InitMenusUI(); @@ -294,8 +294,8 @@ private: //Dialogs. QStringList SetupOpenXmlDialog(); - QString SetupSaveXmlDialog(QString defaultFilename); - QString SetupSaveImageDialog(QString defaultFilename); + QString SetupSaveXmlDialog(const QString& defaultFilename); + QString SetupSaveImageDialog(const QString& defaultFilename); QString SetupSaveFolderDialog(); QColorDialog* m_ColorDialog; FractoriumFinalRenderDialog* m_FinalRenderDialog; @@ -461,5 +461,52 @@ static QWidget* SetTabOrder(QWidget* parent, QWidget* w1, QWidget* w2) return w2; } +/// +/// Wrapper around QLocale::system().toDouble(). +/// +/// The string to convert +/// Pointer to boolean which stores the success value of the conversion +/// The converted value if successful, else 0. +static double ToDouble(const QString &s, bool *ok) +{ + return QLocale::system().toDouble(s, ok); +} + +/// +/// Wrapper around QLocale::system().toString(). +/// +/// The value to convert +/// The string value if successful, else "". +template +static QString ToString(T val) +{ + return QLocale::system().toString(val); +} + +/// +/// Force a QString to end with the specified value. +/// +/// The string to append a suffix to +/// The suffix to append +/// The original string value if it already ended in e, else the original value appended with e. +template +static QString MakeEnd(const QString& s, T e) +{ + if (!s.endsWith(e)) + return s + e; + else + return s; +} + +/// +/// Check if a path is not empty and exists on the file system. +/// +/// The path to check +/// True if s was not empty and existed, else false. +static bool Exists(const QString& s) +{ + return s != "" && QDir(s).exists(); +} + //template void Fractorium::SetupSpinner (QTableWidget* table, const QObject* receiver, int& row, int col, SpinBox*& spinBox, int height, int min, int max, int step, const char* signal, const char* slot, bool incRow, int val, int doubleClickZero, int doubleClickNonZero); //template void Fractorium::SetupSpinner(QTableWidget* table, const QObject* receiver, int& row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, const char* signal, const char* slot, bool incRow, double val, double doubleClickZero, double doubleClickNonZero); diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index aa8406d..f295b6e 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -6,8 +6,8 @@ 0 0 - 1173 - 988 + 1214 + 983 @@ -32,107 +32,143 @@ - - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - - - 255 - 255 - 255 - - - - - - - 240 - 240 - 240 - - - - - - - - - 240 - 240 - 240 - - - - - - - 240 - 240 - 240 - - - - - + + + + 0 + 0 + - - ArrowCursor + + QFrame::NoFrame - + + QFrame::Raised + + true - - Qt::StrongFocus + + Qt::AlignCenter - - true - - - false - - - - 6 + + + + 0 + 0 + 930 + 942 + - - 6 + + + 0 + 0 + - - 6 - - - 6 - - + + + + 0 + 0 + 914 + 824 + + + + + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + + + 255 + 255 + 255 + + + + + + + 240 + 240 + 240 + + + + + + + + + 240 + 240 + 240 + + + + + + + 240 + 240 + 240 + + + + + + + + ArrowCursor + + + true + + + Qt::StrongFocus + + + true + + + false + + + 0 0 - 1173 + 1214 21 @@ -140,7 +176,7 @@ &File - + true @@ -167,7 +203,7 @@ &Tools - + true @@ -189,7 +225,7 @@ &Edit - + true @@ -382,7 +418,7 @@ 0 0 252 - 857 + 852 @@ -485,8 +521,8 @@ 0 0 - 252 - 857 + 98 + 847 @@ -2781,8 +2817,8 @@ SpinBox 0 0 - 238 - 752 + 118 + 597 @@ -4952,8 +4988,8 @@ SpinBox 0 0 - 256 - 861 + 105 + 684 diff --git a/Source/Fractorium/FractoriumEmberController.cpp b/Source/Fractorium/FractoriumEmberController.cpp index bdfefad..c5869ec 100644 --- a/Source/Fractorium/FractoriumEmberController.cpp +++ b/Source/Fractorium/FractoriumEmberController.cpp @@ -65,7 +65,7 @@ FractoriumEmberControllerBase::~FractoriumEmberControllerBase() /// Pointer to the main window. template FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) - : FractoriumEmberControllerBase(fractorium) + : FractoriumEmberControllerBase(fractorium) { m_PreviewRun = false; m_PreviewRunning = false; @@ -79,7 +79,6 @@ FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) m_PreviewRenderer->Callback(NULL); m_PreviewRenderer->NumChannels(4); - m_PreviewRenderer->ReclaimOnResize(true); m_PreviewRenderer->EarlyClip(m_Fractorium->m_Settings->EarlyClip()); m_PreviewRenderer->YAxisUp(m_Fractorium->m_Settings->YAxisUp()); m_PreviewRenderer->SetEmber(m_Ember);//Give it an initial ember, will be updated many times later. @@ -98,7 +97,7 @@ FractoriumEmberController::FractoriumEmberController(Fractorium* fractorium) if (QTreeWidgetItem* top = tree->topLevelItem(0)) { - for (size_t i = start; m_PreviewRun && i < end && i < m_EmberFile.m_Embers.size(); i++) + for (size_t i = start; m_PreviewRun && i < end && i < m_EmberFile.Size(); i++) { Ember ember = m_EmberFile.m_Embers[i]; @@ -144,21 +143,38 @@ FractoriumEmberController::~FractoriumEmberController() { } /// Note that some precision will be lost when going from double to float. /// template void FractoriumEmberController::SetEmber(const Ember& ember, bool verbatim) { SetEmberPrivate(ember, verbatim); } -template void FractoriumEmberController::CopyEmber(Ember& ember) { ember = m_Ember; } +template void FractoriumEmberController::CopyEmber(Ember& ember, std::function& ember)> perEmberOperation) { ember = m_Ember; perEmberOperation(ember); } template void FractoriumEmberController::SetEmberFile(const EmberFile& emberFile) { m_EmberFile = emberFile; } -template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile) { emberFile = m_EmberFile; } +template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) +{ + emberFile.m_Filename = m_EmberFile.m_Filename; + CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); +} + template void FractoriumEmberController::SetTempPalette(const Palette& palette) { m_TempPalette = palette; } template void FractoriumEmberController::CopyTempPalette(Palette& palette) { palette = m_TempPalette; } #ifdef DO_DOUBLE template void FractoriumEmberController::SetEmber(const Ember& ember, bool verbatim) { SetEmberPrivate(ember, verbatim); } -template void FractoriumEmberController::CopyEmber(Ember& ember) { ember = m_Ember; } +template void FractoriumEmberController::CopyEmber(Ember& ember, std::function& ember)> perEmberOperation) { ember = m_Ember; perEmberOperation(ember); } template void FractoriumEmberController::SetEmberFile(const EmberFile& emberFile) { m_EmberFile = emberFile; } -template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile) { emberFile = m_EmberFile; } +template void FractoriumEmberController::CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation) +{ + emberFile.m_Filename = m_EmberFile.m_Filename; + CopyVec(emberFile.m_Embers, m_EmberFile.m_Embers, perEmberOperation); +} + template void FractoriumEmberController::SetTempPalette(const Palette& palette) { m_TempPalette = palette; } template void FractoriumEmberController::CopyTempPalette(Palette& palette) { palette = m_TempPalette; } #endif template Ember* FractoriumEmberController::CurrentEmber() { return &m_Ember; } +template +void FractoriumEmberController::ConstrainDimensions(Ember& ember) +{ + ember.m_FinalRasW = std::min(m_Fractorium->ui.GLDisplay->MaxTexSize(), ember.m_FinalRasW); + ember.m_FinalRasH = std::min(m_Fractorium->ui.GLDisplay->MaxTexSize(), ember.m_FinalRasH); +} + /// /// Set the ember at the specified index from the currently opened file as the current Ember. /// Clears the undo state. @@ -168,7 +184,7 @@ template Ember* FractoriumEmberController::CurrentEmber() { r template void FractoriumEmberController::SetEmber(size_t index) { - if (index < m_EmberFile.m_Embers.size()) + if (index < m_EmberFile.Size()) { if (QTreeWidgetItem* top = m_Fractorium->ui.LibraryTree->topLevelItem(0)) { @@ -235,7 +251,7 @@ void FractoriumEmberController::SetEmberPrivate(const Ember& ember, bool v if (!verbatim) { - m_Ember.SetSizeAndAdjustScale(m_Fractorium->ui.GLDisplay->width(), m_Fractorium->ui.GLDisplay->height(), true, SCALE_WIDTH); + //m_Ember.SetSizeAndAdjustScale(m_Fractorium->ui.GLDisplay->width(), m_Fractorium->ui.GLDisplay->height(), true, SCALE_WIDTH); m_Ember.m_TemporalSamples = 1;//Change once animation is supported. m_Ember.m_Quality = m_Fractorium->m_QualitySpin->value(); m_Ember.m_Supersample = m_Fractorium->m_SupersampleSpin->value(); diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 06ed8b7..ae80d38 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -41,16 +41,16 @@ public: //Embers. virtual void SetEmber(const Ember& ember, bool verbatim = false) { } - virtual void CopyEmber(Ember& ember) { } + virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) { } virtual void SetEmberFile(const EmberFile& emberFile) { } - virtual void CopyEmberFile(EmberFile& emberFile) { } + virtual void CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) { } virtual void SetTempPalette(const Palette& palette) { } virtual void CopyTempPalette(Palette& palette) { } #ifdef DO_DOUBLE virtual void SetEmber(const Ember& ember, bool verbatim = false) { } - virtual void CopyEmber(Ember& ember) { } + virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) { } virtual void SetEmberFile(const EmberFile& emberFile) { } - virtual void CopyEmberFile(EmberFile& emberFile) { } + virtual void CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) { } virtual void SetTempPalette(const Palette& palette) { } virtual void CopyTempPalette(Palette& palette) { } #endif @@ -62,14 +62,15 @@ public: virtual void DeleteCurrentXform() { } virtual void AddFinalXform() { } virtual bool UseFinalXform() { return false; } - virtual size_t XformCount() { return 0; } - virtual size_t TotalXformCount() { return 0; } - virtual string Name() { return ""; } - virtual void Name(string s) { } - virtual unsigned int FinalRasW() { return 0; } + virtual size_t XformCount() const { return 0; } + virtual size_t TotalXformCount() const { return 0; } + virtual QString Name() const { return ""; } + virtual void Name(const string& s) { } + virtual unsigned int FinalRasW() const { return 0; } virtual void FinalRasW(unsigned int w) { } - virtual unsigned int FinalRasH() { return 0; } + virtual unsigned int FinalRasH() const { return 0; } virtual void FinalRasH(unsigned int h) { } + virtual size_t Index() const { return 0; } virtual void AddSymmetry(int sym, QTIsaac& rand) { } virtual void CalcNormalizedWeights() { } @@ -78,7 +79,7 @@ public: virtual void NewEmptyFlameInCurrentFile() { } virtual void NewRandomFlameInCurrentFile() { } virtual void CopyFlameInCurrentFile() { } - virtual void OpenAndPrepFiles(QStringList filenames, bool append) { } + virtual void OpenAndPrepFiles(const QStringList& filenames, bool append) { } virtual void SaveCurrentAsXml() { } virtual void SaveEntireFileAsXml() { } virtual void SaveCurrentToOpenedFile() { } @@ -106,6 +107,8 @@ public: virtual void VibrancyChanged(double d) { } virtual void HighlightPowerChanged(double d) { } virtual void PaletteModeChanged(unsigned int i) { } + virtual void WidthChanged(unsigned int i) { } + virtual void HeightChanged(unsigned int i) { } virtual void CenterXChanged(double d) { } virtual void CenterYChanged(double d) { } virtual void ScaleChanged(double d) { } @@ -165,7 +168,7 @@ public: virtual void ClearXaos() { } //Palette. - virtual bool InitPaletteTable(string s) { return false; } + virtual bool InitPaletteTable(const string& s) { return false; } virtual void ApplyPaletteToEmber() { } virtual void PaletteAdjust() { } virtual QRgb GetQRgbFromPaletteIndex(unsigned int i) { return QRgb(); } @@ -185,7 +188,7 @@ public: //Rendering/progress. virtual bool Render() { return false; } virtual bool CreateRenderer(eRendererType renderType, unsigned int platform, unsigned int device, bool shared = true) { return false; } - virtual unsigned int SizeOfT() { return 0; } + virtual unsigned int SizeOfT() const { return 0; } virtual void ClearUndo() { } virtual GLEmberControllerBase* GLController() { return NULL; } bool RenderTimerRunning(); @@ -195,7 +198,7 @@ public: void Shutdown(); void UpdateRender(eProcessAction action = FULL_RENDER); void DeleteRenderer(); - void SaveCurrentRender(QString filename); + void SaveCurrentRender(const QString& filename, bool forcePull); RendererBase* Renderer() { return m_Renderer.get(); } vector* FinalImage() { return &m_FinalImage; } vector* PreviewFinalImage() { return &m_PreviewFinalImage; } @@ -219,6 +222,7 @@ protected: eEditUndoState m_EditState; GLuint m_OutputTexID; Timing m_RenderElapsedTimer; + EmberStats m_Stats; QImage m_FinalPaletteImage; QString m_LastSaveAll; QString m_LastSaveCurrent; @@ -247,161 +251,165 @@ public: virtual ~FractoriumEmberController(); //Embers. - virtual void SetEmber(const Ember& ember, bool verbatim = false); - virtual void CopyEmber(Ember& ember); - virtual void SetEmberFile(const EmberFile& emberFile); - virtual void CopyEmberFile(EmberFile& emberFile); - virtual void SetTempPalette(const Palette& palette); - virtual void CopyTempPalette(Palette& palette); + virtual void SetEmber(const Ember& ember, bool verbatim = false) override; + virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) override; + virtual void SetEmberFile(const EmberFile& emberFile) override; + virtual void CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) override; + virtual void SetTempPalette(const Palette& palette) override; + virtual void CopyTempPalette(Palette& palette) override; #ifdef DO_DOUBLE - virtual void SetEmber(const Ember& ember, bool verbatim = false); - virtual void CopyEmber(Ember& ember); - virtual void SetEmberFile(const EmberFile& emberFile); - virtual void CopyEmberFile(EmberFile& emberFile); - virtual void SetTempPalette(const Palette& palette); - virtual void CopyTempPalette(Palette& palette); + virtual void SetEmber(const Ember& ember, bool verbatim = false) override; + virtual void CopyEmber(Ember& ember, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) override; + virtual void SetEmberFile(const EmberFile& emberFile) override; + virtual void CopyEmberFile(EmberFile& emberFile, std::function& ember)> perEmberOperation = [&](Ember& ember) { }) override; + virtual void SetTempPalette(const Palette& palette) override; + virtual void CopyTempPalette(Palette& palette) override; #endif - virtual void SetEmber(size_t index); - virtual void Clear() { } - virtual void AddXform(); - virtual void DuplicateXform(); - virtual void ClearCurrentXform(); - virtual void DeleteCurrentXform(); - virtual void AddFinalXform(); - virtual bool UseFinalXform() { return m_Ember.UseFinalXform(); } + virtual void SetEmber(size_t index) override; + virtual void Clear() override { } + virtual void AddXform() override; + virtual void DuplicateXform() override; + virtual void ClearCurrentXform() override; + virtual void DeleteCurrentXform() override; + virtual void AddFinalXform() override; + virtual bool UseFinalXform() override { return m_Ember.UseFinalXform(); } //virtual bool IsFinal(unsigned int i) { return false; } - virtual size_t XformCount() { return m_Ember.XformCount(); } - virtual size_t TotalXformCount() { return m_Ember.TotalXformCount(); } - virtual string Name() { return m_Ember.m_Name; } - virtual void Name(string s) { m_Ember.m_Name = s; } - virtual unsigned int FinalRasW() { return m_Ember.m_FinalRasW; } - virtual void FinalRasW(unsigned int w) { m_Ember.m_FinalRasW = w; } - virtual unsigned int FinalRasH() { return m_Ember.m_FinalRasH; } - virtual void FinalRasH(unsigned int h) { m_Ember.m_FinalRasH = h; } - virtual void AddSymmetry(int sym, QTIsaac& rand) { m_Ember.AddSymmetry(sym, rand); } - virtual void CalcNormalizedWeights() { m_Ember.CalcNormalizedWeights(m_NormalizedWeights); } + virtual size_t XformCount() const override { return m_Ember.XformCount(); } + virtual size_t TotalXformCount() const override { return m_Ember.TotalXformCount(); } + virtual QString Name() const override { return QString::fromStdString(m_Ember.m_Name); } + virtual void Name(const string& s) override { m_Ember.m_Name = s; } + virtual unsigned int FinalRasW() const override { return m_Ember.m_FinalRasW; } + virtual void FinalRasW(unsigned int w) override { m_Ember.m_FinalRasW = w; } + virtual unsigned int FinalRasH() const override { return m_Ember.m_FinalRasH; } + virtual void FinalRasH(unsigned int h) override { m_Ember.m_FinalRasH = h; } + virtual size_t Index() const override { return m_Ember.m_Index; } + virtual void AddSymmetry(int sym, QTIsaac& rand) override { m_Ember.AddSymmetry(sym, rand); } + virtual void CalcNormalizedWeights() override { m_Ember.CalcNormalizedWeights(m_NormalizedWeights); } + void ConstrainDimensions(Ember& ember); Ember* CurrentEmber(); //Menu. - virtual void NewFlock(unsigned int count); - virtual void NewEmptyFlameInCurrentFile(); - virtual void NewRandomFlameInCurrentFile(); - virtual void CopyFlameInCurrentFile(); - virtual void OpenAndPrepFiles(QStringList filenames, bool append); - virtual void SaveCurrentAsXml(); - virtual void SaveEntireFileAsXml(); - virtual void SaveCurrentToOpenedFile(); - virtual void Undo(); - virtual void Redo(); - virtual void CopyXml(); - virtual void CopyAllXml(); - virtual void PasteXmlAppend(); - virtual void PasteXmlOver(); - virtual void AddReflectiveSymmetry(); - virtual void AddRotationalSymmetry(); - virtual void AddBothSymmetry(); - virtual void Flatten(); - virtual void Unflatten(); - virtual void ClearFlame(); + virtual void NewFlock(unsigned int count) override; + virtual void NewEmptyFlameInCurrentFile() override; + virtual void NewRandomFlameInCurrentFile() override; + virtual void CopyFlameInCurrentFile() override; + virtual void OpenAndPrepFiles(const QStringList& filenames, bool append) override; + virtual void SaveCurrentAsXml() override; + virtual void SaveEntireFileAsXml() override; + virtual void SaveCurrentToOpenedFile() override; + virtual void Undo() override; + virtual void Redo() override; + virtual void CopyXml() override; + virtual void CopyAllXml() override; + virtual void PasteXmlAppend() override; + virtual void PasteXmlOver() override; + virtual void AddReflectiveSymmetry() override; + virtual void AddRotationalSymmetry() override; + virtual void AddBothSymmetry() override; + virtual void Flatten() override; + virtual void Unflatten() override; + virtual void ClearFlame() override; //Toolbar. //Params. - virtual void SetCenter(double x, double y); - virtual void FillParamTablesAndPalette(); - virtual void BrightnessChanged(double d); - virtual void GammaChanged(double d); - virtual void GammaThresholdChanged(double d); - virtual void VibrancyChanged(double d); - virtual void HighlightPowerChanged(double d); - virtual void PaletteModeChanged(unsigned int i); - virtual void CenterXChanged(double d); - virtual void CenterYChanged(double d); - virtual void ScaleChanged(double d); - virtual void ZoomChanged(double d); - virtual void RotateChanged(double d); - virtual void ZPosChanged(double d); - virtual void PerspectiveChanged(double d); - virtual void PitchChanged(double d); - virtual void YawChanged(double d); - virtual void DepthBlurChanged(double d); - virtual void SpatialFilterWidthChanged(double d); - virtual void SpatialFilterTypeChanged(const QString& text); - virtual void TemporalFilterWidthChanged(double d); - virtual void TemporalFilterTypeChanged(const QString& text); - virtual void DEFilterMinRadiusWidthChanged(double d); - virtual void DEFilterMaxRadiusWidthChanged(double d); - virtual void DEFilterCurveWidthChanged(double d); - virtual void PassesChanged(int d); - virtual void TemporalSamplesChanged(int d); - virtual void QualityChanged(double d); - virtual void SupersampleChanged(int d); - virtual void AffineInterpTypeChanged(int index); - virtual void InterpTypeChanged(int index); - virtual void BackgroundChanged(const QColor& col); + virtual void SetCenter(double x, double y) override; + virtual void FillParamTablesAndPalette() override; + virtual void BrightnessChanged(double d) override; + virtual void GammaChanged(double d) override; + virtual void GammaThresholdChanged(double d) override; + virtual void VibrancyChanged(double d) override; + virtual void HighlightPowerChanged(double d) override; + virtual void PaletteModeChanged(unsigned int i) override; + virtual void WidthChanged(unsigned int i) override; + virtual void HeightChanged(unsigned int i) override; + virtual void CenterXChanged(double d) override; + virtual void CenterYChanged(double d) override; + virtual void ScaleChanged(double d) override; + virtual void ZoomChanged(double d) override; + virtual void RotateChanged(double d) override; + virtual void ZPosChanged(double d) override; + virtual void PerspectiveChanged(double d) override; + virtual void PitchChanged(double d) override; + virtual void YawChanged(double d) override; + virtual void DepthBlurChanged(double d) override; + virtual void SpatialFilterWidthChanged(double d) override; + virtual void SpatialFilterTypeChanged(const QString& text) override; + virtual void TemporalFilterWidthChanged(double d) override; + virtual void TemporalFilterTypeChanged(const QString& text) override; + virtual void DEFilterMinRadiusWidthChanged(double d) override; + virtual void DEFilterMaxRadiusWidthChanged(double d) override; + virtual void DEFilterCurveWidthChanged(double d) override; + virtual void PassesChanged(int d) override; + virtual void TemporalSamplesChanged(int d) override; + virtual void QualityChanged(double d) override; + virtual void SupersampleChanged(int d) override; + virtual void AffineInterpTypeChanged(int index) override; + virtual void InterpTypeChanged(int index) override; + virtual void BackgroundChanged(const QColor& col) override; //Xforms. - virtual void CurrentXformComboChanged(int index); - virtual void XformWeightChanged(double d); - virtual void EqualizeWeights(); - virtual void XformNameChanged(int row, int col); + virtual void CurrentXformComboChanged(int index) override; + virtual void XformWeightChanged(double d) override; + virtual void EqualizeWeights() override; + virtual void XformNameChanged(int row, int col) override; void FillWithXform(Xform* xform); Xform* CurrentXform(); //Xforms Affine. - virtual void AffineSetHelper(double d, int index, bool pre); - virtual void FlipCurrentXform(bool horizontal, bool vertical, bool pre); - virtual void RotateCurrentXformByAngle(double angle, bool pre); - virtual void MoveCurrentXform(double x, double y, bool pre); - virtual void ScaleCurrentXform(double scale, bool pre); - virtual void ResetCurrentXformAffine(bool pre); + virtual void AffineSetHelper(double d, int index, bool pre) override; + virtual void FlipCurrentXform(bool horizontal, bool vertical, bool pre) override; + virtual void RotateCurrentXformByAngle(double angle, bool pre) override; + virtual void MoveCurrentXform(double x, double y, bool pre) override; + virtual void ScaleCurrentXform(double scale, bool pre) override; + virtual void ResetCurrentXformAffine(bool pre) override; void FillAffineWithXform(Xform* xform, bool pre); //Xforms Color. - virtual void XformColorIndexChanged(double d, bool updateRender); - virtual void XformScrollColorIndexChanged(int d); - virtual void XformColorSpeedChanged(double d); - virtual void XformOpacityChanged(double d); - virtual void XformDirectColorChanged(double d); + virtual void XformColorIndexChanged(double d, bool updateRender) override; + virtual void XformScrollColorIndexChanged(int d) override; + virtual void XformColorSpeedChanged(double d) override; + virtual void XformOpacityChanged(double d) override; + virtual void XformDirectColorChanged(double d) override; void FillColorWithXform(Xform* xform); //Xforms Variations. - virtual void SetupVariationTree(); - virtual void ClearVariationsTree(); - virtual void VariationSpinBoxValueChanged(double d); + virtual void SetupVariationTree() override; + virtual void ClearVariationsTree() override; + virtual void VariationSpinBoxValueChanged(double d) override; void FillVariationTreeWithXform(Xform* xform); //Xforms Xaos. - virtual void FillXaosWithCurrentXform(); - virtual QString MakeXaosNameString(unsigned int i); - virtual void XaosChanged(DoubleSpinBox* sender); - virtual void ClearXaos(); + virtual void FillXaosWithCurrentXform() override; + virtual QString MakeXaosNameString(unsigned int i) override; + virtual void XaosChanged(DoubleSpinBox* sender) override; + virtual void ClearXaos() override; //Palette. - virtual bool InitPaletteTable(string s); - virtual void ApplyPaletteToEmber(); - virtual void PaletteAdjust(); - virtual QRgb GetQRgbFromPaletteIndex(unsigned int i) { return QRgb(); } - virtual void PaletteCellClicked(int row, int col); + virtual bool InitPaletteTable(const string& s) override; + virtual void ApplyPaletteToEmber() override; + virtual void PaletteAdjust() override; + virtual QRgb GetQRgbFromPaletteIndex(unsigned int i) override { return QRgb(); } + virtual void PaletteCellClicked(int row, int col) override; //Library. - virtual void SyncNames(); - virtual void FillLibraryTree(int selectIndex = -1); - virtual void UpdateLibraryTree(); - virtual void EmberTreeItemChanged(QTreeWidgetItem* item, int col); - virtual void EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col); - virtual void RenderPreviews(unsigned int start = UINT_MAX, unsigned int end = UINT_MAX); - virtual void StopPreviewRender(); + virtual void SyncNames() override; + virtual void FillLibraryTree(int selectIndex = -1) override; + virtual void UpdateLibraryTree() override; + virtual void EmberTreeItemChanged(QTreeWidgetItem* item, int col) override; + virtual void EmberTreeItemDoubleClicked(QTreeWidgetItem* item, int col) override; + virtual void RenderPreviews(unsigned int start = UINT_MAX, unsigned int end = UINT_MAX) override; + virtual void StopPreviewRender() override; //Info. //Rendering/progress. - virtual bool Render(); - virtual bool CreateRenderer(eRendererType renderType, unsigned int platform, unsigned int device, bool shared = true); - virtual unsigned int SizeOfT() { return sizeof(T); } - virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs); - virtual void ClearUndo(); - virtual GLEmberControllerBase* GLController() { return m_GLController.get(); } + virtual bool Render() override; + virtual bool CreateRenderer(eRendererType renderType, unsigned int platform, unsigned int device, bool shared = true) override; + virtual unsigned int SizeOfT() const override { return sizeof(T); } + virtual int ProgressFunc(Ember& ember, void* foo, double fraction, int stage, double etaMs) override; + virtual void ClearUndo() override; + virtual GLEmberControllerBase* GLController() override { return m_GLController.get(); } private: //Embers. @@ -424,6 +432,7 @@ private: //Rendering/progress. void Update(std::function func, bool updateRender = true, eProcessAction action = FULL_RENDER); void UpdateCurrentXform(std::function*)> func, bool updateRender = true, eProcessAction action = FULL_RENDER); + bool SyncSizes(); //Templated members. bool m_PreviewRun; diff --git a/Source/Fractorium/FractoriumInfo.cpp b/Source/Fractorium/FractoriumInfo.cpp index 8e283c5..1d49cb2 100644 --- a/Source/Fractorium/FractoriumInfo.cpp +++ b/Source/Fractorium/FractoriumInfo.cpp @@ -24,7 +24,7 @@ void Fractorium::UpdateHistogramBounds() ui.InfoBoundsLabelW->setText(QString(m_WString)); ui.InfoBoundsLabelH->setText(QString(m_HString)); - ui.InfoBoundsTable->item(0, 1)->setText(QString::number(r->GutterWidth())); + ui.InfoBoundsTable->item(0, 1)->setText(ToString(r->GutterWidth())); if (r->GetDensityFilter()) { @@ -54,5 +54,5 @@ void Fractorium::ErrorReportToQTextEdit(vector& errors, QTextEdit* textE QMetaObject::invokeMethod(textEdit, "clear", Qt::QueuedConnection); for (size_t i = 0; i < errors.size(); i++) - QMetaObject::invokeMethod(textEdit, "append", Qt::QueuedConnection, Q_ARG(QString, QString::fromStdString(errors[i]) + "\n")); + QMetaObject::invokeMethod(textEdit, "append", Qt::QueuedConnection, Q_ARG(const QString&, QString::fromStdString(errors[i]) + "\n")); } \ No newline at end of file diff --git a/Source/Fractorium/FractoriumLibrary.cpp b/Source/Fractorium/FractoriumLibrary.cpp index 555f018..0c95a8c 100644 --- a/Source/Fractorium/FractoriumLibrary.cpp +++ b/Source/Fractorium/FractoriumLibrary.cpp @@ -38,7 +38,7 @@ void FractoriumEmberController::SyncNames() { for (int i = 0; i < top->childCount(); i++)//Iterate through all of the children, which will represent the open embers. { - if ((item = dynamic_cast*>(top->child(i))) && i < m_EmberFile.m_Embers.size())//Cast the child widget to the EmberTreeWidgetItem type. + if ((item = dynamic_cast*>(top->child(i))) && i < m_EmberFile.Size())//Cast the child widget to the EmberTreeWidgetItem type. item->setText(0, QString::fromStdString(m_EmberFile.m_Embers[i].m_Name)); } } @@ -72,7 +72,7 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) fileItem->setToolTip(0, m_EmberFile.m_Filename); fileItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); - for (j = 0; j < m_EmberFile.m_Embers.size(); j++) + for (j = 0; j < m_EmberFile.Size(); j++) { Ember* ember = &m_EmberFile.m_Embers[j]; EmberTreeWidgetItem* emberItem = new EmberTreeWidgetItem(ember, fileItem); @@ -80,7 +80,7 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); if (ember->m_Name.empty()) - emberItem->setText(0, QString::number(j)); + emberItem->setText(0, ToString(j)); else emberItem->setText(0, ember->m_Name.c_str()); @@ -96,7 +96,7 @@ void FractoriumEmberController::FillLibraryTree(int selectIndex) emberItem->setSelected(true); QCoreApplication::flush(); - RenderPreviews(0, m_EmberFile.m_Embers.size()); + RenderPreviews(0, m_EmberFile.Size()); tree->expandAll(); } @@ -117,7 +117,7 @@ void FractoriumEmberController::UpdateLibraryTree() tree->blockSignals(true); - for (i = childCount; i < m_EmberFile.m_Embers.size(); i++) + for (i = childCount; i < m_EmberFile.Size(); i++) { Ember* ember = &m_EmberFile.m_Embers[i]; EmberTreeWidgetItem* emberItem = new EmberTreeWidgetItem(ember, top); @@ -125,7 +125,7 @@ void FractoriumEmberController::UpdateLibraryTree() emberItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable); if (ember->m_Name.empty()) - emberItem->setText(0, QString::number(i)); + emberItem->setText(0, ToString(i)); else emberItem->setText(0, ember->m_Name.c_str()); @@ -135,14 +135,14 @@ void FractoriumEmberController::UpdateLibraryTree() //When adding elements to the vector, they may have been reshuffled which will have invalidated //the pointers contained in the EmberTreeWidgetItems. So reassign all pointers here. - for (i = 0; i < m_EmberFile.m_Embers.size(); i++) + for (i = 0; i < m_EmberFile.Size(); i++) { if (EmberTreeWidgetItem* emberItem = dynamic_cast*>(top->child(i))) emberItem->SetEmberPointer(&m_EmberFile.m_Embers[i]); } tree->blockSignals(false); - RenderPreviews(childCount, m_EmberFile.m_Embers.size()); + RenderPreviews(childCount, m_EmberFile.Size()); } } @@ -250,7 +250,7 @@ void FractoriumEmberController::RenderPreviews(unsigned int start, unsigned i } tree->blockSignals(false); - m_PreviewResult = QtConcurrent::run(m_PreviewRenderFunc, 0, m_EmberFile.m_Embers.size()); + m_PreviewResult = QtConcurrent::run(m_PreviewRenderFunc, 0, m_EmberFile.Size()); } else m_PreviewResult = QtConcurrent::run(m_PreviewRenderFunc, start, end); diff --git a/Source/Fractorium/FractoriumMenus.cpp b/Source/Fractorium/FractoriumMenus.cpp index 0693a39..bb68f4d 100644 --- a/Source/Fractorium/FractoriumMenus.cpp +++ b/Source/Fractorium/FractoriumMenus.cpp @@ -61,9 +61,10 @@ void FractoriumEmberController::NewFlock(unsigned int count) { m_SheepTools->Random(ember); ParamsToEmber(ember); + ember.m_Index = i; ember.m_OrigFinalRasW = ember.m_FinalRasW; ember.m_OrigFinalRasH = ember.m_FinalRasH; - ember.m_Name = m_EmberFile.m_Filename.toStdString() + "-" + QString::number(i + 1).toStdString(); + ember.m_Name = m_EmberFile.m_Filename.toStdString() + "-" + ToString(i + 1).toStdString(); m_EmberFile.m_Embers.push_back(ember); } @@ -102,11 +103,12 @@ void FractoriumEmberController::NewEmptyFlameInCurrentFile() xform.m_ColorX = m_Rand.Frand01(); ember.AddXform(xform); ember.m_Palette = *m_PaletteList.GetPalette(-1); - ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.m_Embers.size() + 1).toStdString(); + ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.Size() + 1).toStdString(); + ember.m_Index = m_EmberFile.Size(); m_EmberFile.m_Embers.push_back(ember);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync. m_EmberFile.MakeNamesUnique(); UpdateLibraryTree(); - SetEmber(m_EmberFile.m_Embers.size() - 1); + SetEmber(m_EmberFile.Size() - 1); } void Fractorium::OnActionNewEmptyFlameInCurrentFile(bool checked) { m_Controller->NewEmptyFlameInCurrentFile(); } @@ -126,11 +128,12 @@ void FractoriumEmberController::NewRandomFlameInCurrentFile() ParamsToEmber(ember); ember.m_OrigFinalRasW = ember.m_FinalRasW; ember.m_OrigFinalRasH = ember.m_FinalRasH; - ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.m_Embers.size() + 1).toStdString(); + ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.Size() + 1).toStdString(); + ember.m_Index = m_EmberFile.Size(); m_EmberFile.m_Embers.push_back(ember);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync. m_EmberFile.MakeNamesUnique(); UpdateLibraryTree(); - SetEmber(m_EmberFile.m_Embers.size() - 1); + SetEmber(m_EmberFile.Size() - 1); } void Fractorium::OnActionNewRandomFlameInCurrentFile(bool checked) { m_Controller->NewRandomFlameInCurrentFile(); } @@ -146,11 +149,12 @@ void FractoriumEmberController::CopyFlameInCurrentFile() Ember ember = m_Ember; StopPreviewRender(); - ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.m_Embers.size() + 1).toStdString(); + ember.m_Name = EmberFile::DefaultEmberName(m_EmberFile.Size() + 1).toStdString(); + ember.m_Index = m_EmberFile.Size(); m_EmberFile.m_Embers.push_back(ember);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync. m_EmberFile.MakeNamesUnique(); UpdateLibraryTree(); - SetEmber(m_EmberFile.m_Embers.size() - 1); + SetEmber(m_EmberFile.Size() - 1); } void Fractorium::OnActionCopyFlameInCurrentFile(bool checked) { m_Controller->CopyFlameInCurrentFile(); } @@ -168,7 +172,7 @@ void Fractorium::OnActionCopyFlameInCurrentFile(bool checked) { m_Controller->Co /// A list of full paths and filenames /// True to append the embers in the new files to the end of the currently open embers, false to clear and replace them template -void FractoriumEmberController::OpenAndPrepFiles(QStringList filenames, bool append) +void FractoriumEmberController::OpenAndPrepFiles(const QStringList& filenames, bool append) { if (!filenames.empty()) { @@ -176,25 +180,24 @@ void FractoriumEmberController::OpenAndPrepFiles(QStringList filenames, bool EmberFile emberFile; XmlToEmber parser; vector> embers; - unsigned int previousSize = append ? m_EmberFile.m_Embers.size() : 0; + unsigned int previousSize = append ? m_EmberFile.Size() : 0; StopPreviewRender(); emberFile.m_Filename = filenames[0]; - foreach (QString filename, filenames) + foreach(const QString& filename, filenames) { embers.clear(); if (parser.Parse(filename.toStdString().c_str(), embers) && !embers.empty()) { - //Disregard whatever size was specified in the file and fit it to the output window size. for (i = 0; i < embers.size(); i++) { - embers[i].SetSizeAndAdjustScale(m_Fractorium->ui.GLDisplay->width(), m_Fractorium->ui.GLDisplay->height(), true, SCALE_WIDTH); + ConstrainDimensions(embers[i]);//Do not exceed the max texture size. //Also ensure it has a name. if (embers[i].m_Name == "" || embers[i].m_Name == "No name") - embers[i].m_Name = QString::number(i).toStdString(); + embers[i].m_Name = ToString(i).toStdString(); embers[i].m_Quality = m_Fractorium->m_QualitySpin->value(); embers[i].m_Supersample = m_Fractorium->m_SupersampleSpin->value(); @@ -208,7 +211,7 @@ void FractoriumEmberController::OpenAndPrepFiles(QStringList filenames, bool vector errors = parser.ErrorReport(); m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit); - QMessageBox::critical(m_Fractorium, "Open Failed", "Could not open file, see info tab for details."); + m_Fractorium->ShowCritical("Open Failed", "Could not open file, see info tab for details."); } } @@ -223,7 +226,7 @@ void FractoriumEmberController::OpenAndPrepFiles(QStringList filenames, bool m_EmberFile = emberFile; //Resync indices and names. - for (i = 0; i < m_EmberFile.m_Embers.size(); i++) + for (i = 0; i < m_EmberFile.Size(); i++) m_EmberFile.m_Embers[i].m_Index = i; m_EmberFile.MakeNamesUnique(); @@ -261,7 +264,7 @@ void FractoriumEmberController::SaveCurrentAsXml() } else { - if (m_EmberFile.m_Embers.size() == 1) + if (m_EmberFile.Size() == 1) filename = m_Fractorium->SetupSaveXmlDialog(m_EmberFile.m_Filename);//If only one ember present, just use parent filename. else filename = m_Fractorium->SetupSaveXmlDialog(QString::fromStdString(m_Ember.m_Name));//More than one ember present, use individual ember name. @@ -287,7 +290,7 @@ void FractoriumEmberController::SaveCurrentAsXml() m_LastSaveCurrent = filename; } else - QMessageBox::critical(m_Fractorium, "Save Failed", "Could not save file, try saving to a different folder."); + m_Fractorium->ShowCritical("Save Failed", "Could not save file, try saving to a different folder."); } } @@ -318,7 +321,7 @@ void FractoriumEmberController::SaveEntireFileAsXml() SaveCurrentToOpenedFile();//Save the current ember back to the opened file before writing to disk. emberFile = m_EmberFile; - for (size_t i = 0; i < emberFile.m_Embers.size(); i++) + for (size_t i = 0; i < emberFile.Size(); i++) ApplyXmlSavingTemplate(emberFile.m_Embers[i]); if (writer.Save(filename.toStdString().c_str(), emberFile.m_Embers, 0, true, false, true)) @@ -327,7 +330,7 @@ void FractoriumEmberController::SaveEntireFileAsXml() s->SaveFolder(fileInfo.canonicalPath()); } else - QMessageBox::critical(m_Fractorium, "Save Failed", "Could not save file, try saving to a different folder."); + m_Fractorium->ShowCritical("Save Failed", "Could not save file, try saving to a different folder."); } } @@ -339,9 +342,9 @@ void Fractorium::OnActionSaveEntireFileAsXml(bool checked) { m_Controller->SaveE /// Ignored void Fractorium::OnActionSaveCurrentScreen(bool checked) { - QString filename = SetupSaveImageDialog(QString::fromStdString(m_Controller->Name())); + QString filename = SetupSaveImageDialog(m_Controller->Name()); - m_Controller->SaveCurrentRender(filename); + m_Controller->SaveCurrentRender(filename, true); } /// @@ -354,9 +357,10 @@ void FractoriumEmberController::SaveCurrentToOpenedFile() size_t i; bool fileFound = false; - for (i = 0; i < m_EmberFile.m_Embers.size(); i++) + for (i = 0; i < m_EmberFile.Size(); i++) { - if (m_Ember.m_Name == m_EmberFile.m_Embers[i].m_Name) + if ((m_Ember.m_Name == m_EmberFile.m_Embers[i].m_Name) &&//Check both to be extra sure. + (m_Ember.m_Index == m_EmberFile.m_Embers[i].m_Index)) { m_EmberFile.m_Embers[i] = m_Ember; fileFound = true; @@ -450,8 +454,6 @@ void FractoriumEmberController::CopyXml() EmberToXml emberToXml; FractoriumSettings* settings = m_Fractorium->m_Settings; - ember.m_FinalRasW = settings->XmlWidth(); - ember.m_FinalRasH = settings->XmlHeight(); ember.m_Quality = settings->XmlQuality(); ember.m_Supersample = settings->XmlSupersample(); ember.m_TemporalSamples = settings->XmlTemporalSamples(); @@ -473,16 +475,11 @@ void FractoriumEmberController::CopyAllXml() os << "\n"; - for (size_t i = 0; i < m_EmberFile.m_Embers.size(); i++) + for (size_t i = 0; i < m_EmberFile.Size(); i++) { Ember ember = m_EmberFile.m_Embers[i]; - ember.m_FinalRasW = settings->XmlWidth(); - ember.m_FinalRasH = settings->XmlHeight(); - ember.m_Quality = settings->XmlQuality(); - ember.m_Supersample = settings->XmlSupersample(); - ember.m_TemporalSamples = settings->XmlTemporalSamples(); - + ApplyXmlSavingTemplate(ember); os << emberToXml.ToString(ember, "", 0, false, false, true); } @@ -502,7 +499,7 @@ void Fractorium::OnActionCopyAllXml(bool checked) { m_Controller->CopyAllXml(); template void FractoriumEmberController::PasteXmlAppend() { - unsigned int i, previousSize = m_EmberFile.m_Embers.size(); + unsigned int i, previousSize = m_EmberFile.Size(); string s, errors; XmlToEmber parser; vector> embers; @@ -524,20 +521,19 @@ void FractoriumEmberController::PasteXmlAppend() if (errors != "") { - QMessageBox::critical(m_Fractorium, "Paste Error", QString::fromStdString(errors)); + m_Fractorium->ShowCritical("Paste Error", QString::fromStdString(errors)); } if (!embers.empty()) { for (i = 0; i < embers.size(); i++) { - //Disregard whatever size was specified in the file and fit it to the output window size. - embers[i].m_Index = m_EmberFile.m_Embers.size(); - embers[i].SetSizeAndAdjustScale(m_Fractorium->ui.GLDisplay->width(), m_Fractorium->ui.GLDisplay->height(), true, SCALE_WIDTH); + embers[i].m_Index = m_EmberFile.Size(); + ConstrainDimensions(embers[i]);//Do not exceed the max texture size. //Also ensure it has a name. if (embers[i].m_Name == "" || embers[i].m_Name == "No name") - embers[i].m_Name = QString::number(embers[i].m_Index).toStdString(); + embers[i].m_Name = ToString(embers[i].m_Index).toStdString(); m_EmberFile.m_Embers.push_back(embers[i]);//Will invalidate the pointers contained in the EmberTreeWidgetItems, UpdateLibraryTree() will resync. } @@ -581,20 +577,19 @@ void FractoriumEmberController::PasteXmlOver() if (errors != "") { - QMessageBox::critical(m_Fractorium, "Paste Error", QString::fromStdString(errors)); + m_Fractorium->ShowCritical("Paste Error", QString::fromStdString(errors)); } - if (!m_EmberFile.m_Embers.empty()) + if (m_EmberFile.Size()) { - for (i = 0; i < m_EmberFile.m_Embers.size(); i++) + for (i = 0; i < m_EmberFile.Size(); i++) { - //Disregard whatever size was specified in the file and fit it to the output window size. m_EmberFile.m_Embers[i].m_Index = i; - m_EmberFile.m_Embers[i].SetSizeAndAdjustScale(m_Fractorium->ui.GLDisplay->width(), m_Fractorium->ui.GLDisplay->height(), true, SCALE_WIDTH); + ConstrainDimensions(m_EmberFile.m_Embers[i]);//Do not exceed the max texture size. //Also ensure it has a name. if (m_EmberFile.m_Embers[i].m_Name == "" || m_EmberFile.m_Embers[i].m_Name == "No name") - m_EmberFile.m_Embers[i].m_Name = QString::number(m_EmberFile.m_Embers[i].m_Index).toStdString(); + m_EmberFile.m_Embers[i].m_Name = ToString(m_EmberFile.m_Embers[i].m_Index).toStdString(); } } else @@ -729,6 +724,7 @@ void Fractorium::OnActionFinalRender(bool checked) { //First completely stop what the current rendering process is doing. m_Controller->DeleteRenderer();//Delete the renderer, but not the controller. + OnActionSaveCurrentToOpenedFile(true);//Save whatever was edited back to the current open file. m_RenderStatusLabel->setText("Renderer stopped."); m_FinalRenderDialog->show(); } diff --git a/Source/Fractorium/FractoriumPalette.cpp b/Source/Fractorium/FractoriumPalette.cpp index 17a92c9..fe70f64 100644 --- a/Source/Fractorium/FractoriumPalette.cpp +++ b/Source/Fractorium/FractoriumPalette.cpp @@ -37,7 +37,7 @@ void Fractorium::InitPaletteUI() /// The full path to the palette file /// True if successful, else false. template -bool FractoriumEmberController::InitPaletteTable(string s) +bool FractoriumEmberController::InitPaletteTable(const string& s) { QTableWidget* paletteTable = m_Fractorium->ui.PaletteListTable; QTableWidget* palettePreviewTable = m_Fractorium->ui.PalettePreviewTable; @@ -93,7 +93,7 @@ bool FractoriumEmberController::InitPaletteTable(string s) vector errors = m_PaletteList.ErrorReport(); m_Fractorium->ErrorReportToQTextEdit(errors, m_Fractorium->ui.InfoFileOpeningTextEdit); - QMessageBox::critical(m_Fractorium, "Palette Read Error", "Could not load palette file, all images will be black. See info tab for details."); + m_Fractorium->ShowCritical("Palette Read Error", "Could not load palette file, all images will be black. See info tab for details."); } return false; diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp index 3361c9d..f56a783 100644 --- a/Source/Fractorium/FractoriumParams.cpp +++ b/Source/Fractorium/FractoriumParams.cpp @@ -45,8 +45,8 @@ void Fractorium::InitParamsUI() //Geometry. row = 0; table = ui.GeometryTable; - SetupSpinner (table, this, row, 1, m_WidthSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int))); - SetupSpinner (table, this, row, 1, m_HeightSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int))); + SetupSpinner (table, this, row, 1, m_WidthSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)), true, width(), width(), width()); + SetupSpinner (table, this, row, 1, m_HeightSpin, spinHeight, 10, 2048, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)), true, height(), height(), height()); SetupSpinner(table, this, row, 1, m_CenterXSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0); SetupSpinner(table, this, row, 1, m_CenterYSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0); SetupSpinner(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240); @@ -57,8 +57,8 @@ void Fractorium::InitParamsUI() SetupSpinner(table, this, row, 1, m_PitchSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(double)), SLOT(OnPitchChanged(double)), true, 0, 45, 0); SetupSpinner(table, this, row, 1, m_YawSpin, spinHeight, -180, 180, 1, SIGNAL(valueChanged(double)), SLOT(OnYawChanged(double)), true, 0, 45, 0); SetupSpinner(table, this, row, 1, m_DepthBlurSpin, spinHeight, -100, 100, 0.01, SIGNAL(valueChanged(double)), SLOT(OnDepthBlurChanged(double)), true, 0, 1, 0); - m_WidthSpin->setEnabled(false);//Will programatically change these to match the window size, but the user should never be allowed to. - m_HeightSpin->setEnabled(false); + + //Set w/h max values. m_CenterXSpin->setDecimals(3); m_CenterYSpin->setDecimals(3); m_ZPosSpin->setDecimals(3); @@ -178,9 +178,9 @@ void FractoriumEmberController::BackgroundChanged(const QColor& color) QTableWidget* colorTable = m_Fractorium->ui.ColorTable; colorTable->item(itemRow, 1)->setBackgroundColor(color); - QString r = QString::number(color.red()); - QString g = QString::number(color.green()); - QString b = QString::number(color.blue()); + QString r = ToString(color.red()); + QString g = ToString(color.green()); + QString b = ToString(color.blue()); int threshold = 105; int delta = (color.red() * 0.299) + //Magic numbers gotten from a Stack Overflow post. @@ -218,14 +218,16 @@ void Fractorium::OnPaletteModeComboCurrentIndexChanged(int index) { m_Controller /// Dimensions are set automatically to match the dimensions of GLWidget. /// /// Ignored -void Fractorium::OnWidthChanged(int d) { } +template void FractoriumEmberController::WidthChanged(unsigned int i) { Update([&] { m_Ember.m_FinalRasW = i; }); } +void Fractorium::OnWidthChanged(int i) { m_Controller->WidthChanged(i); } /// /// Placeholder, do nothing. /// Dimensions are set automatically to match the dimensions of GLWidget. /// /// Ignored -void Fractorium::OnHeightChanged(int d) { } +template void FractoriumEmberController::HeightChanged(unsigned int i) { Update([&] { m_Ember.m_FinalRasH = i; }); } +void Fractorium::OnHeightChanged(int i) { m_Controller->HeightChanged(i); } /// /// Set the x offset applied to the center of the image. diff --git a/Source/Fractorium/FractoriumPch.h b/Source/Fractorium/FractoriumPch.h index df82582..25747b4 100644 --- a/Source/Fractorium/FractoriumPch.h +++ b/Source/Fractorium/FractoriumPch.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include diff --git a/Source/Fractorium/FractoriumRender.cpp b/Source/Fractorium/FractoriumRender.cpp index 2e7d349..ffc147e 100644 --- a/Source/Fractorium/FractoriumRender.cpp +++ b/Source/Fractorium/FractoriumRender.cpp @@ -102,14 +102,14 @@ void FractoriumEmberControllerBase::DeleteRenderer() } /// -/// Save the current contents of the GL window to a file. +/// Save the current render results to a file. /// This could benefit from QImageWriter, however it's compression capabilities are /// severely lacking. A Png file comes out larger than a bitmap, so instead use the /// Png and Jpg wrapper functions from the command line programs. /// This will embed the id, url and nick fields from the options in the image comments. /// /// The full path and filename -void FractoriumEmberControllerBase::SaveCurrentRender(QString filename) +void FractoriumEmberControllerBase::SaveCurrentRender(const QString& filename, bool forcePull) { if (filename != "") { @@ -124,15 +124,22 @@ void FractoriumEmberControllerBase::SaveCurrentRender(QString filename) FractoriumSettings* settings = m_Fractorium->m_Settings; RendererCLBase* rendererCL = dynamic_cast(m_Renderer.get()); - if (rendererCL && m_Renderer->PrepFinalAccumVector(m_FinalImage)) + if (forcePull && rendererCL && m_Renderer->PrepFinalAccumVector(m_FinalImage)) { if (!rendererCL->ReadFinal(m_FinalImage.data())) { - QMessageBox::critical(m_Fractorium, "GPU Read Error", "Could not read image from the GPU, aborting image save."); + m_Fractorium->ShowCritical("GPU Read Error", "Could not read image from the GPU, aborting image save.", true); return; } } + //Ensure dimensions are valid. + if (m_FinalImage.size() < (width * height * m_Renderer->NumChannels() * m_Renderer->BytesPerChannel())) + { + m_Fractorium->ShowCritical("Save Failed", "Dimensions didn't match, not saving.", true); + return; + } + data = m_FinalImage.data();//Png and channels = 4. if ((suffix == "jpg" || suffix == "bmp") && m_Renderer->NumChannels() == 4) @@ -146,7 +153,7 @@ void FractoriumEmberControllerBase::SaveCurrentRender(QString filename) string id = settings->Id().toStdString(); string url = settings->Url().toStdString(); string nick = settings->Nick().toStdString(); - EmberImageComments comments = m_Renderer->ImageComments(0, false, true); + EmberImageComments comments = m_Renderer->ImageComments(m_Stats, 0, false, true); if (suffix == "png") b = WritePng(s.c_str(), data, width, height, 1, true, comments, id, url, nick); @@ -155,12 +162,15 @@ void FractoriumEmberControllerBase::SaveCurrentRender(QString filename) else if (suffix == "bmp") b = WriteBmp(s.c_str(), data, width, height); else - QMessageBox::critical(m_Fractorium, "Save Failed", "Unrecognized format " + suffix + ", not saving."); + { + m_Fractorium->ShowCritical("Save Failed", "Unrecognized format " + suffix + ", not saving.", true); + return; + } if (b) settings->SaveFolder(fileInfo.canonicalPath()); else - QMessageBox::critical(m_Fractorium, "Save Failed", "Could not save file, try saving to a different folder."); + m_Fractorium->ShowCritical("Save Failed", "Could not save file, try saving to a different folder.", true); } } @@ -241,27 +251,56 @@ void FractoriumEmberController::ClearUndo() m_Fractorium->ui.ActionRedo->setEnabled(false); } +/// +/// The hierarchy/order of sizes is like so: +/// Ember +/// GL Widget +/// Texture (passed to RendererCL) +/// Viewport +/// Since this uses m_GL->SizesMatch(), which uses the renderer's dimensions, this +/// must be called after the renderer has set the current ember. +/// +/// True if dimensions had to be resized due to a mismatch, else false. +template +bool FractoriumEmberController::SyncSizes() +{ + bool changed = false; + GLWidget* gl = m_Fractorium->ui.GLDisplay; + RendererCL* rendererCL; + + if (!m_GLController->SizesMatch()) + { + m_GLController->ClearWindow(); + gl->SetDimensions(m_Ember.m_FinalRasW, m_Ember.m_FinalRasH); + gl->Allocate(); + gl->SetViewport(); + + if (m_Renderer->RendererType() == OPENCL_RENDERER && (rendererCL = (RendererCL*)m_Renderer.get())) + rendererCL->SetOutputTexture(gl->OutputTexID()); + + changed = true; + } + + return changed; +} + /// /// The main rendering function. /// Called whenever the event loop is idle. /// +/// True if nothing went wrong, else false. template bool FractoriumEmberController::Render() { - bool success = true; - m_Rendering = true; + + bool success = true; GLWidget* gl = m_Fractorium->ui.GLDisplay; + RendererCL* rendererCL; eProcessAction action = CondenseAndClearProcessActions(); - //Set dimensions first. - if ((m_Ember.m_FinalRasW != gl->width() || - m_Ember.m_FinalRasH != gl->height())) - { - m_Ember.SetSizeAndAdjustScale(gl->width(), gl->height(), false, SCALE_WIDTH); - m_Fractorium->m_ScaleSpin->SetValueStealth(m_Ember.m_PixelsPerUnit); - action = FULL_RENDER; - } + if (m_Renderer->RendererType() == OPENCL_RENDERER) + rendererCL = (RendererCL*)m_Renderer.get(); //Force temporal samples to always be 1. Perhaps change later when animation is implemented. m_Ember.m_TemporalSamples = 1; @@ -293,6 +332,13 @@ bool FractoriumEmberController::Render() } } + //Ensure sizes are equal and if not, update dimensions. + if (SyncSizes()) + { + action = FULL_RENDER; + return true; + } + //Determining if a completely new rendering process is being started. bool iterBegin = ProcessState() == NONE; @@ -332,11 +378,11 @@ bool FractoriumEmberController::Render() if (ProcessState() == ACCUM_DONE) { EmberStats stats = m_Renderer->Stats(); + QString iters = ToString(stats.m_Iters); + QString scaledQuality = ToString((unsigned int)m_Renderer->ScaledQuality()); + string renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc()); m_Fractorium->m_ProgressBar->setValue(100); - QString iters = QLocale(QLocale::English).toString(stats.m_Iters); - QString scaledQuality = QString::number((unsigned int)m_Renderer->ScaledQuality()); - string renderTime = m_RenderElapsedTimer.Format(m_RenderElapsedTimer.Toc()); //Only certain status can be reported with OpenCL. if (m_Renderer->RendererType() == OPENCL_RENDERER) @@ -346,8 +392,8 @@ bool FractoriumEmberController::Render() else { double percent = (double)stats.m_Badvals / (double)stats.m_Iters; - QString badVals = QLocale(QLocale::English).toString(stats.m_Badvals); - QString badPercent = QLocale(QLocale::English).toString(percent * 100, 'f', 2); + 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)); } @@ -385,7 +431,7 @@ bool FractoriumEmberController::Render() //Uncomment for debugging kernel build and execution errors. //m_Fractorium->ui.InfoRenderingTextEdit->setText(QString::fromStdString(m_Fractorium->m_Wrapper.DumpInfo())); - //if (RendererCL* rendererCL = dynamic_cast*>(m_Renderer.get())) + //if (rendererCL) // m_Fractorium->ui.InfoRenderingTextEdit->setText(QString::fromStdString(rendererCL->IterKernel())); } } @@ -404,11 +450,10 @@ bool FractoriumEmberController::Render() m_Rendering = false; StopRenderTimer(true); m_Fractorium->m_RenderStatusLabel->setText("Rendering failed 3 or more times, stopping all rendering, see info tab. Try changing renderer types."); - - memset(m_FinalImage.data(), 0, m_FinalImage.size()); + Memset(m_FinalImage); - if (m_Renderer->RendererType() == OPENCL_RENDERER) - ((RendererCL*)m_Renderer.get())->ClearFinal(); + if (rendererCL) + rendererCL->ClearFinal(); m_GLController->ClearWindow(); } @@ -461,7 +506,7 @@ bool FractoriumEmberController::CreateRenderer(eRendererType renderType, unsi else { ok = false; - QMessageBox::critical(m_Fractorium, "Renderer Creation Error", "Could not create requested renderer, fallback CPU renderer created. See info tab for details."); + m_Fractorium->ShowCritical("Renderer Creation Error", "Could not create requested renderer, fallback CPU renderer created. See info tab for details."); m_Fractorium->ErrorReportToQTextEdit(errorReport, m_Fractorium->ui.InfoRenderingTextEdit); } } @@ -503,7 +548,7 @@ bool FractoriumEmberController::CreateRenderer(eRendererType renderType, unsi else { ok = false; - QMessageBox::critical(m_Fractorium, "Renderer Creation Error", "Creating a basic CPU renderer failed, something is catastrophically wrong. Exiting program."); + m_Fractorium->ShowCritical("Renderer Creation Error", "Creating a basic CPU renderer failed, something is catastrophically wrong. Exiting program."); QApplication::quit(); } @@ -525,7 +570,7 @@ bool Fractorium::CreateRendererFromOptions() m_Settings->DeviceIndex())) { //If using OpenCL, will only get here if creating RendererCL failed, but creating a backup CPU Renderer succeeded. - QMessageBox::critical(this, "Renderer Creation Error", "Error creating renderer, most likely a GPU problem. Using CPU instead."); + ShowCritical("Renderer Creation Error", "Error creating renderer, most likely a GPU problem. Using CPU instead."); m_Settings->OpenCL(false); m_OptionsDialog->ui.OpenCLCheckBox->setChecked(false); m_FinalRenderDialog->ui.FinalRenderOpenCLCheckBox->setChecked(false); diff --git a/Source/Fractorium/FractoriumSettings.cpp b/Source/Fractorium/FractoriumSettings.cpp index 4cb8a94..672ff5b 100644 --- a/Source/Fractorium/FractoriumSettings.cpp +++ b/Source/Fractorium/FractoriumSettings.cpp @@ -17,12 +17,6 @@ FractoriumSettings::FractoriumSettings(QObject* parent) /// void FractoriumSettings::EnsureDefaults() { - if (FinalWidth() == 0) - FinalWidth(1920); - - if (FinalHeight() == 0) - FinalHeight(1080); - if (FinalQuality() == 0) FinalQuality(1000); @@ -32,11 +26,8 @@ void FractoriumSettings::EnsureDefaults() if (FinalSupersample() == 0) FinalSupersample(2); - if (XmlWidth() == 0) - XmlWidth(1920); - - if (XmlHeight() == 0) - XmlHeight(1080); + if (FinalStrips() == 0) + FinalStrips(1); if (XmlTemporalSamples() == 0) XmlTemporalSamples(1000); @@ -89,8 +80,19 @@ void FractoriumSettings::EnsureDefaults() if (SaveImageExt() == "") SaveImageExt("Png (*.png)"); - if (FinalDoAllExt() != "jpg" && FinalDoAllExt() != "png") - FinalDoAllExt("png"); + if (FinalExt() != "jpg" && FinalExt() != "png") + FinalExt("png"); + + QString s = SaveFolder(); + QDir dir(s); + + if (s.isEmpty() || !dir.exists()) + { + QStringList paths = QStandardPaths::standardLocations(QStandardPaths::DesktopLocation); + + if (!paths.empty()) + SaveFolder(paths[0]); + } } /// @@ -170,8 +172,8 @@ void FractoriumSettings::FinalKeepAspect(bool b) { setValue(FINALKEEPASPECT, unsigned int FractoriumSettings::FinalScale() { return value(FINALSCALE).toUInt(); } void FractoriumSettings::FinalScale(unsigned int i) { setValue(FINALSCALE, i); } -QString FractoriumSettings::FinalDoAllExt() { return value(FINALDOALLEXT).toString(); } -void FractoriumSettings::FinalDoAllExt(QString s) { setValue(FINALDOALLEXT, s); } +QString FractoriumSettings::FinalExt() { return value(FINALEXT).toString(); } +void FractoriumSettings::FinalExt(const QString& s) { setValue(FINALEXT, s); } unsigned int FractoriumSettings::FinalPlatformIndex() { return value(FINALPLATFORMINDEX).toUInt(); } void FractoriumSettings::FinalPlatformIndex(unsigned int i) { setValue(FINALPLATFORMINDEX, i); } @@ -182,12 +184,6 @@ void FractoriumSettings::FinalDeviceIndex(unsigned int i) { setValue(FINALDE unsigned int FractoriumSettings::FinalThreadCount() { return value(FINALTHREADCOUNT).toUInt(); } void FractoriumSettings::FinalThreadCount(unsigned int i) { setValue(FINALTHREADCOUNT, i); } -unsigned int FractoriumSettings::FinalWidth() { return value(FINALWIDTH).toUInt(); } -void FractoriumSettings::FinalWidth(unsigned int i) { setValue(FINALWIDTH, i); } - -unsigned int FractoriumSettings::FinalHeight() { return value(FINALHEIGHT).toUInt(); } -void FractoriumSettings::FinalHeight(unsigned int i) { setValue(FINALHEIGHT, i); } - unsigned int FractoriumSettings::FinalQuality() { return value(FINALQUALITY).toUInt(); } void FractoriumSettings::FinalQuality(unsigned int i) { setValue(FINALQUALITY, i); } @@ -197,15 +193,12 @@ void FractoriumSettings::FinalTemporalSamples(unsigned int i) { setValue(FINALTE unsigned int FractoriumSettings::FinalSupersample() { return value(FINALSUPERSAMPLE).toUInt(); } void FractoriumSettings::FinalSupersample(unsigned int i) { setValue(FINALSUPERSAMPLE, i); } +unsigned int FractoriumSettings::FinalStrips() { return value(FINALSTRIPS).toUInt(); } +void FractoriumSettings::FinalStrips(unsigned int i) { setValue(FINALSTRIPS, i); } + /// /// Xml file saving settings. /// - -unsigned int FractoriumSettings::XmlWidth() { return value(XMLWIDTH).toUInt(); } -void FractoriumSettings::XmlWidth(unsigned int i) { setValue(XMLWIDTH, i); } - -unsigned int FractoriumSettings::XmlHeight() { return value(XMLHEIGHT).toUInt(); } -void FractoriumSettings::XmlHeight(unsigned int i) { setValue(XMLHEIGHT, i); } unsigned int FractoriumSettings::XmlTemporalSamples() { return value(XMLTEMPORALSAMPLES).toUInt(); } void FractoriumSettings::XmlTemporalSamples(unsigned int i) { setValue(XMLTEMPORALSAMPLES, i); } @@ -217,32 +210,32 @@ unsigned int FractoriumSettings::XmlSupersample() { return value(XML void FractoriumSettings::XmlSupersample(unsigned int i) { setValue(XMLSUPERSAMPLE, i); } QString FractoriumSettings::Id() { return value(IDENTITYID).toString(); } -void FractoriumSettings::Id(QString s) { setValue(IDENTITYID, s); } +void FractoriumSettings::Id(const QString& s) { setValue(IDENTITYID, s); } QString FractoriumSettings::Url() { return value(IDENTITYURL).toString(); } -void FractoriumSettings::Url(QString s) { setValue(IDENTITYURL, s); } +void FractoriumSettings::Url(const QString& s) { setValue(IDENTITYURL, s); } QString FractoriumSettings::Nick() { return value(IDENTITYNICK).toString(); } -void FractoriumSettings::Nick(QString s) { setValue(IDENTITYNICK, s); } +void FractoriumSettings::Nick(const QString& s) { setValue(IDENTITYNICK, s); } /// /// General operations settings. /// QString FractoriumSettings::OpenFolder() { return value(OPENFOLDER).toString(); } -void FractoriumSettings::OpenFolder(QString s) { setValue(OPENFOLDER, s); } +void FractoriumSettings::OpenFolder(const QString& s) { setValue(OPENFOLDER, s); } QString FractoriumSettings::SaveFolder() { return value(SAVEFOLDER).toString(); } -void FractoriumSettings::SaveFolder(QString s) { setValue(SAVEFOLDER, s); } +void FractoriumSettings::SaveFolder(const QString& s) { setValue(SAVEFOLDER, s); } QString FractoriumSettings::OpenXmlExt() { return value(OPENXMLEXT).toString(); } -void FractoriumSettings::OpenXmlExt(QString s) { setValue(OPENXMLEXT, s); } +void FractoriumSettings::OpenXmlExt(const QString& s) { setValue(OPENXMLEXT, s); } QString FractoriumSettings::SaveXmlExt() { return value(SAVEXMLEXT).toString(); } -void FractoriumSettings::SaveXmlExt(QString s) { setValue(SAVEXMLEXT, s); } +void FractoriumSettings::SaveXmlExt(const QString& s) { setValue(SAVEXMLEXT, s); } QString FractoriumSettings::OpenImageExt() { return value(OPENIMAGEEXT).toString(); } -void FractoriumSettings::OpenImageExt(QString s) { setValue(OPENIMAGEEXT, s); } +void FractoriumSettings::OpenImageExt(const QString& s) { setValue(OPENIMAGEEXT, s); } QString FractoriumSettings::SaveImageExt() { return value(SAVEIMAGEEXT).toString(); } -void FractoriumSettings::SaveImageExt(QString s) { setValue(SAVEIMAGEEXT, s); } +void FractoriumSettings::SaveImageExt(const QString& s) { setValue(SAVEIMAGEEXT, s); } diff --git a/Source/Fractorium/FractoriumSettings.h b/Source/Fractorium/FractoriumSettings.h index cb7dfa5..2564fef 100644 --- a/Source/Fractorium/FractoriumSettings.h +++ b/Source/Fractorium/FractoriumSettings.h @@ -30,15 +30,14 @@ #define FINALDOSEQUENCE "finalrender/dosequence" #define FINALKEEPASPECT "finalrender/keepaspect" #define FINALSCALE "finalrender/scale" -#define FINALDOALLEXT "finalrender/doallext" +#define FINALEXT "finalrender/ext" #define FINALPLATFORMINDEX "finalrender/platformindex" #define FINALDEVICEINDEX "finalrender/deviceindex" #define FINALTHREADCOUNT "finalrender/threadcount" -#define FINALWIDTH "finalrender/width" -#define FINALHEIGHT "finalrender/height" #define FINALQUALITY "finalrender/quality" #define FINALTEMPORALSAMPLES "finalrender/temporalsamples" #define FINALSUPERSAMPLE "finalrender/supersample" +#define FINALSTRIPS "finalrender/strips" #define XMLWIDTH "xml/width" #define XMLHEIGHT "xml/height" @@ -139,8 +138,8 @@ public: unsigned int FinalScale(); void FinalScale(unsigned int i); - QString FinalDoAllExt(); - void FinalDoAllExt(QString s); + QString FinalExt(); + void FinalExt(const QString& s); unsigned int FinalPlatformIndex(); void FinalPlatformIndex(unsigned int b); @@ -151,12 +150,6 @@ public: unsigned int FinalThreadCount(); void FinalThreadCount(unsigned int b); - unsigned int FinalWidth(); - void FinalWidth(unsigned int i); - - unsigned int FinalHeight(); - void FinalHeight(unsigned int i); - unsigned int FinalQuality(); void FinalQuality(unsigned int i); @@ -166,11 +159,8 @@ public: unsigned int FinalSupersample(); void FinalSupersample(unsigned int i); - unsigned int XmlWidth(); - void XmlWidth(unsigned int i); - - unsigned int XmlHeight(); - void XmlHeight(unsigned int i); + unsigned int FinalStrips(); + void FinalStrips(unsigned int i); unsigned int XmlTemporalSamples(); void XmlTemporalSamples(unsigned int i); @@ -182,29 +172,29 @@ public: void XmlSupersample(unsigned int i); QString OpenFolder(); - void OpenFolder(QString s); + void OpenFolder(const QString& s); QString SaveFolder(); - void SaveFolder(QString s); + void SaveFolder(const QString& s); QString OpenXmlExt(); - void OpenXmlExt(QString s); + void OpenXmlExt(const QString& s); QString SaveXmlExt(); - void SaveXmlExt(QString s); + void SaveXmlExt(const QString& s); QString OpenImageExt(); - void OpenImageExt(QString s); + void OpenImageExt(const QString& s); QString SaveImageExt(); - void SaveImageExt(QString s); + void SaveImageExt(const QString& s); QString Id(); - void Id(QString s); + void Id(const QString& s); QString Url(); - void Url(QString s); + void Url(const QString& s); QString Nick(); - void Nick(QString s); + void Nick(const QString& s); }; diff --git a/Source/Fractorium/FractoriumXforms.cpp b/Source/Fractorium/FractoriumXforms.cpp index 9419d8e..5c43ec6 100644 --- a/Source/Fractorium/FractoriumXforms.cpp +++ b/Source/Fractorium/FractoriumXforms.cpp @@ -334,7 +334,7 @@ void Fractorium::FillXforms() for (i = 0; i < m_Controller->XformCount(); i++) { - combo->addItem(QString::number(i + 1)); + combo->addItem(ToString(i + 1)); combo->setItemIcon(i, m_XformComboIcons[i % XFORM_COLOR_COUNT]); } diff --git a/Source/Fractorium/FractoriumXformsAffine.cpp b/Source/Fractorium/FractoriumXformsAffine.cpp index 75172c4..4403960 100644 --- a/Source/Fractorium/FractoriumXformsAffine.cpp +++ b/Source/Fractorium/FractoriumXformsAffine.cpp @@ -213,7 +213,7 @@ void Fractorium::OnRotateCButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreRotateCButton; QComboBox* combo = pre ? ui.PreRotateCombo : ui.PostRotateCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->RotateCurrentXformByAngle(d, pre); @@ -230,7 +230,7 @@ void Fractorium::OnRotateCcButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreRotateCcButton; QComboBox* combo = pre ? ui.PreRotateCombo : ui.PostRotateCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->RotateCurrentXformByAngle(-d, pre); @@ -267,7 +267,7 @@ void Fractorium::OnMoveUpButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreMoveUpButton; QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->MoveCurrentXform(0, d, pre); @@ -284,7 +284,7 @@ void Fractorium::OnMoveDownButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreMoveDownButton; QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->MoveCurrentXform(0, -d, pre); @@ -301,7 +301,7 @@ void Fractorium::OnMoveLeftButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreMoveLeftButton; QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->MoveCurrentXform(-d, 0, pre); @@ -318,7 +318,7 @@ void Fractorium::OnMoveRightButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreMoveRightButton; QComboBox* combo = pre ? ui.PreMoveCombo : ui.PostMoveCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->MoveCurrentXform(d, 0, pre); @@ -356,7 +356,7 @@ void Fractorium::OnScaleDownButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreScaleDownButton; QComboBox* combo = pre ? ui.PreScaleCombo : ui.PostScaleCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->ScaleCurrentXform(1.0 / (d / 100.0), pre); @@ -373,7 +373,7 @@ void Fractorium::OnScaleUpButtonClicked(bool checked) bool ok; bool pre = sender() == ui.PreScaleUpButton; QComboBox* combo = pre ? ui.PreScaleCombo : ui.PostScaleCombo; - double d = combo->currentText().toDouble(&ok); + double d = ToDouble(combo->currentText(), &ok); if (ok) m_Controller->ScaleCurrentXform(d / 100.0, pre); diff --git a/Source/Fractorium/FractoriumXformsColor.cpp b/Source/Fractorium/FractoriumXformsColor.cpp index 5c23b88..32cfcfd 100644 --- a/Source/Fractorium/FractoriumXformsColor.cpp +++ b/Source/Fractorium/FractoriumXformsColor.cpp @@ -121,7 +121,7 @@ void Fractorium::OnSoloXformCheckBoxStateChanged(int state) if (state == Qt::Checked) { ui.CurrentXformCombo->setProperty("soloxform", ui.CurrentXformCombo->currentIndex()); - ui.SoloXformCheckBox->setText("Solo (" + QString::number(ui.CurrentXformCombo->currentIndex() + 1) + ")"); + ui.SoloXformCheckBox->setText("Solo (" + ToString(ui.CurrentXformCombo->currentIndex() + 1) + ")"); } else if (state == Qt::Unchecked) { diff --git a/Source/Fractorium/FractoriumXformsXaos.cpp b/Source/Fractorium/FractoriumXformsXaos.cpp index 2b16402..cf36cd9 100644 --- a/Source/Fractorium/FractoriumXformsXaos.cpp +++ b/Source/Fractorium/FractoriumXformsXaos.cpp @@ -62,9 +62,9 @@ QString FractoriumEmberController::MakeXaosNameString(unsigned int i) if (i != -1) { if (m_Fractorium->ui.XaosToRadio->isChecked()) - name = QString("From ") + QString::number(curr) + QString(" To ") + QString::number(i); + name = QString("From ") + ToString(curr) + QString(" To ") + ToString(i); else - name = QString("From ") + QString::number(i) + QString(" To ") + QString::number(curr); + name = QString("From ") + ToString(i) + QString(" To ") + ToString(curr); //if (xform->m_Name != "") // name = name + " (" + QString::fromStdString(xform->m_Name) + ")"; diff --git a/Source/Fractorium/GLEmberController.h b/Source/Fractorium/GLEmberController.h index beb7ac1..4e18c61 100644 --- a/Source/Fractorium/GLEmberController.h +++ b/Source/Fractorium/GLEmberController.h @@ -60,7 +60,7 @@ public: virtual void MouseRelease(QMouseEvent* e) { } virtual void MouseMove(QMouseEvent* e) { } virtual void Wheel(QWheelEvent* e) { } - virtual bool SyncSizes() { return false; } + virtual bool SizesMatch() { return false; } virtual bool CheckForSizeMismatch(int w, int h) { return true; } virtual void QueryMatrices(bool print) { } @@ -86,16 +86,16 @@ class GLEmberController : public GLEmberControllerBase public: GLEmberController(Fractorium* fractorium, GLWidget* glWidget, FractoriumEmberController* controller); virtual ~GLEmberController(); - virtual void DrawImage(); - virtual void DrawAffines(bool pre, bool post); - virtual void ClearWindow(); - virtual void MousePress(QMouseEvent* e); - virtual void MouseRelease(QMouseEvent* e); - virtual void MouseMove(QMouseEvent* e); - virtual void Wheel(QWheelEvent* e); - virtual void QueryMatrices(bool print); - virtual bool SyncSizes(); - virtual bool CheckForSizeMismatch(int w, int h); + virtual void DrawImage() override; + virtual void DrawAffines(bool pre, bool post) override; + virtual void ClearWindow() override; + virtual void MousePress(QMouseEvent* e) override; + virtual void MouseRelease(QMouseEvent* e) override; + virtual void MouseMove(QMouseEvent* e) override; + virtual void Wheel(QWheelEvent* e) override; + virtual void QueryMatrices(bool print) override; + virtual bool SizesMatch() override; + virtual bool CheckForSizeMismatch(int w, int h) override; T CalcScale(); T CalcRotation(); diff --git a/Source/Fractorium/GLWidget.cpp b/Source/Fractorium/GLWidget.cpp index c71b005..cc36078 100644 --- a/Source/Fractorium/GLWidget.cpp +++ b/Source/Fractorium/GLWidget.cpp @@ -120,6 +120,7 @@ void GLEmberController::ClearWindow() m_GL->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_GL->glClearColor(ember->m_Background.r, ember->m_Background.g, ember->m_Background.b, 1.0); + m_GL->makeCurrent(); m_GL->swapBuffers(); m_GL->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -159,10 +160,13 @@ void GLWidget::SetMainWindow(Fractorium* f) { m_Fractorium = f; } bool GLWidget::Init() { return m_Init; } bool GLWidget::Drawing() { return m_Drawing; } +GLint GLWidget::MaxTexSize() { return m_MaxTexSize; } GLuint GLWidget::OutputTexID() { return m_OutputTexID; } /// /// Initialize OpenGL, called once at startup after the main window constructor finishes. +/// Although it seems an awkward place to put some of this setup code, the dimensions of the +/// main window and its widgets are not fully initialized before this is called. /// Once this is done, the render timer is started after a short delay. /// Rendering is then clear to begin. /// @@ -172,6 +176,20 @@ void GLWidget::initializeGL() { glClearColor(0.0, 0.0, 0.0, 1.0); + int w = m_Fractorium->ui.GLParentScrollArea->width(); + int h = m_Fractorium->ui.GLParentScrollArea->height(); + + SetDimensions(w, h); + m_Fractorium->m_WidthSpin->setValue(w); + m_Fractorium->m_HeightSpin->setValue(h); + + glEnable(GL_TEXTURE_2D); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_MaxTexSize); + glDisable(GL_TEXTURE_2D); + + m_Fractorium->m_WidthSpin->setMaximum(m_MaxTexSize); + m_Fractorium->m_HeightSpin->setMaximum(m_MaxTexSize); + //Start with a flock of 10 random embers. Can't do this until now because the window wasn't maximized yet, so the sizes would have been off. m_Fractorium->OnActionNewFlock(false); m_Fractorium->m_Controller->DelayedStartRenderTimer(); @@ -193,9 +211,7 @@ void GLWidget::paintGL() RendererBase* renderer = controller->Renderer(); m_Drawing = true; - //renderer->EnterResize(); controller->GLController()->DrawImage(); - //renderer->LeaveResize();//Unlock, may not be necessary. //Affine drawing. bool pre = m_Fractorium->ui.PreAffineGroupBox->isChecked(); @@ -244,23 +260,23 @@ void GLEmberController::DrawImage() { RendererBase* renderer = m_FractoriumEmberController->Renderer(); Ember* ember = m_FractoriumEmberController->CurrentEmber(); - + m_GL->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); m_GL->glClearColor(ember->m_Background.r, ember->m_Background.g, ember->m_Background.b, 1.0); m_GL->glDisable(GL_DEPTH_TEST); - + renderer->EnterFinalAccum();//Lock, may not be necessary, but just in case. renderer->EnterResize(); - if (SyncSizes())//Ensure all sizes are correct. If not, do nothing. + if (SizesMatch())//Ensure all sizes are correct. If not, do nothing. { vector* finalImage = m_FractoriumEmberController->FinalImage(); - + if (renderer->RendererType() == OPENCL_RENDERER || finalImage)//Final image only matters for CPU renderer. if (renderer->RendererType() == OPENCL_RENDERER || finalImage->size() == renderer->FinalBufferSize()) m_GL->DrawQuad();//Output image is drawn here. } - + renderer->LeaveResize();//Unlock, may not be necessary. renderer->LeaveFinalAccum(); } @@ -575,7 +591,7 @@ void GLEmberController::MouseMove(QMouseEvent* e) glm::ivec2 mouse(e->x(), e->y()); v3T mouseFlipped(e->x(), m_Viewport[3] - e->y(), 0);//Must flip y because in OpenGL, 0,0 is bottom left, but in windows, it's top left. Ember* ember = m_FractoriumEmberController->CurrentEmber(); - + //First check to see if the mouse actually moved. if (mouse == m_MousePos) return; @@ -650,7 +666,7 @@ void GLEmberController::MouseMove(QMouseEvent* e) //if (m_HoverXform == previousHover) // draw = false; } - + //Only update if the user was dragging or hovered over a point. //Use repaint() to update immediately for a more responsive feel. if ((m_DragState != DragNone) || draw) @@ -665,10 +681,10 @@ void GLEmberController::MouseMove(QMouseEvent* e) void GLWidget::mouseMoveEvent(QMouseEvent* e) { setFocus();//Must do this so that this window gets keyboard events. - + if (GLEmberControllerBase* controller = GLController()) controller->MouseMove(e); - + QGLWidget::mouseMoveEvent(e); } @@ -711,12 +727,21 @@ void GLWidget::resizeEvent(QResizeEvent* e) { if (m_Fractorium) { - m_Fractorium->m_WidthSpin->setValue(width()); - m_Fractorium->m_HeightSpin->setValue(height()); + //qDebug() << "GLWidget::resizeEvent() : w, h: " << width() << ", " << height() << ". oldsize: " << e->oldSize().width() << ", " << e->oldSize().height(); + //m_Fractorium->m_WidthSpin->setValue(width()); + //m_Fractorium->m_HeightSpin->setValue(height()); - if (GLEmberControllerBase* controller = GLController()) - controller->SyncSizes();//For some reason the base resize can't be called here or else it causes a crash. + // if (GLEmberControllerBase* controller = GLController()) + // controller->SyncSizes();//For some reason the base resize can't be called here or else it causes a crash. } + + //QGLWidget::resizeEvent(e); +} + +void GLWidget::SetDimensions(int w, int h) +{ + setFixedSize(w, h); + m_Fractorium->ui.GLParentScrollAreaContents->setFixedSize(w, h); } /// @@ -729,13 +754,22 @@ void GLWidget::resizeEvent(QResizeEvent* e) bool GLWidget::Allocate(bool force) { bool alloc = false; + bool resize = force || m_TexWidth != width() || m_TexHeight != height(); + bool doIt = resize || m_OutputTexID == 0; - if (m_OutputTexID == 0) + if (doIt) { m_TexWidth = width(); m_TexHeight = height(); glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + if (resize) + { + glBindTexture(GL_TEXTURE_2D, m_OutputTexID); + Deallocate(); + } + glGenTextures(1, &m_OutputTexID); glBindTexture(GL_TEXTURE_2D, m_OutputTexID); @@ -746,28 +780,7 @@ bool GLWidget::Allocate(bool force) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); alloc = true; } - else - { - if (force || (m_TexWidth != width() || m_TexHeight != height())) - { - m_TexWidth = width(); - m_TexHeight = height(); - glEnable(GL_TEXTURE_2D); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glBindTexture(GL_TEXTURE_2D, m_OutputTexID); - Deallocate(); - glGenTextures(1, &m_OutputTexID); - glBindTexture(GL_TEXTURE_2D, m_OutputTexID); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//Fractron had this as GL_LINEAR_MIPMAP_LINEAR for OpenCL and Cuda. - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TexWidth, m_TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - alloc = true; - } - } - + if (alloc) { glBindTexture(GL_TEXTURE_2D, 0); @@ -801,45 +814,33 @@ bool GLWidget::Deallocate() /// void GLWidget::SetViewport() { - if (m_Init && (m_ViewWidth != width() || m_ViewHeight != height())) + if (m_Init && (m_ViewWidth != m_TexWidth || m_ViewHeight != m_TexHeight)) { - glViewport(0, 0, (GLint)width(), (GLint)height()); - m_ViewWidth = width(); - m_ViewHeight = height(); + glViewport(0, 0, (GLint)m_TexWidth, (GLint)m_TexHeight); + m_ViewWidth = m_TexWidth; + m_ViewHeight = m_TexHeight; } } /// -/// Synchronize the size of the renderer output image, the texture, and this window. -/// They must all match. If the renderer output size doesn't match, then the render -/// timer is stopped and restarted with a delay. -/// This will get called once or twice when a resize occurs. +/// Determine whether the dimensions of the renderer's current ember match +/// the dimensions of the widget, texture and viewport. +/// Since this uses the renderer's dimensions, this +/// must be called after the renderer has set the current ember. /// /// True if all sizes match, else false. template -bool GLEmberController::SyncSizes() +bool GLEmberController::SizesMatch() { - if (m_GL->Init()) - { - m_GL->SetViewport(); + Ember* ember = m_FractoriumEmberController->CurrentEmber(); - //First make sure the dimensions of the ember match the window size. - if (CheckForSizeMismatch(m_GL->width(), m_GL->height())) - { - if (m_Fractorium)//This will stop the rendering process and start the reset timer. - m_Fractorium->Resize(); - - return false; - } - - //The renderer and window dimensions match, now make sure the dims of the texture match. - if (!m_GL->Allocate()) - return false; - - return true; - } - - return false; + return (ember && + ember->m_FinalRasW == m_GL->width() && + ember->m_FinalRasH == m_GL->height() && + m_GL->width() == m_GL->m_TexWidth && + m_GL->height() == m_GL->m_TexHeight && + m_GL->m_TexWidth == m_GL->m_ViewWidth && + m_GL->m_TexHeight == m_GL->m_ViewHeight); } /// diff --git a/Source/Fractorium/GLWidget.h b/Source/Fractorium/GLWidget.h index 182bb2a..ee63a08 100644 --- a/Source/Fractorium/GLWidget.h +++ b/Source/Fractorium/GLWidget.h @@ -43,20 +43,22 @@ public: void SetMainWindow(Fractorium* f); bool Init(); bool Drawing(); + GLint MaxTexSize(); GLuint OutputTexID(); protected: - virtual void initializeGL(); - virtual void paintGL(); - virtual void keyPressEvent(QKeyEvent* e); - virtual void keyReleaseEvent(QKeyEvent* e); - virtual void mousePressEvent(QMouseEvent* e); - virtual void mouseReleaseEvent(QMouseEvent* e); - virtual void mouseMoveEvent(QMouseEvent* e); - virtual void wheelEvent(QWheelEvent* e); - virtual void resizeEvent(QResizeEvent* e); + virtual void initializeGL() override; + virtual void paintGL() override; + virtual void keyPressEvent(QKeyEvent* e) override; + virtual void keyReleaseEvent(QKeyEvent* e) override; + virtual void mousePressEvent(QMouseEvent* e) override; + virtual void mouseReleaseEvent(QMouseEvent* e) override; + virtual void mouseMoveEvent(QMouseEvent* e) override; + virtual void wheelEvent(QWheelEvent* e) override; + virtual void resizeEvent(QResizeEvent* e) override; private: + void SetDimensions(int w, int h); bool Allocate(bool force = false); bool Deallocate(); void SetViewport(); @@ -67,6 +69,7 @@ private: bool m_Init; bool m_Drawing; + GLint m_MaxTexSize; GLint m_TexWidth; GLint m_TexHeight; GLint m_ViewWidth; diff --git a/Source/Fractorium/OptionsDialog.cpp b/Source/Fractorium/OptionsDialog.cpp index 976fbf2..fcd011a 100644 --- a/Source/Fractorium/OptionsDialog.cpp +++ b/Source/Fractorium/OptionsDialog.cpp @@ -21,11 +21,9 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(FractoriumSettings* settings, Q connect(ui.OpenCLCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnOpenCLCheckBoxStateChanged(int)), Qt::QueuedConnection); connect(ui.PlatformCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnPlatformComboCurrentIndexChanged(int)), Qt::QueuedConnection); - SetupSpinner(table, this, row, 1, m_XmlWidthSpin, spinHeight, 10, 100000, 50, "", "", true, 1920); - SetupSpinner(table, this, row, 1, m_XmlHeightSpin, spinHeight, 10, 100000, 50, "", "", true, 1080); - 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); - SetupSpinner(table, this, row, 1, m_XmlSupersampleSpin, spinHeight, 1, 4, 1, "", "", true, 2); + 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); + SetupSpinner(table, this, row, 1, m_XmlSupersampleSpin, spinHeight, 1, 4, 1, "", "", true, 2); m_IdEdit = new QLineEdit(ui.OptionsIdentityTable); ui.OptionsIdentityTable->setCellWidget(0, 1, m_IdEdit); @@ -91,8 +89,6 @@ FractoriumOptionsDialog::FractoriumOptionsDialog(FractoriumSettings* settings, Q ui.CpuSubBatchSpin->setValue(m_Settings->CpuSubBatch()); ui.OpenCLSubBatchSpin->setValue(m_Settings->OpenCLSubBatch()); - m_XmlWidthSpin->setValue(m_Settings->XmlWidth()); - m_XmlHeightSpin->setValue(m_Settings->XmlHeight()); m_XmlTemporalSamplesSpin->setValue(m_Settings->XmlTemporalSamples()); m_XmlQualitySpin->setValue(m_Settings->XmlQuality()); m_XmlSupersampleSpin->setValue(m_Settings->XmlSupersample()); @@ -167,8 +163,6 @@ void FractoriumOptionsDialog::accept() m_Settings->OpenCLDEFilter(ui.OpenCLFilteringDERadioButton->isChecked()); //Xml saving. - m_Settings->XmlWidth(m_XmlWidthSpin->value()); - m_Settings->XmlHeight(m_XmlHeightSpin->value()); m_Settings->XmlTemporalSamples(m_XmlTemporalSamplesSpin->value()); m_Settings->XmlQuality(m_XmlQualitySpin->value()); m_Settings->XmlSupersample(m_XmlSupersampleSpin->value()); @@ -203,8 +197,6 @@ void FractoriumOptionsDialog::reject() ui.OpenCLFilteringDERadioButton->setChecked(m_Settings->OpenCLDEFilter()); //Xml saving. - m_XmlWidthSpin->setValue(m_Settings->XmlWidth()); - m_XmlHeightSpin->setValue(m_Settings->XmlHeight()); m_XmlTemporalSamplesSpin->setValue(m_Settings->XmlTemporalSamples()); m_XmlQualitySpin->setValue(m_Settings->XmlQuality()); m_XmlSupersampleSpin->setValue(m_Settings->XmlSupersample()); diff --git a/Source/Fractorium/OptionsDialog.h b/Source/Fractorium/OptionsDialog.h index 7308612..c0bf4d0 100644 --- a/Source/Fractorium/OptionsDialog.h +++ b/Source/Fractorium/OptionsDialog.h @@ -46,8 +46,6 @@ private: Ui::OptionsDialog ui; OpenCLWrapper m_Wrapper; - SpinBox* m_XmlWidthSpin; - SpinBox* m_XmlHeightSpin; SpinBox* m_XmlTemporalSamplesSpin; SpinBox* m_XmlQualitySpin; SpinBox* m_XmlSupersampleSpin; diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui index 6410e89..3e267a5 100644 --- a/Source/Fractorium/OptionsDialog.ui +++ b/Source/Fractorium/OptionsDialog.ui @@ -7,7 +7,7 @@ 0 0 300 - 411 + 347 @@ -19,13 +19,13 @@ 300 - 411 + 347 300 - 411 + 347 @@ -67,7 +67,7 @@ - 6 + 4 6 @@ -79,7 +79,7 @@ 6 - 6 + 4 @@ -324,13 +324,13 @@ in interactive mode for each mouse movement 0 - 122 + 66 16777215 - 122 + 66 @@ -400,27 +400,17 @@ in interactive mode for each mouse movement false - 24 + 22 false - 24 + 22 false - - - Width - - - - - Height - - Temporal Samples @@ -448,7 +438,7 @@ in interactive mode for each mouse movement - Width + Temporal Samples ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled @@ -461,7 +451,7 @@ in interactive mode for each mouse movement - Height + Quality ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled @@ -473,32 +463,6 @@ in interactive mode for each mouse movement - - Temporal Samples - - - ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled - - - - - 0 - - - - - Quality - - - ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled - - - - - 0 - - - Supersample @@ -506,7 +470,7 @@ in interactive mode for each mouse movement ItemIsDragEnabled|ItemIsUserCheckable|ItemIsEnabled - + 0 @@ -543,13 +507,13 @@ in interactive mode for each mouse movement 120 - 74 + 66 16777215 - 74 + 66 @@ -619,13 +583,13 @@ in interactive mode for each mouse movement false - 24 + 22 false - 24 + 22 false diff --git a/Source/Fractorium/TwoButtonWidget.h b/Source/Fractorium/TwoButtonComboWidget.h similarity index 87% rename from Source/Fractorium/TwoButtonWidget.h rename to Source/Fractorium/TwoButtonComboWidget.h index dd14de3..75ae467 100644 --- a/Source/Fractorium/TwoButtonWidget.h +++ b/Source/Fractorium/TwoButtonComboWidget.h @@ -4,7 +4,7 @@ #include "DoubleSpinBox.h" /// -/// TwoButtonWidget and SpinnerButtonWidget classes. +/// TwoButtonComboWidget and SpinnerButtonWidget classes. /// /// @@ -12,7 +12,7 @@ /// Used for when a layout expects a single widget, but two need to go in its place. /// The buttons are public so the caller can easily use them individually. /// -class TwoButtonWidget : public QWidget +class TwoButtonComboWidget : public QWidget { Q_OBJECT @@ -27,12 +27,15 @@ public: /// The width of the second button /// The height of both buttons /// The parent widget - TwoButtonWidget(QString caption1, QString caption2, int w1, int w2, int h, QWidget* parent) + TwoButtonComboWidget(const QString& caption1, const QString& caption2, QStringList comboStrings, int w1, int w2, int h, QWidget* parent) : QWidget(parent) { QHBoxLayout* layout = new QHBoxLayout(this); m_Button1 = new QPushButton(caption1, parent); m_Button2 = new QPushButton(caption2, parent); + m_Combo = new QComboBox(parent); + + m_Combo->addItems(comboStrings); if (w1 != -1) { @@ -50,7 +53,10 @@ public: m_Button1->setMaximumHeight(h); m_Button2->setMinimumHeight(h); m_Button2->setMaximumHeight(h); + m_Combo->setMinimumHeight(h - 3); + m_Combo->setMaximumHeight(h - 3); + layout->addWidget(m_Combo); layout->addWidget(m_Button1); layout->addWidget(m_Button2); layout->setAlignment(Qt::AlignLeft); @@ -62,6 +68,7 @@ public: QPushButton* m_Button1; QPushButton* m_Button2; + QComboBox* m_Combo; }; /// diff --git a/Source/Fractorium/VariationTreeWidgetItem.h b/Source/Fractorium/VariationTreeWidgetItem.h index 7c9c904..7490854 100644 --- a/Source/Fractorium/VariationTreeWidgetItem.h +++ b/Source/Fractorium/VariationTreeWidgetItem.h @@ -4,7 +4,7 @@ #include "DoubleSpinBox.h" /// -/// TwoButtonWidget class. +/// VariationTreeWidgetItem class. /// ///