2013-10-16 13:10:57 +00:00

270 lines
6.4 KiB
C++

#include "Transformation.h"
#include "ColorPool.h"
#include "../../SyntopiaCore/Math/Matrix4.h"
#include "../../SyntopiaCore/Exceptions/Exception.h"
#include "../../SyntopiaCore/Logging/Logging.h"
#include <QColor>
using namespace SyntopiaCore::Exceptions;
using namespace SyntopiaCore::Logging;
using namespace SyntopiaCore::Math;
namespace StructureSynth {
namespace Model {
Transformation::Transformation() {
matrix = Matrix4f::Identity();
deltaH = 0;
scaleS = 1;
scaleV = 1;
scaleAlpha = 1;
absoluteColor = false;
strength = 0;
}
Transformation::~Transformation() {
};
State Transformation::apply(const State& s, ColorPool* colorPool) const {
State s2(s);
s2.matrix = s.matrix*matrix;
if (absoluteColor) {
// if the absolute hue is larger than 360, we will choose a random color.
if (deltaH > 360) {
QColor c = colorPool->drawColor();
s2.hsv = Vector3f(c.hue(), c.saturation()/255.0, c.value()/255.0);
s2.alpha = 1.0;
} else {
s2.hsv = Vector3f(deltaH,scaleS,scaleV);
s2.alpha = scaleAlpha;
}
} else {
float h = s2.hsv[0] + deltaH;
float sat = s2.hsv[1]*scaleS;
float v = s2.hsv[2]*scaleV;
float a = s2.alpha * scaleAlpha;
if (sat<0) sat=0;
if (v<0) v=0;
if (a<0) a=0;
if (sat>1) sat=1;
if (v>1) v=1;
if (a>1) a=1;
while (h>360) h-=360;
while (h<0) h+=360;
s2.hsv = Vector3f(h,sat,v);
s2.alpha = a;
}
if (strength) {
/*
// We will blend the two colors (in RGB space)
QColor original = QColor::fromHsv((int)(s2.hsv[0]),(int)(s2.hsv[1]*255.0),(int)(s2.hsv[2]*255.0));
double r = original.red() + strength*blendColor.red();
double g = original.green() + strength*blendColor.green();
double b = original.blue() + strength*blendColor.blue();
if (r<0) r=0;
if (g<0) g=0;
if (b<0) b=0;
double max = r;
if (g>max) max = g;
if (b>max) max = b;
if (max > 255) {
r = r * 255 / max;
g = g * 255 / max;
b = b * 255 / max;
}
QColor mixed(r,g,b);
s2.hsv = Vector3f(mixed.hue(), mixed.saturation()/255.0,mixed.value()/255.0);
*/
// We will blend the two colors (in HSV space)
Vector3f bl = Vector3f(blendColor.hue(), blendColor.saturation()/255.0,blendColor.value()/255.0);
Vector3f b(s2.hsv[0]+strength*bl[0], s2.hsv[1]+strength*bl[1], s2.hsv[2]+strength*bl[2]);
b = b/(1+strength);
while (b[0] < 0) b[0]+= 360;
while (b[0] > 360) b[0]-= 360;
if (b[1]>1) b[1]=1;
if (b[2]>1) b[2]=1;
if (b[1]<0) b[1]=0;
if (b[2]<0) b[2]=0;
s2.hsv = b;
}
return s2;
}
void Transformation::append(const Transformation& t) {
this->matrix = this->matrix * t.matrix;
if (!(t.absoluteColor && absoluteColor)) {
if (t.absoluteColor) this->absoluteColor = true;
if (absoluteColor) this->absoluteColor = true;
this->scaleAlpha = this->scaleAlpha * t.scaleAlpha;
this->deltaH = this->deltaH + t.deltaH;
this->scaleS = this->scaleS * t.scaleS;
this->scaleV = this->scaleV * t.scaleV;
} else {
// Mix two absolute colors - this is not possible, so we will just choose one of them
this->absoluteColor = true;
this->scaleAlpha = t.scaleAlpha;
this->deltaH = t.deltaH;
this->scaleS = t.scaleS;
this->scaleV = t.scaleV;
}
if (t.strength != 0) {
this->strength = t.strength;
this->blendColor = t.blendColor;
}
}
// The predefined operators
// Translations
Transformation Transformation::createX(double offset) {
Transformation t;
t.matrix(0,3) = offset;
return t;
}
Transformation Transformation::createY(double offset) {
Transformation t;
t.matrix(1,3) = offset;
return t;
}
Transformation Transformation::createZ(double offset) {
Transformation t;
t.matrix(2,3) = offset;
return t;
}
Transformation Transformation::createPlaneReflection(SyntopiaCore::Math::Vector3f normal) {
Transformation t;
t.matrix = Matrix4f::PlaneReflection(normal);
return t;
}
// Rotations
Transformation Transformation::createRX(double angle) {
Transformation t;
t.matrix =
Matrix4f::Translation(0,0.5,0.5)*
Matrix4f::Rotation(Vector3f(1,0,0), angle)*
Matrix4f::Translation(0,-0.5,-0.5);
return t;
}
Transformation Transformation::createRY(double angle) {
Transformation t;
t.matrix =
Matrix4f::Translation(0.5,0,0.5)*
Matrix4f::Rotation(Vector3f(0,1,0), angle)*
Matrix4f::Translation(-0.5,0,-0.5)
;
return t;
}
Transformation Transformation::createRZ(double angle) {
Transformation t;
t.matrix =
Matrix4f::Translation(0.5,0.5,0)*
Matrix4f::Rotation(Vector3f(0,0,1), angle)*
Matrix4f::Translation(-0.5,-0.5,0);
return t;
}
Transformation Transformation::createHSV(float h, float s, float v, float a) {
Transformation t;
t.deltaH = h;
t.scaleAlpha = a;
t.scaleS = s;
t.scaleV = v;
return t;
}
Transformation Transformation::createColor(QString color) {
Transformation t;
if (color.toLower() != "random") {
QColor c(color);
QColor hsv = c.toHsv();
t.deltaH = hsv.hue();
t.scaleAlpha = hsv.alpha()/255.0;
t.scaleS = hsv.saturation()/255.0;
t.scaleV = hsv.value()/255.0;
t.absoluteColor = true;
} else {
t.deltaH = 1000;
t.absoluteColor = true;
}
//Debug(QString("Abs Color: %1, %2, %3, %4").arg(t.deltaH).arg(t.scaleS).arg(t.scaleV).arg(t.scaleAlpha));
return t;
}
Transformation Transformation::createBlend(QString color, double strength) {
Transformation t;
t.blendColor = QColor(color);
t.strength = strength;
return t;
}
Transformation Transformation::createScale(double x, double y, double z) {
Transformation t;
t.matrix(0,0) = x;
t.matrix(1,1) = y;
t.matrix(2,2) = z;
t.matrix =
Matrix4f::Translation(0.5,0.5,0.5)*
t.matrix*
Matrix4f::Translation(-0.5,-0.5,-0.5);
return t;
}
Transformation Transformation::createMatrix(QVector<double> vals) {
Transformation t;
t.matrix(0,0) = vals[0];
t.matrix(0,1) = vals[1];
t.matrix(0,2) = vals[2];
t.matrix(1,0) = vals[3];
t.matrix(1,1) = vals[4];
t.matrix(1,2) = vals[5];
t.matrix(2,0) = vals[6];
t.matrix(2,1) = vals[7];
t.matrix(2,2) = vals[8];
t.matrix =
Matrix4f::Translation(0.5,0.5,0.5)*
t.matrix*
Matrix4f::Translation(-0.5,-0.5,-0.5);
return t;
}
}
}