540 lines
15 KiB
C++
540 lines
15 KiB
C++
/*
|
|
FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
|
|
Copyright (C) 2008. Rama Hoetzlein, http://www.rchoetzlein.com
|
|
|
|
ZLib license
|
|
This software is provided 'as-is', without any express or implied
|
|
warranty. In no event will the authors be held liable for any damages
|
|
arising from the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software
|
|
in a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
#include "gl_helper.h"
|
|
|
|
#include "point_set.h"
|
|
|
|
int PointSet::m_pcurr = -1;
|
|
|
|
PointSet::PointSet ()
|
|
{
|
|
m_GridRes.Set ( 0, 0, 0 );
|
|
m_pcurr = -1;
|
|
Reset ();
|
|
}
|
|
|
|
int PointSet::GetGridCell ( int x, int y, int z )
|
|
{
|
|
return (int) ( (z*m_GridRes.y + y)*m_GridRes.x + x);
|
|
}
|
|
|
|
Point* PointSet::firstGridParticle ( int gc, int& p )
|
|
{
|
|
m_pcurr = m_Grid [ gc ];
|
|
if ( m_pcurr == -1 ) return 0x0;
|
|
p = m_pcurr;
|
|
return (Point*) (mBuf[0].data + m_pcurr * mBuf[0].stride);
|
|
}
|
|
|
|
Point* PointSet::nextGridParticle ( int& p )
|
|
{
|
|
Point* pnt = 0x0;
|
|
if ( m_pcurr != -1 ) {
|
|
pnt = (Point*) (mBuf[0].data + m_pcurr * mBuf[0].stride);
|
|
p = m_pcurr;
|
|
m_pcurr = pnt->next;
|
|
}
|
|
return pnt;
|
|
}
|
|
|
|
unsigned short* PointSet::getNeighborTable ( int n, int& cnt )
|
|
{
|
|
cnt = m_NC[n];
|
|
if ( cnt == 0 ) return 0x0;
|
|
return &m_Neighbor[n][0];
|
|
}
|
|
|
|
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;
|
|
}
|
|
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);
|
|
}
|
|
|
|
void PointSet::Reset ()
|
|
{
|
|
// Reset number of particles
|
|
// ResetBuffer ( 0 );
|
|
|
|
m_Time = 0;
|
|
m_DT = 0.1;
|
|
m_Param[POINT_GRAV] = 100.0;
|
|
m_Param[PLANE_GRAV] = 0.0;
|
|
|
|
m_Vec[ POINT_GRAV_POS].Set(0,0,50.0);
|
|
m_Vec[ PLANE_GRAV_DIR].Set(0,0,-9.8);
|
|
m_Vec[ EMIT_RATE ].Set ( 1, 10, 0 );
|
|
m_Vec[ EMIT_POS ].Set ( 50, 0, 35 );
|
|
m_Vec[ EMIT_ANG ].Set ( 90, 45, 50.0 );
|
|
m_Vec[ EMIT_DANG ].Set ( 0, 0, 0 );
|
|
m_Vec[ EMIT_SPREAD ].Set ( 4, 4, 1 );
|
|
}
|
|
|
|
void PointSet::Initialize ( int mode, int total )
|
|
{
|
|
switch (mode) {
|
|
case BPOINT: {
|
|
FreeBuffers ();
|
|
AddBuffer ( BPOINT, sizeof ( Point ), total );
|
|
AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false );
|
|
AddAttribute ( 0, "color", sizeof ( DWORD ), false );
|
|
Reset ();
|
|
} break;
|
|
|
|
case BPARTICLE: {
|
|
FreeBuffers ();
|
|
AddBuffer ( BPARTICLE, sizeof ( Particle ), total );
|
|
AddAttribute ( 0, "pos", sizeof ( Vector3DF ), false );
|
|
AddAttribute ( 0, "color", sizeof ( DWORD ), false );
|
|
AddAttribute ( 0, "vel", sizeof ( Vector3DF ), false );
|
|
AddAttribute ( 0, "ndx", sizeof ( unsigned short ), false );
|
|
AddAttribute ( 0, "age", sizeof ( unsigned short ), false );
|
|
Reset ();
|
|
} break;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
int PointSet::AddPoint ()
|
|
{
|
|
xref ndx;
|
|
AddElem ( 0, ndx );
|
|
return ndx;
|
|
}
|
|
|
|
int PointSet::AddPointReuse ()
|
|
{
|
|
xref ndx;
|
|
if ( NumPoints() < mBuf[0].max-1 )
|
|
AddElem ( 0, ndx );
|
|
else
|
|
RandomElem ( 0, ndx );
|
|
return ndx;
|
|
}
|
|
|
|
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);
|
|
//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->clr = COLORA( (x-min.x)/dx, (y-min.y)/dy, (z-min.z)/dz, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PointSet::Draw ( float* view_mat, float rad )
|
|
{
|
|
char* dat;
|
|
Point* p;
|
|
glEnable ( GL_NORMALIZE );
|
|
|
|
if ( m_Param[PNT_DRAWMODE] == 0 ) {
|
|
glLoadMatrixf ( view_mat );
|
|
dat = mBuf[0].data;
|
|
for (int n = 0; n < NumPoints(); n++) {
|
|
p = (Point*) dat;
|
|
glPushMatrix ();
|
|
glTranslatef ( p->pos.x, p->pos.y, p->pos.z );
|
|
glScalef ( 0.2, 0.2, 0.2 );
|
|
glColor4f ( RED(p->clr), GRN(p->clr), BLUE(p->clr), ALPH(p->clr) );
|
|
drawSphere ();
|
|
glPopMatrix ();
|
|
dat += mBuf[0].stride;
|
|
}
|
|
} else if ( m_Param[PNT_DRAWMODE] == 1 ) {
|
|
glLoadMatrixf ( view_mat );
|
|
dat = mBuf[0].data;
|
|
glBegin ( GL_POINTS );
|
|
for (int n=0; n < NumPoints(); n++) {
|
|
p = (Point*) dat;
|
|
glColor3f ( RED(p->clr), GRN(p->clr), BLUE(p->clr) );
|
|
glVertex3f ( p->pos.x, p->pos.y, p->pos.z );
|
|
dat += mBuf[0].stride;
|
|
}
|
|
glEnd ();
|
|
}
|
|
}
|
|
|
|
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->clr = COLORA ( m_Time/10.0, m_Time/5.0, m_Time /4.0, 1 );
|
|
}
|
|
}
|
|
|
|
|
|
void PointSet::Run ()
|
|
{
|
|
if ( m_Vec[EMIT_RATE].x > 0 && ++m_Frame >= (int) m_Vec[EMIT_RATE].x ) {
|
|
m_Frame = 0;
|
|
Emit ( 1.0 );
|
|
}
|
|
Advance();
|
|
}
|
|
|
|
void PointSet::Advance ()
|
|
{
|
|
char* dat;
|
|
Particle* p;
|
|
Vector3DF vnext, accel, norm;
|
|
|
|
vnext = m_Vec[EMIT_DANG];
|
|
vnext *= m_DT;
|
|
m_Vec[EMIT_ANG] += vnext;
|
|
|
|
dat = mBuf[0].data;
|
|
for ( int c = 0; c < NumPoints(); c++ ) {
|
|
p = (Particle*) dat;
|
|
|
|
accel.Set (0, 0, 0);
|
|
|
|
// 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;
|
|
p->pos += vnext; // p(t+1) = p(t) + v(t+1/2) dt
|
|
|
|
// Euler integration -------------------------------
|
|
// accel += m_Gravity;
|
|
// accel *= m_DT;
|
|
// mParticles[c].vel += accel; // v(t+1) = v(t) + a(t) dt
|
|
// mParticles[c].vel_eval += accel;
|
|
// mParticles[c].vel_eval *= m_DT/d;
|
|
// mParticles[c].pos += mParticles[c].vel_eval;
|
|
// mParticles[c].vel_eval = mParticles[c].vel;
|
|
|
|
dat += mBuf[0].stride;
|
|
}
|
|
|
|
m_Time += m_DT;
|
|
}
|
|
|
|
// Ideal grid cell size (gs) = 2 * smoothing radius = 0.02*2 = 0.04
|
|
// Ideal domain size = k*gs/d = k*0.02*2/0.005 = k*8 = {8, 16, 24, 32, 40, 48, ..}
|
|
// (k = number of cells, gs = cell size, d = simulation scale)
|
|
void PointSet::Grid_Setup ( Vector3DF min, Vector3DF max, float sim_scale, float cell_size, float border )
|
|
{
|
|
float world_cellsize = cell_size / sim_scale;
|
|
m_Grid.clear ();
|
|
m_GridMin = min; m_GridMin -= border;
|
|
m_GridMax = max; m_GridMax += border;
|
|
m_GridSize = m_GridMax;
|
|
m_GridSize -= m_GridMin;
|
|
m_GridCellsize = world_cellsize;
|
|
m_GridRes.x = ceil ( m_GridSize.x / world_cellsize ); // Determine grid resolution
|
|
m_GridRes.y = ceil ( m_GridSize.y / world_cellsize );
|
|
m_GridRes.z = ceil ( m_GridSize.z / world_cellsize );
|
|
m_GridSize.x = m_GridRes.x * cell_size / sim_scale; // Adjust grid size to multiple of cell size
|
|
m_GridSize.y = m_GridRes.y * cell_size / sim_scale;
|
|
m_GridSize.z = m_GridRes.z * cell_size / sim_scale;
|
|
m_GridDelta = m_GridRes; // delta = translate from world space to cell #
|
|
m_GridDelta /= m_GridSize;
|
|
m_GridTotal = (int)(m_GridSize.x * m_GridSize.y * m_GridSize.z);
|
|
|
|
m_Grid.clear ();
|
|
m_GridCnt.clear ();
|
|
|
|
m_Grid.reserve ( m_GridTotal );
|
|
m_GridCnt.reserve ( m_GridTotal );
|
|
for (int n=0; n < m_GridTotal; n++) {
|
|
m_Grid.push_back ( -1 );
|
|
m_GridCnt.push_back ( 0 );
|
|
}
|
|
|
|
}
|
|
|
|
void PointSet::Grid_Draw ( float* view_mat )
|
|
{
|
|
float clr;
|
|
int cx, cy, cz;
|
|
float x1, y1, z1;
|
|
float x2, y2, z2;
|
|
int g = 0;
|
|
|
|
glLoadMatrixf ( view_mat );
|
|
glColor3f ( 0.7, 0.7, 0.7 );
|
|
|
|
glBegin ( GL_LINES );
|
|
|
|
cz = 0;
|
|
//for ( cz = 0; cz < m_GridRes.z; cz++ ) {
|
|
for ( cy = 0; cy < m_GridRes.y; cy++ ) {
|
|
for ( cx = 0; cx < m_GridRes.x; cx++ ) {
|
|
// Cell is not empty. Process it.
|
|
//if ( m_Grid[g] != 0x0 ) {
|
|
// clr = m_GridCnt[g]/30.0;
|
|
clr = 0.25;
|
|
if ( clr <0.25) clr =0.25;
|
|
if ( clr >1) clr =1 ;
|
|
glColor3f ( clr, clr, clr );
|
|
x1 = (cx * m_GridDelta.x) + m_GridMin.x; x2 = ((cx+1) * m_GridDelta.x) + m_GridMin.x;
|
|
y1 = (cy * m_GridDelta.y) + m_GridMin.y; y2 = ((cy+1) * m_GridDelta.y) + m_GridMin.y;
|
|
z1 = (cz * m_GridDelta.z) + m_GridMin.z; z2 = ((cz+1) * m_GridDelta.z) + m_GridMin.z;
|
|
glVertex3f ( x1, y1, z1 ); glVertex3f ( x2, y1, z1 );
|
|
glVertex3f ( x2, y1, z1 ); glVertex3f ( x2, y2, z1 );
|
|
glVertex3f ( x2, y2, z1 ); glVertex3f ( x1, y2, z1 );
|
|
glVertex3f ( x1, y2, z1 ); glVertex3f ( x1, y1, z1 );
|
|
glVertex3f ( x1, y1, z2 ); glVertex3f ( x2, y1, z2 );
|
|
glVertex3f ( x2, y1, z2 ); glVertex3f ( x2, y2, z2 );
|
|
glVertex3f ( x2, y2, z2 ); glVertex3f ( x1, y2, z2 );
|
|
glVertex3f ( x1, y2, z2 ); glVertex3f ( x1, y1, z2 );
|
|
glVertex3f ( x1, y1, z1 ); glVertex3f ( x1, y1, z2 );
|
|
glVertex3f ( x1, y2, z1 ); glVertex3f ( x1, y2, z2 );
|
|
glVertex3f ( x2, y2, z1 ); glVertex3f ( x2, y2, z2 );
|
|
glVertex3f ( x2, y1, z1 ); glVertex3f ( x2, y1, z2 );
|
|
//}
|
|
g++;
|
|
}
|
|
}
|
|
//}
|
|
|
|
glEnd ();
|
|
}
|
|
|
|
void PointSet::Grid_InsertParticles ()
|
|
{
|
|
char *dat1, *dat1_end;
|
|
Point *p;
|
|
int gs;
|
|
int gx, gy, gz;
|
|
|
|
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
|
|
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride )
|
|
((Point*) dat1)->next = -1;
|
|
|
|
for (int n=0; n < m_GridTotal; n++) {
|
|
m_Grid[n] = -1;
|
|
m_GridCnt[n] = 0;
|
|
}
|
|
|
|
dat1_end = mBuf[0].data + NumPoints()*mBuf[0].stride;
|
|
int n = 0;
|
|
for ( dat1 = mBuf[0].data; dat1 < dat1_end; dat1 += mBuf[0].stride ) {
|
|
p = (Point*) dat1;
|
|
gx = (int)( (p->pos.x - m_GridMin.x) * m_GridDelta.x); // Determine grid cell
|
|
gy = (int)( (p->pos.y - m_GridMin.y) * m_GridDelta.y);
|
|
gz = (int)( (p->pos.z - m_GridMin.z) * m_GridDelta.z);
|
|
gs = (int)( (gz*m_GridRes.y + gy)*m_GridRes.x + gx);
|
|
if ( gs >= 0 && gs < m_GridTotal ) {
|
|
p->next = m_Grid[gs];
|
|
m_Grid[gs] = n;
|
|
m_GridCnt[gs]++;
|
|
}
|
|
n++;
|
|
}
|
|
}
|
|
|
|
int PointSet::Grid_FindCell ( Vector3DF p )
|
|
{
|
|
int gc;
|
|
Vector3DI cell;
|
|
cell.x = (int) (p.x - m_GridMin.x) * m_GridDelta.x;
|
|
cell.y = (int) (p.y - m_GridMin.y) * m_GridDelta.y;
|
|
cell.z = (int) (p.z - m_GridMin.z) * m_GridDelta.z;
|
|
gc = (int)( (cell.z*m_GridRes.y + cell.y)*m_GridRes.x + cell.x);
|
|
if ( gc < 0 || gc > m_GridTotal ) return -1;
|
|
return gc;
|
|
}
|
|
|
|
void PointSet::Grid_FindCells ( Vector3DF p, float radius )
|
|
{
|
|
Vector3DI sph_min;
|
|
|
|
// Compute sphere range
|
|
sph_min.x = (int)((-radius + p.x - m_GridMin.x) * m_GridDelta.x);
|
|
sph_min.y = (int)((-radius + p.y - m_GridMin.y) * m_GridDelta.y);
|
|
sph_min.z = (int)((-radius + p.z - m_GridMin.z) * m_GridDelta.z);
|
|
if ( sph_min.x < 0 ) sph_min.x = 0;
|
|
if ( sph_min.y < 0 ) sph_min.y = 0;
|
|
if ( sph_min.z < 0 ) sph_min.z = 0;
|
|
|
|
m_GridCell[0] = (int)((sph_min.z * m_GridRes.y + sph_min.y) * m_GridRes.x + sph_min.x);
|
|
m_GridCell[1] = m_GridCell[0] + 1;
|
|
m_GridCell[2] = (int)(m_GridCell[0] + m_GridRes.x);
|
|
m_GridCell[3] = m_GridCell[2] + 1;
|
|
|
|
if ( sph_min.z+1 < m_GridRes.z ) {
|
|
m_GridCell[4] = (int)(m_GridCell[0] + m_GridRes.y*m_GridRes.x);
|
|
m_GridCell[5] = m_GridCell[4] + 1;
|
|
m_GridCell[6] = (int)(m_GridCell[4] + m_GridRes.x);
|
|
m_GridCell[7] = m_GridCell[6] + 1;
|
|
}
|
|
if ( sph_min.x+1 >= m_GridRes.x ) {
|
|
m_GridCell[1] = -1; m_GridCell[3] = -1;
|
|
m_GridCell[5] = -1; m_GridCell[7] = -1;
|
|
}
|
|
if ( sph_min.y+1 >= m_GridRes.y ) {
|
|
m_GridCell[2] = -1; m_GridCell[3] = -1;
|
|
m_GridCell[6] = -1; m_GridCell[7] = -1;
|
|
}
|
|
}
|