void DeviceTestApp::draw() { gl::clear(); gl::color( 0, 0.9f, 0 ); gl::pushMatrices(); gl::translate( 0, mViewYOffset ); if( mMonitor && mMonitor->isEnabled() ) { const audio::Buffer &buffer = mMonitor->getBuffer(); float padding = 20; float waveHeight = ((float)getWindowHeight() - padding * 3.0f ) / (float)buffer.getNumChannels(); float yOffset = padding; float xScale = (float)getWindowWidth() / (float)buffer.getNumFrames(); for( size_t ch = 0; ch < buffer.getNumChannels(); ch++ ) { PolyLine2f waveform; const float *channel = buffer.getChannel( ch ); for( size_t i = 0; i < buffer.getNumFrames(); i++ ) { float x = i * xScale; float y = ( channel[i] * 0.5f + 0.5f ) * waveHeight + yOffset; waveform.push_back( vec2( x, y ) ); } gl::draw( waveform ); yOffset += waveHeight + padding; } float volume = mMonitor->getVolume(); Rectf volumeRect( mGainSlider.mBounds.x1, mGainSlider.mBounds.y2 + padding, mGainSlider.mBounds.x1 + mGainSlider.mBounds.getWidth() * volume, mGainSlider.mBounds.y2 + padding + 20 ); gl::drawSolidRect( volumeRect ); } drawWidgets( mWidgets ); if( mInputDeviceNodeUnderrunFade > 0.0001f ) { gl::color( ColorA( 0.8f, 0.2f, 0, mInputDeviceNodeUnderrunFade ) ); gl::drawSolidRect( mUnderrunRect ); gl::drawStringCentered( "in underrun", mUnderrunRect.getCenter(), Color::black() ); } if( mInputDeviceNodeOverrunFade > 0.0001f ) { gl::color( ColorA( 0.8f, 0.2f, 0, mInputDeviceNodeOverrunFade ) ); gl::drawSolidRect( mOverrunRect ); gl::drawStringCentered( "in overrun", mOverrunRect.getCenter(), Color::black() ); } if( mOutputDeviceNodeClipFade > 0.0001f ) { gl::color( ColorA( 0.8f, 0.2f, 0, mOutputDeviceNodeClipFade ) ); gl::drawSolidRect( mClipRect ); gl::drawStringCentered( "out clip", mClipRect.getCenter(), Color::black() ); } gl::popMatrices(); }
TutorialApp::TutorialApp() { // Set square size mSize = 100.0f; const vec2 sz( mSize ); // We are going to create two UiTrees for each type of transform: // one which uses velocity and one that does not. for ( size_t i = Transform_None + 1; i < Transform_Count; ++i ) { for ( size_t j = 0; j < 2; ++j ) { // Define the data structure. UiData data; data.mColor = Colorf( randFloat(), randFloat(), randFloat() ); data.mTransform = (Transform)i; data.mUseVelocity = j == 1; // Create the node and set its data. UiTree& node = mUiTree.createAndReturnChild() .data( data ) .scale( sz ); const Rectf bounds = calcBounds( node ); const vec2 p = bounds.getCenter() - sz * 0.5f; node.translate( p ); } } }
void ClientApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); gl::color( ColorA::white() ); // button triggers for events gl::drawStrokedRoundedRect( infoRect, 8.0f, 10 ); gl::drawStringCentered( "info", infoRect.getCenter() ); gl::drawStrokedRoundedRect( warnRect, 8.0f, 10 ); gl::drawStringCentered( "warn", warnRect.getCenter() ); gl::drawStrokedRoundedRect( errorRect, 8.0f, 10 ); gl::drawStringCentered( "error", errorRect.getCenter() ); gl::drawStrokedRoundedRect( eventRect, 8.0f, 10 ); gl::drawStringCentered( "event", eventRect.getCenter() ); gl::drawStrokedRoundedRect( crashRect, 8.0f, 10 ); gl::drawStringCentered( "crash", crashRect.getCenter() ); }
void SamplePlayerNodeTestApp::draw() { gl::clear(); if( mTestSelector.currentSection() == "recorder" ) { audio::BufferRef recordedBuffer = mRecorder->getRecordedCopy(); drawAudioBuffer( *recordedBuffer, getWindowBounds() ); } else { auto bufferPlayer = dynamic_pointer_cast<audio::BufferPlayerNode>( mSamplePlayerNode ); if( bufferPlayer ) mWaveformPlot.draw(); else if( mMonitor && mMonitor->isInitialized() ) drawAudioBuffer( mMonitor->getBuffer(), getWindowBounds() ); float readPos = (float)getWindowWidth() * mSamplePlayerNode->getReadPosition() / mSamplePlayerNode->getNumFrames(); gl::color( ColorA( 0, 1, 0, 0.7f ) ); gl::drawSolidRoundedRect( Rectf( readPos - 2, 0, readPos + 2, (float)getWindowHeight() ), 2 ); } if( mUnderrunFade > 0.0001f ) { gl::color( ColorA( 1, 0.5f, 0, mUnderrunFade ) ); gl::drawSolidRect( mUnderrunRect ); gl::drawStringCentered( "play underrun", mUnderrunRect.getCenter(), Color::black() ); } if( mOverrunFade > 0.0001f ) { gl::color( ColorA( 1, 0.5f, 0, mOverrunFade ) ); gl::drawSolidRect( mOverrunRect ); gl::drawStringCentered( "play overrun", mOverrunRect.getCenter(), Color::black() ); } if( mRecorderOverrunFade > 0.0001f ) { gl::color( ColorA( 1, 0.5f, 0, mRecorderOverrunFade ) ); gl::drawSolidRect( mRecorderOverrunRect ); gl::drawStringCentered( "rec overrun", mRecorderOverrunRect.getCenter(), Color::black() ); } drawWidgets( mWidgets ); }
void SegmentationApp::draw() { // clear out the window with black gl::clear( Color( 0, 0, 0 ) ); gl::color(1, 1, 1); gl::drawStrokedRoundedRect(firstImageRect, 10); gl::drawStrokedRoundedRect(secondImageRect, 10); if(drawMode == DRAW_MODE::INPUT) { gl::Texture& inputTexture = inputImage.second; if(inputTexture) { gl::pushMatrices(); gl::translate(firstImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-inputTexture.getWidth()/2.f,-inputTexture.getHeight()/2.f); gl::draw(inputTexture); gl::popMatrices(); } } else if(drawMode == DRAW_MODE::INPUT_GROUNDTRUTH) { gl::Texture& inputTexture = inputImage.second; if(inputTexture) { gl::pushMatrices(); gl::translate(firstImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-inputTexture.getWidth()/2.f,-inputTexture.getHeight()/2.f); gl::draw(inputTexture); gl::popMatrices(); } gl::Texture& groundTruthTexture = groundTruthImage.second; if(groundTruthTexture) { gl::pushMatrices(); gl::translate(secondImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-groundTruthTexture.getWidth()/2.f,-groundTruthTexture.getHeight()/2.f); gl::draw(groundTruthTexture); gl::popMatrices(); } } else if (drawMode == DRAW_MODE::THRESHOLD_GROUNDTRUTH) { gl::Texture& segmentationTexture = segmentedImage.second; if(segmentationTexture) { gl::pushMatrices(); gl::translate(firstImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-segmentationTexture.getWidth()/2.f,-segmentationTexture.getHeight()/2.f); gl::draw(segmentationTexture); gl::popMatrices(); } gl::Texture& groundTruthTexture = groundTruthImage.second; if(groundTruthTexture) { gl::pushMatrices(); gl::translate(secondImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-groundTruthTexture.getWidth()/2.f,-groundTruthTexture.getHeight()/2.f); gl::draw(groundTruthTexture); gl::popMatrices(); } } else if (drawMode == DRAW_MODE::INPUT_THRESHOLD) { gl::Texture& inputTexture = inputImage.second; if(inputTexture) { gl::pushMatrices(); gl::translate(firstImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-inputTexture.getWidth()/2.f,-inputTexture.getHeight()/2.f); gl::draw(inputTexture); gl::popMatrices(); } gl::Texture& thresholdTexture = segmentedImage.second; if(thresholdTexture) { gl::pushMatrices(); gl::translate(secondImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-thresholdTexture.getWidth()/2.f,-thresholdTexture.getHeight()/2.f); gl::draw(thresholdTexture); gl::popMatrices(); } } else if (drawMode == DRAW_MODE::INPUT_RESULT) { gl::Texture& inputTexture = inputImage.second; if(inputTexture) { gl::pushMatrices(); gl::translate(firstImageRect.getCenter()); gl::scale(glScale,glScale); gl::translate(-inputTexture.getWidth()/2.f,-inputTexture.getHeight()/2.f); gl::draw(inputTexture); gl::popMatrices(); } gl::Texture& resultTexture = resultImage.second; if(resultTexture) { gl::pushMatrices(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); float glScale = (float)mouse->getGLScale(); gl::scale(glScale,glScale); gl::translate(ci::Vec2d(mouse->getGLTx(), mouse->getGLTy())); gl::draw(resultTexture); gl::popMatrices(); } } interface->draw(); }
std::map<int, TimelineContentInfo> GridLayoutTimeline::getRenderContent(//SceneContentProvider *contentProvider, bool shouldTransition) { std::map< int, TimelineContentInfo > returnContent; vector<ScreenRegion> transitionRegions; vector<ScreenRegion> compareRegions; vector<ScreenRegion> returnRegions; float curTransitionScale = shouldTransition ? mTransitionAmt : 1.0f; if (shouldTransition && mTransitionAmt < 1.0 && mIdxPrevLayout != -1) { // If there's a previous region, they each get 1/2 of the // allotted transition time. float prevTransitionScale = 1.0 - std::min(mTransitionAmt / 0.5f, 1.0f); float nextTransitionScale = std::max((mTransitionAmt - 0.5f) / 0.5f, 0.0f); if (nextTransitionScale > 0.0) { // Next layout is transitioning. transitionRegions = mGridLayouts[mIdxCurrentLayout].getRegions(); compareRegions = mGridLayouts[mIdxPrevLayout].getRegions(); curTransitionScale = nextTransitionScale; } else { // Previous layout is transitioning. transitionRegions = mGridLayouts[mIdxPrevLayout].getRegions(); compareRegions = mGridLayouts[mIdxCurrentLayout].getRegions(); curTransitionScale = prevTransitionScale; } } else { // Next layout is transitioning. There are no previous regions. transitionRegions = mGridLayouts[mIdxCurrentLayout].getRegions(); } int numRegions = transitionRegions.size(); int numCompareRegions = compareRegions.size(); for (int i = 0; i < numRegions; ++i) { ScreenRegion transitionReg = transitionRegions[i]; Rectf rA = transitionReg.rect; float rectScale = curTransitionScale; for (int j = 0; j < numCompareRegions; ++j) { ScreenRegion compareReg = compareRegions[j]; /* Rectf rB = compareReg.rect; if (compareReg.isActive && rectCompare(rA, rB)) { */ if (compareReg.timelineID == transitionReg.timelineID) { // No transition. Just draw at full blast. rectScale = 1.0f; break; } } //std::pair<ci::Rectf, RenderableContentRef> returnItem; TimelineContentInfo returnItem; returnItem.layoutIndex = i; // Now, create the new rect. Vec2f rectCenter = rA.getCenter(); Vec2f rectHalfSize = rA.getSize() * 0.5f * rectScale; Rectf transitionRect(rectCenter - rectHalfSize, rectCenter + rectHalfSize); // returnItem.first = transitionRect; returnItem.rect = transitionRect; // Append content. SceneContentProviderRef contentProvider = SceneContentProvider::sharedContentProvider(); if (contentProvider) { returnItem.contentKey = transitionReg.contentKey; returnItem.contentRef = contentProvider->contentForKey(transitionReg.contentKey); returnContent[transitionReg.timelineID] = returnItem; } else { ci::app::console() << "ERROR: No content provider.\n"; } } return returnContent; }
void Grove::createMenuModal( const std::string &name, ci::Rectf *rect, ci::vec2 *offset, const WidgetRef &menu, const std::function<void()> &cancel, const std::function<void()> &confirm, bool adaptBackgroundColor ) { // create the layout Rectf fullRect = *rect; fullRect.include( vec2( fullRect.getCenter().x, fullRect.getLowerRight().y + 180 ) ); fullRect = fullRect.getCenteredFit( getWindowBounds(), false ); // get the window bounds #if defined( CINDER_COCOA_TOUCH ) Rectf windowBounds = toPixels( Rectf( vec2( 0.0f ), vec2( getWindowHeight(), getWindowWidth() ) ) ); #else Rectf windowBounds = toPixels( getWindowBounds() ); #endif // if the screen is really small, add some extra margins if( abs( fullRect.getWidth() - windowBounds.getWidth() ) < 300 ) fullRect.scaleCentered( (float) ( windowBounds.getWidth() - 300 ) / (float) fullRect.getWidth() ); if( abs( fullRect.getHeight() - windowBounds.getHeight() ) < 300 ) fullRect.scaleCentered( (float) ( windowBounds.getHeight() - 300 ) / (float) fullRect.getHeight() ); *rect = (*rect).getCenteredFit( fullRect, false ); (*rect).offset( vec2( 0.0f, -( fullRect.getHeight() - (*rect).getHeight() ) / 2.0f ) ); *offset = vec2( 0.0f, -fullRect.getLowerLeft().y ); auto fadeIn = [this](){ timeline().applyPtr( &mFogDensity, 1.0f, 2.0f, EaseInAtan() ); timeline().applyPtr( &mSunIntensity, 0.0f, 2.0f, EaseInAtan() ) .updateFn( [this](){ mTerrain->setFogDensity( mFogDensity ); mTerrain->setSunIntensity( mSunIntensity ); } ); }; auto fadeOut = [this](){ timeline().applyPtr( &mFogDensity, 0.129f, 6.0f, EaseOutAtan() ); timeline().applyPtr( &mSunIntensity, 0.166f, 6.0f, EaseOutAtan() ) .updateFn( [this](){ mTerrain->setFogDensity( mFogDensity ); mTerrain->setSunIntensity( mSunIntensity ); } ); }; // add events if( menu ){ menu->onPressed( name, [=]( WidgetEvent event ) { if( adaptBackgroundColor ) fadeIn(); mModal = true; event.getWidget()->close( true, event.getItem() ); // wait for the menu to close timeline().add( [=](){ timeline().applyPtr( offset, vec2(0), 1.0f, EaseInQuad() ) .finishFn( [=]() { vector<string> items; if( confirm ) items = { "ConfirmWire", "QuitWire" }; else items = { "QuitWire" }; mWidget = Widget::create( Widget::Format() .items( items ) .position( (*rect).getLowerLeft() + vec2( (*rect).getWidth() / 2 + ( confirm ? 69 : 0 ), ( fullRect.getHeight() - (*rect).getHeight() ) / 2 ) ) .autoClose( false ) ); mWidget->onClose( [=]( WidgetEvent event ){ timeline().applyPtr( offset, vec2( 0, -fullRect.getLowerLeft().y ), 1.0f, EaseOutQuad() ); if( adaptBackgroundColor ) fadeOut(); } ); mWidget->onCloseEnded( [=]( WidgetEvent event ){ mOpenMenuButton->open(); } ); if( confirm ){ mWidget->onPressed( "ConfirmWire", [=]( WidgetEvent event ) { event.getWidget()->close(); timeline().add( [=](){ mModal = false; }, timeline().getCurrentTime() + 1.5f ); confirm(); } ); } mWidget->onPressed( "QuitWire", [=]( WidgetEvent event ) { event.getWidget()->close(); timeline().add( [=](){ mModal = false; }, timeline().getCurrentTime() + 1.5f ); if( cancel ) cancel(); } ); } ); }, timeline().getCurrentTime() + 1.0f ); } ); } else { vector<string> items; if( confirm ) items = { "ConfirmWire", "QuitWire" }; else items = { "QuitWire" }; mWidget = Widget::create( Widget::Format() .items( items ) .position( (*rect).getLowerLeft() + vec2( (*rect).getWidth() / 2 + ( confirm ? 69 : 0 ), ( fullRect.getHeight() - (*rect).getHeight() ) / 2 ) ) .autoClose( false ) ); mWidget->onClose( [=]( WidgetEvent event ){ timeline().applyPtr( offset, vec2( 0, -fullRect.getLowerLeft().y ), 1.0f, EaseOutQuad() ); if( adaptBackgroundColor ) fadeOut(); } ); mWidget->onCloseEnded( [=]( WidgetEvent event ){ mOpenMenuButton->open(); } ); if( confirm ){ mWidget->onPressed( "ConfirmWire", [=]( WidgetEvent event ) { event.getWidget()->close(); timeline().add( [=](){ mModal = false; }, timeline().getCurrentTime() + 1.5f ); confirm(); } ); } mWidget->onPressed( "QuitWire", [=]( WidgetEvent event ) { event.getWidget()->close(); timeline().add( [=](){ mModal = false; }, timeline().getCurrentTime() + 1.5f ); if( cancel ) cancel(); } ); if( adaptBackgroundColor ) fadeIn(); mModal = true; timeline().applyPtr( offset, vec2(0), 1.0f, EaseInQuad() ); } }
void Island::makeBumpers() { CI_ASSERT( mOuterVerts.size() == 6 && mInnerVerts.size() == 5 ); mBumpers.clear(); mBumperBoundingBoxes.clear(); mBumperVibrationLevels.clear(); const float padding = 4; const float crookedPaddingPercent = 0.036f; const float boundingBoxExpansion = 1.1f; // left base { Path2d bumper; bumper.moveTo( mOuterVerts[0] ); bumper.lineTo( mOuterVerts[1].x, mOuterVerts[1].y + padding ); bumper.lineTo( mInnerVerts[1].x, mInnerVerts[1].y + padding ); bumper.lineTo( mInnerVerts[0] ); bumper.close(); mBumpers.push_back( bumper ); } // left top { Vec2f offsetOuter = ( mOuterVerts[2] - mOuterVerts[1] ) * crookedPaddingPercent; Vec2f offsetInner = ( Vec2f( mOuterVerts[2].x, mInnerVerts[2].y ) - mInnerVerts[1] ) * crookedPaddingPercent; Path2d bumper; bumper.moveTo( mOuterVerts[1] + offsetOuter ); bumper.lineTo( mOuterVerts[2] ); bumper.lineTo( mOuterVerts[2].x, mInnerVerts[2].y ); bumper.lineTo( mInnerVerts[1] + offsetInner ); bumper.close(); mBumpers.push_back( bumper ); } // right top { Vec2f offsetOuter = ( mOuterVerts[3] - mOuterVerts[4] ) * crookedPaddingPercent; Vec2f offsetInner = ( Vec2f( mOuterVerts[3].x, mInnerVerts[2].y ) - mInnerVerts[3] ) * crookedPaddingPercent; Path2d bumper; bumper.moveTo( mOuterVerts[3] ); bumper.lineTo( mOuterVerts[4] + offsetOuter ); bumper.lineTo( mInnerVerts[3] + offsetInner ); bumper.lineTo( mOuterVerts[3].x, mInnerVerts[2].y ); bumper.close(); mBumpers.push_back( bumper ); } // right base { Path2d bumper; bumper.moveTo( mOuterVerts[4].x, mOuterVerts[4].y + padding ); bumper.lineTo( mOuterVerts[5] ); bumper.lineTo( mInnerVerts[4] ); bumper.lineTo( mInnerVerts[3].x, mInnerVerts[3].y + padding ); bumper.close(); mBumpers.push_back( bumper ); } for( size_t i = 0; i < mBumpers.size(); i++ ) { mBumperVibrationLevels.push_back( 0 ); // calculate an expanded bounding box for each bumper to do hit detection, ensuring that the entire edge is covered. Rectf bbox = mBumpers[i].calcBoundingBox(); Vec2f center = bbox.getCenter(); bbox -= center; bbox *= boundingBoxExpansion; bbox += center; mBumperBoundingBoxes.push_back( bbox ); } }
void TutorialApp::update() { // Animation speed, velocity decay, and epsilon (margin) for all tranform types. static const float decay = 0.96f; static const float epsilon = 0.1f; static const float speed = 0.1f; for ( auto& iter : mUiTree.getChildren() ) { UiTree& node = iter.second; // Get the animation bounds for this node Rectf bounds = calcBounds( node ); // Get the node's transform values const float r = node.getRotation().z; const vec2& s = vec2( node.getScale() ); const vec2& t = vec2( node.getTranslate() ); /* * Switch on this node's animation type, then animate using * either velocity or sequencing. */ switch ( node.getData().mTransform ) { case Transform_Rotate: if ( node.getData().mUseVelocity ) { // Get the velocity values. const float v = node.getRotationVelocity().z; /* * Accelerate the node's rotation CW or CCW randomly when its velocity * gets too low. */ if ( math<float>::abs( v ) < 0.001f ) { node.rotationVelocity( randFloat( -0.1f, 0.1f ), decay ); } } else { // If we're not using velocity, rotate the node CW and CCW. if ( math<float>::abs( node.getRotationTarget().z ) - math<float>::abs( r ) < epsilon ) { const float z = r > 0.0f ? -1.0f : 1.0f; node.setRotation( z, speed ); } } break; case Transform_Scale: if ( node.getData().mUseVelocity ) { /* * Accelerate the node's scale in a random direction when its velocity * gets too low. */ if ( glm::length( node.getScaleVelocity() ) <= epsilon ) { node.scaleVelocity( randVec2() * randFloat( 5.0f, 20.0f ), decay ); } // Get the new scale value. const vec2& scale = vec2( node.getScale() ); // Keep the node centered node.setTranslate( bounds.getCenter() - scale * 0.5f ); // Clamp the node's scale. if ( node.getScale().x > mSize * 2.0f ) { node.setScale( vec2( mSize * 2.0f, scale.y ) ); } else if ( node.getScale().x < mSize * 0.5f ) { node.setScale( vec2( mSize * 0.5f, scale.y ) ); } if ( node.getScale().y > mSize * 2.0f ) { node.setScale( vec2( scale.x, mSize * 2.0f ) ); } else if ( node.getScale().y < mSize * 0.5f ) { node.setScale( vec2( scale.x, mSize * 0.5f ) ); } } else { /* * If we're not using velocity, scale the node up and down. * Keep the node centered in its bounds. */ if ( glm::length( s - vec2( node.getScaleTarget() ) ) < epsilon ) { vec2 scale( s.x > mSize ? mSize * 0.5f : mSize * 2.0f ); node .scale( scale, speed ) .translate( bounds.getCenter() - scale * 0.5f, speed ); } } break; case Transform_Translate: if ( node.getData().mUseVelocity ) { // Get the velocity values. const vec2& v = vec2( node.getTranslateVelocity() ); const float d = node.getTranslateVelocityDecay(); /* * Accelerate the node in a random direction when its velocity * gets too low. */ if ( glm::length( node.getTranslateVelocity() ) <= epsilon ) { node.translateVelocity( randVec2() * randFloat( 5.0f, 20.0f ), decay ); } // Bounce off of bounding box edges. if ( t.x <= bounds.getX1() ) { node .translate( vec2( bounds.getX1() + epsilon, t.y ) ) .translateVelocity( v * vec2( -1.0f, 1.0f ), d ); } else if ( t.x + s.x >= bounds.getX2() ) { node .translate( vec2( ( bounds.getX2() - s.x ) - epsilon, t.y ) ) .translateVelocity( v * vec2( -1.0f, 1.0f ), d ); } if ( t.y <= bounds.getY1() ) { node .translate( vec2( t.x, bounds.getY1() + epsilon ) ) .translateVelocity( v * vec2( 1.0f, -1.0f ), d ); } else if ( t.y + s.y >= bounds.getY2() ) { node .translate( vec2( t.x, ( bounds.getY2() - s.y ) - epsilon ) ) .translateVelocity( v * vec2( 1.0f, -1.0f ), d ); } } else { /* * If we're not using velocity, animate left to right as the * target position is reached. */ if ( glm::length( t - vec2( node.getTranslateTarget() ) ) < epsilon ) { float x = t.x > bounds.getX1() + epsilon ? bounds.getX1() : bounds.getX2() - s.x; node.setTranslate( vec2( x, t.y ), speed ); } } break; default: break; } } mUiTree.update(); }
void GesichtertauschApp::update() { double mDeltaTime = getElapsedSeconds() - mTime; mTime = getElapsedSeconds(); /* heartbeat */ heartbeat(mDeltaTime); { stringstream mStr; mStr << "FPS: " << getAverageFps(); mFPSOut->setText(mStr.str()); } setFrameRate( FRAME_RATE ); /* get new faces */ vector<Rectf> mFaces; mFaceDetection->update(mCameraTexture, mFaces); { stringstream mStr; mStr << "FACES: " << mEntities.size(); mFaceOut->setText(mStr.str()); } /* rescale from capture to window width */ Vec2f mScale = Vec2f(float(CAMERA_WIDTH) / float(DETECTION_WIDTH), float(CAMERA_HEIGHT) / float(DETECTION_HEIGHT)); mScale.x *= float(WINDOW_WIDTH) / float(CAMERA_WIDTH); mScale.y *= float(WINDOW_HEIGHT) / float (CAMERA_HEIGHT); for( vector<Rectf>::iterator faceIter = mFaces.begin(); faceIter != mFaces.end(); ++faceIter ) { Rectf * mFace = &(*faceIter); mFace->x1 *= mScale.x; mFace->x2 *= mScale.x; mFace->y1 *= mScale.y; mFace->y2 *= mScale.y; } /* set all existing entities to dead and invisble*/ for( vector<FaceEntity>::iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter) { FaceEntity* mEntity = &(*mIter); mEntity->alive = false; } /* map new faces to existing entities */ for( vector<FaceEntity>::iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter) { FaceEntity* mEntity = &(*mIter); /* test against all new faces */ for( vector<Rectf>::iterator faceIter = mFaces.begin(); faceIter != mFaces.end(); ) { Rectf mFace = *faceIter; float mDistance = mFace.getCenter().distance(mEntity->border.getCenter()); if (mDistance < MIN_TRACKING_DISTANCE) { // console() << "### found ID again. (" << mEntity->ID << ")" << mEntity->lifetime << endl; // TODO maybe interpolate in a more stable way … Vec2f mAveragedP1 = Vec2f(mFace.x1, mFace.y1); Vec2f mAveragedP2 = Vec2f(mFace.x2, mFace.y2); mAveragedP1 += Vec2f(mEntity->border.x1, mEntity->border.y1); mAveragedP2 += Vec2f(mEntity->border.x2, mEntity->border.y2); mAveragedP1 *= 0.5; mAveragedP2 *= 0.5; mEntity->border.set(mAveragedP1.x, mAveragedP1.y, mAveragedP2.x, mAveragedP2.y); mEntity->alive = true; mEntity->idletime = 0.0; mEntity->lifetime += mDeltaTime; mFaces.erase(faceIter); break; } else { ++faceIter; } } } /* create new entities from left-over faces */ for( vector<Rectf>::iterator faceIter = mFaces.begin(); faceIter != mFaces.end(); ++faceIter) { FaceEntity mNewEntity = FaceEntity(); mNewEntity.ID = mSerialID++; // console() << "### found new face. ID (" << mNewEntity.ID << ")" << endl; Rectf mFace = *faceIter; mNewEntity.border = mFace; mNewEntity.lifetime = 0.0; mNewEntity.idletime = 0.0; mNewEntity.visible = false; mNewEntity.alive = true; mEntities.push_back(mNewEntity); } mFaces.clear(); /* grant dead entities some extra time */ for( vector<FaceEntity>::iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter) { FaceEntity* mEntity = &(*mIter); if (!mEntity->alive) { /* if an entity disappeard we ll grant it some seconds before it gets removed */ if (mEntity->idletime < TIME_BEFOR_IDLE_DEATH) { /* start immediately no matter how long entity already lived */ // if (mEntity->idletime == 0.0) { // console() << "### started dying (" << mEntity->ID << ")" << endl; // } mEntity->idletime += mDeltaTime; mEntity->lifetime += mDeltaTime; /* do we want to count abscence as lifetime? */ mEntity->alive = true; } } } /* erase all dead entities */ for( vector<FaceEntity>::iterator mIter = mEntities.begin(); mIter != mEntities.end();) { FaceEntity mEntity = *mIter; if (mEntity.alive) { ++mIter; } else { mEntities.erase(mIter); } } /* set all 'stable' entities to visible */ for( vector<FaceEntity>::iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter) { FaceEntity * mEntity = &(*mIter); if (mEntity->lifetime > MIN_LIFETIME_TO_VIEW) { mEntity->visible = true; } else { mEntity->visible = false; } } /* update slice */ for( vector<FaceEntity>::iterator mIter = mEntities.begin(); mIter != mEntities.end(); ++mIter) { FaceEntity * mEntity = &(*mIter); mEntity->slice.set(mEntity->border.x1, mEntity->border.y1, mEntity->border.x2, mEntity->border.y2); } }
void Gallery::Picture::render( const Rectf &rect ) { Rectf txtRect; Rectf outRect = rect; gl::pushModelView(); Vec2f flipScale( 1, 1 ); double currentTime = app::getElapsedSeconds(); if ( zooming ) { Rectf zoomRect; if ( mTexture ) zoomRect = mTexture.getBounds(); else zoomRect = Rectf( 0, 0, 1024, 768 ); Rectf screenRect( app::getWindowBounds() ); zoomRect = zoomRect.getCenteredFit( screenRect, true ); if ( screenRect.getAspectRatio() > zoomRect.getAspectRatio() ) zoomRect.scaleCentered( screenRect.getWidth() / zoomRect.getWidth() ); else zoomRect.scaleCentered( screenRect.getHeight() / zoomRect.getHeight() ); Vec2f center = lerp< Vec2f >( zoomRect.getCenter(), outRect.getCenter(), mZoom ); float scale = lerp< float >( zoomRect.getWidth(), outRect.getWidth(), mZoom ) / outRect.getWidth(); outRect.offsetCenterTo( center ); outRect.scaleCentered( scale ); if ( mZoom == 1. ) zooming = false; } else if ( currentTime < appearanceTime ) { flipScale = Vec2f( 0, 1 ); } else if ( currentTime < appearanceTime + sFlipDuration * .5 ) { float flipU = easeOutQuart( ( currentTime - appearanceTime ) / ( sFlipDuration * .5 ) ); flipScale = Vec2f( flipU, 1 ); } else if ( flipping ) { float flipU = easeInOutQuart( math<float>::clamp( ( currentTime - flipStart ) / sFlipDuration ) ); if ( ( flipU >= .5 ) && !flipTextureChanged ) { setRandomTexture(); flipTextureChanged = true; } flipScale = Vec2f( math<float>::abs( flipU * 2 - 1 ), 1 ); if ( flipU >= 1 ) flipping = false; } if ( mTexture ) { txtRect = mTexture.getBounds(); mTexture.bind(); gl::color( Color::white() ); } else { txtRect = Rectf( 0, 0, 1024, 768 ); gl::color( Color::black() ); } txtRect = txtRect.getCenteredFit( outRect, true ); gl::translate( txtRect.getCenter() ); gl::scale( flipScale ); gl::translate( -txtRect.getCenter() ); gl::drawSolidRect( txtRect ); if ( mTexture ) mTexture.unbind(); else gl::color( Color::white() ); gl::popModelView(); }
void motionHistAdvApp::update() { if( !mCapture.checkNewFrame() ) { return; // nothing to do } float secs = getElapsedSeconds(); // always make sure that all the methods have the exact same time. mBoundingRects.clear(); mAngles.clear(); mCaptureSurface = mCapture.getSurface(); mCaptureTex = gl::Texture( mCaptureSurface ); mPrevFrame = mCurrentFrame; mCurrentFrame = toOcv( Channel( mCaptureSurface ) ); if( mPrevFrame.size().width == 0) { return; } cv::absdiff( mCurrentFrame, mPrevFrame, mInput ); cv::threshold( mInput, mInput, 20, 1, cv::THRESH_BINARY ); cv::updateMotionHistory( mInput, mHistory, secs, MHI_DURATION ); cv::convertScaleAbs( mHistory, mMask, 255./MHI_DURATION, (MHI_DURATION - secs)*255.0/MHI_DURATION ); // find the motion gradient cv::calcMotionGradient( mHistory, mMask, mOrientation, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 ); //find the motion segment vector<cv::Rect> tmpRects; cv::segmentMotion( mHistory, mMotionMask, tmpRects, secs, MIN_TIME_DELTA ); if( tmpRects.size() == 0) { mAngles.push_back( cv::calcGlobalOrientation( mOrientation, mMask, mHistory, secs, MHI_DURATION ) ); } else { for( int i=0; i<tmpRects.size(); i++ ){ if( tmpRects[i].area() > 200 ){ cv::Mat mroi( mMask, tmpRects[i] ); cv::Mat oroi( mOrientation, tmpRects[i] ); cv::Mat hroi( mHistory, tmpRects[i] ); double a = cv::calcGlobalOrientation( oroi, mroi, hroi, secs, MAX_TIME_DELTA ); mAngles.push_back(a); mBoundingRects.push_back(tmpRects[i] ); Rectf r = fromOcv( tmpRects[i] ); Vec2f pos = r.getCenter(); float xp = cos( toRadians( mAngles.back() ) ); float yp = sin( toRadians( mAngles.back() ) ); Vec2f vel = Vec2f( xp, yp ); Area area = Area( r ); area.expand( area.getWidth()/3, area.getHeight()/3 ); Rectf rect = r - pos; Surface surf = mCaptureSurface.clone( area ); mQuads.push_back( Quad( pos, vel, surf, rect ) ); } } } mHistoryTex.update( Surface( fromOcv( mHistory ) ) ); mMotionMaskTex.update( Surface( fromOcv( mMotionMask ) ) ); mDiffTex.update( Surface( fromOcv( mInput ) ) ); mOrientTex.update( Surface( fromOcv( mOrientation ) ) ); for( vector<Quad>::iterator it = mQuads.begin(); it != mQuads.end(); ){ if( it->isDead() ){ it = mQuads.erase( it ); } else { it->update(); ++it; } } }