From 56eaa27d4daca9264dac2e822b1126cf6eb8cbf4 Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Wed, 4 May 2016 23:45:29 +0800 Subject: Piano keyboard: first steps. --- visualization/extrasmeltutils.cpp | 91 +++++++++++++++++++++++ visualization/extrasmeltutils.hpp | 19 +++++ visualization/qmpvirtualpiano3d.cpp | 141 ++++++++++++++++++++++++++++++++++++ visualization/qmpvirtualpiano3d.hpp | 29 ++++++++ visualization/qmpvisualization.cpp | 14 ++++ visualization/qmpvisualization.hpp | 3 + visualization/visualization.pro | 8 +- 7 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 visualization/extrasmeltutils.cpp create mode 100644 visualization/extrasmeltutils.hpp create mode 100644 visualization/qmpvirtualpiano3d.cpp create mode 100644 visualization/qmpvirtualpiano3d.hpp (limited to 'visualization') 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;ismRenderQuad(&tq); + } +} +void smEntity3D::drawWithTransformation(smMatrix t,smvec3d p) +{ + for(unsigned i=0;ismRenderQuad(&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 +#include +#include +class smEntity3D +{ + private: + std::vector 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 +#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 +#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;itcs-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)*lpttcs-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 #include #include +#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 -- cgit v1.2.3