00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "SIM_SolverSNOW.h"
00029 #include <strstream.h>
00030 #include <UT/UT_DSOVersion.h>
00031 #include <UT/UT_Floor.h>
00032 #include <UT/UT_Vector3.h>
00033 #include <UT/UT_WorkBuffer.h>
00034 #include <GU/GU_Detail.h>
00035 #include <GU/GU_RayIntersect.h>
00036 #include <GU/GU_PrimTriStrip.h>
00037 #include <PRM/PRM_Include.h>
00038 #include <SIM/SIM_Engine.h>
00039 #include <SIM/SIM_Options.h>
00040 #include <SIM/SIM_Object.h>
00041 #include <SIM/SIM_ObjectArray.h>
00042 #include <SIM/SIM_DopDescription.h>
00043 #include <SIM/SIM_Random.h>
00044 #include <SIM/SIM_RandomTwister.h>
00045 #include <SIM/SIM_Position.h>
00046
00047 #define VOXELARRAY_XDIVISIONS "xdivisions"
00048 #define VOXELARRAY_YDIVISIONS "ydivisions"
00049 #define VOXELARRAY_ZDIVISIONS "zdivisions"
00050
00051 static PRM_Name theBirthRateName(SIM_NAME_BIRTHRATE, "Birth Rate");
00052 static PRM_Name theDivisionsName(SIM_NAME_DIVISIONS, "Divisions");
00053 static PRM_Name theOriginalDepthName(SIM_NAME_ORIGINALDEPTH, "Original Depth");
00054
00055 using namespace HDK_Sample;
00056
00057 void
00058 initializeSIM(void *)
00059 {
00060 IMPLEMENT_DATAFACTORY(SIM_SolverSNOW);
00061 IMPLEMENT_DATAFACTORY(SNOW_VoxelArray);
00062 }
00063
00064 SNOW_VoxelArray::SNOW_VoxelArray(const SIM_DataFactory *factory)
00065 : SIM_Geometry(factory),
00066 myVoxelArray(0)
00067 {
00068 }
00069
00070 SNOW_VoxelArray::~SNOW_VoxelArray()
00071 {
00072 freeArray();
00073 }
00074
00075 int
00076 SNOW_VoxelArray::getXDivisions() const
00077 {
00078 return myXDivisions;
00079 }
00080
00081 void
00082 SNOW_VoxelArray::setXDivisions(int divisions)
00083 {
00084 if( divisions != myXDivisions )
00085 {
00086 freeArray();
00087 myXDivisions = divisions;
00088 }
00089 }
00090
00091 int
00092 SNOW_VoxelArray::getYDivisions() const
00093 {
00094 return myYDivisions;
00095 }
00096
00097 void
00098 SNOW_VoxelArray::setYDivisions(int divisions)
00099 {
00100 if( divisions != myYDivisions )
00101 {
00102 freeArray();
00103 myYDivisions = divisions;
00104 }
00105 }
00106
00107 int
00108 SNOW_VoxelArray::getZDivisions() const
00109 {
00110 return myZDivisions;
00111 }
00112
00113 void
00114 SNOW_VoxelArray::setZDivisions(int divisions)
00115 {
00116 if( divisions != myZDivisions )
00117 {
00118 freeArray();
00119 myZDivisions = divisions;
00120 }
00121 }
00122
00123 u8
00124 SNOW_VoxelArray::getVoxel(int x, int y, int z) const
00125 {
00126 if( !myVoxelArray )
00127 allocateArray();
00128
00129 return myVoxelArray->getValue(x, y, z);
00130 }
00131
00132 void
00133 SNOW_VoxelArray::setVoxel(u8 voxel, int x, int y, int z)
00134 {
00135 if( !myVoxelArray )
00136 allocateArray();
00137
00138 if (x < 0 || x >= myXDivisions)
00139 return;
00140 if (y < 0 || y >= myYDivisions)
00141 return;
00142 if (z < 0 || z >= myZDivisions)
00143 return;
00144
00145 myVoxelArray->setValue(x, y, z, voxel);
00146 }
00147
00148 GU_ConstDetailHandle
00149 SNOW_VoxelArray::getGeometrySubclass() const
00150 {
00151 ((SNOW_VoxelArray *)this)->buildGeometryFromArray();
00152 return myDetailHandle;
00153 }
00154
00155 void
00156 SNOW_VoxelArray::freeArray() const
00157 {
00158 delete myVoxelArray;
00159 myVoxelArray = 0;
00160 }
00161
00162 void
00163 SNOW_VoxelArray::allocateArray() const
00164 {
00165 UT_ASSERT(myVoxelArray == 0);
00166
00167 myVoxelArray = new UT_VoxelArray<u8>;
00168 myVoxelArray->size(myXDivisions, myYDivisions, myZDivisions);
00169
00170
00171 myVoxelArray->setBorder(UT_VOXELBORDER_CONSTANT, VOXEL_WALL);
00172 }
00173
00174 GEO_Point *
00175 SNOW_VoxelArray::createOrFindPoint(GU_Detail *gdp, int x, int y, int z)
00176 {
00177 int idx;
00178 UT_Thing thing;
00179 GEO_Point *pt;
00180
00181 idx = (z * (myYDivisions + 1) + y)*(myXDivisions + 1) + x;
00182
00183 UT_Hash_Int hash(idx);
00184
00185 if (myPointHash.findSymbol(hash, &thing))
00186 {
00187 return (GEO_Point *) thing.value.voidp;
00188 }
00189
00190
00191
00192 pt = gdp->appendPoint();
00193
00194 UT_Vector3 v4;
00195 v4.assign((fpreal) x / (fpreal) (myXDivisions + 1),
00196 (fpreal) y / (fpreal) (myYDivisions + 1),
00197 (fpreal) z / (fpreal) (myZDivisions + 1));
00198 pt->getPos() = v4;
00199
00200
00201 thing.value.voidp = pt;
00202 myPointHash.addSymbol(hash, thing);
00203
00204 return pt;
00205 }
00206
00207 void
00208 SNOW_VoxelArray::buildFace(GU_Detail *gdp,
00209 int x0, int y0, int z0,
00210 int x1, int y1, int z1,
00211 int x2, int y2, int z2,
00212 int x3, int y3, int z3)
00213 {
00214
00215 GU_PrimTriStrip *tristrip;
00216 GEO_Point *pt;
00217
00218
00219 tristrip = GU_PrimTriStrip::build(gdp, 4, 0);
00220
00221 pt = createOrFindPoint(gdp, x0, y0, z0);
00222 (*tristrip)(0).setPt(pt);
00223 pt = createOrFindPoint(gdp, x1, y1, z1);
00224 (*tristrip)(1).setPt(pt);
00225 pt = createOrFindPoint(gdp, x3, y3, z3);
00226 (*tristrip)(2).setPt(pt);
00227 pt = createOrFindPoint(gdp, x2, y2, z2);
00228 (*tristrip)(3).setPt(pt);
00229 }
00230
00231 void
00232 SNOW_VoxelArray::buildGeometryFromArray()
00233 {
00234 if( myDetailHandle.isNull() )
00235 {
00236 GU_Detail *gdp = new GU_Detail();
00237 int x, xdiv, y, ydiv, z, zdiv;
00238 int xstep, ystep, zstep;
00239
00240 myDetailHandle.allocateAndSet(gdp);
00241 xdiv = getXDivisions();
00242 ydiv = getYDivisions();
00243 zdiv = getZDivisions();
00244
00245
00246 xstep = ystep = zstep = 1;
00247 if (xdiv > 64)
00248 xstep = xdiv / 64;
00249 if (ydiv > 64)
00250 ystep = ydiv / 64;
00251 if (zdiv > 64)
00252 zstep = zdiv / 64;
00253
00254 for( z = 0; z < zdiv; z+=zstep )
00255 {
00256 for( y = 0; y < ydiv; y+=ystep )
00257 {
00258 for( x = 0; x < xdiv; x+=xstep )
00259 {
00260 if (getVoxel(x, y, z) == VOXEL_SNOW)
00261 {
00262
00263
00264
00265
00266
00267
00268
00269 if (getVoxel(x-xstep, y, z) != VOXEL_SNOW)
00270 {
00271 buildFace( gdp, x, y, z,
00272 x, y+ystep, z,
00273 x, y+ystep, z+zstep,
00274 x, y, z+zstep );
00275 }
00276 if (getVoxel(x+xstep, y, z) != VOXEL_SNOW)
00277 {
00278 buildFace( gdp, x+xstep, y, z,
00279 x+xstep, y, z+zstep,
00280 x+xstep, y+ystep, z+zstep,
00281 x+xstep, y+ystep, z );
00282 }
00283 if (getVoxel(x, y-ystep, z) != VOXEL_SNOW)
00284 {
00285 buildFace( gdp, x, y, z,
00286 x, y, z+zstep,
00287 x+xstep, y, z+zstep,
00288 x+xstep, y, z );
00289 }
00290 if (getVoxel(x, y+ystep, z) != VOXEL_SNOW)
00291 {
00292 buildFace( gdp, x, y+ystep, z,
00293 x+xstep, y+ystep, z,
00294 x+xstep, y+ystep, z+zstep,
00295 x, y+ystep, z+zstep );
00296 }
00297 if (getVoxel(x, y, z-zstep) != VOXEL_SNOW)
00298 {
00299 buildFace( gdp, x, y, z,
00300 x+xstep, y, z,
00301 x+xstep, y+ystep, z,
00302 x, y+ystep, z );
00303 }
00304 if (getVoxel(x, y, z+zstep) != VOXEL_SNOW)
00305 {
00306 buildFace( gdp, x, y, z+zstep,
00307 x, y+ystep, z+zstep,
00308 x+xstep, y+ystep, z+zstep,
00309 x+xstep, y, z+zstep );
00310 }
00311 }
00312 }
00313 }
00314 }
00315
00316
00317 myPointHash.clear();
00318 }
00319 }
00320
00321 void
00322 SNOW_VoxelArray::initializeSubclass()
00323 {
00324 SIM_Geometry::initializeSubclass();
00325 freeArray();
00326 myXDivisions = 0;
00327 myYDivisions = 0;
00328 myZDivisions = 0;
00329 myDetailHandle.clear();
00330 }
00331
00332 void
00333 SNOW_VoxelArray::makeEqualSubclass(const SIM_Data *source)
00334 {
00335 const SNOW_VoxelArray *srcvox;
00336
00337 SIM_Geometry::makeEqualSubclass(source);
00338 srcvox = SIM_DATA_CASTCONST(source, SNOW_VoxelArray);
00339 if( srcvox )
00340 {
00341 setXDivisions(srcvox->getXDivisions());
00342 setYDivisions(srcvox->getYDivisions());
00343 setZDivisions(srcvox->getZDivisions());
00344
00345 if (srcvox->myVoxelArray)
00346 {
00347
00348 allocateArray();
00349
00350 *myVoxelArray = *srcvox->myVoxelArray;
00351 }
00352 else
00353 {
00354
00355 freeArray();
00356 }
00357 }
00358 }
00359
00360 void
00361 SNOW_VoxelArray::saveSubclass(ostream &os) const
00362 {
00363 SIM_Options voxeldata;
00364 int x, xdiv, y, ydiv, z, zdiv, value;
00365
00366 SIM_Geometry::saveSubclass(os);
00367
00368 xdiv = getXDivisions();
00369 ydiv = getYDivisions();
00370 zdiv = getZDivisions();
00371 voxeldata.setOptionI(VOXELARRAY_XDIVISIONS, xdiv);
00372 voxeldata.setOptionI(VOXELARRAY_YDIVISIONS, ydiv);
00373 voxeldata.setOptionI(VOXELARRAY_ZDIVISIONS, zdiv);
00374 saveOptionPacket(os, classname(), &voxeldata);
00375
00376 os << "{" << endl;
00377 for( z = 0; z < zdiv; z++ )
00378 {
00379 for( y = 0; y < ydiv; y++ )
00380 {
00381 os << "\t";
00382 for( x = 0; x < xdiv; x++ )
00383 {
00384 value = getVoxel(x, y, z);
00385 os << " " << value;
00386 }
00387 os << endl;
00388 }
00389 }
00390 os << "}" << endl;
00391 }
00392
00393 bool
00394 SNOW_VoxelArray::loadSubclass(UT_IStream &is)
00395 {
00396 SIM_Options voxeldata;
00397 UT_WorkBuffer buf;
00398 int xdiv, ydiv, zdiv, idx, arraysize;
00399 int x, y, z;
00400 int value;
00401 bool result = true;
00402
00403 if (!SIM_Geometry::loadSubclass(is))
00404 return false;
00405
00406 if( loadOptionPacket(is, classname(), &voxeldata) )
00407 {
00408 xdiv = voxeldata.getOptionI(VOXELARRAY_XDIVISIONS);
00409 ydiv = voxeldata.getOptionI(VOXELARRAY_YDIVISIONS);
00410 zdiv = voxeldata.getOptionI(VOXELARRAY_ZDIVISIONS);
00411 setXDivisions(xdiv);
00412 setYDivisions(ydiv);
00413 setZDivisions(zdiv);
00414 arraysize = xdiv * ydiv * zdiv;
00415 idx = 0;
00416 x = y = z = 0;
00417 if( is.getLine(buf) && *buf.buffer() == '{' )
00418 {
00419 while( is.getLine(buf) && *buf.buffer() != '}' )
00420 {
00421 istrstream bufis(buf.lock(), buf.length());
00422
00423 while( idx < arraysize && bufis )
00424 {
00425 if( (bufis >> value) )
00426 {
00427 setVoxel(value, x, y, z);
00428 x++;
00429 if (x >= xdiv);
00430 {
00431 x = 0;
00432 y++;
00433 if (y >= ydiv)
00434 {
00435 y = 0;
00436 z++;
00437 }
00438 }
00439 }
00440 }
00441 buf.release();
00442 }
00443 UT_ASSERT(idx == arraysize);
00444 }
00445 }
00446 else
00447 result = false;
00448
00449 return result;
00450 }
00451
00452 void
00453 SNOW_VoxelArray::handleModificationSubclass(int code)
00454 {
00455 SIM_Geometry::handleModificationSubclass(code);
00456 myDetailHandle.clear();
00457 }
00458
00459 void
00460 SNOW_VoxelArray::collapseAllTiles()
00461 {
00462 if (!myVoxelArray)
00463 return;
00464
00465 myVoxelArray->collapseAllTiles();
00466 }
00467
00468 SIM_SolverSNOW::SIM_SolverSNOW(const SIM_DataFactory *factory)
00469 : BaseClass(factory),
00470 SIM_OptionsUser(this)
00471 {
00472 }
00473
00474 SIM_SolverSNOW::~SIM_SolverSNOW()
00475 {
00476 }
00477
00478 const SIM_DopDescription *
00479 SIM_SolverSNOW::getSolverSNOWDopDescription()
00480 {
00481 static PRM_Template theTemplates[] = {
00482 PRM_Template(PRM_FLT_J, 1, &theBirthRateName, PRMpointOneDefaults),
00483 PRM_Template(PRM_INT_J, 1, &theDivisionsName, PRMtenDefaults),
00484 PRM_Template(PRM_INT_J, 1, &theOriginalDepthName),
00485 PRM_Template()
00486 };
00487
00488 static SIM_DopDescription theDopDescription(true,
00489 "hdk_snowsolver",
00490 "SNOW Solver",
00491 SIM_SOLVER_DATANAME,
00492 classname(),
00493 theTemplates);
00494
00495 return &theDopDescription;
00496 }
00497
00498 SIM_Random *
00499 SIM_SolverSNOW::createRandomData(SIM_Object *obj) const
00500 {
00501 SIM_Random *rand = 0;
00502
00503
00504
00505
00506 rand = SIM_DATA_GET(*obj, "Random", SIM_Random);
00507 if( !rand )
00508 rand = SIM_DATA_CREATE(*obj, "Random", SIM_RandomTwister, 0);
00509
00510 return rand;
00511 }
00512
00513 bool
00514 SIM_SolverSNOW::brownianize(int &v, int dv, int max, SIM_Random *rand) const
00515 {
00516 if (dv)
00517 {
00518 v += dv;
00519 if (v < 0 || v >= max)
00520 return false;
00521 }
00522 else
00523 {
00524 v += rand_choice(3, rand) - 1;
00525 if (v < 0)
00526 v = 0;
00527 if (v >= max)
00528 v = max - 1;
00529 }
00530
00531 return true;
00532 }
00533
00534 int
00535 SIM_SolverSNOW::clearInDirection(const SNOW_VoxelArray &snow,
00536 int sx, int sy, int sz,
00537 int dx, int dy, int dz,
00538 int &rx, int &ry, int &rz,
00539 int maxdist,
00540 SIM_Random *rand) const
00541 {
00542 int dist = 0;
00543 int xdiv, ydiv, zdiv;
00544
00545 xdiv = snow.getXDivisions();
00546 ydiv = snow.getYDivisions();
00547 zdiv = snow.getZDivisions();
00548
00549 while (1)
00550 {
00551
00552 if (!brownianize(sx, dx, xdiv, rand))
00553 return maxdist;
00554 if (!brownianize(sy, dy, ydiv, rand))
00555 return maxdist;
00556 if (!brownianize(sz, dz, zdiv, rand))
00557 return maxdist;
00558
00559
00560 if (snow.getVoxel(sx, sy, sz) == VOXEL_EMPTY)
00561 {
00562 break;
00563 }
00564
00565 dist++;
00566 }
00567
00568 rx = sx;
00569 ry = sy;
00570 rz = sz;
00571 return dist;
00572 }
00573
00574
00575
00576 void
00577 SIM_SolverSNOW::clearSnow(SNOW_VoxelArray &snow,
00578 int x, int y, int z, SIM_Random *rand) const
00579 {
00580
00581
00582
00583
00584 int end_x[6], end_y[6], end_z[6], dist[6];
00585
00586 int dxvals[6] = { -1, 0, 0, 1, 0, 0 };
00587 int dyvals[6] = { 0, -1, 1, 0, 0, 0 };
00588 int dzvals[6] = { 0, 0, 0, 0, 1, -1 };
00589 int direction, mindir, mindist = 320000;
00590
00591 for (direction = 0; direction < 6; direction++)
00592 {
00593 dist[direction] =
00594 clearInDirection(snow,
00595 x, y, z,
00596 dxvals[direction], dyvals[direction], dzvals[direction],
00597 end_x[direction], end_y[direction], end_z[direction],
00598 mindist,
00599 rand);
00600
00601 if (dist[direction] < mindist)
00602 {
00603 mindir = direction;
00604 mindist = dist[direction];
00605 }
00606 }
00607
00608 if (mindist == 320000)
00609 {
00610
00611 UT_ASSERT(!"No snow removal possible!");
00612 }
00613 else
00614 {
00615
00616 snow.setVoxel(VOXEL_SNOW, end_x[mindir], end_y[mindir], end_z[mindir]);
00617 }
00618 }
00619
00620 int
00621 SIM_SolverSNOW::rand_choice(int numchoice, SIM_Random *rand) const
00622 {
00623 int choice;
00624
00625 choice = rand->choice(numchoice);
00626
00627 return choice;
00628 }
00629
00630 void
00631 SIM_SolverSNOW::fillRow(SNOW_VoxelArray &snow,
00632 fpreal startx, fpreal endx,
00633 int y, int z,
00634 u8 voxeltype,
00635 SIM_Random *rand) const
00636 {
00637 int xdiv, ydiv, zdiv;
00638 int x, sx, ex;
00639
00640 xdiv = snow.getXDivisions();
00641 ydiv = snow.getYDivisions();
00642 zdiv = snow.getZDivisions();
00643
00644 sx = (int)(startx * xdiv);
00645 ex = (int)(endx * xdiv);
00646 if (sx < 0) sx = 0;
00647 if (sx >= xdiv) return;
00648 if (ex < 0) return;
00649 if (ex >= xdiv) ex = xdiv - 1;
00650
00651 if (voxeltype == VOXEL_OBJECT)
00652 {
00653 for (x = sx; x < ex; x++)
00654 {
00655
00656 if (snow.getVoxel(x, y, z) == VOXEL_SNOW)
00657 clearSnow(snow, x, y, z, rand);
00658 snow.setVoxel(VOXEL_OBJECT, x, y, z);
00659 }
00660 }
00661 else if (voxeltype == VOXEL_SNOW)
00662 {
00663 for (x = sx; x < ex; x++)
00664 {
00665 snow.setVoxel(VOXEL_SNOW, x, y, z);
00666 }
00667 }
00668 }
00669
00670 void
00671 SIM_SolverSNOW::applyGeometry(SNOW_VoxelArray &snow,
00672 const GU_ConstDetailHandle &gdh,
00673 const UT_DMatrix4 &xform,
00674 u8 voxeltype,
00675 SIM_Random *rand) const
00676 {
00677 if( !gdh.isNull() )
00678 {
00679 GU_DetailHandleAutoReadLock gdl(gdh);
00680 const GU_Detail *gdp = gdl.getGdp();
00681 int xdiv, ydiv, zdiv;
00682 int y, z;
00683
00684 xdiv = snow.getXDivisions();
00685 ydiv = snow.getYDivisions();
00686 zdiv = snow.getZDivisions();
00687
00688 GU_RayIntersect *isect;
00689 UT_BoundingBox bbox;
00690 GU_RayInfo hitinfo;
00691 int numhit, hitnum;
00692 UT_Matrix4 fxform;
00693
00694 fxform = xform;
00695
00696 fxform.invert();
00697 gdp->getBBox(&bbox);
00698 bbox.transform(fxform);
00699
00700
00701 int bminx, bminy, bminz;
00702 int bmaxx, bmaxy, bmaxz;
00703 UT_Vector3 orig, dir, pos;
00704 UT_Vector3 xorig, xdir, xpos;
00705
00706
00707
00708 bminx = (int)UTfloor(bbox(0, 0) * (xdiv + 1));
00709 if (bminx < 0) bminx = 0;
00710 bmaxx = (int)UTceil(bbox(0, 1) * (xdiv + 1));
00711 if (bmaxx >= xdiv) bmaxx = xdiv-1;
00712 bminy = (int)UTfloor(bbox(1, 0) * (ydiv + 1));
00713 if (bminy < 0) bminy = 0;
00714 bmaxy = (int)UTceil(bbox(1, 1) * (ydiv + 1));
00715 if (bmaxy >= ydiv) bmaxy = ydiv-1;
00716 bminz = (int)UTfloor(bbox(2, 0) * (zdiv + 1));
00717 if (bminz < 0) bminz = 0;
00718 bmaxz = (int)UTceil(bbox(2, 1) * (zdiv + 1));
00719 if (bmaxz >= zdiv) bmaxz = zdiv-1;
00720
00721
00722 isect = new GU_RayIntersect(gdp);
00723
00724
00725
00726 orig.x() = 0.0;
00727 dir.assign(1.0, 0.0, 0.0);
00728 xdir = dir;
00729 xdir.multiply3(xform);
00730
00731 for (z = bmaxz; z >= bminz; z--)
00732 {
00733 orig.z() = (z + 0.5) / (zdiv + 1);
00734 for (y = bminy; y <= bmaxy; y++)
00735 {
00736 orig.y() = (y + 0.5) / (ydiv + 1);
00737 hitinfo.reset();
00738
00739 xorig = orig;
00740 xorig *= xform;
00741
00742 hitinfo.init(1.0, 0.0, GU_FIND_ALL, 1e-4);
00743
00744 numhit = isect->sendRay(xorig, xdir, hitinfo);
00745
00746
00747 if (numhit < 0)
00748 return;
00749
00750
00751
00752 numhit = hitinfo.myHitList->entries();
00753
00754 fpreal lt, t;
00755
00756
00757
00758
00759 lt = 0.0;
00760
00761 for (hitnum = 0; hitnum <= numhit; hitnum++)
00762 {
00763 if (hitnum < numhit)
00764 t = (*hitinfo.myHitList)(hitnum).t;
00765 else
00766 t = 1.0;
00767
00768
00769 pos = orig;
00770 pos.x() = (t + lt) / 2.0;
00771 xpos = pos;
00772 xpos *= xform;
00773 if (isect->isInsideWinding(xpos, 0))
00774 {
00775 fillRow(snow, lt, t, y, z, voxeltype, rand);
00776 }
00777
00778 lt = t;
00779 }
00780 }
00781 }
00782
00783 delete isect;
00784 }
00785 }
00786
00787 void
00788 SIM_SolverSNOW::solveForObject(SIM_Object &object,
00789 SNOW_VoxelArray &snow,
00790 const SIM_Time & ) const
00791 {
00792
00793 int xdiv, ydiv, zdiv;
00794 int x, y, z;
00795 int i, n;
00796 fpreal birthrate;
00797 SIM_Random *rand = createRandomData(&object);
00798
00799 xdiv = getDivisions();
00800 ydiv = getDivisions();
00801 zdiv = getDivisions();
00802
00803 birthrate = getBirthRate();
00804
00805
00806 const SIM_Geometry *geometry = 0;
00807
00808
00809 for (z = 0; z < zdiv; z++)
00810 {
00811 for (y = 0; y <= ydiv; y++)
00812 {
00813 for (x = 0; x <= xdiv; x++)
00814 {
00815 if (snow.getVoxel(x, y, z) == VOXEL_OBJECT)
00816 snow.setVoxel(VOXEL_EMPTY, x, y, z);
00817 }
00818 }
00819 }
00820
00821
00822 SIM_ObjectArray sourceaffectors;
00823 SIM_ColliderInfoArray colliderinfo;
00824 UT_String sourceobjects;
00825
00826 object.getAffectors(sourceaffectors, "SIM_RelationshipSource");
00827 n = sourceaffectors.entries();
00828 for (i = 0; i < n; i++)
00829 {
00830 const SIM_Object *affector = sourceaffectors(i);
00831 const SIM_Position *pos = affector->getPosition();
00832 UT_DMatrix4 xform, worldtogeo;
00833
00834 geometry = affector->getGeometry();
00835
00836 if (!geometry)
00837 continue;
00838
00839 geometry->getTransform(xform);
00840 xform.invert();
00841 if (pos)
00842 {
00843 pos->getInverseTransform(worldtogeo);
00844 xform = worldtogeo * xform;
00845 }
00846
00847 applyGeometry(snow, geometry->getGeometry(), xform, VOXEL_SNOW, rand);
00848 }
00849
00850
00851 object.getColliderInfo(colliderinfo);
00852 n = colliderinfo.entries();
00853 for (i = 0; i < n; i++)
00854 {
00855 const SIM_Object *affector = colliderinfo(i).getAffector();
00856 const SIM_Position *pos = affector->getPosition();
00857 UT_DMatrix4 xform, worldtogeo;
00858
00859 geometry = affector->getGeometry();
00860
00861 if (!geometry)
00862 continue;
00863
00864 geometry->getTransform(xform);
00865 xform.invert();
00866 if (pos)
00867 {
00868 pos->getInverseTransform(worldtogeo);
00869 xform = worldtogeo * xform;
00870 }
00871
00872 applyGeometry(snow, geometry->getGeometry(), xform, VOXEL_OBJECT, rand);
00873 }
00874
00875
00876 if (!UTequalZero(birthrate))
00877 for (y = 0; y < ydiv; y++)
00878 {
00879 for (x = 0; x < xdiv; x++)
00880 {
00881 if (rand->frandom() < birthrate)
00882 {
00883 snow.setVoxel(VOXEL_SNOW, x, y, zdiv-1);
00884 }
00885 }
00886 }
00887
00888 int dxvals[9] = { -1, -1, -1, 0, 0, 0, 1, 1, 1 };
00889 int dyvals[9] = { -1, 0, 1, -1, 0, 1, -1, 0, 1 };
00890 int validdxidx[9];
00891 int numdxidx, dxidx;
00892
00893
00894 #if 1
00895 for (z = 1; z < zdiv; z++)
00896 {
00897
00898
00899
00900
00901
00902 int yend, ystart, yinc;
00903 int xend, xstart, xinc;
00904
00905 if (z & 1)
00906 {
00907 ystart = 0;
00908 yend = ydiv;
00909 yinc = 1;
00910 xstart = 0;
00911 xend = xdiv;
00912 xinc = 1;
00913 }
00914 else
00915 {
00916 ystart = ydiv-1;
00917 yend = -1;
00918 yinc = -1;
00919 xstart = xdiv-1;
00920 xend = -1;
00921 xinc = -1;
00922 }
00923
00924 for (y = ystart; y != yend; y += yinc)
00925 {
00926 for (x = xstart; x != xend; x += xinc)
00927 {
00928 if (snow.getVoxel(x, y, z) == VOXEL_SNOW)
00929 {
00930
00931 numdxidx = 0;
00932 for (dxidx = 0; dxidx < 9; dxidx++)
00933 {
00934 if (snow.getVoxel(x + dxvals[dxidx],
00935 y + dyvals[dxidx],
00936 z-1) == VOXEL_EMPTY)
00937 {
00938 validdxidx[numdxidx++] = dxidx;
00939 }
00940 }
00941
00942 if (numdxidx)
00943 {
00944 dxidx = rand_choice(numdxidx, rand);
00945
00946 dxidx = validdxidx[dxidx];
00947
00948
00949 snow.setVoxel(VOXEL_EMPTY, x, y, z);
00950 UT_ASSERT(snow.getVoxel(x + dxvals[dxidx],
00951 y + dyvals[dxidx],
00952 z-1) == VOXEL_EMPTY);
00953 snow.setVoxel(VOXEL_SNOW, x + dxvals[dxidx],
00954 y + dyvals[dxidx],
00955 z-1);
00956 }
00957 }
00958 }
00959 }
00960 }
00961 #endif
00962
00963
00964 snow.collapseAllTiles();
00965 snow.pubHandleModification();
00966 }
00967
00968 void
00969 SIM_SolverSNOW::setVoxelArrayAttributes(SNOW_VoxelArray *voxelarray) const
00970 {
00971 if( voxelarray )
00972 {
00973 voxelarray->setXDivisions(getDivisions());
00974 voxelarray->setYDivisions(getDivisions());
00975 voxelarray->setZDivisions(getDivisions());
00976
00977 int x, y, z, div, depth;
00978
00979 div = getDivisions();
00980
00981 depth = getOriginalDepth();
00982
00983 for (z = 0; z < depth; z++)
00984 {
00985 for (y = 0; y < div; y++)
00986 {
00987 for (x = 0; x < div; x++)
00988 {
00989 voxelarray->setVoxel(VOXEL_SNOW, x, y, z);
00990 }
00991 }
00992 }
00993 voxelarray->collapseAllTiles();
00994 voxelarray->pubHandleModification();
00995 }
00996 }
00997
00998 SIM_Solver::SIM_Result
00999 SIM_SolverSNOW::solveSingleObjectSubclass(SIM_Engine & ,
01000 SIM_Object &object,
01001 SIM_ObjectArray &,
01002 const SIM_Time ×tep,
01003 bool)
01004 {
01005 SNOW_VoxelArray *snow;
01006 SIM_Result result;
01007
01008 result = SIM_SOLVER_FAIL;
01009
01010 snow = SIM_DATA_GET(object, "SnowValue", SNOW_VoxelArray);
01011 if (!snow)
01012 {
01013 snow = SIM_DATA_CREATE(object, "SnowValue", SNOW_VoxelArray, 0);
01014 setVoxelArrayAttributes(snow);
01015 }
01016
01017
01018 if( snow )
01019 {
01020 solveForObject(object, *snow, timestep);
01021 result = SIM_SOLVER_SUCCESS;
01022 }
01023
01024 return result;
01025 }
01026