Exemplo n.º 1
0
/* Computes acceleration to every control point of the jello cube, 
   which is in state given by 'jello'.
   Returns result in array 'a'. */
void computeAcceleration(struct world * jello, struct point a[8][8][8])
{
	bool side;
	point planeNormal;
	// check the position of the jello cube
	inclinedPlaneSide(jello, jello->p[0][0][0], side, planeNormal);
	if (side == false)
	{
		pMULTIPLY(planeNormal, -1, planeNormal);
	}
	for (int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 8; j++)
		{
			for (int k = 0; k < 8; k++)
			{
				a[i][j][k].x = 0;
				a[i][j][k].y = 0;
				a[i][j][k].z = 0;
				// calculate the internal force of the jello
				structualForce(jello, i, j, k, a[i][j][k]);
				shearForce(jello, i, j, k, a[i][j][k]);
				bendForce(jello, i, j, k, a[i][j][k]);
				
				////internalForce(jello, i, j, k, );
				//point internalForce = a[i][j][k];
				// calculate the external force in the bounding box
				
				point externF;
				externalForce(jello, i, j, k, externF);
				pSUM(a[i][j][k], externF, a[i][j][k]);
				// calculate the collision force in the bounding box
				//point collisionF;
				collisionForce(jello, i, j, k, a[i][j][k]);
				
				// check the point position
				bool s;
				inclinedPlaneSide(jello, jello->p[i][j][k], s, planeNormal);
				// calculate the inclined plane response force in the bounding box
				//point pCollisionF;
				planeCollisionForce(jello, i, j, k, s, planeNormal, a[i][j][k]);
				
				// calculate the acceleration using F = m * a, a = F / m
				//point F;
				/*pSUM(internF, externF, F);
				pSUM(F, collisionF, F);
				pSUM(F, pCollisionF, F);*/
				pMULTIPLY(a[i][j][k], (1 / jello->mass), a[i][j][k]);
			}
		}
	}
}
/*
 Calculate the acceleration of every particle in a brute force manner (n^2).
 Used for debugging.
*/
void PARTICLE_SYSTEM::calculateAccelerationBrute() {
        
  ///////////////////
  // STEP 1: UPDATE DENSITY & PRESSURE OF EACH PARTICLE
  
  for (int i = 0; i < PARTICLE::count; i++) {
    
    // grab ith particle reference
    
    PARTICLE& particle = _particles[i];
    
    // now iteratate through neighbors
    
    particle.density() = 0.0;
            
    for (int j = 0; j < PARTICLE::count; j++) {
      
      PARTICLE& neighborParticle = _particles[j];
      
      vec3 diffPosition = particle.position() - neighborParticle.position();
      
      float radiusSquared = dot(diffPosition, diffPosition);
      
      if (radiusSquared <= h*h)
        particle.density() += Wpoly6(radiusSquared);
    }
    
    particle.density() *= PARTICLE_MASS;
    
    // p = k(density - density_rest)
    
    particle.pressure() = GAS_STIFFNESS * (particle.density() - REST_DENSITY);
  
    //totalDensity += particle.density();
  }
    
  ///////////////////
  // STEP 2: COMPUTE FORCES FOR ALL PARTICLES
  
  for (int i = 0; i < PARTICLE::count; i++) {
    
    PARTICLE& particle = _particles[i];
    
    //cout << "particle id: " << particle.id() << endl;
    
    vec3 f_pressure,
    f_viscosity, 
    f_surface, 
    f_gravity(0.0, particle.density() * -9.80665, 0.0),
    n, 
    colorFieldNormal,
    colorFieldLaplacian; // n is gradient of colorfield
    //float n_mag;
    
    for (int j = 0; j < PARTICLE::count; j++) {
      PARTICLE& neighbor = _particles[j];
      
      vec3 diffPosition = particle.position() - neighbor.position();
      vec3 diffPositionNormalized = normalize(diffPosition); // need?
      float radiusSquared = dot(diffPosition, diffPosition);
      
      if (radiusSquared <= h*h) {
        
                
        if (radiusSquared > 0.0) {
          
          //neighborsVisited++;
          //cout << neighborsVisited << endl;
          
          //cout << neighbor.id() << endl;
          
          vec3 gradient;
                    
          Wpoly6Gradient(diffPosition, radiusSquared, gradient);
                    
          f_pressure += (particle.pressure() + neighbor.pressure()) / (2.0f * neighbor.density()) * gradient;
          
          colorFieldNormal += gradient / neighbor.density();
        }
        
        f_viscosity += (neighbor.velocity() - particle.velocity()) * WviscosityLaplacian(radiusSquared) / neighbor.density();
        
        colorFieldLaplacian += Wpoly6Laplacian(radiusSquared) / neighbor.density();
      }
      
    }
    
    f_pressure *= -PARTICLE_MASS;
    
    //totalPressure += f_pressure;
    
    f_viscosity *= VISCOSITY * PARTICLE_MASS;
    
    colorFieldNormal *= PARTICLE_MASS;
    
    particle.normal = -1.0f * colorFieldNormal;
    
    colorFieldLaplacian *= PARTICLE_MASS;
    
    // surface tension force
    
    float colorFieldNormalMagnitude = colorFieldNormal.length();
    
    if (colorFieldNormalMagnitude > surfaceThreshold) {
      
      particle.flag() = true;
      f_surface = -SURFACE_TENSION * colorFieldLaplacian * colorFieldNormal / colorFieldNormalMagnitude;
      
    }
    else {
      particle.flag() = false;
    }
    
    // ADD IN SPH FORCES
    
    particle.acceleration() = (f_pressure + f_viscosity + f_surface + f_gravity) / particle.density();
    
    
    // EXTERNAL FORCES HERE (USER INTERACTION, SWIRL)
    
    vec3 f_collision;
    
    collisionForce(particle, f_collision);    

  }
}
/*
 Calculate the acceleration of each particle using a grid optimized approach.
 For each particle, only particles in the same grid cell and the (26) neighboring grid cells must be considered,
 since any particle beyond a grid cell distance away contributes no force.
*/
void PARTICLE_SYSTEM::calculateAcceleration() {
  
  ///////////////////
  // STEP 1: UPDATE DENSITY & PRESSURE OF EACH PARTICLE
  
  for (int x = 0; x < (*grid).xRes(); x++) {
    for (int y = 0; y < (*grid).yRes(); y++) {
      for (int z = 0; z < (*grid).zRes(); z++) {
        
        vector<PARTICLE>& particles = (*grid)(x,y,z);
                
        for (int p = 0; p < particles.size(); p++) {
          
          PARTICLE& particle = particles[p];

          particle.density() = 0.0;
          
          // now iteratate through neighbors
          
          for (int offsetX = -1; offsetX <= 1; offsetX++) {
            if (x+offsetX < 0) continue;
            if (x+offsetX >= (*grid).xRes()) break;
            
            for (int offsetY = -1; offsetY <= 1; offsetY++) {
              if (y+offsetY < 0) continue;
              if (y+offsetY >= (*grid).yRes()) break;
              
              for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
                if (z+offsetZ < 0) continue;
                if (z+offsetZ >= (*grid).zRes()) break;
                
                vector<PARTICLE>& neighborGridCellParticles = (*grid)(x+offsetX, y+offsetY, z+offsetZ);
              
                for (int i = 0; i < neighborGridCellParticles.size(); i++) {
                  
                  PARTICLE& neighborParticle = neighborGridCellParticles[i];
                  
                  vec3 diffPosition = particle.position() - neighborParticle.position();
                  
                  float radiusSquared = dot(diffPosition, diffPosition);
                  
                  if (radiusSquared <= h*h)
                    particle.density() += Wpoly6(radiusSquared);
                  
                }
              }
            }
          }
          
          particle.density() *= PARTICLE_MASS;
                        
          // p = k(density - density_rest)
          
          particle.pressure() = GAS_STIFFNESS * (particle.density() - REST_DENSITY);           
        }
      }
    }
  }
  
  ///////////////////
  // STEP 2: COMPUTE FORCES FOR ALL PARTICLES
  
  for (int x = 0; x < (*grid).xRes(); x++) {
    for (int y = 0; y < (*grid).yRes(); y++) {
      for (int z = 0; z < (*grid).zRes(); z++) {
        
        vector<PARTICLE>& particles = (*grid)(x,y,z);
        
        for (int p = 0; p < particles.size(); p++) {
          
          PARTICLE& particle = particles[p];
          
          //cout << "particle id: " << particle.id() << endl;
          
          vec3 f_pressure,
          f_viscosity, 
          f_surface, 
          f_gravity = gravityVector * particle.density(),
          colorFieldNormal;
          
          float colorFieldLaplacian;
                    
          // now iteratate through neighbors
          
          for (int offsetX = -1; offsetX <= 1; offsetX++) {
            if (x+offsetX < 0) continue;
            if (x+offsetX >= (*grid).xRes()) break;
            
            for (int offsetY = -1; offsetY <= 1; offsetY++) {
              if (y+offsetY < 0) continue;
              if (y+offsetY >= (*grid).yRes()) break;
              
              for (int offsetZ = -1; offsetZ <= 1; offsetZ++) {
                if (z+offsetZ < 0) continue;
                if (z+offsetZ >= (*grid).zRes()) break;
                
                vector<PARTICLE>& neighborGridCellParticles = (*grid)(x+offsetX, y+offsetY, z+offsetZ);
                
                for (int i = 0; i < neighborGridCellParticles.size(); i++) {
                  
                  PARTICLE& neighbor = neighborGridCellParticles[i];
                  
                  //if (particle.id() == neighbor.id()) continue; // SKIPPING COMPARISON OF THE SAME PARTICLE
                  
                  vec3 diffPosition = particle.position() - neighbor.position();
                  float radiusSquared = dot(diffPosition, diffPosition);
                  
                  if (radiusSquared <= h*h) {
                    
                    vec3 poly6Gradient, spikyGradient;
                    
                    Wpoly6Gradient(diffPosition, radiusSquared, poly6Gradient);
                    
                    WspikyGradient(diffPosition, radiusSquared, spikyGradient);
                    
                    if (particle.id() != neighbor.id()) {
                      
                      f_pressure += (float)(particle.pressure()/pow(particle.density(),2)+neighbor.pressure()/pow(neighbor.density(),2))*spikyGradient;
                      
                      f_viscosity += (neighbor.velocity() - particle.velocity()) * WviscosityLaplacian(radiusSquared) / neighbor.density();

                    }
                    
                                        
                    colorFieldNormal += poly6Gradient / neighbor.density();
                    
                    colorFieldLaplacian += Wpoly6Laplacian(radiusSquared) / neighbor.density();
                    
                  }
                }
              }
            }
          } // end of neighbor grid cell iteration
          
          f_pressure *= -PARTICLE_MASS * particle.density();
          
          f_viscosity *= VISCOSITY * PARTICLE_MASS;
          
          colorFieldNormal *= PARTICLE_MASS;
          
          
          particle.normal = -1.0f * colorFieldNormal;
          
          colorFieldLaplacian *= PARTICLE_MASS;
          
          
          // surface tension force
          
          float colorFieldNormalMagnitude = colorFieldNormal.length();
          
          if (colorFieldNormalMagnitude > SURFACE_THRESHOLD) {
            
            particle.flag() = true;
            f_surface = -SURFACE_TENSION * colorFieldNormal / colorFieldNormalMagnitude * colorFieldLaplacian;
            
          }
          else {
            particle.flag() = false;
          }
          
          // ADD IN SPH FORCES
          
          particle.acceleration() = (f_pressure + f_viscosity + f_surface + f_gravity) / particle.density();
          
          // EXTERNAL FORCES HERE (USER INTERACTION, SWIRL)
          
          vec3 f_collision;
          collisionForce(particle, f_collision);
          
        } 
      }
    }
  }
  
}