void ParticleController::doubleDensityRelaxation( float neighborhood, float restDensity, float stiffnessParameter, float stiffnessParameterNear )
{
    float neighborhoodSqrd = neighborhood * neighborhood;
    for ( list<Particle>::iterator p1 = mParticles.begin(); p1 != mParticles.end(); ++p1 ){
		p1->mDensity = 0.0f;
        p1->mNearDensity = 0.0f;
        for ( list<Particle>::iterator p2 = p1->mNeighbors.begin(); p2 != p1->mNeighbors.end(); ++p2 ){
            Vec2f rij = p1->mPos - p2->mPos;
            float rijSqrd = rij.lengthSquared();
            float q = rijSqrd / neighborhoodSqrd;
            p1->mDensity += ( 1-q ) * ( 1-q );
            p1->mNearDensity += ( 1-q ) * ( 1-q ) * ( 1-q );
        }
        p1->mPressure = stiffnessParameter * ( p1->mDensity - restDensity );
        p1->mNearPressure = stiffnessParameterNear * p1->mNearDensity;
        Vec2f dpos = Vec2f::zero();
        for ( list<Particle>::iterator p2 = p1->mNeighbors.begin(); p2 != p1->mNeighbors.end(); ++p2 ){
            Vec2f rij = p1->mPos - p2->mPos;
            float rijSqrd = rij.lengthSquared();
            float q = rijSqrd / neighborhoodSqrd;
            Vec2f DPos = rij.normalized() * ( p1->mPressure * ( 1-q ) + p1->mNearPressure * ( 1-q ) * ( 1-q ) );
            p2->mPos += DPos/2;
            dpos -= DPos/2;
        }
        p1->mPos += dpos;
    }

}
Beispiel #2
0
//---------------------------------------------------------------------------------------------------
void FactionState::ProcessAction(AIAction action, const ActionBuffer& commandBuffer)
{
  ShipState* ship;
  uint32_t shipId;
  switch (action)
  {
  case kForce:
    shipId = commandBuffer.ReadUInt();
    ship = battle_.ships().has(shipId) ? &battle_.ships().lookup(shipId) : nullptr;
    if (ship != nullptr && &ship->faction() == this)
    {
      Vec2f force = commandBuffer.ReadVec2f();
      float totalForceSquared = force.lengthSquared();
      if (totalForceSquared > AICommand::kMaxForce*AICommand::kMaxForce)
        force = force.normalized() * AICommand::kMaxForce;        
      ship->set_force(force);
    }
    break;
  case kFire:
    shipId = commandBuffer.ReadUInt();
    ship = battle_.ships().has(shipId) ? &battle_.ships().lookup(shipId) : nullptr;
    if (ship != nullptr && &ship->faction() == this)
      battle_.Fire(*ship);
    break;
  }
}
void ParticleEmitter::repulseParticles()
{
	for( list<Particle>::iterator p1 = mParticles.begin(); p1 != mParticles.end(); ++p1 ){
		
		list<Particle>::iterator p2 = p1;
		for( ++p2; p2 != mParticles.end(); ++p2 ) {
			Vec2f dir = p1->mLoc - p2->mLoc;
			
			float thresh = ( p1->mRadius + p2->mRadius ) * 5.0f;
			if( dir.x > -thresh && dir.x < thresh && dir.y > -thresh && dir.y < thresh ){
				float distSqrd = dir.lengthSquared() * dir.length();
				
				if( distSqrd > 0.0f ){
					float F = 1.0f/distSqrd;
					dir.normalize();
					
					// acceleration = force / mass
					p1->mAcc += ( F * dir ) / p1->mMass;
					p2->mAcc -= ( F * dir ) / p2->mMass;

					// TMP
					p1->mAcc *= 0.005;
					p2->mAcc *= 0.005;
					
				}
			}
		}
	}
}
void WaterSimApp::mouseMove( MouseEvent event )
{
	Vec2f delta = Vec2f( getWindowWidth(), getWindowHeight() ) / 2.0f - event.getPos();
	if( delta.lengthSquared() > 5 ) {
		mGravityVector = delta.normalized() * 9.8f;
		mGravityVector.y = -mGravityVector.y;
	}
}
        //--------------------------------------------------------------
        void DrawerBase::drawVectors(float x, float y, float renderWidth, float renderHeight)  const {
            if(enabled == false) return;
            
            ofPushStyle();
            if(useAdditiveBlending) ofEnableBlendMode(OF_BLENDMODE_ADD);
            else ofDisableAlphaBlending();

            int fw = _fluidSolver->getWidth();
            int fh = _fluidSolver->getHeight();

            //	int xStep = renderWidth / 10;		// every 10 pixels
            //	int yStep = renderHeight / 10;		// every 10 pixels
            
            ofPushMatrix();
            ofTranslate(x, y, 0);
            ofScale(renderWidth/(fw-2), renderHeight/(fh-2), 1.0);
            
            float maxVel = 5.0f/20000;
            
            Vec2f vel;
            float vt = velDrawThreshold * _fluidSolver->getInvWidth() * _fluidSolver->getInvHeight();
            vt *= vt;
            
            for (int j=0; j<fh-2; j+=vectorSkipCount+1 ){
                for (int i=0; i<fw-2; i+=vectorSkipCount+1 ){
                    vel = _fluidSolver->getVelocityAtCell(i+1, j+1);
                    float d2 = vel.lengthSquared();
                    if(d2>vt) {
                        if(d2 > maxVel * maxVel) {
                            float mult = maxVel * maxVel/ d2;
                            //				float mult = (d2 - maxVel * maxVel) / d2;
                            vel.x *= mult;
                            vel.y *= mult;
                        }
                        vel *= velDrawMult * 50000;
                        float b = mapRange(d2, vt, maxVel, 0.0f, brightness);
                        b = brightness*255;
//                        ofBeginShape();
//                        ofSetColor(0, 0, 0);
//                        ofVertex(i, j);
                        ofSetColor(b, b, b);
                        ofDrawLine(i, j, i + vel.x, j + vel.y);
//                        ofVertex(i + vel.x, j + vel.y);
//                        ofEndShape();
                    }
                }
            }
            ofPopMatrix();
            ofPopStyle();
        }
