diff options
author | Chris Xiong <chirs241097@gmail.com> | 2020-02-14 00:30:42 +0800 |
---|---|---|
committer | Chris Xiong <chirs241097@gmail.com> | 2020-02-15 18:44:07 +0800 |
commit | 59b0a4f74fd358d44c65137e41594fc7dc8a106e (patch) | |
tree | cfc218d5e0b75123f6635d9e8609558a859ff4e5 /visualization | |
parent | 002baf9367417604412ed19d283835c23454349e (diff) | |
download | QMidiPlayer-59b0a4f74fd358d44c65137e41594fc7dc8a106e.tar.xz |
New scheme for visualizing note velocity.
Updated default color scheme for better results.
New class smColor, which is going to replace smColorHSVA & smColorRGBA
in the future.
Diffstat (limited to 'visualization')
-rw-r--r-- | visualization/extrasmeltutils.cpp | 171 | ||||
-rw-r--r-- | visualization/extrasmeltutils.hpp | 38 | ||||
-rw-r--r-- | visualization/qmpvisualization.cpp | 17 |
3 files changed, 219 insertions, 7 deletions
diff --git a/visualization/extrasmeltutils.cpp b/visualization/extrasmeltutils.cpp index c8b3446..2d0a807 100644 --- a/visualization/extrasmeltutils.cpp +++ b/visualization/extrasmeltutils.cpp @@ -196,3 +196,174 @@ void smParticleSystem::updatePS() } void smParticleSystem::renderPS() {for(unsigned i=0;i<particles.size();++i)particles[i]->render();} + +smColor::smColor() +{r=g=b=h=s=v=a=0;} + +void smColor::update_rgb() +{ + auto f=[this](float n){ + float k=fmodf(n+6.0f*this->h,6.0f); + return this->v-this->v*this->s*max(0.0f,min(1.0f,min(k,4.0f-k))); + }; + r=f(5); + g=f(3); + b=f(1); +} +void smColor::update_hsv() +{ + v=max(r,max(g,b)); + float vm=min(r,min(g,b)); + float chroma=v-vm; + if(v-vm<EPSF)h=0; + else if(v-r<EPSF)h=(0.0f+(g-b)/chroma)/6.0f; + else if(v-g<EPSF)h=(2.0f+(b-r)/chroma)/6.0f; + else if(v-b<EPSF)h=(4.0f+(r-g)/chroma)/6.0f; + if(v<EPSF)s=0;else s=chroma/v; +} + +void smColor::clamp(bool hsv) +{ + if(hsv) + { + h=min(1.0f,max(0.0f,h)); + s=min(1.0f,max(0.0f,s)); + v=min(1.0f,max(0.0f,v)); + update_rgb(); + } + else + { + r=min(1.0f,max(0.0f,r)); + g=min(1.0f,max(0.0f,g)); + b=min(1.0f,max(0.0f,b)); + update_hsv(); + } +} +float smColor::alpha()const +{return a;} +float smColor::red()const +{return r;} +float smColor::green()const +{return g;} +float smColor::blue()const +{return b;} +float smColor::hue()const +{return h;} +float smColor::saturation()const +{return s;} +float smColor::hslSaturation()const +{ + float l=lightness(); + if(fabsf(l)<EPSF||fabsf(l-1)<EPSF)return 0; + return (v-l)/min(l,1-l); +} +float smColor::value()const +{return v;} +float smColor::lightness()const +{return v-v*s/2;} + +void smColor::setAlpha(float alpha) +{a=alpha;} +void smColor::setRed(float red) +{ + if(fabsf(r-red)>EPSF) + { + r=red; + update_hsv(); + } +} +void smColor::setGreen(float green) +{ + if(fabsf(g-green)>EPSF) + { + g=green; + update_hsv(); + } +} +void smColor::setBlue(float blue) +{ + if(fabsf(b-blue)>EPSF) + { + b=blue; + update_hsv(); + } +} +void smColor::setHue(float hue) +{ + if(fabsf(h-hue)>EPSF) + { + h=hue; + update_rgb(); + } +} +void smColor::setSaturation(float saturation) +{ + if(fabsf(s-saturation)>EPSF) + { + s=saturation; + update_rgb(); + } +} +void smColor::setHSLSaturation(float saturation) +{ + float ss=hslSaturation(); + float l=lightness(); + if(fabsf(ss-saturation)>EPSF) + { + ss=saturation; + v=l+ss*min(l,1-l); + if(v<EPSF)s=0; + else s=2-2*l/v; + update_rgb(); + } +} +void smColor::setValue(float value) +{ + if(fabsf(v-value)>EPSF) + { + v=value; + update_rgb(); + } +} +void smColor::setLightness(float lightness) +{ + float ss=hslSaturation(); + float l=this->lightness(); + if(fabsf(l-lightness)>EPSF) + { + l=lightness; + v=l+ss*min(l,1-l); + if(v<EPSF)s=0; + else s=2-2*l/v; + update_rgb(); + } +} +smColor smColor::lighter(int factor) +{ + smColor ret(*this); + ret.setValue(v*(factor/100.0f)); + ret.clamp(true); + return ret; +} +smColor smColor::darker(int factor) +{ + smColor ret(*this); + ret.setValue(factor?(v/(factor/100.0f)):1.); + ret.clamp(true); + return ret; +} + +uint32_t smColor::toHWColor() +{ + return RGBA(r*255,g*255,b*255,a*255); +} +smColor smColor::fromHWColor(uint32_t color) +{ + smColor ret; + ret.r=GETR(color)/255.0f; + ret.g=GETG(color)/255.0f; + ret.b=GETB(color)/255.0f; + ret.a=GETA(color)/255.0f; + ret.update_hsv(); + return ret; +} diff --git a/visualization/extrasmeltutils.hpp b/visualization/extrasmeltutils.hpp index d827567..3cea3fc 100644 --- a/visualization/extrasmeltutils.hpp +++ b/visualization/extrasmeltutils.hpp @@ -1,3 +1,8 @@ +//Extra utilities for SMELT +//Chris Xiong, 2016-2020 +//License: LGPL v3 +//This file contains staging extensions for SMELT, +//which will be moved into SMELT once they are mature. #ifndef EXTRASMELTUTILS_H #define EXTRASMELTUTILS_H #include <ctime> @@ -5,6 +10,7 @@ #include <smelt.hpp> #include <smmath.hpp> #include <smrandom.hpp> +#define EPSF 1e-6f class smEntity3D { friend class smEntity3DBuffer; @@ -34,6 +40,38 @@ class smEntity3DBuffer void drawBatch(); }; +class smColor +{ + private: + float r,g,b,h,s,v,a; + void update_rgb(); + void update_hsv(); + public: + smColor(); + void clamp(bool hsv); + float alpha()const; + float red()const; + float green()const; + float blue()const; + float hue()const; + float saturation()const; + float hslSaturation()const; + float value()const; + float lightness()const; + void setAlpha(float alpha); + void setRed(float red); + void setGreen(float green); + void setBlue(float blue); + void setHue(float hue); + void setSaturation(float saturation); + void setHSLSaturation(float saturation); + void setValue(float value); + void setLightness(float lightness); + smColor lighter(int factor); + smColor darker(int factor); + uint32_t toHWColor(); + static smColor fromHWColor(uint32_t color); +}; class smPSEmissionPositionGenerator { public: diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp index e725263..5ada18f 100644 --- a/visualization/qmpvisualization.cpp +++ b/visualization/qmpvisualization.cpp @@ -18,13 +18,13 @@ const wchar_t* minors=L"abebbbf c g d a e b f#c#g#d#a#"; const wchar_t* majors=L"CbGbDbAbEbBbF C G D A E B F#C#"; double fpoffsets[]={1,18,28,50,55,82,98,109,130,137,161,164,191}; double froffsets[]={0,18,33,50,65,82,98,113,130,145,161,176,191}; -DWORD iccolors[]={0XFFFF0000,0XFFFF8000,0XFFFFBF00,0XFFFFFF00, - 0XFFBFFF00,0XFF80FF00,0XFF00FF00,0XFF00FFBF, - 0XFF00FFFF,0XFF333333,0XFF00BFFF,0XFF007FFF, +DWORD iccolors[]={0XFFFF0000,0XFFFF8000,0XFFFFBF00,0XFFF0F000, + 0XFFB2EE00,0XFF80FF00,0XFF00FF00,0XFF00EEB2, + 0XFF00EEEE,0XFF333333,0XFF00BFFF,0XFF007FFF, 0XFF0000FF,0XFF7F00FF,0XFFBF00FF,0XFFFF00BF}; -DWORD accolors[]={0XFFFF9999,0XFFFFCC99,0XFFFFEE99,0XFFFFFF99, - 0XFFEEFF99,0XFFCCFF99,0XFF99FF99,0XFF99FFCC, - 0XFF99FFFF,0XFF999999,0XFF99EEFF,0XFF99CCFF, +DWORD accolors[]={0XFFFF9999,0XFFFFCC99,0XFFFFF4D4,0XFFFFFFDD, + 0XFFF0FFC2,0XFFDDFFBB,0XFFBBFFBB,0XFFAAFFEA, + 0XFFBBFFFF,0XFF999999,0XFF99EEFF,0XFF99CCFF, 0XFF9999FF,0XFFCC99FF,0XFFEE99FF,0XFFFF99EE}; std::set<BYTE> sustaininst={16,17,18,19,20,21,22,23, @@ -329,7 +329,10 @@ void qmpVisualization::updateVisualization3D() spectra[pool[i]->ch][pool[i]->key]=pool[i]->vel*(api->getChannelCC(pool[i]->ch,7)/127.); } else - drawCube(a,b,SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*1.6+(isnoteon?52:32))),0); + { + smColor col=smColor::fromHWColor(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch]); + drawCube(a,b,col.lighter(37+pool[i]->vel/2).toHWColor(),0); + } } } if(usespectrum&&playing) |