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
00029 #include "VRAY_DemoSprite.h"
00030
00031 #include <VRAY/VRAY_IO.h>
00032
00033 #include <GU/GU_Detail.h>
00034 #include <GU/GU_PrimPoly.h>
00035
00036 #include <UT/UT_Defines.h>
00037 #include <SYS/SYS_Floor.h>
00038
00039
00040 #define MIN_CHUNK 8
00041 #define SPRITE_LIMIT 1000
00042 #define META_CORRECT 0.5
00043 #define DEFAULT_ATTRIB_PATTERN ""
00044
00045
00046 namespace HDK_Sample {
00047
00048 class vray_SpriteAttribMap
00049 {
00050 public:
00051 GA_ROAttributeRef myOffset;
00052 int myDIndex;
00053 const GA_Attribute *myAttrib;
00054
00055 vray_SpriteAttribMap *myNext;
00056 };
00057
00058 }
00059
00060 using namespace HDK_Sample;
00061
00062
00063 static vray_SpriteAttribMap *
00064 makeMap(const GU_Detail *tplate, const GA_Attribute *atr)
00065 {
00066 vray_SpriteAttribMap *map;
00067 UT_String n;
00068
00069 map = new vray_SpriteAttribMap();
00070 map->myOffset = tplate->findPointAttrib(*atr);
00071
00072 map->myDIndex = -1;
00073 map->myAttrib = atr;
00074
00075 return map;
00076 }
00077
00078 static void
00079 destroyMap(vray_SpriteAttribMap *map)
00080 {
00081 vray_SpriteAttribMap *next;
00082 while (map)
00083 {
00084 next = map->myNext;
00085 delete map;
00086 map = next;
00087 }
00088 }
00089
00090 static void
00091 setAttribMap(vray_SpriteAttribMap *&maphead, const GU_Detail *gdp,
00092 const char *pattern)
00093 {
00094 const GA_AttributeDict *dict;
00095 const GA_Attribute *atr;
00096 UT_String name;
00097 vray_SpriteAttribMap *map;
00098 int index = 0;
00099
00100 if (!gdp)
00101 return;
00102
00103 dict = &gdp->pointAttribs();
00104 for (GA_AttributeDict::iterator it = dict->begin(GA_SCOPE_PUBLIC);
00105 !it.atEnd(); ++it)
00106 {
00107 atr = it.attrib();
00108 name = atr->getName();
00109 if (name.multiMatch(pattern) && (atr->getAIFTuple() || atr->getAIFStringTuple()))
00110 {
00111 map = makeMap(gdp, atr);
00112 map->myDIndex = index++;
00113 map->myNext = maphead;
00114 maphead = map;
00115 }
00116 }
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 static VRAY_ProceduralArg theArgs[] = {
00130 VRAY_ProceduralArg("velocity", "string", "v"),
00131 VRAY_ProceduralArg("object", "string", ""),
00132 VRAY_ProceduralArg("attribute", "string", ""),
00133 VRAY_ProceduralArg("chunksize", "int", "16"),
00134 VRAY_ProceduralArg("maxsprites", "int", "1000"),
00135 VRAY_ProceduralArg(),
00136 };
00137
00138
00139 VRAY_Procedural *
00140 allocProcedural(const char *)
00141 {
00142 return new VRAY_DemoSprite();
00143 }
00144
00145
00146 const VRAY_ProceduralArg *
00147 getProceduralArgs(const char *)
00148 {
00149 return theArgs;
00150 }
00151
00152 VRAY_DemoSprite::VRAY_DemoSprite()
00153 {
00154 myBox.initBounds(0, 0, 0);
00155 myVelBox = myBox;
00156 myParms = 0;
00157 }
00158
00159
00160
00161
00162 static void
00163 getRoughSpriteBox(UT_BoundingBox &box, UT_BoundingBox &vbox,
00164 const GEO_Point *point, const UT_Vector3 &sprite_scale,
00165 const GA_ROAttributeRef &voff,
00166 fpreal tscale, const UT_Matrix4 &xform)
00167 {
00168 fpreal maxradius;
00169 static fpreal isin45 = 1.0F / SYSsin(M_PI/4);
00170 UT_Vector3 pt;
00171
00172 maxradius = SYSmax(sprite_scale.x(), sprite_scale.y()) * isin45 * 0.5F;
00173
00174 pt = UT_Vector3(-maxradius, -maxradius, 0)*xform; box.initBounds(pt);
00175 pt = UT_Vector3(-maxradius, maxradius, 0)*xform; box.enlargeBounds(pt);
00176 pt = UT_Vector3( maxradius, -maxradius, 0)*xform; box.enlargeBounds(pt);
00177 pt = UT_Vector3( maxradius, maxradius, 0)*xform; box.enlargeBounds(pt);
00178
00179 box.translate(point->getPos());
00180 vbox = box;
00181
00182 if (voff.isValid())
00183 {
00184 UT_Vector3 vel;
00185 int i;
00186 fpreal amount;
00187
00188 vel = point->getValue<UT_Vector3>(voff);
00189 for (i = 0; i < 3; i++)
00190 {
00191 amount = vel(i) * tscale;
00192 if (amount < 0)
00193 vbox.vals[i][1] -= amount;
00194 else vbox.vals[i][0] -= amount;
00195
00196 }
00197 }
00198 }
00199
00200 static inline void
00201 clampBox(UT_BoundingBox &from, const UT_BoundingBox &to)
00202 {
00203 if (from.vals[0][0] < to.vals[0][0]) from.vals[0][0] = to.vals[0][0];
00204 if (from.vals[1][0] < to.vals[1][0]) from.vals[1][0] = to.vals[1][0];
00205 if (from.vals[2][0] < to.vals[2][0]) from.vals[2][0] = to.vals[2][0];
00206 if (from.vals[0][1] > to.vals[0][1]) from.vals[0][1] = to.vals[0][1];
00207 if (from.vals[1][1] > to.vals[1][1]) from.vals[1][1] = to.vals[1][1];
00208 if (from.vals[2][1] > to.vals[2][1]) from.vals[2][1] = to.vals[2][1];
00209 }
00210
00211 static inline int
00212 testClampBox(const UT_BoundingBox &from, const UT_BoundingBox &to)
00213 {
00214 if (from.vals[0][0] < to.vals[0][0]) return 1;
00215 if (from.vals[1][0] < to.vals[1][0]) return 1;
00216 if (from.vals[2][0] < to.vals[2][0]) return 1;
00217 if (from.vals[0][1] > to.vals[0][1]) return 1;
00218 if (from.vals[1][1] > to.vals[1][1]) return 1;
00219 if (from.vals[2][1] > to.vals[2][1]) return 1;
00220 return 0;
00221 }
00222
00223 int
00224 VRAY_DemoSprite::initChild(VRAY_DemoSprite *sprite, const UT_BoundingBox &box)
00225 {
00226 int i, first, idx;
00227 UT_BoundingBox tbox, tvbox;
00228 const GEO_Point *ppt;
00229 GU_Detail *gdp;
00230 UT_Matrix4 xform;
00231
00232 myParms = sprite->myParms;
00233 myParms->myRefCount++;
00234
00235 gdp = getPointGdp();
00236
00237 UT_Vector3 sprite_scale(0.1, 0.1, 0.1);
00238
00239
00240
00241
00242
00243
00244 myPointList.resize(sprite->myPointList.entries());
00245 for (i = sprite->myPointList.entries(); i-- > 0; )
00246 {
00247 idx = sprite->myPointList(i);
00248 ppt = gdp->points()(idx);
00249 if (box.isInside(ppt->getPos()))
00250 {
00251 myPointList.append(idx);
00252 }
00253 }
00254 myPointList.resize(myPointList.entries());
00255
00256 first = 1;
00257 xform = myParms->myXformInverse;
00258 for (i = myPointList.entries(); i-- > 0; )
00259 {
00260 idx = myPointList(i);
00261 ppt = gdp->points()(idx);
00262
00263 if (myParms->mySpriteScaleOff.isValid())
00264 sprite_scale = ppt->getValue<UT_Vector3>(myParms->mySpriteScaleOff);
00265
00266 getRoughSpriteBox(tbox, tvbox, ppt, sprite_scale,
00267 myParms->myVelOff, myParms->myTimeScale, xform);
00268
00269 if (first)
00270 {
00271 myBox = tbox;
00272 myVelBox = tvbox;
00273 first = 0;
00274 }
00275 else
00276 {
00277 myBox.enlargeBounds(tbox);
00278 myVelBox.enlargeBounds(tvbox);
00279 }
00280 }
00281
00282
00283 if (first)
00284 return 0;
00285 clampBox(myBox, box);
00286 return 1;
00287 }
00288
00289 VRAY_DemoSprite::~VRAY_DemoSprite()
00290 {
00291 myParms->myRefCount--;
00292 if (!myParms->myRefCount)
00293 {
00294 destroyMap(myParms->myAttribMap);
00295 delete myParms;
00296 }
00297 }
00298
00299 const char *
00300 VRAY_DemoSprite::getClassName()
00301 {
00302 return "VRAY_DemoSprite";
00303 }
00304
00305 int
00306 VRAY_DemoSprite::initialize(const UT_BoundingBox *box)
00307 {
00308 void *handle;
00309 const char *name;
00310 GEO_Point *ppt;
00311 int i, first;
00312 UT_BoundingBox tbox, tvbox;
00313 GU_Detail *gdp;
00314 UT_Matrix4 xform;
00315 UT_String str;
00316 int vblur;
00317
00318 myParms = new VRAY_DemoSpriteParms;
00319 myParms->myGdp = 0;
00320 myParms->myVelOff.clear();
00321 myParms->mySpriteScaleOff.clear();
00322 myParms->mySpriteRotOff.clear();
00323 myParms->mySpriteShopOff.clear();
00324 myParms->mySpriteTexOff.clear();
00325 myParms->myChunkSize = MIN_CHUNK * 2;
00326 myParms->mySpriteLimit = SPRITE_LIMIT;
00327 myParms->myRefCount = 1;
00328 myParms->myAttribMap = 0;
00329
00330
00331
00332 name = 0;
00333 if (import("object", str))
00334 name = str.isstring() ? (const char *)str : 0;
00335 handle = queryObject(name);
00336 if (!handle)
00337 {
00338 VRAYerror("%s couldn't find object '%s'", getClassName(), name);
00339 return 0;
00340 }
00341 name = queryObjectName(handle);
00342 gdp = myParms->myGdp = (GU_Detail *)queryGeometry(handle, 0);
00343 if (!gdp)
00344 {
00345 VRAYerror("%s object '%s' has no geometry", getClassName(), name);
00346 return 0;
00347 }
00348
00349
00350
00351 if (!import("object:velocityscale", &myParms->myTimeScale, 1))
00352 myParms->myTimeScale = 0.5F / 24.0F;
00353
00354 vblur = 0;
00355 import("object:velocityblur", &vblur, 0);
00356
00357 myParms->myXformInverse = queryTransform(handle, 0);
00358 myParms->myXformInverse.invert();
00359
00360 myParms->mySpriteScaleOff = gdp->findFloatTuple(GA_ATTRIB_POINT,
00361 "spritescale", 3);
00362 myParms->mySpriteRotOff = gdp->findFloatTuple(GA_ATTRIB_POINT,
00363 "spriterot", 1);
00364 myParms->mySpriteShopOff = gdp->findStringTuple(GA_ATTRIB_POINT,
00365 "spriteshop", 1);
00366 myParms->mySpriteTexOff = gdp->findFloatTuple(GA_ATTRIB_POINT,
00367 "spriteuv", 4);
00368
00369
00370
00371 if (vblur)
00372 {
00373 str = 0;
00374 import("velocity", str);
00375 if (str.isstring())
00376 {
00377 myParms->myVelOff = gdp->findFloatTuple(GA_ATTRIB_POINT, str, 3);
00378 if (myParms->myVelOff.isInvalid())
00379 VRAYwarning("%s object (%s) couldn't find the '%s' attribute",
00380 getClassName(), name, (const char *)str);
00381 }
00382 }
00383
00384 UT_Vector3 sprite_scale(0.1, 0.1, 0.1);
00385
00386 first = 1;
00387 xform = myParms->myXformInverse;
00388 for (i = gdp->points().entries(); i-- > 0; )
00389 {
00390 ppt = gdp->points()(i);
00391 if (myParms->mySpriteScaleOff.isValid())
00392 sprite_scale = ppt->getValue<UT_Vector3>(myParms->mySpriteScaleOff);
00393
00394 getRoughSpriteBox(tbox, tvbox, ppt, sprite_scale,
00395 myParms->myVelOff, myParms->myTimeScale, xform);
00396 myPointList.append(i);
00397 if (first)
00398 {
00399 myBox = tbox;
00400 myVelBox = tvbox;
00401 first = 0;
00402 }
00403 else
00404 {
00405 myBox.enlargeBounds(tbox);
00406 myVelBox.enlargeBounds(tvbox);
00407 }
00408 }
00409 if (first)
00410 {
00411 VRAYwarning("%s found no points in %s", getClassName(), name);
00412 return 0;
00413 }
00414 if (!myPointList.entries())
00415 return 0;
00416
00417 str = 0;
00418 import("attribute", str);
00419 if (str.isstring())
00420 setAttribMap(myParms->myAttribMap, gdp, str);
00421 import("chunksize", &myParms->myChunkSize, 1);
00422 if (myParms->myChunkSize < MIN_CHUNK)
00423 myParms->myChunkSize = MIN_CHUNK;
00424 import("maxsprites", &myParms->mySpriteLimit, 1);
00425 if (myParms->mySpriteLimit < SPRITE_LIMIT)
00426 myParms->mySpriteLimit = SPRITE_LIMIT;
00427
00428 if (box)
00429 {
00430 if (myParms->myVelOff.isValid())
00431 {
00432 if (testClampBox(myBox, *box) || testClampBox(myVelBox, *box))
00433 VRAYwarning("%s[%s] cannot render a partial box %s",
00434 getClassName(), name, "with motion blur");
00435 }
00436 else
00437 {
00438 clampBox(myBox, *box);
00439 clampBox(myVelBox, *box);
00440 }
00441 }
00442
00443 return 1;
00444 }
00445
00446 void
00447 VRAY_DemoSprite::getBoundingBox(UT_BoundingBox &box)
00448 {
00449
00450 box = myVelBox;
00451 }
00452
00453 #define DEFAULT_SIZE 0.05F
00454
00455 #define SPRITE_SIZE(xsize, ysize, size) \
00456 { xsize = src_point->getValue<float>(parms.mySpriteScaleOff, 0) * 0.5F; \
00457 ysize = src_point->getValue<float>(parms.mySpriteScaleOff, 1) * 0.5F; }
00458
00459 #define SPRITE_TEXTURE(u1, v1, u2, v2, txt) \
00460 { UT_Vector3 txt = src_point->getValue<UT_Vector3>(parms.mySpriteTexOff); \
00461 u1 = txt.x(); v1 = txt.y(); u2 = txt.x()+txt.z(); v2 = txt.y()+txt.z(); }
00462
00463 #define ASSIGN_VERTEX(poly, ppt, i, XDELTA, YDELTA, u, v) \
00464 ppt = poly->getVertex(i).getPt(); \
00465 ppt->getPos() = src_point->getPos(); \
00466 ppt->getPos().x() XDELTA; ppt->getPos().y() YDELTA; \
00467 if (txt_off >= 0) \
00468 ppt->setValue<UT_Vector3>(txt_off, UT_Vector3(u, v, 0));
00469
00470 static void
00471 applyMapToPrimitive(vray_SpriteAttribMap *map,
00472 const UT_RefArray<GA_RWAttributeRef> &dest_offsets,
00473 GEO_Primitive *dest, const GEO_Point *src_point)
00474 {
00475 float float_buffer[128];
00476 float *abuf = NULL;
00477 float *fdata;
00478 int asize = 0;
00479 int i;
00480
00481 while (map)
00482 {
00483 UT_ASSERT(map->myAttrib);
00484
00485 const GA_AIFTuple *tuple = map->myAttrib->getAIFTuple();
00486 const GA_AIFStringTuple *stuple = map->myAttrib->getAIFStringTuple();
00487 const int tuple_size = map->myAttrib->getTupleSize();
00488
00489
00490
00491 if (stuple)
00492 {
00493 for (i = 0; i < tuple_size; ++i)
00494 {
00495 const char *str = src_point->getString(map->myOffset, i);
00496 dest->setString(dest_offsets(map->myDIndex), str, i);
00497 }
00498 }
00499 else if (tuple)
00500 {
00501
00502
00503 if (tuple_size <= 128)
00504 fdata = float_buffer;
00505 else
00506 {
00507 if (tuple_size > asize)
00508 {
00509 delete [] abuf;
00510 asize = tuple_size + 1024;
00511 abuf = new float[asize];
00512 }
00513
00514 fdata = abuf;
00515 }
00516
00517 src_point->get<float>(map->myOffset, fdata, tuple_size);
00518 dest->set<float>(dest_offsets(map->myDIndex), fdata, tuple_size);
00519 }
00520
00521 map = map->myNext;
00522 }
00523
00524 delete [] abuf;
00525 }
00526
00527 static void
00528 transformPoint(GEO_Point *ppt, fpreal dx, fpreal dy, const UT_Matrix4 &xform)
00529 {
00530 UT_Vector4 P = ppt->getPos();
00531 P.x() += dx;
00532 P.y() += dy;
00533 P *= xform;
00534 ppt->setPos(P);
00535 }
00536
00537 static void
00538 convertPath(const char *src_path, const char *path, UT_String &full_path)
00539 {
00540 if (path && strlen(path) > 0 && path[0] != '/')
00541 {
00542 full_path = src_path;
00543 full_path += "/";
00544 full_path += path;
00545 full_path.collapseAbsolutePath();
00546 }
00547 else
00548 full_path = path;
00549 }
00550
00551 static int
00552 makeSpritePoly(GU_Detail *gdp, GU_Detail *src, UT_IntArray &points,
00553 const VRAY_DemoSpriteParms &parms, const char *srcpath)
00554 {
00555 int i;
00556 GA_RWAttributeRef shop_off;
00557 GA_RWAttributeRef txt_off;
00558 fpreal xSize = DEFAULT_SIZE;
00559 fpreal ySize = DEFAULT_SIZE;
00560 fpreal uMin = 0.0F;
00561 fpreal vMin = 0.0F;
00562 fpreal uMax = 1.0F;
00563 fpreal vMax = 1.0F;
00564 GU_PrimPoly *poly;
00565 const GEO_Point *src_point;
00566 GEO_Point *ppt;
00567 UT_Matrix4 xform;
00568 UT_Matrix4 view_inverse;
00569 UT_RefArray<GA_RWAttributeRef> dest_offsets;
00570 static int num_polys = 0;
00571
00572 view_inverse = parms.myXformInverse;
00573
00574 if (points.entries())
00575 {
00576 if (parms.mySpriteShopOff.isValid())
00577 {
00578 shop_off = gdp->addStringTuple(
00579 GA_ATTRIB_PRIMITIVE, "shop_vm_surface", 1);
00580
00581 if (parms.mySpriteTexOff.isValid())
00582 {
00583 txt_off = gdp->addTextureAttribute(GEO_POINT_DICT);
00584 }
00585 }
00586
00587
00588 if (parms.myAttribMap)
00589 {
00590 vray_SpriteAttribMap *map;
00591 const GA_Attribute *atr;
00592
00593 dest_offsets.resize(parms.myAttribMap->myDIndex+1);
00594 dest_offsets.entries(parms.myAttribMap->myDIndex+1);
00595
00596 for (map = parms.myAttribMap; map; map = map->myNext)
00597 {
00598 atr = map->myAttrib;
00599 dest_offsets(map->myDIndex) = gdp->addPrimAttrib(atr);
00600 UT_ASSERT(dest_offsets(map->myDIndex).isValid());
00601 }
00602 }
00603 }
00604
00605
00606
00607
00608
00609 for (i = 0; i < points.entries(); i++)
00610 {
00611 poly = GU_PrimPoly::build(gdp, 4, GU_POLY_CLOSED, 1);
00612
00613 src_point = src->points()(points(i));
00614 if (parms.mySpriteScaleOff.isValid())
00615 {
00616 SPRITE_SIZE(xSize, ySize, ssize);
00617 }
00618 if (parms.mySpriteTexOff.isValid())
00619 {
00620 SPRITE_TEXTURE(uMin, vMin, uMax, vMax, txt);
00621 }
00622
00623 xform.identity();
00624 xform.translate(src_point->getPos().x(),
00625 src_point->getPos().y(),
00626 src_point->getPos().z());
00627
00628 xform.leftMult(view_inverse);
00629 if (parms.mySpriteRotOff.isValid())
00630 xform.prerotate(UT_Axis3::ZAXIS, UTdegToRad(
00631 src_point->getValue<float>(parms.mySpriteRotOff)));
00632
00633 ppt = poly->getVertexElement(2).getPt();
00634
00635 ::transformPoint(ppt, xSize, ySize, xform);
00636 if (txt_off.isValid())
00637 {
00638 ppt->setValue<UT_Vector3>(txt_off, UT_Vector3(uMax, vMax, 0));
00639 }
00640
00641 ppt = poly->getVertexElement(3).getPt();
00642
00643 ::transformPoint(ppt, -xSize, ySize, xform);
00644 if (txt_off.isValid())
00645 {
00646 ppt->setValue<UT_Vector3>(txt_off, UT_Vector3(uMin, vMax, 0));
00647 }
00648
00649 ppt = poly->getVertexElement(0).getPt();
00650
00651 ::transformPoint(ppt, -xSize, -ySize, xform);
00652 if (txt_off.isValid())
00653 {
00654 ppt->setValue<UT_Vector3>(txt_off, UT_Vector3(uMin, vMin, 0));
00655 }
00656
00657 ppt = poly->getVertexElement(1).getPt();
00658
00659 ::transformPoint(ppt, xSize, -ySize, xform);
00660 if (txt_off.isValid())
00661 {
00662 ppt->setValue<UT_Vector3>(txt_off, UT_Vector3(uMax, vMin, 0));
00663 }
00664
00665 if (shop_off.isValid())
00666 {
00667 UT_String full_path;
00668 const char *path;
00669
00670 path = src_point->getString(parms.mySpriteShopOff);
00671 convertPath(srcpath, path, full_path);
00672 poly->setString(shop_off, full_path.buffer());
00673 }
00674
00675
00676 if (parms.myAttribMap)
00677 applyMapToPrimitive(parms.myAttribMap, dest_offsets,
00678 (GEO_Primitive *)poly->castToGeo(), src_point);
00679 }
00680 num_polys += gdp->primitives().entries();
00681
00682
00683 return gdp->primitives().entries();
00684 }
00685
00686 static void
00687 velocityMove(GU_Detail *gdp2, GU_Detail *gdp1, GU_Detail *src,
00688 const UT_IntArray &points, const GA_ROAttributeRef &off,
00689 fpreal scale)
00690 {
00691 int i;
00692 GEO_Point *ppt;
00693 const GEO_Point *spt;
00694 UT_Vector3 vel;
00695
00696 gdp2->merge(*gdp1);
00697 for (i = points.entries(); i-- > 0;)
00698 {
00699 spt = src->points()(points(i));
00700 vel = spt->getValue<UT_Vector3>(off);
00701 vel *= scale;
00702
00703 ppt = gdp2->points()(i*4);
00704 ppt->setPos(ppt->getPos() + vel);
00705 ppt = gdp2->points()(i*4+1);
00706 ppt->setPos(ppt->getPos() + vel);
00707 ppt = gdp2->points()(i*4+2);
00708 ppt->setPos(ppt->getPos() + vel);
00709 ppt = gdp2->points()(i*4+3);
00710 ppt->setPos(ppt->getPos() + vel);
00711 }
00712 }
00713
00714 static inline int
00715 computeDivs(fpreal inc, fpreal min)
00716 {
00717 int divs = (int)SYSceil(inc / min);
00718 if (divs < 1) divs = 1;
00719 else if (divs > 4) divs = 4;
00720 return divs;
00721 }
00722
00723 void
00724 VRAY_DemoSprite::render()
00725 {
00726 GU_Detail *gdp, *vgdp;
00727 fpreal max;
00728 UT_BoundingBox kidbox;
00729 VRAY_DemoSprite *kid;
00730 int dogeo;
00731 int nx, ny, nz;
00732 int ix, iy, iz;
00733 fpreal xinc, yinc, zinc, factor;
00734 fpreal xv, yv, zv;
00735 fpreal dfactor;
00736 int sprite_limit = myParms->mySpriteLimit;
00737 fpreal lod;
00738
00739 dogeo = 1;
00740
00741 lod = getLevelOfDetail(myBox);
00742 if (lod > myParms->myChunkSize && myPointList.entries() > sprite_limit)
00743 {
00744
00745 dogeo = 0;
00746 xinc = myBox.sizeX();
00747 yinc = myBox.sizeY();
00748 zinc = myBox.sizeZ();
00749
00750 max = myBox.sizeMax();
00751 dfactor = (xinc+yinc+zinc)/max;
00752 factor = SYSpow((fpreal)myPointList.entries() / sprite_limit,
00753 1.0F/dfactor);
00754 if (factor > 4)
00755 factor = 4;
00756 max /= factor;
00757
00758
00759
00760
00761 nx = ::computeDivs(xinc, max);
00762 ny = ::computeDivs(yinc, max);
00763 nz = ::computeDivs(zinc, max);
00764
00765 if (nx == 1 && ny == 1 && nz == 1)
00766 {
00767 if (xinc > yinc)
00768 {
00769 if (xinc > zinc) nx = 2;
00770 else nz = 2;
00771 }
00772 else
00773 {
00774 if (yinc > zinc) ny = 2;
00775 else nz = 2;
00776 }
00777 }
00778 xinc /= (fpreal)nx;
00779 yinc /= (fpreal)ny;
00780 zinc /= (fpreal)nz;
00781
00782
00783 for (iz = 0, zv = myBox.vals[2][0]; iz < nz; iz++, zv += zinc)
00784 {
00785 for (iy = 0, yv = myBox.vals[1][0]; iy < ny; iy++, yv += yinc)
00786 {
00787 for (ix = 0, xv = myBox.vals[0][0]; ix < nx; ix++, xv += xinc)
00788 {
00789 kidbox.initBounds(xv, yv, zv);
00790 kidbox.enlargeBounds(xv+xinc, yv+yinc, zv+zinc);
00791 kid = new VRAY_DemoSprite();
00792 if (!kid->initChild(this, kidbox))
00793 delete kid;
00794 else
00795 {
00796 if (openProceduralObject())
00797 {
00798 addProcedural(kid);
00799 closeObject();
00800 }
00801 else
00802 {
00803 dogeo = 1;
00804 break;
00805 }
00806 }
00807 }
00808 if (dogeo) break;
00809 }
00810 if (dogeo) break;
00811 }
00812 }
00813
00814 if (dogeo)
00815 {
00816 if (lod < 3) lod = 3;
00817 gdp = allocateGeometry();
00818
00819
00820
00821
00822
00823
00824 if (!makeSpritePoly(gdp, getPointGdp(), myPointList, *myParms,
00825 queryRootName()))
00826 freeGeometry(gdp);
00827 else
00828 {
00829 if (myParms->myVelOff.isValid())
00830 {
00831 vgdp = allocateGeometry();
00832 velocityMove(vgdp, gdp, getPointGdp(), myPointList,
00833 myParms->myVelOff, getTime());
00834 }
00835 else vgdp = 0;
00836 openGeometryObject();
00837 addGeometry(gdp, 0);
00838 if (vgdp)
00839 {
00840 addGeometry(vgdp, 1);
00841 }
00842 closeObject();
00843 }
00844 }
00845 }