00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <iostream>
00020 #include <uwsim/BulletHfFluid/btHfFluid.h>
00021 #include <uwsim/BulletHfFluid/btHfFluidCollisionShape.h>
00022 #include <uwsim/BulletHfFluid/btHfFluidBuoyantConvexShape.h>
00023 #include <BulletCollision/NarrowPhaseCollision/btPersistentManifold.h>
00024 #include <BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h>
00025 #include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
00026 #include <BulletCollision/CollisionDispatch/btManifoldResult.h>
00027 #include <BulletCollision/CollisionShapes/btTriangleShape.h>
00028 #include <BulletDynamics/Dynamics/btRigidBody.h>
00029
00030
00031 btHfFluid::btHfFluid(btScalar gridCellWidth, int numNodesWidth, int numNodesLength)
00032 {
00033 m_eta = NULL;
00034 m_temp = NULL;
00035 m_ground = NULL;
00036 m_height[0] = NULL;
00037 m_height[1] = NULL;
00038 m_u[0] = NULL;
00039 m_u[1] = NULL;
00040 m_v[0] = NULL;
00041 m_v[1] = NULL;
00042 m_r[0] = NULL;
00043 m_r[1] = NULL;
00044 m_flags = NULL;
00045 m_fillRatio = NULL;
00046 m_internalType = CO_HF_FLUID;
00047 m_heightIndex = 0;
00048 m_velocityIndex = 0;
00049 m_rIndex = 0;
00050 setGridDimensions(gridCellWidth, numNodesWidth, numNodesLength);
00051
00052 btScalar maxHeight = 20.0;
00053 m_aabbMin = btVector3(0.0, 0.0, -10.0);
00054 m_aabbMax = btVector3(m_gridWidth, m_gridLength, maxHeight);
00055
00056 setCollisionShape(new btHfFluidCollisionShape(this));
00057
00058 m_globalVelocityU = btScalar(0.0f);
00059 m_globalVelocityV = btScalar(0.0f);
00060 m_gravity = btScalar(-1.0f);
00061
00062 m_volumeDisplacementScale = btScalar(0.5f);
00063 m_horizontalVelocityScale = btScalar(0.5f);
00064
00065 m_epsEta = btScalar(0.01f);
00066 m_epsHeight = btScalar(0.001f);
00067 }
00068
00069 btHfFluid::btHfFluid(btScalar gridCellWidth, int minX, int maxX, int minY, int maxY, int depth, int height)
00070 {
00071 m_eta = NULL;
00072 m_temp = NULL;
00073 m_ground = NULL;
00074 m_height[0] = NULL;
00075 m_height[1] = NULL;
00076 m_u[0] = NULL;
00077 m_u[1] = NULL;
00078 m_v[0] = NULL;
00079 m_v[1] = NULL;
00080 m_r[0] = NULL;
00081 m_r[1] = NULL;
00082 m_flags = NULL;
00083 m_fillRatio = NULL;
00084 m_internalType = CO_HF_FLUID;
00085 m_heightIndex = 0;
00086 m_velocityIndex = 0;
00087 m_rIndex = 0;
00088
00089 setGridDimensions(gridCellWidth, ceil(maxX - minX) / gridCellWidth, ceil(maxY - minY) / gridCellWidth);
00090
00091 m_aabbMin = btVector3(minX, minY, depth);
00092 m_aabbMax = btVector3(maxX, maxY, height);
00093
00094 setCollisionShape(new btHfFluidCollisionShape(this));
00095
00096 m_globalVelocityU = btScalar(0.0f);
00097 m_globalVelocityV = btScalar(0.0f);
00098 m_gravity = btScalar(-1.0f);
00099
00100 m_volumeDisplacementScale = btScalar(0.5f);
00101 m_horizontalVelocityScale = btScalar(0.5f);
00102
00103 m_epsEta = btScalar(0.01f);
00104 m_epsHeight = btScalar(0.001f);
00105 }
00106
00107 btHfFluid::~btHfFluid()
00108 {
00109 btCollisionShape* collisionShape = getCollisionShape();
00110 delete collisionShape;
00111 btAlignedFree (m_temp);
00112 btAlignedFree (m_height[0]);
00113 btAlignedFree(m_height[1]);
00114 btAlignedFree (m_ground);
00115 btAlignedFree (m_eta);
00116 btAlignedFree (m_u[0]);
00117 btAlignedFree(m_u[1]);
00118 btAlignedFree (m_v[0]);
00119 btAlignedFree(m_v[1]);
00120 btAlignedFree (m_flags);
00121 btAlignedFree (m_fillRatio);
00122 }
00123
00124 void btHfFluid::predictMotion(btScalar dt)
00125 {
00126 transferDisplaced(dt);
00127
00128 advectEta(dt);
00129 advectVelocityU(dt);
00130 advectVelocityV(dt);
00131 updateHeight(dt);
00132 computeFlagsAndFillRatio();
00133 updateVelocity(dt);
00134 setReflectBoundaryLeft();
00135 setReflectBoundaryRight();
00136 setReflectBoundaryTop();
00137 setReflectBoundaryBottom();
00138 debugTests();
00139
00140
00141 }
00142
00143 void btHfFluid::prep()
00144 {
00145 for (int i = 0; i < m_numNodesLength * m_numNodesWidth; i++)
00146 {
00147 m_height[0][i] = m_eta[i] + m_ground[i];
00148 m_height[1][i] = m_eta[i] + m_ground[i];
00149 }
00150 computeFlagsAndFillRatio();
00151 }
00152
00153 btScalar btHfFluid::widthPos(int i) const
00154 {
00155 return m_gridCellWidth * i + m_aabbMin.getX();
00156 }
00157
00158 btScalar btHfFluid::lengthPos(int j) const
00159 {
00160 return m_gridCellWidth * j + m_aabbMin.getX();
00161 }
00162
00163 int btHfFluid::arrayIndex(int i, int j) const
00164 {
00165 btAssert(i >= 0);
00166 btAssert(i < m_numNodesWidth);
00167 btAssert(j >= 0);
00168 btAssert(j < m_numNodesLength);
00169 int index = i + (j * m_numNodesWidth);
00170 return index;
00171 }
00172
00173 int btHfFluid::arrayIndex(btScalar i, btScalar j) const
00174 {
00175 int ii = (int)i;
00176 int ij = (int)j;
00177
00178 return arrayIndex(ii, ij);
00179 }
00180
00181 const btScalar* btHfFluid::getHeightArray() const
00182 {
00183 return m_height[m_heightIndex];
00184 }
00185
00186 const btScalar* btHfFluid::getGroundArray() const
00187 {
00188 return m_ground;
00189 }
00190 const btScalar* btHfFluid::getEtaArray() const
00191 {
00192 return m_eta;
00193 }
00194 const btScalar* btHfFluid::getVelocityUArray() const
00195 {
00196 return m_u[m_velocityIndex];
00197 }
00198 const btScalar* btHfFluid::getVelocityVArray() const
00199 {
00200 return m_v[m_velocityIndex];
00201 }
00202
00203 const bool* btHfFluid::getFlagsArray() const
00204 {
00205 return m_flags;
00206 }
00207
00208 btScalar* btHfFluid::getHeightArray()
00209 {
00210 return m_height[m_heightIndex];
00211 }
00212 btScalar* btHfFluid::getGroundArray()
00213 {
00214 return m_ground;
00215 }
00216 btScalar* btHfFluid::getEtaArray()
00217 {
00218 return m_eta;
00219 }
00220 btScalar* btHfFluid::getVelocityUArray()
00221 {
00222 return m_u[m_velocityIndex];
00223 }
00224 btScalar* btHfFluid::getVelocityVArray()
00225 {
00226 return m_v[m_velocityIndex];
00227 }
00228
00229 bool* btHfFluid::getFlagsArray()
00230 {
00231 return m_flags;
00232 }
00233
00234 void btHfFluid::setFluidHeight(int x, int y, btScalar height)
00235 {
00236 int index = arrayIndex(x, y);
00237 setFluidHeight(index, height);
00238 }
00239
00240 void btHfFluid::setFluidHeight(int index, btScalar height)
00241 {
00242 m_eta[index] = height - m_ground[index];
00243 m_height[m_heightIndex][index] = m_ground[index] + m_eta[index];
00244 m_flags[index] = true;
00245 }
00246
00247 void btHfFluid::addFluidHeight(int x, int y, btScalar height)
00248 {
00249 int index = arrayIndex(x, y);
00250 m_eta[index] += height;
00251 m_height[m_heightIndex][index] = m_ground[index] + m_eta[index];
00252 m_flags[index] = true;
00253 }
00254
00255 void btHfFluid::getAabbForColumn(int i, int j, btVector3& aabbMin, btVector3& aabbMax)
00256 {
00257 btVector3 com = getWorldTransform().getOrigin();
00258 int sw = arrayIndex(i, j);
00259 int se = arrayIndex(i + 1, j);
00260 int nw = arrayIndex(i, j + 1);
00261 int ne = arrayIndex(i + 1, j + 1);
00262
00263 btScalar h = m_height[m_heightIndex][sw];
00264 btScalar g = m_ground[sw];
00265
00266 aabbMin = btVector3(widthPos(i), lengthPos(j), g);
00267 aabbMax = btVector3(widthPos(i + 1), lengthPos(j + 1), h);
00268
00269 aabbMin += com;
00270 aabbMax += com;
00271 }
00272
00273 void btHfFluid::foreachGroundTriangle(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax)
00274 {
00275 btVector3 verts[3];
00276
00277 btScalar minX, minZ, maxX, maxZ;
00278 int startNodeX, startNodeZ, endNodeX, endNodeZ;
00279
00280 minX = aabbMin.getX();
00281 minZ = aabbMin.getY();
00282 maxX = aabbMax.getX();
00283 maxZ = aabbMax.getY();
00284
00285 startNodeX = (int)((minX - m_aabbMin.getX()) * m_gridCellWidthInv);
00286 startNodeZ = (int)((minZ - m_aabbMin.getY()) * m_gridCellWidthInv);
00287
00288 endNodeX = (int)((maxX - m_aabbMin.getX()) * m_gridCellWidthInv);
00289 endNodeZ = (int)((maxZ - m_aabbMin.getY()) * m_gridCellWidthInv);
00290
00291 endNodeX++;
00292 endNodeZ++;
00293
00294 startNodeX = btMax(1, startNodeX);
00295 startNodeZ = btMax(1, startNodeZ);
00296 endNodeX = btMin(m_numNodesWidth - 1, endNodeX);
00297 endNodeZ = btMin(m_numNodesLength - 1, endNodeZ);
00298
00299 #ifdef __BRUTE__
00300 for (int i = 1; i < m_numNodesWidth-1; i++)
00301 {
00302 for (int j = 1; j < m_numNodesLength-1; j++)
00303 {
00304
00305 verts[0] = btVector3(widthPos(i), m_ground[arrayIndex(i,j)], lengthPos(j));
00306 verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i,j+1)], lengthPos(j+1));
00307 verts[2] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j)], lengthPos(j));
00308 callback->processTriangle(verts,i,j);
00309
00310 verts[0] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j)], lengthPos(j));
00311 verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i,j+1)], lengthPos(j+1));
00312 verts[2] = btVector3(widthPos(i+1), m_ground[arrayIndex(i+1,j+1)], lengthPos(j+1));
00313 callback->processTriangle(verts,i,j);
00314 }
00315 }
00316 #else
00317
00318 for (int i = startNodeX; i < endNodeX; i++)
00319 {
00320 for (int j = startNodeZ; j < endNodeZ; j++)
00321 {
00322
00323 verts[0] = btVector3(widthPos(i), m_ground[arrayIndex(i, j)], lengthPos(j));
00324 verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i, j + 1)], lengthPos(j + 1));
00325 verts[2] = btVector3(widthPos(i + 1), m_ground[arrayIndex(i + 1, j)], lengthPos(j));
00326 callback->processTriangle(verts, i, j);
00327
00328 verts[0] = btVector3(widthPos(i + 1), m_ground[arrayIndex(i + 1, j)], lengthPos(j));
00329 verts[1] = btVector3(widthPos(i), m_ground[arrayIndex(i, j + 1)], lengthPos(j + 1));
00330 verts[2] = btVector3(widthPos(i + 1), m_ground[arrayIndex(i + 1, j + 1)], lengthPos(j + 1));
00331 callback->processTriangle(verts, i, j);
00332 }
00333 }
00334 #endif
00335 }
00336
00337 void btHfFluid::foreachFluidColumn(btHfFluidColumnCallback* callback, const btVector3& aabbMin,
00338 const btVector3& aabbMax)
00339 {
00340 btScalar minX, minZ, maxX, maxZ;
00341 int startNodeX, startNodeZ, endNodeX, endNodeZ;
00342
00343 minX = aabbMin.getX();
00344 minZ = aabbMin.getY();
00345 maxX = aabbMax.getX();
00346 maxZ = aabbMax.getY();
00347
00348 startNodeX = (int)((minX - m_aabbMin.getX()) * m_gridCellWidthInv);
00349 startNodeZ = (int)((minZ - m_aabbMin.getY()) * m_gridCellWidthInv);
00350
00351 endNodeX = (int)((maxX - m_aabbMin.getX()) * m_gridCellWidthInv);
00352 endNodeZ = (int)((maxZ - m_aabbMin.getY()) * m_gridCellWidthInv);
00353
00354 endNodeX++;
00355 endNodeZ++;
00356
00357 startNodeX = btMax(1, startNodeX);
00358 startNodeZ = btMax(1, startNodeZ);
00359 endNodeX = btMin(m_numNodesWidth - 2, endNodeX);
00360 endNodeZ = btMin(m_numNodesLength - 2, endNodeZ);
00361
00362 bool r;
00363 for (int i = startNodeX; i < endNodeX; i++)
00364 {
00365 for (int j = startNodeZ; j < endNodeZ; j++)
00366 {
00367 if (m_flags[arrayIndex(i, j)] == false)
00368 continue;
00369
00370 r = callback->processColumn(this, i, j);
00371 if (!r)
00372 return;
00373 }
00374 }
00375 }
00376
00377 void btHfFluid::foreachSurfaceTriangle(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax)
00378 {
00379 btVector3 verts[3];
00380
00381 btScalar minX, minZ, maxX, maxZ;
00382 int startNodeX, startNodeZ, endNodeX, endNodeZ;
00383
00384 minX = aabbMin.getX();
00385 minZ = aabbMin.getY();
00386 maxX = aabbMax.getX();
00387 maxZ = aabbMax.getY();
00388
00389 startNodeX = (int)((minX - m_aabbMin.getX()) * m_gridCellWidthInv);
00390 startNodeZ = (int)((minZ - m_aabbMin.getY()) * m_gridCellWidthInv);
00391
00392 endNodeX = (int)((maxX - m_aabbMin.getX()) * m_gridCellWidthInv);
00393 endNodeZ = (int)((maxZ - m_aabbMin.getY()) * m_gridCellWidthInv);
00394
00395 endNodeX++;
00396 endNodeZ++;
00397
00398 startNodeX = btMax(1, startNodeX);
00399 startNodeZ = btMax(1, startNodeZ);
00400 endNodeX = m_numNodesWidth - 1;
00401 endNodeZ = m_numNodesLength - 1;
00402
00403 for (int i = startNodeX; i < endNodeX; i++)
00404 {
00405 for (int j = startNodeZ; j < endNodeZ; j++)
00406 {
00407 if (!m_flags[arrayIndex(i, j)])
00408 continue;
00409
00410 verts[0] = btVector3(widthPos(i), m_height[m_heightIndex][arrayIndex(i, j)], lengthPos(j));
00411 verts[1] = btVector3(widthPos(i), m_height[m_heightIndex][arrayIndex(i, j + 1)], lengthPos(j + 1));
00412 verts[2] = btVector3(widthPos(i + 1), m_height[m_heightIndex][arrayIndex(i + 1, j)], lengthPos(j));
00413 callback->processTriangle(verts, i, j);
00414
00415 verts[0] = btVector3(widthPos(i + 1), m_height[m_heightIndex][arrayIndex(i + 1, j)], lengthPos(j));
00416 verts[1] = btVector3(widthPos(i), m_height[m_heightIndex][arrayIndex(i, j + 1)], lengthPos(j + 1));
00417 verts[2] = btVector3(widthPos(i + 1), m_height[m_heightIndex][arrayIndex(i + 1, j + 1)], lengthPos(j + 1));
00418 callback->processTriangle(verts, i, j);
00419 }
00420 }
00421 }
00422
00423 void btHfFluid::setGridDimensions(btScalar gridCellWidth, int numNodesWidth, int numNodesLength)
00424 {
00425 m_gridWidth = gridCellWidth * numNodesWidth;
00426 m_gridLength = gridCellWidth * numNodesLength;
00427 m_gridCellWidth = gridCellWidth;
00428 m_numNodesWidth = numNodesWidth;
00429 m_numNodesLength = numNodesLength;
00430 m_gridCellWidthInv = btScalar(1.0) / gridCellWidth;
00431
00432 allocateArrays();
00433 }
00434
00435 btScalar btHfFluid::bilinearInterpolate(const btScalar* array, btScalar iPos, btScalar jPos)
00436 {
00437 int i = (int)iPos;
00438 int j = (int)jPos;
00439
00440 btScalar iParam1 = iPos - btScalar(i);
00441 btScalar iParam0 = btScalar(1.0) - iParam1;
00442
00443 btScalar jParam1 = jPos - btScalar(j);
00444 btScalar jParam0 = btScalar(1.0) - jParam1;
00445
00446 btScalar SW = array[arrayIndex(i, j)];
00447 btScalar SE = array[arrayIndex(i + 1, j)];
00448 btScalar NW = array[arrayIndex(i, j + 1)];
00449 btScalar NE = array[arrayIndex(i + 1, j + 1)];
00450
00451 btScalar a = jParam0 * SW + jParam1 * NW;
00452 btScalar b = jParam0 * SE + jParam1 * NE;
00453 return iParam0 * a + iParam1 * b;
00454 }
00455
00456 btScalar btHfFluid::advect(const btScalar* array, btScalar i, btScalar j, btScalar di, btScalar dj, btScalar dt)
00457 {
00458
00459 btScalar srcI = i - di * dt * m_gridCellWidthInv;
00460 btScalar srcJ = j - dj * dt * m_gridCellWidthInv;
00461
00462
00463
00464 srcI = btMax(srcI, btScalar(0.0));
00465 srcI = btMin(srcI, btScalar(m_numNodesWidth - 1));
00466 srcJ = btMax(srcJ, btScalar(0.0));
00467 srcJ = btMin(srcJ, btScalar(m_numNodesLength - 1));
00468
00469 return bilinearInterpolate(array, srcI, srcJ);
00470 }
00471
00472 void btHfFluid::advectEta(btScalar dt)
00473 {
00474 for (int i = 1; i < m_numNodesWidth - 1; i++)
00475 {
00476 for (int j = 1; j < m_numNodesLength - 1; j++)
00477 {
00478 int index = arrayIndex(i, j);
00479
00480 if (!m_flags[index])
00481 continue;
00482
00483 btScalar u = m_globalVelocityU;
00484 btScalar v = m_globalVelocityV;
00485
00486 u += (m_u[m_velocityIndex][index] + m_u[m_velocityIndex][index + 1]) * btScalar(0.5);
00487 v += (m_v[m_velocityIndex][index] + m_v[m_velocityIndex][index + m_numNodesWidth]) * btScalar(0.5);
00488
00489 m_temp[index] = advect(m_eta, btScalar(i), btScalar(j), u, v, dt);
00490 }
00491 }
00492 for (int i = 1; i < m_numNodesWidth - 1; i++)
00493 {
00494 for (int j = 1; j < m_numNodesLength - 1; j++)
00495 {
00496 int index = arrayIndex(i, j);
00497 m_eta[index] = m_temp[index];
00498 }
00499 }
00500 }
00501
00502 void btHfFluid::updateHeight(btScalar dt)
00503 {
00504 for (int j = 1; j < m_numNodesLength - 1; j++)
00505 {
00506 for (int i = 1; i < m_numNodesWidth - 1; i++)
00507 {
00508 int index = arrayIndex(i, j);
00509 if (!m_flags[index])
00510 {
00511 m_height[m_heightIndex][index] = m_ground[index] + m_eta[index];
00512 continue;
00513 }
00514 btScalar deta = -btScalar(0.5f) * m_eta[index] * dt * m_gridCellWidthInv
00515 * ((m_u[m_velocityIndex][index + 1] - m_u[m_velocityIndex][index])
00516 + (m_v[m_velocityIndex][index + m_numNodesWidth] - m_v[m_velocityIndex][index]));
00517 m_eta[index] += deta;
00518 m_height[m_heightIndex][index] = m_ground[index] + btMax(m_eta[index], btScalar(0.0f));
00519 }
00520 }
00521 }
00522
00523 void btHfFluid::advectVelocityU(btScalar dt)
00524 {
00525 for (int i = 1; i < m_numNodesWidth - 1; i++)
00526 {
00527 for (int j = 1; j < m_numNodesLength - 1; j++)
00528 {
00529 int index = arrayIndex(i, j);
00530 if (!m_flags[index])
00531 {
00532 continue;
00533 }
00534 btScalar u = m_globalVelocityU;
00535 btScalar v = m_globalVelocityV;
00536
00537 u += m_u[m_velocityIndex][index];
00538 v += (m_v[m_velocityIndex][index] + m_v[m_velocityIndex][index + 1]
00539 + m_v[m_velocityIndex][index + m_numNodesWidth] + m_v[m_velocityIndex][index + m_numNodesWidth + 1])
00540 * btScalar(0.25);
00541
00542 m_temp[index] = advect(m_u[m_velocityIndex], btScalar(i), btScalar(j), u, v, dt);
00543 }
00544 }
00545
00546 for (int i = 1; i < m_numNodesWidth - 1; i++)
00547 {
00548 for (int j = 1; j < m_numNodesLength - 1; j++)
00549 {
00550 int index = arrayIndex(i, j);
00551 m_u[m_velocityIndex][index] = m_temp[index];
00552 }
00553 }
00554 }
00555
00556 void btHfFluid::advectVelocityV(btScalar dt)
00557 {
00558 for (int i = 1; i < m_numNodesWidth - 1; i++)
00559 {
00560 for (int j = 1; j < m_numNodesLength - 1; j++)
00561 {
00562 int index = arrayIndex(i, j);
00563 if (!m_flags[index])
00564 {
00565 continue;
00566 }
00567 btScalar u = m_globalVelocityU;
00568 btScalar v = m_globalVelocityV;
00569
00570 u += (m_u[m_velocityIndex][index] + m_u[m_velocityIndex][index + 1]
00571 + m_u[m_velocityIndex][index + m_numNodesWidth] + m_u[m_velocityIndex][index + m_numNodesWidth + 1])
00572 * btScalar(0.25);
00573 v += m_v[m_velocityIndex][index];
00574
00575 m_temp[index] = advect(m_v[m_velocityIndex], btScalar(i), btScalar(j), u, v, dt);
00576 }
00577 }
00578 for (int i = 1; i < m_numNodesWidth - 1; i++)
00579 {
00580 for (int j = 1; j < m_numNodesLength - 1; j++)
00581 {
00582 int index = arrayIndex(i, j);
00583 m_v[m_velocityIndex][index] = m_temp[index];
00584 }
00585 }
00586 }
00587
00588 void btHfFluid::addDisplaced(int i, int j, btScalar r)
00589 {
00590 m_r[m_rIndex][arrayIndex(i, j)] += r;
00591 }
00592
00593 void btHfFluid::transferDisplaced(btScalar dt)
00594 {
00595 for (int i = 2; i < m_numNodesWidth - 2; i++)
00596 {
00597 for (int j = 2; j < m_numNodesLength - 2; j++)
00598 {
00599 btScalar deltaR = m_r[m_rIndex][arrayIndex(i, j)] - m_r[(m_rIndex + 1) % 2][arrayIndex(i, j)];
00600
00601 deltaR = deltaR / (m_gridCellWidth * m_gridCellWidth);
00602 deltaR *= m_volumeDisplacementScale;
00603 btScalar qdeltaR = deltaR / btScalar(4.0f);
00604 m_eta[arrayIndex(i - 1, j - 1)] += qdeltaR;
00605 m_eta[arrayIndex(i - 1, j + 1)] += qdeltaR;
00606 m_eta[arrayIndex(i + 1, j - 1)] += qdeltaR;
00607 m_eta[arrayIndex(i + 1, j + 1)] += qdeltaR;
00608 m_eta[arrayIndex(i, j)] -= deltaR;
00609
00610 m_r[(m_rIndex + 1) % 2][arrayIndex(i, j)] = btScalar(0.0);
00611 }
00612 }
00613 m_rIndex = (m_rIndex + 1) % 2;
00614 }
00615
00616 void btHfFluid::updateVelocity(btScalar dt)
00617 {
00618 for (int j = 1; j < m_numNodesLength - 1; j++)
00619 {
00620 for (int i = 2; i < m_numNodesWidth - 1; i++)
00621 {
00622 int index = arrayIndex(i, j);
00623 if (!m_flags[index])
00624 {
00625 continue;
00626 }
00627 m_u[m_velocityIndex][index] += m_gravity * dt * m_gridCellWidthInv
00628 * (m_height[m_heightIndex][index] - m_height[m_heightIndex][index - 1]);
00629 }
00630 }
00631
00632 for (int j = 2; j < m_numNodesLength - 1; j++)
00633 {
00634 for (int i = 1; i < m_numNodesWidth - 1; i++)
00635 {
00636 int index = arrayIndex(i, j);
00637 if (!m_flags[index])
00638 {
00639 continue;
00640 }
00641 m_v[m_velocityIndex][index] += m_gravity * dt * m_gridCellWidthInv
00642 * (m_height[m_heightIndex][index] - m_height[m_heightIndex][index - m_numNodesWidth]);
00643 }
00644 }
00645 }
00646
00647 void btHfFluid::setReflectBoundaryLeft()
00648 {
00649 for (int j = 0; j < m_numNodesLength; j++)
00650 {
00651 int indexL = arrayIndex(0, j);
00652
00653 m_height[m_heightIndex][indexL] = m_height[m_heightIndex][indexL + 1];
00654 m_u[m_velocityIndex][indexL + 1] = btScalar(0.0);
00655 m_v[m_velocityIndex][indexL] = btScalar(0.0);
00656 }
00657 }
00658
00659 void btHfFluid::setReflectBoundaryRight()
00660 {
00661 for (int j = 0; j < m_numNodesLength; j++)
00662 {
00663 int indexR = arrayIndex(m_numNodesWidth - 1, j);
00664
00665 m_height[m_heightIndex][indexR] = m_height[m_heightIndex][indexR - 1];
00666 m_u[m_velocityIndex][indexR - 1] = btScalar(0.0);
00667 m_v[m_velocityIndex][indexR] = btScalar(0.0);
00668 }
00669 }
00670
00671 void btHfFluid::setReflectBoundaryBottom()
00672 {
00673 for (int i = 0; i < m_numNodesWidth; i++)
00674 {
00675 int indexT = arrayIndex(i, 0);
00676
00677 m_height[m_heightIndex][indexT] = m_height[m_heightIndex][indexT + m_numNodesWidth];
00678 m_v[m_velocityIndex][indexT + m_numNodesWidth] = btScalar(0.0);
00679 m_u[m_velocityIndex][indexT] = btScalar(0.0);
00680 }
00681 }
00682
00683 void btHfFluid::setReflectBoundaryTop()
00684 {
00685 for (int i = 0; i < m_numNodesWidth; i++)
00686 {
00687 int indexB = arrayIndex(i, m_numNodesLength - 1);
00688
00689 m_height[m_heightIndex][indexB] = m_height[m_heightIndex][indexB - m_numNodesWidth];
00690 m_v[m_velocityIndex][indexB - m_numNodesWidth] = btScalar(0.0);
00691 m_u[m_velocityIndex][indexB] = btScalar(0.0);
00692 }
00693 }
00694
00695 void btHfFluid::setAbsorbBoundaryLeft(btScalar dt)
00696 {
00697 for (int j = 0; j < m_numNodesLength; j++)
00698 {
00699 int indexL = arrayIndex(0, j);
00700
00701 btScalar c = btSqrt(m_eta[indexL + 1] * m_gravity);
00702 m_height[m_heightIndex][indexL] = ((m_gridCellWidthInv * m_height[(m_heightIndex + 1) % 2][indexL + 1])
00703 + (dt * c * m_height[m_heightIndex][indexL + 1])) / (m_gridCellWidthInv + dt * c);
00704 m_u[m_velocityIndex][indexL + 1] = btScalar(0.0f);
00705 m_v[m_velocityIndex][indexL + 1] = btScalar(0.0);
00706 }
00707 }
00708
00709 void btHfFluid::setAbsorbBoundaryRight(btScalar dt)
00710 {
00711 }
00712
00713 void btHfFluid::setAbsorbBoundaryTop(btScalar dt)
00714 {
00715 }
00716
00717 void btHfFluid::setAbsorbBoundaryBottom(btScalar dt)
00718 {
00719 }
00720
00721 void btHfFluid::computeFlagsAndFillRatio()
00722 {
00723 for (int i = 1; i < m_numNodesWidth - 1; i++)
00724 {
00725 for (int j = 1; j < m_numNodesLength - 1; j++)
00726 {
00727 btScalar h = m_height[m_heightIndex][arrayIndex(i, j)];
00728 btScalar hMin = computeHmin(i, j);
00729 btScalar hMax = computeHmax(i, j);
00730 btScalar etaMax = computeEtaMax(i, j);
00731 if (h <= hMin && etaMax < m_epsEta)
00732 {
00733 m_flags[arrayIndex(i, j)] = false;
00734 m_fillRatio[arrayIndex(i, j)] = btScalar(0.0f);
00735 }
00736 else if (h > hMax)
00737 {
00738 m_flags[arrayIndex(i, j)] = true;
00739 m_fillRatio[arrayIndex(i, j)] = btScalar(1.0f);
00740 }
00741 else
00742 {
00743 m_flags[arrayIndex(i, j)] = true;
00744 m_fillRatio[arrayIndex(i, j)] = (h - hMin) / (hMax - hMin);
00745 }
00746
00747 }
00748 }
00749 }
00750
00751 btScalar btHfFluid::computeHmin(int i, int j)
00752 {
00753 btAssert(i > 0);
00754 btAssert(i < m_numNodesWidth - 1);
00755 btAssert(j > 0);
00756 btAssert(j < m_numNodesLength - 1);
00757
00758 btScalar h1 = m_height[m_heightIndex][arrayIndex(i - 1, j - 1)];
00759 btScalar h2 = m_height[m_heightIndex][arrayIndex(i - 1, j + 1)];
00760 btScalar h3 = m_height[m_heightIndex][arrayIndex(i + 1, j - 1)];
00761 btScalar h4 = m_height[m_heightIndex][arrayIndex(i + 1, j + 1)];
00762 btScalar h = m_height[m_heightIndex][arrayIndex(i, j)];
00763 btScalar minh = btMin(h1, btMin(h2, btMin(h3, h4)));
00764
00765 return (minh + h) * btScalar(0.5f);
00766 }
00767
00768 btScalar btHfFluid::computeHmax(int i, int j)
00769 {
00770 btAssert(i > 0);
00771 btAssert(i < m_numNodesWidth - 1);
00772 btAssert(j > 0);
00773 btAssert(j < m_numNodesLength - 1);
00774
00775 btScalar h1 = m_height[m_heightIndex][arrayIndex(i - 1, j - 1)];
00776 btScalar h2 = m_height[m_heightIndex][arrayIndex(i - 1, j + 1)];
00777 btScalar h3 = m_height[m_heightIndex][arrayIndex(i + 1, j - 1)];
00778 btScalar h4 = m_height[m_heightIndex][arrayIndex(i + 1, j + 1)];
00779 btScalar h = m_height[m_heightIndex][arrayIndex(i, j)];
00780 btScalar maxh = btMax(h1, btMax(h2, btMax(h3, h4)));
00781
00782 return (maxh + h) * btScalar(0.5f) + m_epsHeight;
00783 }
00784
00785 btScalar btHfFluid::computeEtaMax(int i, int j)
00786 {
00787 btAssert(i > 0);
00788 btAssert(i < m_numNodesWidth - 1);
00789 btAssert(j > 0);
00790 btAssert(j < m_numNodesLength - 1);
00791
00792 btScalar eta1 = m_eta[arrayIndex(i - 1, j - 1)];
00793 btScalar eta2 = m_eta[arrayIndex(i - 1, j + 1)];
00794 btScalar eta3 = m_eta[arrayIndex(i + 1, j - 1)];
00795 btScalar eta4 = m_eta[arrayIndex(i + 1, j + 1)];
00796 btScalar eta = m_eta[arrayIndex(i, j)];
00797 btScalar maxeta = btMax(eta1, btMax(eta2, btMax(eta3, eta4)));
00798
00799 return (maxeta + eta) * btScalar(0.5f);
00800 }
00801
00802 void btHfFluid::allocateArrays()
00803 {
00804 if (m_temp)
00805 btAlignedFree (m_temp);
00806 if (m_height[0])
00807 {
00808 btAlignedFree (m_height[0]);
00809 btAlignedFree(m_height[1]);
00810 }
00811 if (m_ground)
00812 btAlignedFree (m_ground);
00813 if (m_eta)
00814 btAlignedFree (m_eta);
00815 if (m_u[0])
00816 {
00817 btAlignedFree (m_u[0]);
00818 btAlignedFree(m_u[1]);
00819 }
00820 if (m_v)
00821 {
00822 btAlignedFree (m_v[0]);
00823 btAlignedFree(m_v[1]);
00824 }
00825 if (m_r)
00826 {
00827 btAlignedFree (m_r[0]);
00828 btAlignedFree(m_r[1]);
00829 }
00830 if (m_flags)
00831 btAlignedFree (m_flags);
00832 if (m_fillRatio)
00833 btAlignedFree (m_fillRatio);
00834
00835 m_heightIndex = 0;
00836 m_velocityIndex = 0;
00837 m_temp = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00838 m_height[0] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00839 m_height[1] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00840 m_ground = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00841 m_eta = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00842 m_u[0] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00843 m_u[1] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00844 m_v[0] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00845 m_v[1] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00846 m_r[0] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00847 m_r[1] = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00848 m_fillRatio = (btScalar*)btAlignedAlloc(sizeof(btScalar) * m_numNodesWidth * m_numNodesLength, 16);
00849 m_flags = (bool*)btAlignedAlloc(sizeof(bool) * m_numNodesWidth * m_numNodesLength, 16);
00850
00851 {
00852 int bufferSize = sizeof(btScalar) * m_numNodesWidth * m_numNodesLength;
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862 }
00863 for (int i = 0; i < m_numNodesWidth * m_numNodesLength; i++)
00864 {
00865 m_eta[i] = btScalar(0.0);
00866 m_u[0][i] = btScalar(0.0);
00867 m_u[1][i] = btScalar(0.0);
00868 m_v[0][i] = btScalar(0.0);
00869 m_v[1][i] = btScalar(0.0);
00870 m_r[0][i] = btScalar(0.0);
00871 m_r[1][i] = btScalar(0.0);
00872 m_height[0][i] = btScalar(0.0);
00873 m_height[1][i] = btScalar(0.0);
00874 m_ground[i] = btScalar(-10.0);
00875 m_flags[i] = false;
00876 m_fillRatio[i] = btScalar(0.0);
00877 m_temp[i] = btScalar(0.0);
00878 }
00879 }
00880
00881 void btHfFluid::debugTests()
00882 {
00883 static btScalar total_volume = btScalar(0.0f);
00884 btScalar new_total_volume = btScalar(0.0f);
00885 for (int i = 0; i < m_numNodesWidth * m_numNodesLength; i++)
00886 {
00887 new_total_volume += m_eta[i] * m_gridCellWidth * m_gridCellWidth;
00888 }
00889
00890 total_volume = new_total_volume;
00891 }
00892
00893
00894
00895 void btHfFluid::setGlobaVelocity(btScalar globalVelocityU, btScalar globalVelocityV)
00896 {
00897 m_globalVelocityU = globalVelocityU;
00898 m_globalVelocityV = globalVelocityV;
00899 }
00900
00901 void btHfFluid::getGlobalVelocity(btScalar& globalVelocityU, btScalar& globalVelocityV) const
00902 {
00903 globalVelocityU = m_globalVelocityU;
00904 globalVelocityV = m_globalVelocityV;
00905 }
00906
00907
00908
00909 void btHfFluid::setGravity(btScalar gravity)
00910 {
00911 m_gravity = gravity;
00912 }
00913 btScalar btHfFluid::getGravity() const
00914 {
00915 return m_gravity;
00916 }
00917
00918
00919
00920
00921
00922 void btHfFluid::setVolumeDisplacementScale(btScalar volumeDisplacementScale)
00923 {
00924 m_volumeDisplacementScale = volumeDisplacementScale;
00925 }
00926
00927 btScalar btHfFluid::getVolumeDisplacementScale() const
00928 {
00929 return m_volumeDisplacementScale;
00930 }
00931
00932
00933
00934
00935
00936 void btHfFluid::setHorizontalVelocityScale(btScalar horizontalVelocityScale)
00937 {
00938 m_horizontalVelocityScale = horizontalVelocityScale;
00939 }
00940
00941 btScalar btHfFluid::getHorizontalVelocityScale() const
00942 {
00943 return m_horizontalVelocityScale;
00944 }
00945
00946 static btScalar rangeOverlap(btScalar lo1, btScalar hi1, btScalar lo2, btScalar hi2, btScalar& loOut, btScalar& hiOut)
00947 {
00948 if (!(lo1 <= hi2 && lo2 <= hi1))
00949 return btScalar(0.0f);
00950
00951 if (lo1 >= lo2 && lo1 <= hi2 && hi1 >= lo2 && hi1 <= hi2)
00952 {
00953 hiOut = hi1;
00954 loOut = lo1;
00955 return hi1 - lo1;
00956 }
00957 else if (lo2 >= lo1 && lo2 <= hi1 && hi2 >= lo1 && hi2 <= hi1)
00958 {
00959 hiOut = hi2;
00960 loOut = lo2;
00961 return hi2 - lo2;
00962 }
00963 else if (hi1 >= lo2 && lo1 <= lo2)
00964 {
00965 hiOut = hi1;
00966 loOut = lo2;
00967 return hi1 - lo2;
00968 }
00969 else
00970 {
00971 hiOut = hi2;
00972 loOut = lo1;
00973 return hi2 - lo1;
00974 }
00975 }
00976
00977 btHfFluidColumnRigidBodyCallback::btHfFluidColumnRigidBodyCallback(btRigidBody* rigidBody, btIDebugDraw* debugDraw,
00978 btScalar density, btScalar floatyness)
00979 {
00980 m_rigidBody = rigidBody;
00981 m_buoyantShape = (btHfFluidBuoyantConvexShape*)rigidBody->getCollisionShape();
00982 m_debugDraw = debugDraw;
00983 m_rigidBody->getAabb(m_aabbMin, m_aabbMax);
00984 m_volume = btScalar(0.0f);
00985 m_density = density;
00986 m_floatyness = floatyness;
00987 m_numVoxels = m_buoyantShape->getNumVoxels();
00988 m_voxelPositionsXformed = (btVector3*)btAlignedAlloc(sizeof(btVector3) * m_numVoxels, 16);
00989 m_voxelSubmerged = (bool*)btAlignedAlloc(sizeof(bool) * m_numVoxels, 16);
00990 for (int i = 0; i < m_numVoxels; i++)
00991 {
00992 btVector3 p = m_buoyantShape->getVoxelPositionsArray()[i];
00993 p = m_rigidBody->getWorldTransform().getBasis() * p;
00994 p += m_rigidBody->getWorldTransform().getOrigin();
00995 m_voxelPositionsXformed[i] = p;
00996 m_voxelSubmerged[i] = false;
00997 }
00998 }
00999
01000 btHfFluidColumnRigidBodyCallback::~btHfFluidColumnRigidBodyCallback()
01001 {
01002 if (m_voxelPositionsXformed)
01003 btAlignedFree (m_voxelPositionsXformed);
01004 if (m_voxelSubmerged)
01005 btAlignedFree (m_voxelSubmerged);
01006 }
01007
01008 static bool sphereVsAABB(const btVector3& aabbMin, const btVector3& aabbMax, const btVector3& sphereCenter,
01009 const btScalar sphereRadius)
01010 {
01011 btScalar totalDistance = 0;
01012
01013
01014 for (int i = 0; i < 3; ++i)
01015 {
01016
01017
01018 if (sphereCenter[i] < aabbMin[i])
01019 {
01020 btScalar borderDistance = aabbMin[i] - sphereCenter[i];
01021 totalDistance += borderDistance * borderDistance;
01022
01023 }
01024 else if (sphereCenter[i] > aabbMax[i])
01025 {
01026 btScalar borderDistance = sphereCenter[i] - aabbMax[i];
01027 totalDistance += borderDistance * borderDistance;
01028
01029 }
01030
01031
01032
01033 }
01034
01035
01036 return (totalDistance <= (sphereRadius * sphereRadius));
01037 }
01038
01039 bool btHfFluidColumnRigidBodyCallback::processColumn(btHfFluid* fluid, int w, int l)
01040 {
01041 btVector3 columnAabbMin, columnAabbMax;
01042
01043 fluid->getAabbForColumn(w, l, columnAabbMin, columnAabbMax);
01044
01045 bool applyBuoyancyImpulse = true;
01046 bool applyFluidVelocityImpulse = true;
01047 bool applyFluidDisplace = true;
01048
01049 btScalar dt = btScalar(1.0f / 60.0f);
01050
01051 btScalar columnVolume = btScalar(0.0f);
01052
01053 for (int i = 0; i < m_buoyantShape->getNumVoxels(); i++)
01054 {
01055 if (m_voxelSubmerged[i])
01056 continue;
01057
01058 if (sphereVsAABB(columnAabbMin, columnAabbMax, m_voxelPositionsXformed[i], m_buoyantShape->getVoxelRadius()))
01059 {
01060
01061 m_voxelSubmerged[i] = true;
01062 btScalar voxelVolume = m_buoyantShape->getVolumePerVoxel();
01063 columnVolume += voxelVolume;
01064
01065 btVector3 application_point = m_voxelPositionsXformed[i];
01066 btVector3 relative_position = application_point - m_rigidBody->getCenterOfMassPosition();
01067
01068 if (applyBuoyancyImpulse)
01069 {
01070
01071 btScalar massDisplacedWater = voxelVolume * 1027 * m_floatyness;
01072 btScalar force = massDisplacedWater * -fluid->getGravity();
01073 btScalar impulseMag = force * dt;
01074
01075 btVector3 impulseVec = btVector3(btScalar(0.0f), btScalar(0.0f), btScalar(1.0f)) * impulseMag;
01076
01077
01078 #ifdef CENTER_IMPULSE_ONLY
01079 m_rigidBody->applyCentralImpulse (impulseVec);
01080 #else
01081 m_rigidBody->applyImpulse(impulseVec, relative_position);
01082 #endif
01083 }
01084 }
01085 }
01086
01087 if (columnVolume > btScalar(0.0))
01088 {
01089 m_volume += columnVolume;
01090
01091 if (applyFluidDisplace)
01092 {
01093 fluid->addDisplaced(w, l, columnVolume);
01094 }
01095
01096 if (applyFluidVelocityImpulse)
01097 {
01098 int index = fluid->arrayIndex(w, l);
01099 btScalar u = fluid->getVelocityUArray()[index];
01100 btScalar v = fluid->getVelocityVArray()[index];
01101 btVector3 vd = btVector3(u, btScalar(0.0f), v);
01102 btVector3 impulse = vd * dt * fluid->getHorizontalVelocityScale();
01103
01104 m_rigidBody->applyCentralImpulse(impulse);
01105 }
01106 }
01107
01108 return true;
01109 }
01110