aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2016-05-04 23:45:29 +0800
committerGravatar Chris Xiong <chirs241097@gmail.com> 2016-05-04 23:45:29 +0800
commit56eaa27d4daca9264dac2e822b1126cf6eb8cbf4 (patch)
treeb4da915a530814cd6e1705e72b1bde5ad196d8d2
parent015a45c276caf34be3ce9175a1bcce644d736a0b (diff)
downloadQMidiPlayer-56eaa27d4daca9264dac2e822b1126cf6eb8cbf4.tar.xz
Piano keyboard: first steps.
-rw-r--r--ChangeLog3
-rw-r--r--visualization/extrasmeltutils.cpp91
-rw-r--r--visualization/extrasmeltutils.hpp19
-rw-r--r--visualization/qmpvirtualpiano3d.cpp141
-rw-r--r--visualization/qmpvirtualpiano3d.hpp29
-rw-r--r--visualization/qmpvisualization.cpp14
-rw-r--r--visualization/qmpvisualization.hpp3
-rw-r--r--visualization/visualization.pro8
8 files changed, 306 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 5468866..9caf977 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2016-05-04 0.8.1 pre
+Piano keyboard: first steps.
+
2016-05-03 0.8.0 beta
Finish option proxying for all types.
Add more options for the visualization plugin.
diff --git a/visualization/extrasmeltutils.cpp b/visualization/extrasmeltutils.cpp
new file mode 100644
index 0000000..3e86549
--- /dev/null
+++ b/visualization/extrasmeltutils.cpp
@@ -0,0 +1,91 @@
+#include "extrasmeltutils.hpp"
+SMELT *smEntity3D::sm=NULL;
+smEntity3D::smEntity3D()
+{
+ sm=smGetInterface(SMELT_APILEVEL);
+ surfaces.clear();
+}
+void smEntity3D::pushSurface(smQuad q)
+{surfaces.push_back(q);}
+void smEntity3D::pushCube(smvec3d a,smvec3d b,DWORD color,DWORD mask)
+{
+ //a: top left corner b: bottom right corner
+ smQuad q;q.blend=BLEND_ALPHABLEND;q.tex=0;
+ for(int i=0;i<4;++i)q.v[i].col=color,q.v[i].tx=q.v[i].ty=0;
+ //top
+ if(mask&1)
+ {
+ q.v[0].x=a.x;q.v[0].y=a.y;q.v[0].z=a.z;
+ q.v[1].x=b.x;q.v[1].y=a.y;q.v[1].z=a.z;
+ q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=a.z;
+ q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=a.z;
+ pushSurface(q);
+ }
+ //bottom
+ if(mask&2)
+ {
+ q.v[0].x=a.x;q.v[0].y=a.y;q.v[0].z=b.z;
+ q.v[1].x=b.x;q.v[1].y=a.y;q.v[1].z=b.z;
+ q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=b.z;
+ q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=b.z;
+ pushSurface(q);
+ }
+ //left
+ if(mask&4)
+ {
+ q.v[0].x=a.x;q.v[0].y=b.y;q.v[0].z=a.z;
+ q.v[1].x=a.x;q.v[1].y=b.y;q.v[1].z=b.z;
+ q.v[2].x=a.x;q.v[2].y=a.y;q.v[2].z=b.z;
+ q.v[3].x=a.x;q.v[3].y=a.y;q.v[3].z=a.z;
+ pushSurface(q);
+ }
+ //right
+ if(mask&8)
+ {
+ q.v[0].x=b.x;q.v[0].y=b.y;q.v[0].z=a.z;
+ q.v[1].x=b.x;q.v[1].y=b.y;q.v[1].z=b.z;
+ q.v[2].x=b.x;q.v[2].y=a.y;q.v[2].z=b.z;
+ q.v[3].x=b.x;q.v[3].y=a.y;q.v[3].z=a.z;
+ pushSurface(q);
+ }
+ //front
+ if(mask&16)
+ {
+ q.v[0].x=a.x;q.v[0].y=b.y;q.v[0].z=a.z;
+ q.v[1].x=b.x;q.v[1].y=b.y;q.v[1].z=a.z;
+ q.v[2].x=b.x;q.v[2].y=b.y;q.v[2].z=b.z;
+ q.v[3].x=a.x;q.v[3].y=b.y;q.v[3].z=b.z;
+ pushSurface(q);
+ }
+ //back
+ if(mask&32)
+ {
+ q.v[0].x=a.x;q.v[0].y=a.y;q.v[0].z=a.z;
+ q.v[1].x=b.x;q.v[1].y=a.y;q.v[1].z=a.z;
+ q.v[2].x=b.x;q.v[2].y=a.y;q.v[2].z=b.z;
+ q.v[3].x=a.x;q.v[3].y=a.y;q.v[3].z=b.z;
+ pushSurface(q);
+ }
+}
+void smEntity3D::drawAt(smvec3d p)
+{
+ for(unsigned i=0;i<surfaces.size();++i)
+ {
+ smQuad tq=surfaces[i];
+ for(unsigned j=0;j<4;++j)tq.v[j].x+=p.x,tq.v[j].y+=p.y,tq.v[j].z+=p.z;
+ sm->smRenderQuad(&tq);
+ }
+}
+void smEntity3D::drawWithTransformation(smMatrix t,smvec3d p)
+{
+ for(unsigned i=0;i<surfaces.size();++i)
+ {
+ smQuad tq=surfaces[i];
+ for(unsigned j=0;j<4;++j)
+ {
+ smvec3d tp=t*smvec3d(tq.v[j].x,tq.v[j].y,tq.v[j].z);
+ tq.v[j].x=tp.x+p.x;tq.v[j].y=tp.y+p.y;tq.v[j].z=tp.z+p.z;
+ }
+ sm->smRenderQuad(&tq);
+ }
+}
diff --git a/visualization/extrasmeltutils.hpp b/visualization/extrasmeltutils.hpp
new file mode 100644
index 0000000..4b6c167
--- /dev/null
+++ b/visualization/extrasmeltutils.hpp
@@ -0,0 +1,19 @@
+#ifndef EXTRASMELTUTILS_H
+#define EXTRASMELTUTILS_H
+#include <vector>
+#include <smelt.hpp>
+#include <smmath.hpp>
+class smEntity3D
+{
+ private:
+ std::vector<smQuad> surfaces;
+ static SMELT *sm;
+ public:
+ smEntity3D();
+ ~smEntity3D(){surfaces.clear();sm->smRelease();}
+ void pushSurface(smQuad q);
+ void pushCube(smvec3d a,smvec3d b,DWORD color,DWORD mask);
+ void drawAt(smvec3d p);
+ void drawWithTransformation(smMatrix t,smvec3d p);
+};
+#endif // EXTRASMELTUTILS_H
diff --git a/visualization/qmpvirtualpiano3d.cpp b/visualization/qmpvirtualpiano3d.cpp
new file mode 100644
index 0000000..458d3ef
--- /dev/null
+++ b/visualization/qmpvirtualpiano3d.cpp
@@ -0,0 +1,141 @@
+#include <cstring>
+#include "qmpvirtualpiano3d.hpp"
+#define configureVertex(v,sub,_x,_y,_z) v[sub].x=_x,v[sub].y=_y,v[sub].z=_z;
+const double gap[]={WK_TALWIDTH/2*0.92,WK_TALWIDTH/2*1.23,WK_TALWIDTH/2*1.2,
+ WK_TALWIDTH/2*0.95,WK_TALWIDTH*1.1,WK_TALWIDTH/2*0.95,
+ WK_TALWIDTH/2*1.2,WK_TALWIDTH/2*1.15,WK_TALWIDTH/2*1,
+ WK_TALWIDTH/2*1.3,WK_TALWIDTH/2*0.85,WK_TALWIDTH*1.1};
+qmpVirtualPiano3D::qmpVirtualPiano3D()
+{
+ buildKeys();memset(traveld,0,sizeof(traveld));
+}
+qmpVirtualPiano3D::~qmpVirtualPiano3D()
+{
+ delete wkcf;delete wkeb;delete wkd;delete wkg;delete wka;delete bk;
+}
+void qmpVirtualPiano3D::render(smvec3d p)
+{
+ p.x-=WK_TALWIDTH*37*1.075;
+ for(int i=0;i<128;++i)
+ {
+ smMatrix m;m.loadIdentity();m.rotate(-0.2*traveld[i],1,0,0);
+ switch(i%12)
+ {
+ case 0:case 5:
+ wkcf->drawWithTransformation(m,p);
+ break;
+ case 2:
+ wkd->drawWithTransformation(m,p);
+ break;
+ case 4:case 11:
+ wkeb->drawWithTransformation(m,p);
+ break;
+ case 7:
+ wkg->drawWithTransformation(m,p);
+ break;
+ case 9:
+ wka->drawWithTransformation(m,p);
+ break;
+ case 1:case 3:case 6:case 8:case 10:
+ bk->drawWithTransformation(m,p);
+ break;
+ }
+ p.x+=gap[i%12];
+ }
+}
+void qmpVirtualPiano3D::setKeyTravelDist(int k,double td)
+{traveld[k]=td;}
+
+void qmpVirtualPiano3D::buildKeys()
+{
+ wkcf=new smEntity3D();wkeb=new smEntity3D();wkd=new smEntity3D();
+ wkg=new smEntity3D();wka=new smEntity3D();
+ smQuad q;q.blend=BLEND_ALPHABLEND;q.tex=0;
+ for(int i=0;i<4;++i)q.v[i].col=0xFFFFFFFF,q.v[i].tx=q.v[i].ty=0;
+ //TAL
+ configureVertex(q.v,0,-WK_TALWIDTH/2,WK_PRELEN ,WK_HEIGHT);
+ configureVertex(q.v,1, WK_TALWIDTH/2,WK_PRELEN ,WK_HEIGHT);
+ configureVertex(q.v,2, WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT);
+ configureVertex(q.v,3,-WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN,WK_HEIGHT);
+ wkcf->pushSurface(q);wkeb->pushSurface(q);wkd->pushSurface(q);
+ wkg->pushSurface(q);wka->pushSurface(q);
+ wkcf->pushCube(
+ smvec3d(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT),
+ smvec3d( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN-WK_WING,0),
+ 0xFFCCCCCC,30);
+ wkeb->pushCube(
+ smvec3d(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT),
+ smvec3d( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN-WK_WING,0),
+ 0xFFCCCCCC,30);
+ wkd->pushCube(
+ smvec3d(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT),
+ smvec3d( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN-WK_WING,0),
+ 0xFFCCCCCC,30);
+ wkg->pushCube(
+ smvec3d(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT),
+ smvec3d( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN-WK_WING,0),
+ 0xFFCCCCCC,30);
+ wka->pushCube(
+ smvec3d(-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT),
+ smvec3d( WK_TALWIDTH/2,WK_PRELEN+WK_TALLEN-WK_WING,0),
+ 0xFFCCCCCC,30);
+ //PRE
+ configureVertex(q.v,0,-WK_TALWIDTH/2,0 ,WK_HEIGHT);
+ configureVertex(q.v,1, WK_TALWIDTH/2,0 ,WK_HEIGHT);
+ configureVertex(q.v,2, WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT);
+ configureVertex(q.v,3,-WK_TALWIDTH/2,WK_PRELEN,WK_HEIGHT);
+ wkcf->pushSurface(q);wkeb->pushSurface(q);wkd->pushSurface(q);
+ wkg->pushSurface(q);wka->pushSurface(q);
+ wkcf->pushCube(
+ smvec3d(-WK_TALWIDTH/2,0,WK_HEIGHT),
+ smvec3d(-WK_TALWIDTH/2+WK_PREWIDTH,WK_PRELEN,0),
+ 0xFFCCCCCC,46);
+ wkeb->pushCube(
+ smvec3d(WK_TALWIDTH/2-WK_PREWIDTH,0,WK_HEIGHT),
+ smvec3d(WK_TALWIDTH/2,WK_PRELEN,0),
+ 0xFFCCCCCC,46);
+ wkd->pushCube(
+ smvec3d(-WK_TALWIDTH/2+(WK_TALWIDTH-WK_PREWIDTH)/2,0,WK_HEIGHT),
+ smvec3d( WK_TALWIDTH/2-(WK_TALWIDTH-WK_PREWIDTH)/2,WK_PRELEN,0),
+ 0xFFCCCCCC,46);
+ wkg->pushCube(
+ smvec3d(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12,0,WK_HEIGHT),
+ smvec3d(-WK_TALWIDTH/2+WK_WING+WK_TALWIDTH/12+WK_PREWIDTH,WK_PRELEN,0),
+ 0xFFCCCCCC,46);
+ wka->pushCube(
+ smvec3d(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24,0,WK_HEIGHT),
+ smvec3d(WK_TALWIDTH/2-WK_WING-WK_TALWIDTH/24-WK_PREWIDTH,WK_PRELEN,0),
+ 0xFFCCCCCC,46);
+
+ bk=new smEntity3D();
+ for(int i=0;i<4;++i)q.v[i].col=0xFF000000;
+ bk->pushCube(
+ smvec3d(-BK_WIDTH/2,0,BK_HEIGHT+BK_BOTTOM),
+ smvec3d( BK_WIDTH/2,BK_PRELEN,BK_BOTTOM),
+ 0xFF000000,47);
+ configureVertex(q.v,0,-BK_WIDTH/2,BK_PRELEN,BK_HEIGHT+BK_BOTTOM);
+ configureVertex(q.v,1, BK_WIDTH/2,BK_PRELEN,BK_HEIGHT+BK_BOTTOM);
+ configureVertex(q.v,2, BK_WIDTH/2,WK_PRELEN*0.95,BK_DBOTTOM+BK_BOTTOM);
+ configureVertex(q.v,3,-BK_WIDTH/2,WK_PRELEN*0.95,BK_DBOTTOM+BK_BOTTOM);
+ bk->pushSurface(q);
+ configureVertex(q.v,0,-BK_WIDTH/2,BK_PRELEN,BK_HEIGHT+BK_BOTTOM);
+ configureVertex(q.v,1,-BK_WIDTH/2,WK_PRELEN*0.95,BK_DBOTTOM+BK_BOTTOM);
+ configureVertex(q.v,2,-BK_WIDTH/2,WK_PRELEN*0.95,BK_BOTTOM);
+ configureVertex(q.v,3,-BK_WIDTH/2,BK_PRELEN,BK_BOTTOM);
+ bk->pushSurface(q);
+ configureVertex(q.v,0, BK_WIDTH/2,BK_PRELEN,BK_HEIGHT+BK_BOTTOM);
+ configureVertex(q.v,1, BK_WIDTH/2,WK_PRELEN*0.95,BK_DBOTTOM+BK_BOTTOM);
+ configureVertex(q.v,2, BK_WIDTH/2,WK_PRELEN*0.95,BK_BOTTOM);
+ configureVertex(q.v,3, BK_WIDTH/2,BK_PRELEN,BK_BOTTOM);
+ bk->pushSurface(q);
+ configureVertex(q.v,0,-BK_WIDTH/2,WK_PRELEN*0.95,BK_DBOTTOM+BK_BOTTOM);
+ configureVertex(q.v,1, BK_WIDTH/2,WK_PRELEN*0.95,BK_DBOTTOM+BK_BOTTOM);
+ configureVertex(q.v,2, BK_WIDTH/2,WK_PRELEN*0.95,BK_BOTTOM);
+ configureVertex(q.v,3,-BK_WIDTH/2,WK_PRELEN*0.95,BK_BOTTOM);
+ bk->pushSurface(q);
+ configureVertex(q.v,0,-BK_WIDTH/2,BK_PRELEN,BK_BOTTOM);
+ configureVertex(q.v,1, BK_WIDTH/2,BK_PRELEN,BK_BOTTOM);
+ configureVertex(q.v,2, BK_WIDTH/2,WK_PRELEN*0.95,BK_BOTTOM);
+ configureVertex(q.v,3,-BK_WIDTH/2,WK_PRELEN*0.95,BK_BOTTOM);
+ bk->pushSurface(q);
+}
diff --git a/visualization/qmpvirtualpiano3d.hpp b/visualization/qmpvirtualpiano3d.hpp
new file mode 100644
index 0000000..5c30718
--- /dev/null
+++ b/visualization/qmpvirtualpiano3d.hpp
@@ -0,0 +1,29 @@
+#ifndef QMPVIRTUALPIANO3D_H
+#define QMPVIRTUALPIANO3D_H
+#include <smelt.hpp>
+#include "extrasmeltutils.hpp"
+#define WK_PREWIDTH 0.8
+#define WK_TALWIDTH 1.2
+#define WK_PRELEN 3.5
+#define WK_TALLEN 2.5
+#define WK_WING 0.1
+#define WK_HEIGHT 1.5
+#define BK_WIDTH 7*(WK_TALWIDTH-WK_PREWIDTH)/5
+#define BK_FWIDTH 7*(WK_TALWIDTH-WK_PREWIDTH)/5
+#define BK_PRELEN 3.
+#define BK_HEIGHT 1.5
+#define BK_BOTTOM 0.5
+#define BK_DBOTTOM 1.
+class qmpVirtualPiano3D
+{
+ private:
+ smEntity3D *wkcf,*wkeb,*wkd,*wkg,*wka,*bk;
+ void buildKeys();
+ double traveld[128];
+ public:
+ qmpVirtualPiano3D();
+ ~qmpVirtualPiano3D();
+ void render(smvec3d p);
+ void setKeyTravelDist(int k,double td);
+};
+#endif // QMPVIRTUALPIANO3D_H
diff --git a/visualization/qmpvisualization.cpp b/visualization/qmpvisualization.cpp
index 60b1fbb..8efe07a 100644
--- a/visualization/qmpvisualization.cpp
+++ b/visualization/qmpvisualization.cpp
@@ -63,6 +63,7 @@ void qmpVisualization::showThread()
sm->smInit();shouldclose=false;
sm->smTextureOpt(TPOT_POT,TFLT_LINEAR);
chequer=sm->smTextureLoad("chequerboard.png");
+ p3d=new qmpVirtualPiano3D();
if(!chequer)
chequer=sm->smTextureLoad("/usr/share/qmidiplayer/img/chequerboard.png");
tdscn=sm->smTargetCreate(wwidth*wsupersample,wheight*wsupersample);
@@ -81,6 +82,7 @@ void qmpVisualization::show()
void qmpVisualization::close()
{
shouldclose=true;
+ delete p3d;
rendererTh->join();
sm->smFinale();
font.releaseTTF();
@@ -146,6 +148,7 @@ bool qmpVisualization::update()
//printf("pos: %f %f %f\n",pos[0],pos[1],pos[2]);
//printf("rot: %f %f %f\n",rot[0],rot[1],rot[2]);
double lpt=(double)notestretch/api->getDivision()/10.;
+ memset(notestatus,0,sizeof(notestatus));
for(uint32_t i=elb;i<pool.size();++i)
{
if(((double)pool[i]->tcs-ctk)*lpt>viewdist*2)break;
@@ -157,10 +160,21 @@ bool qmpVisualization::update()
bool isnoteon=pool[i]->tcs<=ctk&&pool[i]->tce>=ctk;if(isnoteon)
a.x=((double)pool[i]->key-64+api->getPitchBend(pool[i]->ch)),
b.x=((double)pool[i]->key-64+api->getPitchBend(pool[i]->ch))+.9;
+ notestatus[pool[i]->ch][pool[i]->key]|=isnoteon;
if(((double)pool[i]->tce-pool[i]->tcs)*lpt<minnotelength/100.)a.z=((double)pool[i]->tcs-ctk)*lpt-minnotelength/100.;
drawCube(a,b,SETA(isnoteon?accolors[pool[i]->ch]:iccolors[pool[i]->ch],int(pool[i]->vel*(isnoteon?2.0:1.6))),0);
}
}
+ for(int i=0;i<16;++i)
+ for(int j=0;j<128;++j)
+ {
+ if(notestatus[i][j])
+ if(traveld[i][j]<1)traveld[i][j]+=0.2;else traveld[i][j]=1;
+ else
+ if(traveld[i][j]>0)traveld[i][j]-=0.2;else traveld[i][j]=0;
+ }
+ for(int j=0;j<128;++j)p3d->setKeyTravelDist(j,traveld[0][j]);
+ //p3d->render(smvec3d(0,15,10));
if(playing)ctk+=(int)(1e6/(api->getRawTempo()/api->getDivision())*sm->smGetDelta());
while(pool.size()&&((double)ctk-pool[elb]->tce)*lpt>viewdist*2)++elb;
sm->smRenderEnd();
diff --git a/visualization/qmpvisualization.hpp b/visualization/qmpvisualization.hpp
index f37bddb..a161111 100644
--- a/visualization/qmpvisualization.hpp
+++ b/visualization/qmpvisualization.hpp
@@ -7,6 +7,7 @@
#include <smelt.hpp>
#include <smmath.hpp>
#include <smttfont.hpp>
+#include "qmpvirtualpiano3d.hpp"
#include "../include/qmpcorepublic.hpp"
class qmpVisualization;
@@ -49,11 +50,13 @@ class qmpVisualization:public qmpPluginIntf
SMTRG tdscn;
SMTEX chequer;
smTTFont font,font2;
+ qmpVirtualPiano3D* p3d;
float pos[3],rot[3],lastx,lasty;
uint32_t ctc,ctk,fintk,elb;
double etps;
bool shouldclose,playing;
int hvif,herif,hehif;
+ double traveld[16][128];bool notestatus[16][128];
void drawCube(smvec3d a,smvec3d b,DWORD col,SMTEX tex);
void showThread();
public:
diff --git a/visualization/visualization.pro b/visualization/visualization.pro
index f27a0e1..e4588c4 100644
--- a/visualization/visualization.pro
+++ b/visualization/visualization.pro
@@ -13,9 +13,13 @@ TEMPLATE = lib
DEFINES += VISUALIZATION_LIBRARY
-SOURCES += qmpvisualization.cpp
+SOURCES += qmpvisualization.cpp \
+ extrasmeltutils.cpp \
+ qmpvirtualpiano3d.cpp
-HEADERS += qmpvisualization.hpp
+HEADERS += qmpvisualization.hpp \
+ extrasmeltutils.hpp \
+ qmpvirtualpiano3d.hpp
unix {
target.path = /usr/lib/qmidiplayer