0.4.0.8 Beta 07/26/2014

0.4.0.8 Beta 07/26/2014
--Bug Fixes
Fix falloff, falloff2, falloff3.
This commit is contained in:
mfeemster 2014-07-26 17:26:15 -07:00
parent d9d676393c
commit a5d69c75a2
16 changed files with 93 additions and 55 deletions

8
.gitignore vendored
View File

@ -29,4 +29,10 @@
*moc_*
*GeneratedFiles*
*.unsuccessfulbuild
*\Obj\*
*\Obj\*
Builds/MSVC/VS2010/Obj/x64/Debug/EmberCL_manifest.rc
Builds/MSVC/VS2010/Obj/EmberTester/x64/Debug/EmberTester_manifest.rc
Builds/MSVC/VS2010/Obj/EmberRender/x64/Debug/EmberRender_manifest.rc
Builds/MSVC/VS2010/Obj/EmberGenome/x64/Debug/EmberGenome_manifest.rc
Builds/MSVC/VS2010/Obj/EmberAnimate/x64/Debug/EmberAnimate_manifest.rc
Builds/MSVC/VS2010/Obj/Ember/x64/Debug/Ember_manifest.rc

View File

@ -579,6 +579,7 @@ Global
{C8096C47-E358-438C-A520-146D46B0637D}.Release|Mixed Platforms.Build.0 = Release|x86
{C8096C47-E358-438C-A520-146D46B0637D}.Release|Win32.ActiveCfg = Release|x86
{C8096C47-E358-438C-A520-146D46B0637D}.Release|x64.ActiveCfg = Release|x64
{C8096C47-E358-438C-A520-146D46B0637D}.Release|x64.Build.0 = Release|x64
{C8096C47-E358-438C-A520-146D46B0637D}.Release|x86.ActiveCfg = Release|x86
{C8096C47-E358-438C-A520-146D46B0637D}.Release|x86.Build.0 = Release|x86
{C8096C47-E358-438C-A520-146D46B0637D}.Release-MT|Mixed Platforms.ActiveCfg = Release|x86

View File

@ -6,7 +6,7 @@
<ProductVersion>3.7</ProductVersion>
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>Fractorium_Beta_0.4.0.7</OutputName>
<OutputName>Fractorium_Beta_0.4.0.8</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductVersion="0.4.0.7" ?>
<?define ProductVersion="0.4.0.8" ?>
<?define ProductName="Fractorium Beta $(var.ProductVersion) ($(var.GpuType))" ?>
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
<?define Manufacturer="Fractorium"?>
@ -13,7 +13,7 @@
<!--
Change this for every release.
-->
<?define ProductCode="{CA02C021-90D4-45F4-84C0-01E18E2474F3}"?>
<?define ProductCode="{567692F8-C869-4EEA-98C4-5D69982F9F76}"?>
<Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<Package

View File

@ -1,3 +1,7 @@
0.4.0.8 Beta 07/26/2014
--Bug Fixes
Fix falloff, falloff2, falloff3.
0.4.0.7 Beta 07/26/2014
--User Changes
Color code xforms like Apo does.

View File

@ -25,7 +25,7 @@ namespace EmberNs
extern void sincos(double x, double *s, double *c);
#endif
#define EMBER_VERSION "0.4.0.7"
#define EMBER_VERSION "0.4.0.8"
#define EPS6 T(1e-6)
#define EPS std::numeric_limits<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
#define ISAAC_SIZE 4

View File

@ -4211,8 +4211,6 @@ public:
}
}
helper.Out.x = 0;//Needed because of possible sum below.
helper.Out.y = 0;
r = fabs(r0 - T(0.5)) * m_OneOverRmax;
if (r < 1)
@ -4220,6 +4218,11 @@ public:
helper.Out.x = m_Size * (x + Floor<T>(helper.In.x));
helper.Out.y = m_Size * (y + Floor<T>(helper.In.y));
}
else
{
helper.Out.x = 0;//Needed because of possible sum below.
helper.Out.y = 0;
}
r = fabs(r1 - T(0.5)) * m_OneOverRmax;
@ -4346,8 +4349,6 @@ public:
<< "\t\t }\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tvOut.x = 0;\n"
<< "\t\tvOut.y = 0;\n"
<< "\t\tr = fabs(r0 - 0.5) * " << oneOverRmax << ";\n"
<< "\n"
<< "\t\tif (r < 1)\n"
@ -4355,6 +4356,11 @@ public:
<< "\t\t vOut.x = " << size << " * (x + floor(vIn.x));\n"
<< "\t\t vOut.y = " << size << " * (y + floor(vIn.y));\n"
<< "\t\t}\n"
<< "\t\telse\n"
<< "\t\t{\n"
<< "\t\t vOut.x = 0.0;\n"
<< "\t\t vOut.y = 0.0;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tr = fabs(r1 - 0.5) * " << oneOverRmax << ";\n"
<< "\n"

