void Particle::update( const Channel32f &channel, const ci::Channel32f &rChan, const ci::Channel32f &gChan, const ci::Channel32f &bChan, const ci::Vec2i &mouseLoc ) { //calculate the vector that points from the particl to the mouse. mDirToCursor = mouseLoc - mLoc; mDirToCursor.safeNormalize(); //normalize it so it gives us a unit vector. Vec2f newLoc = mLoc + mDirToCursor * 100.f; newLoc.x = constrain( newLoc.x, 0.0f, channel.getWidth() - 1.0f ); newLoc.y = constrain( newLoc.y, 0.0f, channel.getHeight() - 1.0f ); //mRadius = channel.getValue( mLoc ) * mScale; mRadius = channel.getValue( newLoc ) * mScale; Vec2i mLoci = (Vec2i) mLoc; r = rChan.getValue( newLoc ); g = gChan.getValue( newLoc ); b = bChan.getValue( newLoc ); //console() << r << ", " << g << ", " << b << std::endl; //console() << channel.getValue(mLoc) << std::endl; //console() << "hello" << std::endl; }
void Particle::update( const Channel32f &channel ) { //mLoc += mDir * mVel; float gray = channel.getValue( mLoc ); mColor = Color( gray, gray, gray ); mRadius = channel.getValue( mLoc ) * mScale; //mRadius = 3.0f; }
void getMinMax( const Channel32f &channel, float *resultMin, float *resultMax ) { float minVal = *(channel.getData( Vec2i::zero() )), maxVal = *(channel.getData( Vec2i::zero() )); Channel32f::ConstIter iter = channel.getIter(); while( iter.line() ) { while( iter.pixel() ) { minVal = std::min( minVal, iter.v() ); maxVal = std::max( maxVal, iter.v() ); } } *resultMin = minVal; *resultMax = maxVal; }
void Particle::update(Channel32f channel) { if (age > lifespan) { alive = false; return; } loc += dir * vel; auto lifePhase = ((float)age) / lifespan; blue = channel.getValue(loc); green = (15.0f * green + blue) / 16.0f; radius = 3.0f * (1 - (abs(lifePhase - 0.5f))) * channel.getValue(loc) + 1.0f; age++; vel*=0.97f; }
void Particle::update(const Channel32f &channel) { //mLoc += mDir * mVel; //float gray = channel.getValue(mLoc); mDesiredRadius = channel.getValue( mLoc ) * 7.0f; if (mDesiredRadius > mRadius) { mRadius += 0.1; } else if (mDesiredRadius < mRadius) { mRadius -= 0.1; } if (mDesiredLoc.x > mLoc.x ) { mLoc.x += (mDesiredLoc.x - mLoc.x) / 20.0 ; } if (mDesiredLoc.x < mLoc.x) { mLoc.x -= (mLoc.x - mDesiredLoc.x) / 20.0; } if (mDesiredLoc.y > mLoc.y ) { mLoc.y += (mDesiredLoc.y - mLoc.y) / 20.0; } if (mDesiredLoc.y < mLoc.y) { mLoc.y -= (mLoc.y - mDesiredLoc.y) / 20.0; } }
void DirVector::update(const Channel32f &channel, const Vec2f &windDirection){ //console() << "Update1: << " << mDir << ", " << mRotationVector << endl; //mDir = Vec2f(1.0f, 0.0f); mDir = mRotationVector; //mouseLoc - mLoc; mDir.safeNormalize(); //mDir.normalize(); Vec2f newLoc = mLoc + mDir * 100.f; newLoc.x = constrain(newLoc.x, 0.f, channel.getWidth() - 1.f); newLoc.x = constrain(newLoc.x, 0.f, channel.getHeight() - 1.f); mRadius = channel.getValue(newLoc) * 7.0f; //console() << "Update2: << " << mDir << endl; }
void AudioVisualizerApp::update() { // update FMOD so it can notify us of events mFMODSystem->update(); // handle signal: if audio has ended, play next file if(mIsAudioPlaying && signalChannelEnd) playAudio( nextAudio( mAudioPath ) ); // reset FMOD signals signalChannelEnd= false; // get spectrum for left and right channels and copy it into our channels float* pDataLeft = mChannelLeft.getData() + kBands * mOffset; float* pDataRight = mChannelRight.getData() + kBands * mOffset; mFMODSystem->getSpectrum( pDataLeft, kBands, 0, FMOD_DSP_FFT_WINDOW_HANNING ); mFMODSystem->getSpectrum( pDataRight, kBands, 1, FMOD_DSP_FFT_WINDOW_HANNING ); // increment texture offset mOffset = (mOffset+1) % kHistory; // clear the spectrum for this row to avoid old data from showing up pDataLeft = mChannelLeft.getData() + kBands * mOffset; pDataRight = mChannelRight.getData() + kBands * mOffset; memset( pDataLeft, 0, kBands * sizeof(float) ); memset( pDataRight, 0, kBands * sizeof(float) ); // animate camera if mouse has not been down for more than 30 seconds if(!mIsMouseDown && (getElapsedSeconds() - mMouseUpTime) > mMouseUpDelay) { float t = float( getElapsedSeconds() ); float x = 0.5f + 0.5f * math<float>::cos( t * 0.07f ); float y = 0.1f - 0.2f * math<float>::sin( t * 0.09f ); float z = 0.25f * math<float>::sin( t * 0.05f ) - 0.25f; Vec3f eye = Vec3f(kWidth * x, kHeight * y, kHeight * z); x = 1.0f - x; y = -0.3f; z = 0.6f + 0.2f * math<float>::sin( t * 0.12f ); Vec3f interest = Vec3f(kWidth * x, kHeight * y, kHeight * z); // gradually move to eye position and center of interest mCamera.setEyePoint( eye.lerp(0.995f, mCamera.getEyePoint()) ); mCamera.setCenterOfInterestPoint( interest.lerp(0.990f, mCamera.getCenterOfInterestPoint()) ); } }
void Particle::update( const Channel32f &channel ) { mRadius = channel.getValue( mLoc ) * 7.0f; //float gray = channel.getValue( mLoc ); mLoc += mDir * mVel; }
void Particle::update( const Channel32f &channel, const Vec2i &mouseLoc ) { mDirToCursor = mouseLoc - mLoc; float distToCursor = mDirToCursor.length(); float time = app::getElapsedSeconds(); float dist = distToCursor * 0.025f; float sinOffset = sin( dist - time ) + 1.0f; mDirToCursor.normalize(); mDirToCursor *= sinOffset * 100.0f; Rectf rect( mLoc.x, mLoc.y, mLoc.x + mRadius, mLoc.y + mRadius ); gl::drawSolidRect( rect ); Vec2f newLoc = mLoc + mDirToCursor; newLoc.x = constrain( newLoc.x, 0.0f, channel.getWidth() - 1.0f ); newLoc.y = constrain( newLoc.y, 0.0f, channel.getHeight() - 1.0f ); mRadius = channel.getValue( newLoc ) * mScale; }
void Circle::update(const Vec2i &mouseLoc, const Channel32f &channel) { mMouseLoc = mouseLoc; mDirToCursor = mMouseLoc-mLoc; float distToCursor = mDirToCursor.length(); float time = app::getElapsedSeconds(); float dist = distToCursor * 0.025f; float sinOffset = sin(dist-time)+1.0f; mDirToCursor.normalize(); mDirToCursor *= sinOffset * 100.0f; Vec2f newLoc = mLoc+mDirToCursor; newLoc.x = constrain(newLoc.x, 0.0f, channel.getWidth()-1.0f); newLoc.y = constrain(newLoc.y, 0.0f, channel.getHeight() - 1.0f); mRadius = channel.getValue(newLoc)*mScale+2.0f; float gray=channel.getValue(mLoc); mColor=Color(gray,gray,gray); }
void HeightfieldTerrainApp::setupHeightfield() { // mHeightfieldMap = Channel32f( loadImage( loadAsset( "heightfield.jpg" ) ) ); Perlin perlin( 4, 12 ); mHeightfieldMap = Channel32f( Width, Depth ); auto minHeight = 0.0f; auto maxHeight = 0.0f; // Now we'll give our Map some Height values. for( int y = 0; y < Depth; ++y ) { for( int x = 0; x < Width; ++x ) { // Now create our heightfield, which is just a two-dimensional array that has // a value, height. Instead of this you could easily use Perline to get smoother // values or create a black and white image. auto val = 25.0f * perlin.fBm( x/float(Depth), y/float(Width) ); if( val > maxHeight ) maxHeight = val; else if ( val < minHeight ) minHeight = val; mHeightfieldMap.setValue( ivec2( x, y ), val ); } } // Create our heightfieldShape with our heightfieldMap and maxHeight and minHeight auto heightField = bt::createHeightfieldShape( &mHeightfieldMap, maxHeight, minHeight, vec3( 10 ) ); heightField->setLocalScaling( bt::toBullet( vec3( 100 ) ) ); // Make our rigidbody out of this collision shape. mHeightfieldTerrain = bt::RigidBody::create( bt::RigidBody::Format().collisionShape( heightField ) ); ci::AxisAlignedBox3f box; mHeightfieldTerrain->getAabb( box ); cout << box.getCenter() << endl; // Collect it in my vector mRigidBodies.push_back( mHeightfieldTerrain ); // And add that rigidbody to the world. mContext->addRigidBody( mHeightfieldTerrain ); // Now we can create a batch using the draw helper from bullet which passes back a vboMesh based on our map. mBatch = gl::Batch::create( bt::drawableHelpers::getDrawableHeightfield( &mHeightfieldMap ), mPhongShader ); }
/// This update method takes a float channel, which is our image, and /// the current mouse location. It then takes this data, based on the /// amount of time that has elapsed, and will store the new properties /// of the the Particle for drawing void Particle::update( const Channel32f &channel, const Vec2i &mouseLoc) { /// calculates the direction to the cursor, and finds /// the distance to it, myDirToCursor_ = mouseLoc - myLocation_; float dist_To_Cursor_ = myDirToCursor_.length(); /// with the time and distance change factored in, /// we can generate our sine function offset and /// apply it to the particle. float time_ = app::getElapsedSeconds()*4.0f; float dist_ = dist_To_Cursor_ * myDistChange_; float sinOffset_ = sin(dist_-time_)*2.0f; myDirToCursor_ *= sinOffset_*15.0; /// the radius of the particle is then changed based on the /// current sinOffset_ value. myRadius_ = channel.getValue(myLocation_)*sinOffset_; }
/// This update method takes a float channel, which is our image, and /// the current mouse location. It then takes this data, based on the /// amount of time that has elapsed, and will store the new properties /// of the the Particle for drawing void Particle::update( const Channel32f &channel, const Vec2i &mouseLoc) { /// calculates the direction to the cursor, and finds /// the distance to it, myDirToCursor_ = mouseLoc - myLocation_; float dist_To_Cursor_ = myDirToCursor_.length(); /// with the time and distance change factored in, /// we can generate our sine function offset and /// apply it to the particle. float time_ = app::getElapsedSeconds()*4.0f; float dist_ = dist_To_Cursor_ * myDistChange_; float sinOffset_ = sin(dist_-time_)*2.0f; myDirToCursor_ *= sinOffset_*15.0; /// this if ... else if stack determines the /// color of the particle based on the values /// of the booleans isRed_, isGreen_, and isBlue_. if (!isRed_) { /// makes it red rand_ = randFloat(0.75f, 1.0f); myColor_ = Color(rand_, 0.0f, 0.0f); } else if (!isGreen_) { /// makes it green rand_ = randFloat(0.75f, 1.0f); myColor_ = Color(0.0f, rand_, 0.0f); } else if (!isBlue_) { /// makes it blue rand_ = randFloat(0.75f, 1.0f); myColor_ = Color(0.0f, 0.0f, rand_); } /// the radius of the particle is then changed based on the /// current sinOffset_ value. myRadius_ = channel.getValue(myLocation_)*sinOffset_; }
void AudioVisualizerApp::setup() { // initialize signals signalChannelEnd = false; // make a list of valid audio file extensions and initialize audio variables const char* extensions[] = { "mp3", "wav", "ogg" }; mAudioExtensions = vector<string>( extensions, extensions + 2 ); mAudioPath = getAssetPath( "" ); mIsAudioPlaying = false; // setup camera mCamera.setPerspective( 50.0f, 1.0f, 1.0f, 10000.0f ); mCamera.lookAt( vec3( -kWidth / 4, kHeight / 2, -kWidth / 8 ), vec3( kWidth / 4, -kHeight / 8, kWidth / 4 ) ); mCameraUi.setCamera( &mCamera ); // create channels from which we can construct our textures mChannelLeft = Channel32f( kBands, kHistory ); mChannelRight = Channel32f( kBands, kHistory ); memset( mChannelLeft.getData(), 0, mChannelLeft.getRowBytes() * kHistory ); memset( mChannelRight.getData(), 0, mChannelRight.getRowBytes() * kHistory ); // create texture format (wrap the y-axis, clamp the x-axis) mTextureFormat.setWrapS( GL_CLAMP_TO_BORDER ); mTextureFormat.setWrapT( GL_REPEAT ); mTextureFormat.setMinFilter( GL_LINEAR ); mTextureFormat.setMagFilter( GL_LINEAR ); mTextureFormat.loadTopDown( true ); // compile shader try { mShader = gl::GlslProg::create( loadAsset( "shaders/spectrum.vert" ), loadAsset( "shaders/spectrum.frag" ) ); } catch( const std::exception& e ) { console() << e.what() << std::endl; quit(); return; } // create static mesh (all animation is done in the vertex shader) std::vector<vec3> positions; std::vector<Colorf> colors; std::vector<vec2> coords; std::vector<uint32_t> indices; for( size_t h = 0; h < kHeight; ++h ) { for( size_t w = 0; w < kWidth; ++w ) { // add polygon indices if( h < kHeight - 1 && w < kWidth - 1 ) { size_t offset = positions.size(); indices.emplace_back( offset ); indices.emplace_back( offset + kWidth ); indices.emplace_back( offset + kWidth + 1 ); indices.emplace_back( offset ); indices.emplace_back( offset + kWidth + 1 ); indices.emplace_back( offset + 1 ); } // add vertex positions.emplace_back( vec3( float( w ), 0, float( h ) ) ); // add texture coordinates // note: we only want to draw the lower part of the frequency bands, // so we scale the coordinates a bit const float part = 0.5f; float s = w / float( kWidth - 1 ); float t = h / float( kHeight - 1 ); coords.emplace_back( vec2( part - part * s, t ) ); // add vertex colors colors.emplace_back( Color( CM_HSV, s, 0.5f, 0.75f ) ); } } gl::VboMesh::Layout layout; layout.usage( GL_STATIC_DRAW ); layout.attrib( geom::Attrib::POSITION, 3 ); layout.attrib( geom::Attrib::COLOR, 3 ); layout.attrib( geom::Attrib::TEX_COORD_0, 2 ); mMesh = gl::VboMesh::create( positions.size(), GL_TRIANGLES, { layout }, indices.size(), GL_UNSIGNED_INT ); mMesh->bufferAttrib( geom::POSITION, positions.size() * sizeof( vec3 ), positions.data() ); mMesh->bufferAttrib( geom::COLOR, colors.size() * sizeof( vec3 ), colors.data() ); mMesh->bufferAttrib( geom::TEX_COORD_0, coords.size() * sizeof( vec2 ), coords.data() ); mMesh->bufferIndices( indices.size() * sizeof( uint32_t ), indices.data() ); // play audio using the Cinder FMOD block FMOD::System_Create( &mFMODSystem ); mFMODSystem->init( 32, FMOD_INIT_NORMAL | FMOD_INIT_ENABLE_PROFILE, NULL ); mFMODSound = nullptr; mFMODChannel = nullptr; playAudio( findAudio( mAudioPath ) ); mIsMouseDown = false; mMouseUpDelay = 30.0; mMouseUpTime = getElapsedSeconds() - mMouseUpDelay; // the texture offset has two purposes: // 1) it tells us where to upload the next spectrum data // 2) we use it to offset the texture coordinates in the shader for the scrolling effect mOffset = 0; }
Texture::Texture( const Channel32f &channel, Format format ) : mObj( shared_ptr<Obj>( new Obj( channel.getWidth(), channel.getHeight() ) ) ) { #if defined( CINDER_MAC ) bool supportsTextureFloat = gl::isExtensionAvailable( "GL_ARB_texture_float" ); #elif defined( CINDER_MSW ) bool supportsTextureFloat = GLEE_ARB_texture_float != 0; #endif if( format.mInternalFormat < 0 ) { #if ! defined( CINDER_GLES ) if( supportsTextureFloat ) format.mInternalFormat = GL_LUMINANCE32F_ARB; else format.mInternalFormat = GL_LUMINANCE; #else format.mInternalFormat = GL_LUMINANCE; #endif } mObj->mInternalFormat = format.mInternalFormat; mObj->mTarget = format.mTarget; // if the data is not already contiguous, we'll need to create a block of memory that is if( ( channel.getIncrement() != 1 ) || ( channel.getRowBytes() != channel.getWidth() * sizeof(float) ) ) { shared_ptr<float> data( new float[channel.getWidth() * channel.getHeight()], checked_array_deleter<float>() ); float *dest = data.get(); const int8_t inc = channel.getIncrement(); const int32_t width = channel.getWidth(); for( int y = 0; y < channel.getHeight(); ++y ) { const float *src = channel.getData( 0, y ); for( int x = 0; x < width; ++x ) { *dest++ = *src; src += inc; } } init( data.get(), GL_LUMINANCE, format ); } else init( channel.getData(), GL_LUMINANCE, format ); }
void BulletTestApp::update() { // Run next test if ( mTest != mTestPrev ) { mTestPrev = mTest; initTest(); } mFrameRate = getAverageFps(); // Update light mLight->update( mCamera ); if ( mTest < 3 ) { // Set box rotation float rotation = math<float>::sin( ( float )getElapsedSeconds() * 0.3333f ) * 0.35f ; mGroundTransform.setRotation( btQuaternion( 0.25f, 0.0f, 1.0f + rotation * 0.1f, rotation ) ); mGroundTransform.setOrigin( btVector3( 0.0f, -60.0f, 0.0f ) ); // Apply rotation to box btRigidBody* body = bullet::toBulletRigidBody( mGround ); body->getMotionState()->setWorldTransform( mGroundTransform ); body->setWorldTransform( mGroundTransform ); } else if ( mTest == 6 ) { // Read data Channel32f& input = mTerrain->getData(); // Get image dimensions int32_t height = input.getHeight(); int32_t width = input.getWidth(); // Create output channel Channel32f output = Channel32f( width, height ); // Move pixel value over by one for ( int32_t y = 0; y < height; y++ ) { for ( int32_t x = 0; x < width; x++ ) { float value = input.getValue( Vec2i( x, y ) ); Vec2i position( ( x + 1 ) % width, ( y + 1 ) % height ); output.setValue( position, value ); } } // Copy new data back to original input.copyFrom( output, output.getBounds() ); // Shift texture coordinates to match positions vector<Vec2f>& texCoords = mTerrain->getTexCoords(); Vec2f delta( 1.0f / (float)width, 1.0f / (float)height ); for ( vector<Vec2f>::iterator uv = texCoords.begin(); uv != texCoords.end(); ++uv ) { *uv -= delta; } // Update terrain VBO mTerrain->updateVbo(); } else if ( mTest == 7 ) { bool init = !mSurface; if ( mCapture.isCapturing() && mCapture.checkNewFrame() ) { mSurface = mCapture.getSurface(); ip::flipVertical( &mSurface ); if ( init ) { mTerrain = new DynamicTerrain( Channel32f( 160, 160 ), -1.0f, 1.0f, Vec3f( 2.0f, 70.0f, 2.0f ), 0.0f ); mWorld->pushBack( mTerrain ); btRigidBody* terrain = ( btRigidBody* )mTerrain->getBulletBody(); terrain->setAngularFactor( 0.6f ); terrain->setFriction( 0.6f ); } else { mTerrain->getData().copyFrom( Channel32f( mSurface ), Area( 0, 0, 160, 160 ) ); mTerrain->updateVbo(); } } } // Update dynamics world mWorld->update( mFrameRate ); /*if ( mGround ) { Iter iter = mWorld->find( mGround ); OutputDebugStringA( toString( iter->getPosition().x ).c_str() ); OutputDebugStringA( "\n" ); }*/ // Remove out of bounbds objects for ( bullet::Iter object = mWorld->begin(); object != mWorld->end(); ) { if ( object != mWorld->begin() && object->getPosition().y < -800.0f ) { object = mWorld->erase( object ); } else { ++object; } } // Remove objects when count is too high uint32_t max = mTest >= 4 ? MAX_OBJECTS_TERRAIN : MAX_OBJECTS; if ( mWorld->getNumObjects() > max + 1 ) { for ( uint32_t i = 1; i < mWorld->getNumObjects() - MAX_OBJECTS_TERRAIN; i++ ) { mWorld->erase( mWorld->begin() + 1 ); } } }