From 64dfc352d7a85dad7cc4af595636d96b7ad4bc3c Mon Sep 17 00:00:00 2001 From: psperl Date: Thu, 26 Jun 2008 03:43:28 +0000 Subject: [PATCH] MilkdropWaveform added and tested as little as possible git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/trunk@1060 6778bc44-b910-0410-a7a0-be141de4315d --- src/projectM-engine/CMakeLists.txt | 3 +- src/projectM-engine/MilkdropWaveform.cpp | 358 +++++++++++++++++++++++ src/projectM-engine/MilkdropWaveform.hpp | 62 ++++ src/projectM-engine/Renderable.cpp | 5 +- src/projectM-engine/Renderable.hpp | 12 +- src/projectM-engine/Renderer.cpp | 14 +- src/projectM-engine/Renderer.hpp | 10 +- 7 files changed, 443 insertions(+), 21 deletions(-) create mode 100644 src/projectM-engine/MilkdropWaveform.cpp create mode 100644 src/projectM-engine/MilkdropWaveform.hpp diff --git a/src/projectM-engine/CMakeLists.txt b/src/projectM-engine/CMakeLists.txt index 44633088b..09e2993c6 100644 --- a/src/projectM-engine/CMakeLists.txt +++ b/src/projectM-engine/CMakeLists.txt @@ -31,7 +31,8 @@ SET(projectM_SOURCES projectM.cpp FBO.cpp InitCond.cpp Func.cpp Eval.cpp PerFrameEqn.cpp PerPointEqn.cpp fftsg.cpp KeyHandler.cpp timer.cpp wipemalloc.cpp BuiltinFuncs.cpp BuiltinParams.cpp Renderer.cpp PresetLoader.cpp PresetChooser.cpp PresetFrameIO.cpp PresetMerge.cpp PipelineContext.cpp -ConfigFile.cpp IdlePreset.cpp TextureManager.cpp TimeKeeper.cpp Filters.cpp Renderable.cpp Pipeline.cpp PerPixelMesh.cpp ${GLEW_SOURCES}) +ConfigFile.cpp IdlePreset.cpp TextureManager.cpp TimeKeeper.cpp Filters.cpp Renderable.cpp Pipeline.cpp PerPixelMesh.cpp +MilkdropWaveform.cpp ${GLEW_SOURCES}) if (USE_DEVIL) SET (projectM_SOURCES ${projectM_SOURCES}) diff --git a/src/projectM-engine/MilkdropWaveform.cpp b/src/projectM-engine/MilkdropWaveform.cpp new file mode 100644 index 000000000..589493ea9 --- /dev/null +++ b/src/projectM-engine/MilkdropWaveform.cpp @@ -0,0 +1,358 @@ +/* + * MilkdropWaveform.cpp + * + * Created on: Jun 25, 2008 + * Author: pete + */ + + +#include "MilkdropWaveform.hpp" +#include "math.h" + +MilkdropWaveform::MilkdropWaveform() + : x(0.5), y(0.5), r(1), g(0), b(0), a(1), mystery(0), mode(Line), scale(10), smoothing(0), rot(0), samples(0),modOpacityStart(0),modOpacityEnd(1), + modulateAlphaByVolume(false), maximizeColors(false), additive(false), dots(false), thick(false), loop(false) {} + +void MilkdropWaveform::Draw(RenderContext &context) +{ + WaveformMath(context); + + glMatrixMode( GL_MODELVIEW ); + glPushMatrix(); + glLoadIdentity(); + + if(modulateAlphaByVolume) ModulateOpacityByVolume(context); + MaximizeColors(context); + + #ifndef USE_GLES1 + if(dots==1) glEnable(GL_LINE_STIPPLE); + #endif + + //Thick wave drawing + if (thick==1) glLineWidth( (context.texsize < 512 ) ? 2 : 2*context.texsize/512); + else glLineWidth( (context.texsize < 512 ) ? 1 : context.texsize/512); + + //Additive wave drawing (vice overwrite) + if (additive==0) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + else glBlendFunc(GL_SRC_ALPHA, GL_ONE); + + glTranslatef(.5, .5, 0); + glRotatef(rot, 0, 0, 1); + glScalef(aspectScale, 1.0, 1.0); + glTranslatef(-.5, -.5, 0); + + + glEnableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + glVertexPointer(2,GL_FLOAT,0,wavearray); + + if (loop) + glDrawArrays(GL_LINE_LOOP,0,samples); + else + glDrawArrays(GL_LINE_STRIP,0,samples); + + + if (two_waves) + { + glVertexPointer(2,GL_FLOAT,0,wavearray2); + if (loop) + glDrawArrays(GL_LINE_LOOP,0,samples); + else + glDrawArrays(GL_LINE_STRIP,0,samples); + } + + + #ifndef USE_GLES1 + if(dots==1) glDisable(GL_LINE_STIPPLE); + #endif + + glPopMatrix(); +} + +void MilkdropWaveform::ModulateOpacityByVolume(RenderContext &context) +{ + + //modulate volume by opacity + // + //set an upper and lower bound and linearly + //calculate the opacity from 0=lower to 1=upper + //based on current volume + + if (context.beatDetect->vol<= modOpacityStart) a=0.0; + else if (context.beatDetect->vol>=modOpacityEnd) a=a; + else a*=((context.beatDetect->vol-modOpacityStart)/(modOpacityEnd-modOpacityStart)); + +} + +void MilkdropWaveform::MaximizeColors(RenderContext &context) +{ + + float wave_r_switch=0, wave_g_switch=0, wave_b_switch=0; + //wave color brightening + // + //forces max color value to 1.0 and scales + // the rest accordingly + if(mode==Blob2 || mode==Blob5) + switch(context.texsize) + { + case 256: a *= 0.07f; break; + case 512: a *= 0.09f; break; + case 1024: a *= 0.11f; break; + case 2048: a *= 0.13f; break; + } + else if(mode==Blob3) + { + switch(context.texsize) + { + case 256: a *= 0.075f; break; + case 512: a *= 0.15f; break; + case 1024: a *= 0.22f; break; + case 2048: a *= 0.33f; break; + } + a*=1.3f; + a*=powf(context.beatDetect->treb , 2.0f); + } + + if (maximizeColors==true) + { + if(r>=g && r>=b) //red brightest + { + wave_b_switch=b*(1/r); + wave_g_switch=g*(1/r); + wave_r_switch=1.0; + } + else if (b>=g && b>=r) //blue brightest + { + wave_r_switch=r*(1/b); + wave_g_switch=g*(1/b); + wave_b_switch=1.0; + + } + + else if (g>=b && g>=r) //green brightest + { + wave_b_switch=b*(1/g); + wave_r_switch=r*(1/g); + wave_g_switch=1.0; + } + + + glColor4f(wave_r_switch, wave_g_switch, wave_b_switch, a); + } + else + { + glColor4f(r, g, b, a); + } + +} + + +void MilkdropWaveform::WaveformMath(RenderContext &context) +{ + + int i; + + float r, theta; + + float offset; + + float wave_x_temp=0; + float wave_y_temp=0; + + float cos_rot; + float sin_rot; + + offset=x-.5; + float temp_y; + + two_waves = false; + loop = false; + + switch(mode) + { + + case RadialBlob: + { + loop = true; + rot = 0; + aspectScale=1.0; + temp_y=-1*(y-1.0); + + + samples = 0? 512-32 : context.beatDetect->pcm->numsamples; + + float inv_nverts_minus_one = 1.0f/(float)(samples); + + float last_value = context.beatDetect->pcm->pcmdataR[samples-1]+context.beatDetect->pcm->pcmdataL[samples-1]; + float first_value = context.beatDetect->pcm->pcmdataR[0]+context.beatDetect->pcm->pcmdataL[0]; + float offset = first_value-last_value; + + for ( int i=0;ipcm->pcmdataR[i]+context.beatDetect->pcm->pcmdataL[i]; + value += offset * (x/(float)samples); + + r=(0.5 + 0.4f*.12*value*scale + mystery)*.5; + theta=(x)*inv_nverts_minus_one*6.28f + context.time*0.2f; + + wavearray[i][0]=(r*cos(theta)*(context.aspectCorrect? context.aspectRatio : 1.0)+x); + wavearray[i][1]=(r*sin(theta)+temp_y); + } + } + + break; + + case 1://circularly moving waveform + + rot = 0; + aspectScale = context.aspectRatio; + + temp_y=-1*(y-1.0); + + samples = 512-32; + for ( int i=0;i<512-32;i++) + { + theta=context.beatDetect->pcm->pcmdataL[i+32]*0.06*scale * 1.57 + context.time*2.3; + r=(0.53 + 0.43*context.beatDetect->pcm->pcmdataR[i]*0.12*scale+ mystery)*.5; + + wavearray[i][0]=(r*cos(theta)*(context.aspectCorrect ? context.aspectRatio : 1.0)+i); + wavearray[i][1]=(r*sin(theta)+temp_y); + } + + break; + + case Blob2://EXPERIMENTAL + + temp_y=-1*(y-1.0); + rot = 0; + aspectScale =1.0; + samples = 512-32; + + for ( int i=0;i<512-32;i++) + { + wavearray[i][0]=(context.beatDetect->pcm->pcmdataR[i]*scale*0.5*(context.aspectCorrect ? context.aspectRatio : 1.0) + x); + wavearray[i][1]=(context.beatDetect->pcm->pcmdataL[i+32]*scale*0.5 + temp_y); + } + + break; + + case Blob3://EXPERIMENTAL + + temp_y=-1*(y-1.0); + + rot = 0; + aspectScale =1.0; + + samples = 512-32; + + for ( int i=0;i<512-32;i++) + { + wavearray[i][0]=(context.beatDetect->pcm->pcmdataR[i] * scale*0.5 + x); + wavearray[i][1]=( (context.beatDetect->pcm->pcmdataL[i+32]*scale*0.5 + temp_y)); + } + + break; + + case DerivativeLine://single x-axis derivative waveform + { + rot =-mystery*90; + aspectScale=1.0; + + temp_y=-1*(y-1.0); + + float w1 = 0.45f + 0.5f*(mystery*0.5f + 0.5f); + float w2 = 1.0f - w1; + float xx[512], yy[512]; + samples = 512-32; + + for (int i=0; i<512-32; i++) + { + xx[i] = -1.0f + 2.0f*(i/(512.0-32.0)) + x; + yy[i] =0.4* context.beatDetect->pcm->pcmdataL[i]*0.47f*scale + temp_y; + xx[i] += 0.4*context.beatDetect->pcm->pcmdataR[i]*0.44f*scale; + + if (i>1) + { + xx[i] = xx[i]*w2 + w1*(xx[i-1]*2.0f - xx[i-2]); + yy[i] = yy[i]*w2 + w1*(yy[i-1]*2.0f - yy[i-2]); + } + wavearray[i][0]=xx[i]; + wavearray[i][1]=yy[i]; + } } + break; + + case Blob5://EXPERIMENTAL + + rot = 0; + aspectScale =1.0; + + temp_y=-1*(y-1.0); + + cos_rot = cosf(context.time*0.3f); + sin_rot = sinf(context.time*0.3f); + samples = 512-32; + + for ( int i=0;i<512-32;i++) + { + float x0 = (context.beatDetect->pcm->pcmdataR[i]*context.beatDetect->pcm->pcmdataL[i+32] + context.beatDetect->pcm->pcmdataL[i+32]*context.beatDetect->pcm->pcmdataR[i]); + float y0 = (context.beatDetect->pcm->pcmdataR[i]*context.beatDetect->pcm->pcmdataR[i] - context.beatDetect->pcm->pcmdataL[i+32]*context.beatDetect->pcm->pcmdataL[i+32]); + wavearray[i][0]=((x0*cos_rot - y0*sin_rot)*scale*0.5*(context.aspectCorrect ? context.aspectRatio : 1.0) + x); + wavearray[i][1]=( (x0*sin_rot + y0*cos_rot)*scale*0.5 + temp_y); + } + break; + + case Line://single waveform + + + wave_x_temp=-2*0.4142*(fabs(fabs(mystery)-.5)-.5); + + rot = -mystery*90; + aspectScale =1.0+wave_x_temp; + wave_x_temp=-1*(x-1.0); + samples = 0 ? 512-32 : context.beatDetect->pcm->numsamples; + + for ( int i=0;i< samples;i++) + { + + wavearray[i][0]=i/(float) samples; + wavearray[i][1]=context.beatDetect->pcm->pcmdataR[i]*.04*scale+wave_x_temp; + + } + // printf("%f %f\n",renderTarget->texsize*wave_y_temp,wave_y_temp); + + break; + + case DoubleLine://dual waveforms + + + wave_x_temp=-2*0.4142*(fabs(fabs(mystery)-.5)-.5); + + rot = -mystery*90; + aspectScale =1.0+wave_x_temp; + + + samples = 0 ? 512-32 : context.beatDetect->pcm->numsamples; + two_waves = true; + + double y_adj = y*y*.5; + + wave_y_temp=-1*(x-1); + + for ( int i=0;ipcm->pcmdataL[i]*.04*scale+(wave_y_temp+y_adj); + } + + for ( int i=0;ipcm->pcmdataR[i]*.04*scale+(wave_y_temp-y_adj); + } + + break; + + } +} diff --git a/src/projectM-engine/MilkdropWaveform.hpp b/src/projectM-engine/MilkdropWaveform.hpp new file mode 100644 index 000000000..3e3f6ab26 --- /dev/null +++ b/src/projectM-engine/MilkdropWaveform.hpp @@ -0,0 +1,62 @@ +/* + * MilkdropWaveform.hpp + * + * Created on: Jun 25, 2008 + * Author: pete + */ + +#ifndef MILKDROPWAVEFORM_HPP_ +#define MILKDROPWAVEFORM_HPP_ + +#include "Renderable.hpp" + +class MilkdropWaveform : public RenderItem +{ +public: + + enum MilkdropWaveformMode + { + RadialBlob, Circle, Blob2, Blob3, DerivativeLine, Blob5, Line, DoubleLine + }; + + float x; + float y; + + float r; + float g; + float b; + float a; + + float mystery; + + MilkdropWaveformMode mode; + + bool additive; + bool dots; + bool thick; + bool modulateAlphaByVolume; + bool maximizeColors; + float scale; + float smoothing; + + MilkdropWaveform(); + void Draw(RenderContext &context); + + float modOpacityStart; + float modOpacityEnd; + +private: + float rot; + float aspectScale; + int samples; + bool two_waves; + bool loop; + float wavearray[2048][2]; + float wavearray2[2048][2]; + + void MaximizeColors(RenderContext &context); + void ModulateOpacityByVolume(RenderContext &context); + void WaveformMath(RenderContext &context); + +}; +#endif /* MILKDROPWAVEFORM_HPP_ */ diff --git a/src/projectM-engine/Renderable.cpp b/src/projectM-engine/Renderable.cpp index cd2304f5a..17a175600 100644 --- a/src/projectM-engine/Renderable.cpp +++ b/src/projectM-engine/Renderable.cpp @@ -16,7 +16,8 @@ #include RenderContext::RenderContext() - :texsize(512), aspectRatio(1), aspectCorrect(false){}; + : time(0),texsize(512), aspectRatio(1), aspectCorrect(false){}; + Shape::Shape() { @@ -73,7 +74,7 @@ void Shape::Draw(RenderContext &context) { if (imageUrl !="") { - GLuint tex = textureManager->getTexture(imageUrl); + GLuint tex = context.textureManager->getTexture(imageUrl); if (tex != 0) { glBindTexture(GL_TEXTURE_2D, tex); diff --git a/src/projectM-engine/Renderable.hpp b/src/projectM-engine/Renderable.hpp index ae4f94979..43eeef3d7 100644 --- a/src/projectM-engine/Renderable.hpp +++ b/src/projectM-engine/Renderable.hpp @@ -3,13 +3,17 @@ #include #include "TextureManager.hpp" +#include "BeatDetect.hpp" class RenderContext { public: + float time; int texsize; float aspectRatio; bool aspectCorrect; + BeatDetect *beatDetect; + TextureManager *textureManager; RenderContext(); }; @@ -20,13 +24,7 @@ public: virtual void Draw(RenderContext &context) = 0; }; -class TexturedItem -{ -public: - TextureManager *textureManager; -}; - -class Shape : public TexturedItem, public RenderItem +class Shape : public RenderItem { public: std::string imageUrl; diff --git a/src/projectM-engine/Renderer.cpp b/src/projectM-engine/Renderer.cpp index a5b8ab9cd..c9fa6f8c3 100644 --- a/src/projectM-engine/Renderer.cpp +++ b/src/projectM-engine/Renderer.cpp @@ -134,7 +134,7 @@ myCgContext = cgCreateContext(); cgGLSetDebugMode( CG_FALSE ); cgSetParameterSettingMode(myCgContext, CG_DEFERRED_PARAMETER_SETTING); - + myCgProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); cgGLSetOptimalOptions(myCgProfile); checkForCgError("selecting fragment profile"); @@ -151,7 +151,7 @@ myCgContext = cgCreateContext(); cgGLLoadProgram(myCgWarpProgram); checkForCgError("loading fragment program"); - + myCgCompositeProgram = cgCreateProgramFromFile( @@ -181,7 +181,7 @@ void Renderer::ResetTextures() textureManager->Preload(); } -void Renderer::RenderFrame(const Pipeline* pipeline) +void Renderer::RenderFrame(const Pipeline* pipeline, const PipelineContext &pipelineContext) { glMatrixMode(GL_PROJECTION); @@ -233,9 +233,12 @@ void Renderer::RenderFrame(const Pipeline* pipeline) checkForCgError("disabling fragment profile"); #endif + renderContext.time = pipelineContext.time; renderContext.texsize = texsize; renderContext.aspectCorrect = correction; renderContext.aspectRatio = aspect; + renderContext.textureManager = textureManager; + renderContext.beatDetect = beatDetect; for (std::vector::const_iterator pos = pipeline->drawables.begin(); pos != pipeline->drawables.end(); ++pos) (*pos)->Draw(renderContext); @@ -583,10 +586,7 @@ void Renderer::Interpolation(const Pipeline *pipeline) } Pipeline* Renderer::currentPipe; -Point Renderer::PerPixel(Point p, PerPixelContext context) -{ -return currentPipe->PerPixel(p,context); -} + Renderer::~Renderer() { diff --git a/src/projectM-engine/Renderer.hpp b/src/projectM-engine/Renderer.hpp index 318410600..4080a1ab1 100644 --- a/src/projectM-engine/Renderer.hpp +++ b/src/projectM-engine/Renderer.hpp @@ -71,7 +71,7 @@ public: Renderer( int width, int height, int gx, int gy, int texsize, BeatDetect *beatDetect, std::string presetURL, std::string title_fontURL, std::string menu_fontURL); ~Renderer(); void RenderFrame(PresetOutputs *presetOutputs, PresetInputs *presetInputs); - void RenderFrame(const Pipeline *pipeline); + void RenderFrame(const Pipeline *pipeline, const PipelineContext &pipelineContext); void ResetTextures(); void reset(int w, int h); GLuint initRenderToTexture(); @@ -117,7 +117,7 @@ private: CGcontext myCgContext; CGprofile myCgProfile; - + CGprogram myCgWarpProgram, myCgCompositeProgram; @@ -145,8 +145,10 @@ void SetupCg(); void CompositeOutput(const Pipeline* pipeline); void Interpolation(const Pipeline* pipeline); - static Point PerPixel(Point p, PerPixelContext context); - + inline static Point PerPixel(Point p, PerPixelContext &context) + { + return currentPipe->PerPixel(p,context); + } void Interpolation(PresetOutputs *presetOutputs, PresetInputs *presetInputs);