void ParticleController::applyViscosity( float neighborhood, float viscositySigma, float viscosityBeta )
{
    float neighborhoodSqrd = neighborhood * neighborhood;
    for ( list<Particle>::iterator p1 = mParticles.begin(); p1 != mParticles.end(); ++p1 ){
		for ( list<Particle>::iterator p2 = p1->mNeighbors.begin(); p2 != p1->mNeighbors.end(); ++p2 ){
            Vec2f rij = p1->mPos - p2->mPos;
            float rijSqrd = rij.lengthSquared();
            float u = ( p1->mVel - p2->mVel ).dot( rij.normalized() );
            float q = rijSqrd / neighborhoodSqrd;
            if ( u > 0 ){
                Vec2f I = ( 1 - q ) * ( ( viscositySigma * u ) + ( viscosityBeta * u * u ) ) * rij.normalized();
                p1->mVel -= I/2;
                p2->mVel += I/2;
            }
        }
    }
}
void Arcball::mapToSphere(const Vector2D& point, Vector3D& newVec) const{
  Vec2f tempVec = Vec2f(point.x, point.y);
  //scale to [-1..1]
  tempVec.x = (tempVec.x * ADJ_WIDTH) - 1.0f;
  tempVec.y = 1.0f - (tempVec.y * ADJ_HEIGHT);
  float length = tempVec.lengthSquared();
  //outside of the sphere?
  if (length > 1.0f){
    float norm = sqrt(length);
    newVec.x = tempVec.x*norm;
    newVec.y = tempVec.y*norm;
    newVec.z = 0.0f;
  }
  else{
    newVec.x = tempVec.x;
    newVec.y = tempVec.y;
    newVec.z = sqrt(1.0f-length);
  }
}
Beispiel #8
0
void Controller::checkForBalloonPop( const Vec2f &mousePos )
{
	for( vector<Balloon>::reverse_iterator it = mBalloons.rbegin(); it != mBalloons.rend(); ++it ){
		Vec2f dir		= mousePos - it->mScreenPos;
		float distSqrd	= dir.lengthSquared();
		if( distSqrd < 1000.0f ){
			Vec3f pos		= it->mPos;
			float lifespan	= 12.0f;
			float speed		= 20.0f;
			mShockwaves.push_back( Shockwave( it->mPos, Vec3f::yAxis(), lifespan, speed ) );
			
			int numConfettis = 250;
			addConfettis( numConfettis, pos, 0.5f );
			
			// PLAY A BALLOON POP AUDIO FILE HERE
			
			it->mIsDead = true;
			
			break;
		}
	}
}
double PathFitter::computeMaxError(vector<Vec2f> const &d, int first, int last, vector<Vec2f> *bezCurve, vector<double> const &u, int *splitPoint)