View File

@ -2117,12 +2117,12 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
const T ax = rand.Frand11<T>();
const T ay = rand.Frand11<T>();
const T az = rand.Frand11<T>();
const T ax = rand.Frand<T>(T(-0.5), T(0.5));
const T ay = rand.Frand<T>(T(-0.5), T(0.5));
const T az = rand.Frand<T>(T(-0.5), T(0.5));
const T r = sqrt(Sqr(helper.In.x - m_X0) + Sqr(helper.In.y - m_Y0) + Sqr(helper.In.z - m_Z0));
const T rc = ((m_Invert != 0 ? min<T>(1 - r, 0) : min<T>(r, 0)) - m_MinDist) * m_InternalScatter;
const T rs = min<T>(rc, 0);
const T rc = ((m_Invert != 0 ? max<T>(1 - r, 0) : max<T>(r, 0)) - m_MinDist) * m_InternalScatter;//Original called a macro named min, which internally performed max.
const T rs = max<T>(rc, 0);
T sigma, phi, rad, sigmas, sigmac, phis, phic;
T scale, denom;
@ -2178,12 +2178,12 @@ public:
string internalScatter = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tconst real_t ax = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t ay = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t az = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t ax = MwcNext0505(mwc);\n"
<< "\t\tconst real_t ay = MwcNext0505(mwc);\n"
<< "\t\tconst real_t az = MwcNext0505(mwc);\n"
<< "\t\tconst real_t r = sqrt(Sqr(vIn.x - " << x0 << ") + Sqr(vIn.y - " << y0 << ") + Sqr(vIn.z - " << z0 << "));\n"
<< "\t\tconst real_t rc = ((" << invert << " != 0 ? min(1 - r, 0.0) : min(r, 0.0)) - " << minDist << ") * " << internalScatter << ";\n"
<< "\t\tconst real_t rs = min(rc, 0.0);\n"
<< "\t\tconst real_t rc = ((" << invert << " != 0 ? max(1 - r, 0.0) : max(r, 0.0)) - " << minDist << ") * " << internalScatter << ";\n"
<< "\t\tconst real_t rs = max(rc, 0.0);\n"
<< "\n"
<< "\t\treal_t sigma, phi, rad, sigmas, sigmac, phis, phic;\n"
<< "\t\treal_t scale, denom;\n"
@ -2278,10 +2278,10 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
const v4T random(rand.Frand11<T>(), rand.Frand11<T>(), rand.Frand11<T>(), rand.Frand11<T>());
const v4T random(rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)));
const T distA = sqrt(Sqr(helper.In.x - m_X0) + Sqr(helper.In.y - m_Y0) + Sqr(helper.In.z - m_Z0));
const T distB = m_Invert != 0 ? min<T>(1 - distA, 0) : min<T>(distA, 0);
const T dist = min<T>((distB - m_MinDist) * m_RMax, 0);
const T distB = m_Invert != 0 ? max<T>(1 - distA, 0) : max<T>(distA, 0);//Original called a macro named min, which internally performed max.
const T dist = max<T>((distB - m_MinDist) * m_RMax, 0);
switch ((int)m_Type)
{
@ -2356,13 +2356,13 @@ public:
string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tconst real_t randx = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randy = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randz = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randc = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randx = MwcNext0505(mwc);\n"
<< "\t\tconst real_t randy = MwcNext0505(mwc);\n"
<< "\t\tconst real_t randz = MwcNext0505(mwc);\n"
<< "\t\tconst real_t randc = MwcNext0505(mwc);\n"
<< "\t\tconst real_t distA = sqrt(Sqr(vIn.x - " << x0 << ") + Sqr(vIn.y - " << y0 << ") + Sqr(vIn.z - " << z0 << "));\n"
<< "\t\tconst real_t distB = " << invert << " != 0 ? min(1 - distA, 0.0) : min(distA, 0.0);\n"
<< "\t\tconst real_t dist = min((distB - " << minDist << ") * " << rMax<< ", 0.0);\n"
<< "\t\tconst real_t distB = " << invert << " != 0 ? max(1 - distA, 0.0) : max(distA, 0.0);\n"
<< "\t\tconst real_t dist = max((distB - " << minDist << ") * " << rMax<< ", 0.0);\n"
<< "\n"
<< "\t\tswitch ((int)" << type << ")\n"
<< "\t\t{\n"
@ -2474,7 +2474,7 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
const v4T random(rand.Frand11<T>(), rand.Frand11<T>(), rand.Frand11<T>(), rand.Frand11<T>());
const v4T random(rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)), rand.Frand<T>(T(-0.5), T(0.5)));
T radius;
switch ((int)m_BlurShape)
@ -2483,11 +2483,11 @@ public:
radius = sqrt(Sqr(helper.In.x - m_CenterX) + Sqr(helper.In.y - m_CenterY) + Sqr(helper.In.z - m_CenterZ));
break;
case 1://Square.
radius = min(fabs(helper.In.x - m_CenterX), min(fabs(helper.In.y - m_CenterY), (fabs(helper.In.z - m_CenterZ))));
radius = max(fabs(helper.In.x - m_CenterX), max(fabs(helper.In.y - m_CenterY), (fabs(helper.In.z - m_CenterZ))));//Original called a macro named min, which internally performed max.
break;
}
const T dist = min<T>(((m_InvertDistance != 0 ? min<T>(1 - radius, 0) : min<T>(radius, 0)) - m_MinDistance) * m_RMax, 0);
const T dist = max<T>(((m_InvertDistance != 0 ? max<T>(1 - radius, 0) : max<T>(radius, 0)) - m_MinDistance) * m_RMax, 0);
switch ((int)m_BlurType)
{
@ -2566,10 +2566,10 @@ public:
string rMax = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\tconst real_t randx = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randy = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randz = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randc = MwcNextNeg1Pos1(mwc);\n"
<< "\t\tconst real_t randx = MwcNext0505(mwc);\n"
<< "\t\tconst real_t randy = MwcNext0505(mwc);\n"
<< "\t\tconst real_t randz = MwcNext0505(mwc);\n"
<< "\t\tconst real_t randc = MwcNext0505(mwc);\n"
<< "\t\treal_t radius;\n"
<< "\n"
<< "\t\tswitch ((int)" << blurShape << ")\n"
@ -2578,11 +2578,11 @@ public:
<< "\t\t radius = sqrt(Sqr(vIn.x - " << centerX << ") + Sqr(vIn.y - " << centerY << ") + Sqr(vIn.z - " << centerZ << "));\n"
<< "\t\t break;\n"
<< "\t\t case 1:\n"
<< "\t\t radius = min(fabs(vIn.x - " << centerX << "), min(fabs(vIn.y - " << centerY << "), (fabs(vIn.z - " << centerZ << "))));\n"
<< "\t\t radius = max(fabs(vIn.x - " << centerX << "), max(fabs(vIn.y - " << centerY << "), (fabs(vIn.z - " << centerZ << "))));\n"
<< "\t\t break;\n"
<< "\t\t}\n"
<< "\n"
<< "\t\tconst real_t dist = min(((" << invertDist << " != 0 ? min(1 - radius, 0.0) : min(radius, 0.0)) - " << minDist << ") * " << rMax << ", 0.0);\n"
<< "\t\tconst real_t dist = max(((" << invertDist << " != 0 ? max(1 - radius, 0.0) : max(radius, 0.0)) - " << minDist << ") * " << rMax << ", 0.0);\n"
<< "\n"
<< "\t\tswitch ((int)" << blurType << ")\n"
<< "\t\t{\n"

View File

@ -49,8 +49,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,4,0,7
PRODUCTVERSION 0,4,0,7
FILEVERSION 0,4,0,8
PRODUCTVERSION 0,4,0,8
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -67,12 +67,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as animations with motion blur"
VALUE "FileVersion", "0.4.0.7"
VALUE "FileVersion", "0.4.0.8"
VALUE "InternalName", "EmberAnimate.rc"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3"
VALUE "OriginalFilename", "EmberAnimate.rc"
VALUE "ProductName", "Ember Animate"
VALUE "ProductVersion", "0.4.0.7"
VALUE "ProductVersion", "0.4.0.8"
END
END
BLOCK "VarFileInfo"

View File

@ -171,6 +171,12 @@ static const char* RandFunctionString =
" real_t f = (real_t)MwcNext(s) / (real_t)UINT_MAX;\n"
" return -1.0 + (f * 2.0);\n"
"}\n"
"\n"
"inline real_t MwcNext0505(uint2* s)\n"
"{\n"
" real_t f = (real_t)MwcNext(s) / (real_t)UINT_MAX;\n"
" return -0.5 + f;\n"
"}\n"
"\n";
/// <summary>

View File

@ -49,8 +49,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,4,0,7
PRODUCTVERSION 0,4,0,7
FILEVERSION 0,4,0,8
PRODUCTVERSION 0,4,0,8
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -67,12 +67,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Manipulates fractal flames parameter files"
VALUE "FileVersion", "0.4.0.7"
VALUE "FileVersion", "0.4.0.8"
VALUE "InternalName", "EmberGenome.rc"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3"
VALUE "OriginalFilename", "EmberGenome.rc"
VALUE "ProductName", "Ember Genome"
VALUE "ProductVersion", "0.4.0.7"
VALUE "ProductVersion", "0.4.0.8"
END
END
BLOCK "VarFileInfo"

View File

@ -49,8 +49,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,4,0,7
PRODUCTVERSION 0,4,0,7
FILEVERSION 0,4,0,8
PRODUCTVERSION 0,4,0,8
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -67,12 +67,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Open Source"
VALUE "FileDescription", "Renders fractal flames as single images"
VALUE "FileVersion", "0.4.0.7"
VALUE "FileVersion", "0.4.0.8"
VALUE "InternalName", "EmberRender.rc"
VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3"
VALUE "OriginalFilename", "EmberRender.rc"
VALUE "ProductName", "Ember Render"
VALUE "ProductVersion", "0.4.0.7"
VALUE "ProductVersion", "0.4.0.8"
END
END
BLOCK "VarFileInfo"

View File

@ -1719,13 +1719,28 @@ void TestCross(T x, T y, T weight)
cout << "Second way, outX, outY == " << outX << ", " << outY << endl;
}
double RandD(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
return ((((rand.Rand()^(rand.Rand()<<15))&0xfffffff)*3.72529e-09)-0.5);
}
int _tmain(int argc, _TCHAR* argv[])
{
int i;
Timing t(4);
QTIsaac<ISAAC_SIZE, ISAAC_INT> rand;
//cout << pow(-1, 5.1) << endl;
/*for (i = 0; i < 2500000000; i++)
{
double d = fabs(RandD(rand));
if (d >= 0.5)
cout << d << endl;
}
return 0;*/
//cout << "sizeof(Ember<float>): " << sizeof(Ember<float>) << endl;
//cout << "sizeof(Ember<double>): " << sizeof(Ember<double>) << endl;
//

View File

@ -52,7 +52,7 @@
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.0.7 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.0.8 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

Binary file not shown.

View File

@ -25,7 +25,7 @@ void Fractorium::InitParamsUI()
//Color.
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 100, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 2.0, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, -1.0, -1.0, -1.0);
@ -47,10 +47,10 @@ void Fractorium::InitParamsUI()
table = ui.GeometryTable;
SetupSpinner<SpinBox, int> (table, this, row, 1, m_WidthSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnWidthChanged(int)));
SetupSpinner<SpinBox, int> (table, this, row, 1, m_HeightSpin, spinHeight, 10, 100000, 50, SIGNAL(valueChanged(int)), SLOT(OnHeightChanged(int)));
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterXSpin, spinHeight, -10, 10, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterYSpin, spinHeight, -10, 10, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, 5000, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 5, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterXSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterXChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_CenterYSpin, spinHeight, -dmax, dmax, 0.05, SIGNAL(valueChanged(double)), SLOT(OnCenterYChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ScaleSpin, spinHeight, 10, dmax, 20, SIGNAL(valueChanged(double)), SLOT(OnScaleChanged(double)), true, 240, 240, 240);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZoomSpin, spinHeight, 0, 100, 0.2, SIGNAL(valueChanged(double)), SLOT(OnZoomChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_RotateSpin, spinHeight, -180, 180, 10, SIGNAL(valueChanged(double)), SLOT(OnRotateChanged(double)), true, 0, 0, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_ZPosSpin, spinHeight, -1000, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnZPosChanged(double)), true, 0, 1, 0);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_PerspectiveSpin, spinHeight, -500, 500, 0.01, SIGNAL(valueChanged(double)), SLOT(OnPerspectiveChanged(double)), true, 0, 1, 0);