void PointSet::Emit ( float spacing )
{
	Particle* p;
	Vector3DF dir;
	Vector3DF pos;
	float ang_rand, tilt_rand;
	float rnd = m_Vec[EMIT_RATE].y * 0.15;	
	int x = (int) sqrt(m_Vec[EMIT_RATE].y);

	for ( int n = 0; n < m_Vec[EMIT_RATE].y; n++ ) {
		ang_rand = (float(rand()*2.0/RAND_MAX) - 1.0) * m_Vec[EMIT_SPREAD].x;
		tilt_rand = (float(rand()*2.0/RAND_MAX) - 1.0) * m_Vec[EMIT_SPREAD].y;
		dir.x = cos ( ( m_Vec[EMIT_ANG].x + ang_rand) * DEGtoRAD ) * sin( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z;
		dir.y = sin ( ( m_Vec[EMIT_ANG].x + ang_rand) * DEGtoRAD ) * sin( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z;
		dir.z = cos ( ( m_Vec[EMIT_ANG].y + tilt_rand) * DEGtoRAD ) * m_Vec[EMIT_ANG].z;
		pos = m_Vec[EMIT_POS];
		pos.x += spacing * (n/x);
		pos.y += spacing * (n%x);
		
		p = (Particle*) GetElem( 0, AddPointReuse () );
		p->pos = pos;
		p->vel = dir;
		p->vel_eval = dir;
		p->age = 0;	
		p->type = 0;
		p->clr = COLORA ( m_Time/10.0, m_Time/5.0, m_Time /4.0, 1 );
	}
}
int PointSet::AddVolume ( Vector3DF min, Vector3DF max, float spacing )
{
	Vector3DF pos;
	Point* p;	
	float dx, dy, dz;
	dx = max.x-min.x;
	dy = max.y-min.y;
	dz = max.z-min.z;
	int cnt = 0;
	for (float z = max.z; z >= min.z; z -= spacing ) {
		for (float y = min.y; y <= max.y; y += spacing ) {	
			for (float x = min.x; x <= max.x; x += spacing ) {
				p = GetPoint ( AddPointReuse () );
				pos.Set ( x, y, z);
				//pos.x += -0.05 + float( rand() * 0.1 ) / RAND_MAX;
				//pos.y += -0.05 + float( rand() * 0.1 ) / RAND_MAX;
				//pos.z += -0.05 + float( rand() * 0.1 ) / RAND_MAX;
				p->pos = pos;	
				p->type = 0;
				p->clr = COLORA( (x-min.x)/dx, (y-min.y)/dy, (z-min.z)/dz, 1);
				cnt++;
			}
		}
	}
	sphPoints = cnt ;
	return sphPoints;
}
Beispiel #3
0
void PointSet::AddVolume ( Vector3DF min, Vector3DF max, float spacing )
{
	Vector3DF pos;
	Point* p;	
	float dx, dy, dz;
	dx = max.x-min.x;
	dy = max.y-min.y;
	dz = max.z-min.z;
	for (float z = max.z; z >= min.z; z -= spacing ) {
		for (float y = min.y; y <= max.y; y += spacing ) {	
			for (float x = min.x; x <= max.x; x += spacing ) {
				p = GetPoint ( AddPointReuse () );
				pos.Set ( x, y, z);
				p->pos = pos;				
				p->clr = COLORA( (x-min.x)/dx, (y-min.y)/dy, (z-min.z)/dz, 1);
			}
		}
	}	
}
DWORD PointSet::GetColor ( float x, float y, float z )
{
	Vector3DF clr;  
	float dx, dy, dz, dsq;
	float sum;
	int pndx;
	Point* pcurr;
	float R2 = (m_GridCellsize/2.0)*(m_GridCellsize/2.0);

	Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 );

	int cnt = 0;
	sum = 0.0;
	clr.Set (0,0,0);
	for (int cell=0; cell < 8; cell++ ) {
		if ( m_GridCell[cell] != -1 ) {
			pndx = m_Grid [ m_GridCell[cell] ];
			while ( pndx != -1 ) {					
				pcurr = (Point*) (mBuf[0].data + pndx*mBuf[0].stride);
				dx = x - pcurr->pos.x;
				dy = y - pcurr->pos.y;
				dz = z - pcurr->pos.z;
				dsq = dx*dx+dy*dy+dz*dz;				
				if ( dsq < R2 ) {
					dsq = 2.0*R2 / (dsq*dsq);					
					clr.x += RED(pcurr->clr) * dsq;
					clr.y += GRN(pcurr->clr) * dsq;
					clr.z += BLUE(pcurr->clr) * dsq;						
				}
				pndx = pcurr->next;
			}	
		}
	}
	clr.Normalize ();
	return COLORA(clr.x, clr.y, clr.z, 1.0);
}
void PointSet::AddControlVolume ( std::vector<glm::vec3> *allvertices )
{
    Vector3DF pos;
	Point* p;	
	int dimx=5;
	int dimy=5;
	float dimz=10;
	int ccnt=0;
	//vec3 a = myvertices. ; 
	glm::vec3 startpoint(0,0.0,-5.0);
	glm::vec3 direction(0,0,1.0);
	glm::vec3 vertex1(0,1.0,2.0);
	glm::vec3 vertex2(-1.0,-1.0,0);
	glm::vec3 vertex3(1.0,-1.0,0);
	glm::vec3 v1,v2,v3;
	int a = allvertices->size();
	double value=0;
	value=PointSet::Test_RayPolyIntersect(startpoint,direction,vertex1,vertex2,vertex3);
	int count=0;
	float var=1.0;
	//glm::vec3 *a = myvertices;
	for (float x = -5; x < 18; x += 1.0)
	{
		for (float y = -5; y <= 14; y += 1.0)
		{	
			 for (float z = -5; z <= 25; z += var )
			 {
				 /*if(z>=-5.0 && z <2.0)
					 var =1.0;
				  else if(z>=2.0 && z < 8.0)
					 var =0.70;
				   else if(z>=8.0 && z < 15.0)
					 var =0.6;
				    else if(z >= 15.0 && z <=25.0)
					 var =0.3;*/

				 count = 0 ;
				 startpoint=glm::vec3((float)x,(float)y,(float)z);

				 direction=glm::vec3(1.0,0.1,0);
				 for(int v=0 ;v < a ; v+=3)
				 {
					 //checking each vertex in the grid with all the 192 triangles of mesh
					 v1=(*allvertices)[v];
					 v2=(*allvertices)[v+1];
					 v3=(*allvertices)[v+2];
					 vertex1= vec3(v1[0],v1[1],v1[2]);
					 vertex2= vec3(v2[0],v2[1],v2[2]);
					 vertex3= vec3(v3[0],v3[1],v3[2]);
					 value=PointSet::Test_RayPolyIntersect(startpoint,direction,vertex1,vertex2,vertex3);
						if(value != -1.0)
						{
							 count++;
						}

				 }

				 //odd
				 if( count % 2 == 1)
				 {
							 //inside the mesh
						p = GetPoint ( AddPointReuse () );
						pos.Set ( x,y,z+10.0f);
						p->pos = pos;	
						p->type = 1;
						p->clr = COLORA( 1.0,0.3,0.3, 0);  ///   0.1,0.3,1.0,1.0 
						
						ccnt++;
				 }
				 //var=var-0.1;
			}
			// var = 1.0;
			 
		}

	}	

}
void FluidSystem::Advance ()
{
	char *dat1, *dat1_end;
	Fluid* p;
	Vector3DF norm, z;
	Vector3DF dir, accel;
	Vector3DF vnext;
	Vector3DF min, max;
	double adj;
	float SL, SL2, ss, radius;
	float stiff, damp, speed, diff; 
	SL = m_Param[SPH_LIMIT];
	SL2 = SL*SL;
	
	stiff = m_Param[SPH_EXTSTIFF];
	damp = m_Param[SPH_EXTDAMP];
	radius = m_Param[SPH_PRADIUS];
	min = m_Vec[SPH_VOLMIN];
	max = m_Vec[SPH_VOLMAX];
	ss = m_Param[SPH_SIMSCALE];

	dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
	for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
		p = (Fluid*) dat1;		

		// Compute Acceleration		
		accel = p->sph_force;
		accel *= m_Param[SPH_PMASS];

		// Velocity limiting 
		speed = accel.x*accel.x + accel.y*accel.y + accel.z*accel.z;
		if ( speed > SL2 ) {
			accel *= SL / sqrt(speed);
		}		
	
		// Boundary Conditions

		// Z-axis walls
		diff = 2 * radius - ( p->pos.z - min.z - (p->pos.x - m_Vec[SPH_VOLMIN].x) * m_Param[BOUND_ZMIN_SLOPE] )*ss;
		if (diff > EPSILON ) {			
			norm.Set ( -m_Param[BOUND_ZMIN_SLOPE], 0, 1.0 - m_Param[BOUND_ZMIN_SLOPE] );
			adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
			accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
		}		

		diff = 2 * radius - ( max.z - p->pos.z )*ss;
		if (diff > EPSILON) {
			norm.Set ( 0, 0, -1 );
			adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
			accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
		}
		
		// X-axis walls
		if ( !m_Toggle[WRAP_X] ) {
			diff = 2 * radius - ( p->pos.x - min.x + (sin(m_Time*10.0)-1+(p->pos.y*0.025)*0.25) * m_Param[FORCE_XMIN_SIN] )*ss;	
			//diff = 2 * radius - ( p->pos.x - min.x + (sin(m_Time*10.0)-1) * m_Param[FORCE_XMIN_SIN] )*ss;	
			if (diff > EPSILON ) {
				norm.Set ( 1.0, 0, 0 );
				adj = (m_Param[ FORCE_XMIN_SIN ] + 1) * stiff * diff - damp * norm.Dot ( p->vel_eval ) ;
				accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;					
			}

			diff = 2 * radius - ( max.x - p->pos.x + (sin(m_Time*10.0)-1) * m_Param[FORCE_XMAX_SIN] )*ss;	
			if (diff > EPSILON) {
				norm.Set ( -1, 0, 0 );
				adj = (m_Param[ FORCE_XMAX_SIN ]+1) * stiff * diff - damp * norm.Dot ( p->vel_eval );
				accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
			}
		}

		// Y-axis walls
		diff = 2 * radius - ( p->pos.y - min.y )*ss;			
		if (diff > EPSILON) {
			norm.Set ( 0, 1, 0 );
			adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
			accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
		}
		diff = 2 * radius - ( max.y - p->pos.y )*ss;
		if (diff > EPSILON) {
			norm.Set ( 0, -1, 0 );
			adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
			accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
		}

		// Wall barrier
		if ( m_Toggle[WALL_BARRIER] ) {
			diff = 2 * radius - ( p->pos.x - 0 )*ss;					
			if (diff < 2*radius && diff > EPSILON && fabs(p->pos.y) < 3 && p->pos.z < 10) {
				norm.Set ( 1.0, 0, 0 );
				adj = 2*stiff * diff - damp * norm.Dot ( p->vel_eval ) ;	
				accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;					
			}
		}
		
		// Levy barrier
		if ( m_Toggle[LEVY_BARRIER] ) {
			diff = 2 * radius - ( p->pos.x - 0 )*ss;					
			if (diff < 2*radius && diff > EPSILON && fabs(p->pos.y) > 5 && p->pos.z < 10) {
				norm.Set ( 1.0, 0, 0 );
				adj = 2*stiff * diff - damp * norm.Dot ( p->vel_eval ) ;	
				accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;					
			}
		}
		// Drain barrier
		if ( m_Toggle[DRAIN_BARRIER] ) {
			diff = 2 * radius - ( p->pos.z - min.z-15 )*ss;
			if (diff < 2*radius && diff > EPSILON && (fabs(p->pos.x)>3 || fabs(p->pos.y)>3) ) {
				norm.Set ( 0, 0, 1);
				adj = stiff * diff - damp * norm.Dot ( p->vel_eval );
				accel.x += adj * norm.x; accel.y += adj * norm.y; accel.z += adj * norm.z;
			}
		}

		// Plane gravity
		if ( m_Param[PLANE_GRAV] > 0) 
			accel += m_Vec[PLANE_GRAV_DIR];

		// Point gravity
		if ( m_Param[POINT_GRAV] > 0 ) {
			norm.x = ( p->pos.x - m_Vec[POINT_GRAV_POS].x );
			norm.y = ( p->pos.y - m_Vec[POINT_GRAV_POS].y );
			norm.z = ( p->pos.z - m_Vec[POINT_GRAV_POS].z );
			norm.Normalize ();
			norm *= m_Param[POINT_GRAV];
			accel -= norm;
		}

		// Leapfrog Integration ----------------------------
		vnext = accel;							
		vnext *= m_DT;
		vnext += p->vel;						// v(t+1/2) = v(t-1/2) + a(t) dt
		p->vel_eval = p->vel;
		p->vel_eval += vnext;
		p->vel_eval *= 0.5;					// v(t+1) = [v(t-1/2) + v(t+1/2)] * 0.5		used to compute forces later
		p->vel = vnext;
		vnext *= m_DT/ss;
		p->pos += vnext;						// p(t+1) = p(t) + v(t+1/2) dt

		if ( m_Param[CLR_MODE]==1.0 ) {
			adj = fabs(vnext.x)+fabs(vnext.y)+fabs(vnext.z) / 7000.0;
			adj = (adj > 1.0) ? 1.0 : adj;
			p->clr = COLORA( 0, adj, adj, 1 );
		}
		if ( m_Param[CLR_MODE]==2.0 ) {
			float v = 0.5 + ( p->pressure / 1500.0); 
			if ( v < 0.1 ) v = 0.1;
			if ( v > 1.0 ) v = 1.0;
			p->clr = COLORA ( v, 1-v, 0, 1 );
		}


		// Euler integration -------------------------------
		/* accel += m_Gravity;
		accel *= m_DT;
		p->vel += accel;				// v(t+1) = v(t) + a(t) dt
		p->vel_eval += accel;
		p->vel_eval *= m_DT/d;
		p->pos += p->vel_eval;
		p->vel_eval = p->vel;  */	


		if ( m_Toggle[WRAP_X] ) {
			diff = p->pos.x - (m_Vec[SPH_VOLMIN].x + 2);			// -- Simulates object in center of flow
			if ( diff <= 0 ) {
				p->pos.x = (m_Vec[SPH_VOLMAX].x - 2) + diff*2;				
				p->pos.z = 10;
			}
		}	
	}

	m_Time += m_DT;
}