{
    int		i;
    double	maxDist;        // Maximum error
    double	dist;           // Current error
    Vec2f	P;              // Point on curve
    Vec2f	v;              // Vector from point to curve
    
    *splitPoint = (last - first + 1)/2;
    maxDist = 0.0;
    for (i = first + 1; i < last; i++) {
		P = bezierII(3, *bezCurve, u[i-first]);
		v = P - d[i];
        dist = v.lengthSquared();
		if (dist >= maxDist) {
	    	maxDist = dist;
	    	*splitPoint = i;
		}
    }
    return (maxDist);
}
Beispiel #10
0
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 );
}
 /*
  * RETURNS numeric_limits<float>::max() IF CLOSEST POINT IS FARTHER THAN threshold DISTANCE
  *
  * REFERENCE: "Minimum Distance between a Point and a Line" BY Paul Bourke
  * http://paulbourke.net/geometry/pointlineplane
  */
 float getShortestDistance(const Vec2f &point, const vector<Vec2f> &polygon, bool close, float threshold)
 {
     float min = threshold * threshold; // BECAUSE IT IS MORE EFFICIENT TO WORK WITH MAGNIFIED DISTANCES
     
     int end = polygon.size();
     bool found = false;
     
     for (int i = 0; i < end; i++)
     {
         int i0, i1;
         
         if (i == end - 1)
         {
             if (close)
             {
                 i0 = i;
                 i1 = 0;
             }
             else
             {
                 break;
             }
         }
         else
         {
             i0 = i;
             i1 = i + 1;
         }
         
         Vec2f p0 = polygon[i0];
         Vec2f p1 = polygon[i1];
         
         if (p0 != p1)
         {
             Vec2f delta = p1 - p0;
             float u = delta.dot(point - p0) / delta.lengthSquared();
             
             if (u >= 0 && u <= 1)
             {
                 Vec2f p = p0 + u * delta;
                 float mag = (p - point).lengthSquared();
                 
                 if (mag < min)
                 {
                     min = mag;
                     found = true;
                 }
             }
             else
             {
                 float mag0 = (p0 - point).lengthSquared();
                 float mag1 = (p1 - point).lengthSquared();
                 
                 if ((mag0 < min) && (mag0 < mag1))
                 {
                     min = mag0;
                     found = true;
                 }
                 else if ((mag1 < min) && (mag1 < mag0))
                 {
                     min = mag1;
                     found = true;
                 }
             }
         }
     }
     
     return found ? ci::math<float>::sqrt(min) : numeric_limits<float>::max();
 }
