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; }
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; }