void Fluid2DTextureApp::keyDown( KeyEvent event ) { switch( event.getCode() ) { case KeyEvent::KEY_r: mFluid2D.resetTexCoords(); break; case KeyEvent::KEY_c: mFluid2D.clearAll(); break; } }
void Fluid2DBasicApp::touchesMoved( TouchEvent event ) { const std::vector<TouchEvent::Touch>& touches = event.getTouches(); for( std::vector<TouchEvent::Touch>::const_iterator cit = touches.begin(); cit != touches.end(); ++cit ) { Vec2f prevPos = cit->getPrevPos(); Vec2f pos = cit->getPos(); float x = (pos.x/(float)getWindowWidth())*mFluid2D.resX(); float y = (pos.y/(float)getWindowHeight())*mFluid2D.resY(); Vec2f dv = pos - prevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); mFluid2D.splatDensity( x, y, mDenScale ); } }
void Fluid2DCamAppApp::mouseDrag( MouseEvent event ) { float x = (event.getX()/(float)getWindowWidth())*mFluid2D.resX(); float y = (event.getY()/(float)getWindowHeight())*mFluid2D.resY(); if( event.isLeftDown() ) { Vec2f dv = event.getPos() - mPrevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); mFluid2D.splatDensity( x, y, mDenScale ); } mPrevPos = event.getPos(); }
void Fluid2DTextureApp::mouseDrag( MouseEvent event ) { float x = (event.getX()/(float)getWindowWidth())*mFluid2D.resX(); float y = (event.getY()/(float)getWindowHeight())*mFluid2D.resY(); if( event.isLeftDown() ) { vec2 dv = vec2( event.getPos() ) - mPrevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); if( mFluid2D.isBuoyancyEnabled() ) { mFluid2D.splatDensity( x, y, mDenScale ); } } mPrevPos = event.getPos(); }
void Fluid2DBasicApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); Channel32f chan( mFluid2D.resX(), mFluid2D.resY(), mFluid2D.resX()*sizeof(float), 1, const_cast<float*>( mFluid2D.density().data() ) ); if( ! mTex ) { mTex = gl::Texture( chan ); } else { mTex.update( chan ); } gl::color( Color( 1, 1, 1 ) ); gl::draw( mTex, getWindowBounds() ); mParams.draw(); }
void Fluid2DParticlesApp::keyDown( KeyEvent event ) { switch( event.getCode() ) { case KeyEvent::KEY_r: mFluid2D.initSimData(); break; } }
void Fluid2DRGBApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); //RenderFluidRgb( mFluid2D, getWindowBounds() ); float* data = const_cast<float*>( (float*)mFluid2D.rgb().data() ); Surface32f surf( data, mFluid2D.resX(), mFluid2D.resY(), mFluid2D.resX()*sizeof(Colorf), SurfaceChannelOrder::RGB ); if ( ! mTex ) { mTex = gl::Texture::create( surf ); } else { mTex->update( surf ); } gl::draw( mTex, getWindowBounds() ); mParams.draw(); }
void Fluid2DParticlesApp::touchesMoved( TouchEvent event ) { float s = 10; const std::vector<TouchEvent::Touch>& touches = event.getTouches(); for( std::vector<TouchEvent::Touch>::const_iterator cit = touches.begin(); cit != touches.end(); ++cit ) { if( mTouchColors.find( cit->getId() ) == mTouchColors.end() ) continue; vec2 prevPos = cit->getPrevPos(); vec2 pos = cit->getPos(); float x = (pos.x/(float)getWindowWidth())*mFluid2D.resX(); float y = (pos.y/(float)getWindowHeight())*mFluid2D.resY(); vec2 dv = pos - prevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); mFluid2D.splatRgb( x, y, mRgbScale*mTouchColors[cit->getId()] ); if( mFluid2D.isBuoyancyEnabled() ) { mFluid2D.splatDensity( x, y, mDenScale ); } for( int i = 0; i < 5; ++i ) { vec2 partPos = pos + vec2( Rand::randFloat( -s, s ), Rand::randFloat( -s, s ) ); float life = Rand::randFloat( 3.0f, 6.0f ); mParticles.append( Particle( partPos, life, mTouchColors[cit->getId()] ) ); } } }
void Fluid2DTextureApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); gl::setMatricesWindow( getWindowWidth(), getWindowHeight() ); // Update the positions and tex coords Rectf drawRect = getWindowBounds(); int limX = mFluid2D.resX() - 1; int limY = mFluid2D.resY() - 1; float dx = drawRect.getWidth()/(float)limX; float dy = drawRect.getHeight()/(float)limY; for( int j = 0; j < mFluid2D.resY(); ++j ) { for( int i = 0; i < mFluid2D.resX(); ++i ) { vec2 P = vec2( i*dx, j*dy ); vec2 uv = mFluid2D.texCoordAt( i, j ); int idx = j*mFluid2D.resX() + i; mTriMesh->getPositions<2>()[idx] = P; mTriMesh->getTexCoords0<2>()[idx] = uv; } } mTex->bind(); gl::bindStockShader( gl::ShaderDef().color().texture() ); gl::draw( gl::VboMesh::create(*mTriMesh) ); mTex->unbind(); mParams.draw(); }
void Fluid2DTextureApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); gl::setMatricesWindow( getWindowWidth(), getWindowHeight() ); // Update the positions and tex coords Rectf drawRect = getWindowBounds(); int limX = mFluid2D.resX() - 1; int limY = mFluid2D.resY() - 1; float dx = drawRect.getWidth()/(float)limX; float dy = drawRect.getHeight()/(float)limY; for( int j = 0; j < mFluid2D.resY(); ++j ) { for( int i = 0; i < mFluid2D.resX(); ++i ) { Vec2f P = Vec2f( i*dx, j*dy ); Vec2f uv = mFluid2D.texCoordAt( i, j ); int idx = j*mFluid2D.resX() + i; mTriMesh.getVertices()[idx] = P; mTriMesh.getTexCoords()[idx] = uv; } } mTex.bind(); gl::draw( mTriMesh ); mTex.unbind(); mParams.draw(); }
void Fluid2DParticleSoupApp::touchesMoved( TouchEvent event ) { const std::vector<TouchEvent::Touch>& touches = event.getTouches(); for( std::vector<TouchEvent::Touch>::const_iterator cit = touches.begin(); cit != touches.end(); ++cit ) { vec2 prevPos = cit->getPrevPos(); vec2 pos = cit->getPos(); float x = (pos.x/(float)getWindowWidth())*mFluid2D.resX(); float y = (pos.y/(float)getWindowHeight())*mFluid2D.resY(); vec2 dv = pos - prevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); mFluid2D.splatRgb( x, y, mRgbScale*mColor ); if( mFluid2D.isBuoyancyEnabled() ) { mFluid2D.splatDensity( x, y, mDenScale ); } } }
void Fluid2DParticleSoupApp::mouseDrag( MouseEvent event ) { float x = (event.getX()/(float)getWindowWidth())*mFluid2D.resX(); float y = (event.getY()/(float)getWindowHeight())*mFluid2D.resY(); if( event.isLeftDown() ) { Vec2f dv = event.getPos() - mPrevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); mFluid2D.splatRgb( x, y, mRgbScale*mColor ); if( mFluid2D.isBuoyancyEnabled() ) { mFluid2D.splatDensity( x, y, mDenScale ); } } mPrevPos = event.getPos(); }
void Fluid2DParticlesApp::mouseDrag( MouseEvent event ) { float x = (event.getX()/(float)getWindowWidth())*mFluid2D.resX(); float y = (event.getY()/(float)getWindowHeight())*mFluid2D.resY(); float s = 10; if( event.isLeftDown() ) { vec2 dv = vec2( event.getPos() ) - mPrevPos; mFluid2D.splatVelocity( x, y, mVelScale*dv ); mFluid2D.splatRgb( x, y, mRgbScale*mColor ); if( mFluid2D.isBuoyancyEnabled() ) { mFluid2D.splatDensity( x, y, mDenScale ); } // for( int i = 0; i < 10; ++i ) { vec2 partPos = vec2( event.getPos() ) + vec2( Rand::randFloat( -s, s ), Rand::randFloat( -s, s ) ); float life = Rand::randFloat( 2.0f, 4.0f ); mParticles.append( Particle( partPos, life, mColor ) ); } } mPrevPos = event.getPos(); }
void Fluid2DBasicApp::update() { mFluid2D.step(); }
void Fluid2DTextureApp::setup() { mFrameRate = 0.0f; mTex = gl::Texture::create( loadImage( loadResource( RES_IMAGE ) ) ); mFluid2D.enableTexCoord(); mFluid2D.setTexCoordViscosity( 1.0f ); mDenScale = 50; mFluid2D.set( 192, 192 ); mFluid2D.setDensityDissipation( 0.99f ); mVelScale = 0.50f*std::max( mFluid2D.resX(), mFluid2D.resY() ); mParams = params::InterfaceGl( "Params", ivec2( 300, 400 ) ); mParams.addParam( "Stam Step", mFluid2D.stamStepAddr() ); mParams.addSeparator(); mParams.addParam( "Velocity Input Scale", &mVelScale, "min=0 max=10000 step=1" ); mParams.addParam( "Density Input Scale", &mDenScale, "min=0 max=1000 step=1" ); mParams.addSeparator(); mParams.addParam( "Velocity Dissipation", mFluid2D.velocityDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addParam( "Density Dissipation", mFluid2D.densityDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addParam( "TexCoord Dissipation", mFluid2D.texCoordDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addSeparator(); mParams.addParam( "Velocity Viscosity", mFluid2D.velocityViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addParam( "Density Viscosity", mFluid2D.densityViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addParam( "TexCoord Viscosity", mFluid2D.texCoordViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addSeparator(); //mParams.addParam( "Vorticity Confinement", mFluid2D.enableVorticityConfinementAddr() ); //mParams.addSeparator(); std::vector<std::string> boundaries; boundaries.push_back( "None" ); boundaries.push_back( "Wall" ); boundaries.push_back( "Wrap" ); mParams.addParam( "Boundary Type", boundaries, mFluid2D.boundaryTypeAddr() ); mParams.addSeparator(); mParams.addParam( "Enable Buoyancy", mFluid2D.enableBuoyancyAddr() ); mParams.addParam( "Buoyancy Scale", mFluid2D.buoyancyScaleAddr(), "min=0 max=100 step=0.001" ); mParams.addParam( "Vorticity Scale", mFluid2D.vorticityScaleAddr(), "min=0 max=1 step=0.001" ); mTriMesh = ci::TriMesh::create( TriMesh::Format().positions(2).texCoords0(2) ); // Points and texture coordinates for( int j = 0; j < mFluid2D.resY(); ++j ) { for( int i = 0; i < mFluid2D.resX(); ++i ) { mTriMesh->appendPosition( vec2( 0.0f, 0.0f ) ); mTriMesh->appendTexCoord0( vec2( 0.0f, 0.0f ) ); } } // Triangles for( int j = 0; j < mFluid2D.resY() - 1; ++j ) { for( int i = 0; i < mFluid2D.resX() - 1; ++i ) { int idx0 = (j + 0)*mFluid2D.resX() + (i + 0 ); int idx1 = (j + 1)*mFluid2D.resX() + (i + 0 ); int idx2 = (j + 1)*mFluid2D.resX() + (i + 1 ); int idx3 = (j + 0)*mFluid2D.resX() + (i + 1 ); mTriMesh->appendTriangle( idx0, idx1, idx2 ); mTriMesh->appendTriangle( idx0, idx2, idx3 ); } } //console() << mFluid2D << std::endl; }
void Fluid2DTextureApp::update() { mFluid2D.step(); mFrameRate = getAverageFps(); }
void Fluid2DRGBApp::update() { mFluid2D.step(); }
void Fluid2DCamAppApp::setup() { glEnable( GL_TEXTURE_2D ); mVelThreshold = 0.75f; mNumActiveFlowVectors = 0; #if defined( CINDER_MSW ) mVelScale = 0.5f; mDenScale = 0.0025f; #elif defined( CINDER_MAC ) mVelScale = 2.0f; mDenScale = 0.007f; #endif mFluid2D.set( mFluid2DResX, mFluid2DResY ); mFluid2D.enableDensity(); mFluid2D.enableVorticityConfinement(); mFluid2D.setNumPressureIters( 24 ); mFluid2D.initSimData(); // Create these so we can create the textures ahead of time mSurfVel0 = Surface32f( mFluid2DResX, mFluid2DResY, false, SurfaceChannelOrder::RGB ); mSurfVel1 = Surface32f( mFluid2DResX, mFluid2DResY, false, SurfaceChannelOrder::RGB ); mChanDen0 = Channel32f( mFluid2DResX, mFluid2DResY ); mChanDen1 = Channel32f( mFluid2DResX, mFluid2DResY ); mChanDiv = Channel32f( mFluid2DResX, mFluid2DResY ); mChanPrs = Channel32f( mFluid2DResX, mFluid2DResY ); mChanCurl = Channel32f( mFluid2DResX, mFluid2DResY ); mChanCurlLen = Channel32f( mFluid2DResX, mFluid2DResY ); mTexVel0 = gl::Texture( mSurfVel0 ); mTexVel1 = gl::Texture( mSurfVel1 ); mTexDen0 = gl::Texture( mChanDen0 ); mTexDen1 = gl::Texture( mChanDen1 ); mTexDiv = gl::Texture( mChanDiv ); mTexPrs = gl::Texture( mChanPrs ); mTexCurl = gl::Texture( mChanCurl ); mTexCurlLen = gl::Texture( mChanCurlLen ); mParams = params::InterfaceGl( "Params", Vec2i( 300, 400 ) ); mParams.addParam( "Stam Step", mFluid2D.stamStepAddr() ); mParams.addSeparator(); mParams.addParam( "Velocity Threshold", &mVelThreshold, "min=0 max=2 step=0.001" ); mParams.addSeparator(); mParams.addParam( "Velocity Input Scale", &mVelScale, "min=0 max=10 step=0.001" ); mParams.addParam( "Density Input Scale", &mDenScale, "min=0 max=1 step=0.0001" ); mParams.addSeparator(); mParams.addParam( "Velocity Dissipation", mFluid2D.velocityDissipationAddr(), "min=0 max=1 step=0.0001" ); mParams.addParam( "Density Dissipation", mFluid2D.densityDissipationAddr(), "min=0 max=1 step=0.0001" ); mParams.addSeparator(); mParams.addParam( "Velocity Viscosity", mFluid2D.velocityViscosityAddr(), "min=0 max=10 step=0.000001" ); mParams.addParam( "Density Viscosity", mFluid2D.densityViscosityAddr(), "min=0 max=10 step=0.000001" ); mParams.addSeparator(); mParams.addParam( "Vorticity Confinement", mFluid2D.enableVorticityConfinementAddr() ); mParams.addSeparator(); std::vector<std::string> boundaries; boundaries.push_back( "None" ); boundaries.push_back( "Wall" ); boundaries.push_back( "Wrap" ); mParams.addParam( "Boundary Type", boundaries, mFluid2D.boundaryTypeAddr() ); mParams.addSeparator(); mParams.addParam( "Enable Buoyancy", mFluid2D.enableBuoyancyAddr() ); mParams.addParam( "Buoyancy Scale", mFluid2D.buoyancyScaleAddr(), "min=0 max=100 step=0.001" ); mParams.addParam( "Vorticity Scale", mFluid2D.vorticityScaleAddr(), "min=0 max=1 step=0.001" ); // Camera try { mCapture = Capture( 640, 480 ); mCapture.start(); } catch( ... ) { console() << "Failed to initialize capture" << std::endl; } }
void Fluid2DParticlesApp::update() { mFluid2D.step(); mParticles.update(); }
void Fluid2DParticleSoupApp::setup() { glEnable( GL_TEXTURE_2D ); mDenScale = 50; mRgbScale = 40; mFluid2D.set( 192, 192 ); mFluid2D.setDensityDissipation( 0.99f ); mFluid2D.setRgbDissipation( 0.99f ); mVelScale = 3.0f*std::max( mFluid2D.resX(), mFluid2D.resY() ); mParams = params::InterfaceGl( "Params", Vec2i( 300, 400 ) ); mParams.addParam( "Stam Step", mFluid2D.stamStepAddr() ); mParams.addSeparator(); mParams.addParam( "Velocity Input Scale", &mVelScale, "min=0 max=10000 step=1" ); mParams.addParam( "Density Input Scale", &mDenScale, "min=0 max=1000 step=1" ); mParams.addParam( "Rgb Input Scale", &mRgbScale, "min=0 max=1000 step=1" ); mParams.addSeparator(); mParams.addParam( "Velocity Dissipation", mFluid2D.velocityDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addParam( "Density Dissipation", mFluid2D.densityDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addParam( "Rgb Dissipation", mFluid2D.rgbDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addSeparator(); mParams.addParam( "Velocity Viscosity", mFluid2D.velocityViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addParam( "Density Viscosity", mFluid2D.densityViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addParam( "Rgb Viscosity", mFluid2D.rgbViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addSeparator(); mParams.addParam( "Vorticity Confinement", mFluid2D.enableVorticityConfinementAddr() ); mParams.addSeparator(); std::vector<std::string> boundaries; boundaries.push_back( "None" ); boundaries.push_back( "Wall" ); boundaries.push_back( "Wrap" ); mParams.addParam( "Boundary Type", boundaries, mFluid2D.boundaryTypeAddr() ); mParams.addSeparator(); mParams.addParam( "Enable Buoyancy", mFluid2D.enableBuoyancyAddr() ); mParams.addParam( "Buoyancy Scale", mFluid2D.buoyancyScaleAddr(), "min=0 max=100 step=0.001" ); mParams.addParam( "Vorticity Scale", mFluid2D.vorticityScaleAddr(), "min=0 max=1 step=0.001" ); mFluid2D.setRgbDissipation( 0.9930f ); mFluid2D.enableDensity(); mFluid2D.enableRgb(); mFluid2D.enableVorticityConfinement(); mFluid2D.initSimData(); mParticleSoup.setup( &mFluid2D ); mColor = Colorf( 0.98f, 0.7f, 0.4f ); }
void Fluid2DParticleSoupApp::update() { mFluid2D.step(); mParticleSoup.setColor( mColor ); mParticleSoup.update(); }
void Fluid2DParticlesApp::setup() { glEnable( GL_TEXTURE_2D ); gl::enableAlphaBlending(); gl::enableAdditiveBlending(); mRgbScale = 50; mDenScale = 50; mFluid2D.set( 192, 192 ); mFluid2D.setDensityDissipation( 0.99f ); mFluid2D.setRgbDissipation( 0.99f ); mVelScale = 3.0f*std::max( mFluid2D.resX(), mFluid2D.resY() ); mParams = params::InterfaceGl( "Params", ivec2( 300, 400 ) ); mParams.addParam( "Stam Step", mFluid2D.stamStepAddr() ); mParams.addSeparator(); mParams.addParam( "Velocity Input Scale", &mVelScale, "min=0 max=10000 step=1" ); mParams.addParam( "Density Input Scale", &mDenScale, "min=0 max=1000 step=1" ); mParams.addParam( "Rgb Input Scale", &mRgbScale, "min=0 max=1000 step=1" ); mParams.addSeparator(); mParams.addParam( "Velocity Dissipation", mFluid2D.velocityDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addParam( "Density Dissipation", mFluid2D.densityDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addParam( "Rgb Dissipation", mFluid2D.rgbDissipationAddr(), "min=0.0001 max=1 step=0.0001" ); mParams.addSeparator(); mParams.addParam( "Velocity Viscosity", mFluid2D.velocityViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addParam( "Density Viscosity", mFluid2D.densityViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addParam( "Rgb Viscosity", mFluid2D.rgbViscosityAddr(), "min=0.000001 max=10 step=0.000001" ); mParams.addSeparator(); mParams.addSeparator(); mParams.addParam( "Vorticity Confinement", mFluid2D.enableVorticityConfinementAddr() ); mParams.addSeparator(); std::vector<std::string> boundaries; boundaries.push_back( "None" ); boundaries.push_back( "Wall" ); boundaries.push_back( "Wrap" ); mParams.addParam( "Boundary Type", boundaries, mFluid2D.boundaryTypeAddr() ); mParams.addSeparator(); mParams.addParam( "Enable Buoyancy", mFluid2D.enableBuoyancyAddr() ); mParams.addParam( "Buoyancy Scale", mFluid2D.buoyancyScaleAddr(), "min=0 max=100 step=0.001" ); mParams.addParam( "Vorticity Scale", mFluid2D.vorticityScaleAddr(), "min=0 max=1 step=0.001" ); mFluid2D.setDt( 0.1f ); mFluid2D.enableDensity(); mFluid2D.enableRgb(); mFluid2D.enableVorticityConfinement(); mParticles.setup( getWindowBounds(), &mFluid2D ); }
void Fluid2DCamAppApp::update() { if( mCapture && mCapture.checkNewFrame() ) { if( ! mTexCam ) { mTexCam = gl::Texture( mCapture.getSurface() ); } // Flip the image if( ! mFlipped ) { Surface8u srcImg = mCapture.getSurface(); mFlipped = Surface8u( srcImg.getWidth(), srcImg.getHeight(), srcImg.hasAlpha(), srcImg.getChannelOrder() ); } Surface8u srcImg = mCapture.getSurface(); mFlipped = Surface8u( srcImg.getWidth(), srcImg.getHeight(), srcImg.hasAlpha(), srcImg.getChannelOrder() ); for( int y = 0; y < mCapture.getHeight(); ++y ) { const Color8u* src = (const Color8u*)(srcImg.getData() + (y + 1)*srcImg.getRowBytes() - srcImg.getPixelInc()); Color8u* dst = (Color8u*)(mFlipped.getData() + y*mFlipped.getRowBytes()); for( int x = 0; x < mCapture.getWidth(); ++x ) { *dst = *src; ++dst; --src; } } // Create scaled image if( ! mCurScaled ) { mCurScaled = Surface8u( mFlipped.getWidth()/kFlowScale, mFlipped.getHeight()/kFlowScale, mFlipped.hasAlpha(), mFlipped.getChannelOrder() ); } ip::resize( mFlipped, &mCurScaled ); // Optical flow if( mCurScaled && mPrvScaled ) { mPrvCvData = mCurCvData; mCurCvData = cv::Mat( toOcv( Channel( mCurScaled ) ) ); if( mPrvCvData.data && mCurCvData.data ) { int pyrLvels = 3; int winSize = 3; int iters = 5; int poly_n = 7; double poly_sigma = 1.5; cv::calcOpticalFlowFarneback( mPrvCvData, mCurCvData, mFlow, 0.5, pyrLvels, 2*winSize + 1, iters, poly_n, poly_sigma, cv::OPTFLOW_FARNEBACK_GAUSSIAN ); if( mFlow.data ) { if( mFlowVectors.empty() ) { mFlowVectors.resize( mCurScaled.getWidth()*mCurScaled.getHeight() ); } //memset( &mFlowVectors[0], 0, mCurScaled.getWidth()*mCurScaled.getHeight()*sizeof( Vec2f ) ); mNumActiveFlowVectors = 0; for( int j = 0; j < mCurScaled.getHeight(); ++j ) { for( int i = 0; i < mCurScaled.getWidth(); ++i ) { const float* fptr = reinterpret_cast<float*>(mFlow.data + j*mFlow.step + i*sizeof(float)*2); // Vec2f v = Vec2f( fptr[0], fptr[1] ); if( v.lengthSquared() >= mVelThreshold ) { if( mNumActiveFlowVectors >= (int)mFlowVectors.size() ) { mFlowVectors.push_back( std::make_pair( Vec2i( i, j ), v ) ); } else { mFlowVectors[mNumActiveFlowVectors] = std::make_pair( Vec2i( i, j ), v ); } ++mNumActiveFlowVectors; } } } } } } // Update texture mTexCam.update( mFlipped ); // Save previous frame if( ! mPrvScaled ) { mPrvScaled = Surface8u( mCurScaled.getWidth(), mCurScaled.getHeight(), mCurScaled.hasAlpha(), mCurScaled.getChannelOrder() ); } memcpy( mPrvScaled.getData(), mCurScaled.getData(), mCurScaled.getHeight()*mCurScaled.getRowBytes() ); } // Update fluid float dx = (mFluid2DResX - 2)/(float)(640/kFlowScale); float dy = (mFluid2DResY - 2)/(float)(480/kFlowScale); for( int i = 0; i < mNumActiveFlowVectors; ++i ) { Vec2f P = mFlowVectors[i].first; const Vec2f& v = mFlowVectors[i].second; mFluid2D.splatDensity( P.x*dx + 1, P.y*dy + 1, mDenScale*v.lengthSquared() ); mFluid2D.splatVelocity( P.x*dx + 1, P.y*dy + 1, v*mVelScale ); } mFluid2D.step(); // Update velocity const Vec2f* srcVel0 = mFluid2D.dbgVel0().data(); const Vec2f* srcVel1 = mFluid2D.dbgVel1().data(); Colorf* dstVel0 = (Colorf*)mSurfVel0.getData(); Colorf* dstVel1 = (Colorf*)mSurfVel1.getData(); for( int j = 0; j < mFluid2DResY; ++j ) { for( int i = 0; i < mFluid2DResX; ++i ) { *dstVel0 = Colorf( srcVel0->x, srcVel0->y, 0.0f ); *dstVel1 = Colorf( srcVel1->x, srcVel1->y, 0.0f ); ++srcVel0; ++srcVel1; ++dstVel0; ++dstVel1; } } // Update Density mChanDen0 = Channel32f( mFluid2DResX, mFluid2DResY, mFluid2DResX*sizeof(float), 1, mFluid2D.dbgDen0().data() ); mChanDen1 = Channel32f( mFluid2DResX, mFluid2DResY, mFluid2DResX*sizeof(float), 1, mFluid2D.dbgDen1().data() ); mTexDen0.update( mChanDen0 ); mTexDen1.update( mChanDen1 ); // Update velocity textures mTexVel0.update( mSurfVel0 ); mTexVel1.update( mSurfVel1 ); // Update Divergence mChanDiv = Channel32f( mFluid2DResX, mFluid2DResY, mFluid2DResX*sizeof(float), 1, mFluid2D.dbgDivergence().data() ); mTexDiv.update( mChanDiv ); // Update Divergence mChanPrs = Channel32f( mFluid2DResX, mFluid2DResY, mFluid2DResX*sizeof(float), 1, mFluid2D.dbgPressure().data() ); mTexPrs.update( mChanPrs ); // Update Curl, Curl Length mChanCurl = Channel32f( mFluid2DResX, mFluid2DResY, mFluid2DResX*sizeof(float), 1, mFluid2D.dbgCurl().data() ); mTexCurl.update( mChanCurl ); mChanCurlLen = Channel32f( mFluid2DResX, mFluid2DResY, mFluid2DResX*sizeof(float), 1, mFluid2D.dbgCurlLength().data() ); mTexCurlLen.update( mChanCurlLen ); }