float PointSet::GetValue ( float x, float y, float z ) { float dx, dy, dz, dsq; float sum; int pndx; Point* pcurr; float R2 = 1.8*1.8; Grid_FindCells ( Vector3DF(x,y,z), m_GridCellsize/2.0 ); int cnt = 0; sum = 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 ) sum += R2 / dsq; pndx = pcurr->next; } } } return sum; }
// Compute Forces - Using spatial grid. Faster. void FluidSystem::SPH_ComputeForceGrid () { char *dat1, *dat1_end; Fluid *p; Fluid *pcurr; int pndx; Vector3DF force, fcurr; register double pterm, vterm, dterm; double c, d, dsq, r; double dx, dy, dz; double mR, mR2, visc; float radius = m_Param[SPH_SMOOTHRADIUS] / m_Param[SPH_SIMSCALE]; d = m_Param[SPH_SIMSCALE]; mR = m_Param[SPH_SMOOTHRADIUS]; mR2 = (mR*mR); visc = m_Param[SPH_VISC]; dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) { p = (Fluid*) dat1; force.Set ( 0, 0, 0 ); Grid_FindCells ( p->pos, radius ); for (int cell=0; cell < 8; cell++) { if ( m_GridCell[cell] != -1 ) { pndx = m_Grid [ m_GridCell[cell] ]; while ( pndx != -1 ) { pcurr = (Fluid*) (mBuf[0].data + pndx*mBuf[0].stride); if ( pcurr == p ) {pndx = pcurr->next; continue; } dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm dy = ( p->pos.y - pcurr->pos.y)*d; dz = ( p->pos.z - pcurr->pos.z)*d; dsq = (dx*dx + dy*dy + dz*dz); if ( mR2 > dsq ) { r = sqrt ( dsq ); c = (mR - r); pterm = -0.5f * c * m_SpikyKern * ( p->pressure + pcurr->pressure) / r; dterm = c * p->density * pcurr->density; vterm = m_LapKern * visc; force.x += ( pterm * dx + vterm * (pcurr->vel_eval.x - p->vel_eval.x) ) * dterm; force.y += ( pterm * dy + vterm * (pcurr->vel_eval.y - p->vel_eval.y) ) * dterm; force.z += ( pterm * dz + vterm * (pcurr->vel_eval.z - p->vel_eval.z) ) * dterm; } pndx = pcurr->next; } } } p->sph_force = force; } }
// Compute Pressures - Using spatial grid, and also create neighbor table void FluidSystem::SPH_ComputePressureGrid () { char *dat1, *dat1_end; Fluid* p; Fluid* pcurr; int pndx; int i, cnt = 0; float dx, dy, dz, sum, dsq, c; float d, d2, mR, mR2; float radius = m_Param[SPH_SMOOTHRADIUS] / m_Param[SPH_SIMSCALE]; d = m_Param[SPH_SIMSCALE]; d2 = d*d; mR = m_Param[SPH_SMOOTHRADIUS]; mR2 = mR*mR; dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride; i = 0; for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride, i++ ) { p = (Fluid*) dat1; sum = 0.0; m_NC[i] = 0; Grid_FindCells ( p->pos, radius ); for (int cell=0; cell < 8; cell++) { if ( m_GridCell[cell] != -1 ) { pndx = m_Grid [ m_GridCell[cell] ]; while ( pndx != -1 ) { pcurr = (Fluid*) (mBuf[0].data + pndx*mBuf[0].stride); if ( pcurr == p ) {pndx = pcurr->next; continue; } dx = ( p->pos.x - pcurr->pos.x)*d; // dist in cm dy = ( p->pos.y - pcurr->pos.y)*d; dz = ( p->pos.z - pcurr->pos.z)*d; dsq = (dx*dx + dy*dy + dz*dz); if ( mR2 > dsq ) { c = m_R2 - dsq; sum += c * c * c; if ( m_NC[i] < MAX_NEIGHBOR ) { m_Neighbor[i][ m_NC[i] ] = pndx; m_NDist[i][ m_NC[i] ] = sqrt(dsq); m_NC[i]++; } } pndx = pcurr->next; } } m_GridCell[cell] = -1; } p->density = sum * m_Param[SPH_PMASS] * m_Poly6Kern ; p->pressure = ( p->density - m_Param[SPH_RESTDENSITY] ) * m_Param[SPH_INTSTIFF]; p->density = 1.0f / p->density; } }
Vector3DF PointSet::GetGradient ( float x, float y, float z ) { Vector3DF norm; 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; norm.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 > 0 && dsq < R2 ) { dsq = 2.0*R2 / (dsq*dsq); norm.x += dx * dsq; norm.y += dy * dsq; norm.z += dz * dsq; } pndx = pcurr->next; } } } norm.Normalize (); return norm; }
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); }