void PeerCircle::update()
{
	// attraction to torrent position
	Vec2f dir = mAttractorPos - mPos;
	float distSqrd = dir.lengthSquared();

	float strength = 5.f;

	if ( distSqrd > 0.f )
	{
		float minDistSqrd = 1000.f;
		if ( distSqrd < minDistSqrd )
		{
			strength = lmap< float >( 1.f, minDistSqrd, 0.f, strength, distSqrd );
			strength = math< float >::clamp( strength, 0.f, 5.f );
		}
		float force = strength * mMass / distSqrd;
		Vec2f deltaForce = dir * force;
		moveBy( deltaForce * mInvMass, false );
	}

	// repel other peers
	const std::vector< PeerRef > &peers = mTorrentRef->getPeers();
	for ( PeerRef peer : peers )
	{
		if ( peer->getId() == mId )
			continue;

		auto other = std::static_pointer_cast< PeerCircle >( peer );
		Vec2d dir = mPos - other->getPos();
		float distSqrd = dir.lengthSquared();
		if ( distSqrd > .0f )
		{
			float force = .1f * mMass * other->getMass() / distSqrd;
			Vec2f deltaForce = dir * force;
			moveBy( deltaForce * mInvMass, false );
			other->moveBy( - deltaForce * other->getInvMass(), false );
		}
	}

	// do verlet
	Vec2f curPos = mPos;
	Vec2f vel = mPos - mOldPos;
	mPos += vel * mDrag;
	mOldPos = curPos;

	/*
	// TODO: attract actual torrent position
	Vec2d dir = Vec2d( 500, 500 ) - mPos;
	double distSqrd = dir.lengthSquared();

	if ( distSqrd > 0. )
	{
		double f = math< double >::sqrt( distSqrd ) * .00001;
		mAcc += dir.normalized() * f;
	}

	mVel += mAcc;
	mPos += mVel;
	mVel *= mDecay;
	mAcc.set( 0., 0. );
	//mRadius = lerp< double, double >( mRadius, mRadiusOrig, .01 );
	*/
}
void ParticleController::checkForNeighbors( float neighborhood )
{
    int ctr1 = 0;
    int ctr2 = 0;
    float neighborhoodSqrd = neighborhood * neighborhood;
    int scnt = 0;
    Spring *s1;
    Particle *it;
    for ( list<Particle>::iterator p1 = mParticles.begin(); p1 != mParticles.end(); ++p1 ){
        if ( ctr1 < mParticles.size() - 1 ){
            
        
        for ( list<Particle>::iterator p2 = mParticles.begin(); p2 != mParticles.end(); ++p2 ){
            //std::cout << "s: " << scnt << "\n";
            //std::cout << "1: " << ctr1 << "\n";
            //std::cout << "2: " << ctr2 << "\n";
            if ( ctr1 != ctr2 ){
                Vec2f rij = p1->mPos - p2->mPos;
                float rijSqrd = rij.lengthSquared();
                float q = rijSqrd / neighborhoodSqrd;
                it = &*p2;
                //s1 = mSprings.at( scnt );
                //std::cout << "before: " << s1.mIsActive << "\n";
                /*
                std::cout << "p1: ";
                std::cout << p1->mPos;
                std::cout << " p2: ";
                std::cout << p2->mPos << "\n";
                std::cout << "sA: ";
                std::cout << s1.pA->mPos;
                std::cout << " sb: ";
                std::cout << s1.pB->mPos << "\n\n";
                 */
                Particle *part1 = &*p1;
                Particle *part2 = &*p2;
                
                if ( q < 1.0f ){
                    p1->addNeighbor( it );
                    if ( ctr2 > ctr1 ){
                        p1->addForwardNeighbor( it );
                        //std::cout << scnt << "\n";
                        s1 = new Spring( part1, part2, neighborhood );
                        //std::cout << scnt << ": " << s1->particleA->mPos << ": " << s1->particleB->mPos << "\n";
                        addSpring( s1 );
                        //s1.makeActive();
                        //s1.mIsActive = true;
                    }
                }
                else {
                    //std::cout << "FALSE";
                    if ( ctr2 > ctr1 ){
                        //std::cout << scnt << "\n";
                        //s1 = new Spring( part1, part2, neighborhood );
                        //destroySpring( s1 );
                        //s1.kill();
                        //s1.mIsActive = false;
                    }
                }
                //std::cout << "after: " << s1.mIsActive << "\n";
                
                if ( ctr2 > ctr1 ){
                   scnt++; // springs are forward counting
                }
            }
            ctr2++;
        }
        }
        ctr1++;
        ctr2 = 0;
        //scnt++;
    }
}