00001
00002
00003 #include <yafraycore/kdtree.h>
00004 #include <core_api/material.h>
00005 #include <core_api/scene.h>
00006 #include <stdexcept>
00007
00008 #include <limits>
00009 #include <set>
00010 #if ( HAVE_PTHREAD && defined (__GNUC__) )
00011 #include <ext/mt_allocator.h>
00012 #endif
00013 #include <time.h>
00014
00015 __BEGIN_YAFRAY
00016
00017 #define LOWER_B 0
00018 #define UPPER_B 2
00019 #define BOTH_B 1
00020
00021 #define _TRI_CLIP 1 //tempoarily disabled
00022 #define TRI_CLIP_THRESH 32
00023 #define CLIP_DATA_SIZE (3*12*sizeof(double))
00024 #define KD_BINS 1024
00025
00026 #define KD_MAX_STACK 64
00027
00028
00029
00030
00031 #if (defined(_M_IX86) || defined(i386) || defined(_X86_))
00032 #define Y_FAST_INT 1
00033 #else
00034 #define Y_FAST_INT 0
00035 #endif
00036
00037 #define _doublemagicroundeps (0.5 - 1.4e-11)
00038
00039 inline int Y_Round2Int(double val) {
00040 #if Y_FAST_INT > 0
00041 union { double f; int i[2]; } u;
00042 u.f = val + 6755399441055744.0;
00043 return u.i[0];
00044 #else
00045 return int(val);
00046 #endif
00047 }
00048
00049 inline int Y_Float2Int(double val) {
00050 #if Y_FAST_INT > 0
00051 return (val<0) ? Y_Round2Int( val+_doublemagicroundeps ) :
00052 Y_Round2Int(val-_doublemagicroundeps);
00053 #else
00054 return (int)val;
00055 #endif
00056 }
00057
00058 int Kd_inodes=0, Kd_leaves=0, _emptyKd_leaves=0, Kd_prims=0, _clip=0, _bad_clip=0, _null_clip=0, _early_out=0;
00059
00060
00061
00062
00063
00064 triKdTree_t::triKdTree_t(const triangle_t **v, int np, int depth, int leafSize,
00065 float cost_ratio, float emptyBonus)
00066 : costRatio(cost_ratio), eBonus(emptyBonus), maxDepth(depth)
00067 {
00068 std::cout << "starting build of kd-tree ("<<np<<" prims, cr:"<<costRatio<<" eb:"<<eBonus<<")\n";
00069 clock_t c_start, c_end;
00070 c_start = clock();
00071 Kd_inodes=0, Kd_leaves=0, _emptyKd_leaves=0, Kd_prims=0, depthLimitReached=0, NumBadSplits=0,
00072 _clip=0, _bad_clip=0, _null_clip=0, _early_out=0;
00073 totalPrims = np;
00074 nextFreeNode = 0;
00075 allocatedNodesCount = 256;
00076 nodes = (kdTreeNode*)y_memalign(64, 256 * sizeof(kdTreeNode));
00077 if(maxDepth <= 0) maxDepth = int( 7.0f + 1.66f * log(float(totalPrims)) );
00078 double logLeaves = 1.442695f * log(double(totalPrims));
00079 if(leafSize <= 0)
00080 {
00081
00082 int mls = int( logLeaves - 16.0 );
00083 if(mls <= 0) mls = 1;
00084 maxLeafSize = (unsigned int) mls;
00085 }
00086 else maxLeafSize = (unsigned int) leafSize;
00087 if(maxDepth>KD_MAX_STACK) maxDepth = KD_MAX_STACK;
00088
00089 if( logLeaves > 16.0 ) costRatio += 0.25*( logLeaves - 16.0 );
00090 allBounds = new bound_t[totalPrims + TRI_CLIP_THRESH+1];
00091 std::cout << "getting triangle bounds...";
00092 for(u_int32 i=0; i<totalPrims; i++)
00093 {
00094 allBounds[i] = v[i]->getBound();
00095
00096 if(i) treeBound = bound_t(treeBound, allBounds[i]);
00097 else treeBound = allBounds[i];
00098 }
00099
00100
00101 for(int i=0;i<3;i++)
00102 {
00103 double foo = (treeBound.g[i] - treeBound.a[i])*0.001;
00104 treeBound.a[i] -= foo, treeBound.g[i] += foo;
00105 }
00106 std::cout << "done!\n";
00107
00108 boundEdge *edges[3];
00109 u_int32 rMemSize = 3*totalPrims;
00110 u_int32 *leftPrims = new u_int32[std::max( (u_int32)2*TRI_CLIP_THRESH, totalPrims )];
00111 u_int32 *rightPrims = new u_int32[rMemSize];
00112
00113 for (int i = 0; i < 3; ++i) edges[i] = new boundEdge[514];
00114 clip = new int[maxDepth+2];
00115 cdata = (char*)y_memalign(64, (maxDepth+2)*TRI_CLIP_THRESH*CLIP_DATA_SIZE);
00116
00117
00118 for (u_int32 i = 0; i < totalPrims; i++) leftPrims[i] = i;
00119 for (int i = 0; i < maxDepth+2; i++) clip[i] = -1;
00120
00121
00122 prims = v;
00123 std::cout << "starting recursive build...\n";
00124 buildTree(totalPrims, treeBound, leftPrims,
00125 leftPrims, rightPrims, edges,
00126 rMemSize, 0, 0 );
00127
00128
00129 delete[] leftPrims;
00130 delete[] rightPrims;
00131 delete[] allBounds;
00132 for (int i = 0; i < 3; ++i) delete[] edges[i];
00133 delete[] clip;
00134 y_free(cdata);
00135
00136 c_end = clock() - c_start;
00137 std::cout << "\n=== kd-tree stats ("<< float(c_end) / (float)CLOCKS_PER_SEC <<"s) ===\n";
00138 std::cout << "used/allocated kd-tree nodes: " << nextFreeNode << "/" << allocatedNodesCount
00139 << " (" << 100.f * float(nextFreeNode)/allocatedNodesCount << "%)\n";
00140 std::cout << "primitives in tree: " << totalPrims << std::endl;
00141 std::cout << "interior nodes: " << Kd_inodes << " / " << "leaf nodes: " << Kd_leaves
00142 << " (empty: " << _emptyKd_leaves << " = " << 100.f * float(_emptyKd_leaves)/Kd_leaves << "%)\n";
00143 std::cout << "leaf prims: " << Kd_prims << " (" << float(Kd_prims)/totalPrims << "x prims in tree, leaf size:"<< maxLeafSize<<")\n";
00144 std::cout << " => " << float(Kd_prims)/ (Kd_leaves-_emptyKd_leaves) << " prims per non-empty leaf\n";
00145 std::cout << "leaves due to depth limit/bad splits: " << depthLimitReached << "/" << NumBadSplits << "\n";
00146 std::cout << "clipped triangles: " << _clip << " (" <<_bad_clip << " bad clips, "<<_null_clip
00147 <<" null clips)\n";
00148
00149 }
00150
00151 triKdTree_t::~triKdTree_t()
00152 {
00153
00154 y_free(nodes);
00155
00156
00157 }
00158
00159
00166 void triKdTree_t::pigeonMinCost(u_int32 nPrims, bound_t &nodeBound, u_int32 *primIdx, splitCost_t &split)
00167 {
00168 bin_t bin[ KD_BINS+1 ];
00169 PFLOAT d[3];
00170 d[0] = nodeBound.longX();
00171 d[1] = nodeBound.longY();
00172 d[2] = nodeBound.longZ();
00173 split.oldCost = float(nPrims);
00174 split.bestCost = std::numeric_limits<PFLOAT>::infinity();
00175 float invTotalSA = 1.0f / (d[0]*d[1] + d[0]*d[2] + d[1]*d[2]);
00176 PFLOAT t_low, t_up;
00177 int b_left, b_right;
00178
00179 for(int axis=0;axis<3;axis++)
00180 {
00181 PFLOAT s = KD_BINS/d[axis];
00182 PFLOAT min = nodeBound.a[axis];
00183
00184 for(unsigned int i=0; i<nPrims; ++i)
00185 {
00186 const bound_t &bbox = allBounds[ primIdx[i] ];
00187 t_low = bbox.a[axis];
00188 t_up = bbox.g[axis];
00189 b_left = (int)((t_low - min)*s);
00190 b_right = (int)((t_up - min)*s);
00191
00192
00193 if(b_left<0) b_left=0; else if(b_left > KD_BINS) b_left = KD_BINS;
00194 if(b_right<0) b_right=0; else if(b_right > KD_BINS) b_right = KD_BINS;
00195
00196 if(t_low == t_up)
00197 {
00198 if(bin[b_left].empty() || (t_low >= bin[b_left].t && !bin[b_left].empty() ) )
00199 {
00200 bin[b_left].t = t_low;
00201 bin[b_left].c_both++;
00202 }
00203 else
00204 {
00205 bin[b_left].c_left++;
00206 bin[b_left].c_right++;
00207 }
00208 bin[b_left].n += 2;
00209 }
00210 else
00211 {
00212 if(bin[b_left].empty() || (t_low > bin[b_left].t && !bin[b_left].empty() ) )
00213 {
00214 bin[b_left].t = t_low;
00215 bin[b_left].c_left += bin[b_left].c_both + bin[b_left].c_bleft;
00216 bin[b_left].c_right += bin[b_left].c_both;
00217 bin[b_left].c_both = bin[b_left].c_bleft = 0;
00218 bin[b_left].c_bleft++;
00219 }
00220 else if(t_low == bin[b_left].t)
00221 {
00222 bin[b_left].c_bleft++;
00223 }
00224 else bin[b_left].c_left++;
00225 bin[b_left].n++;
00226
00227 bin[b_right].c_right++;
00228 if(bin[b_right].empty() || t_up > bin[b_right].t)
00229 {
00230 bin[b_right].t = t_up;
00231 bin[b_right].c_left += bin[b_right].c_both + bin[b_right].c_bleft;
00232 bin[b_right].c_right += bin[b_right].c_both;
00233 bin[b_right].c_both = bin[b_right].c_bleft = 0;
00234 }
00235 bin[b_right].n++;
00236 }
00237
00238 }
00239
00240 const int axisLUT[3][3] = { {0,1,2}, {1,2,0}, {2,0,1} };
00241 float capArea = d[ axisLUT[1][axis] ] * d[ axisLUT[2][axis] ];
00242 float capPerim = d[ axisLUT[1][axis] ] + d[ axisLUT[2][axis] ];
00243
00244 unsigned int nBelow=0, nAbove=nPrims;
00245
00246 for(int i=0; i<KD_BINS+1; ++i)
00247 {
00248 if(!bin[i].empty())
00249 {
00250 nBelow += bin[i].c_left;
00251 nAbove -= bin[i].c_right;
00252
00253 PFLOAT edget = bin[i].t;
00254 if (edget > nodeBound.a[axis] &&
00255 edget < nodeBound.g[axis]) {
00256
00257 float l1 = edget - nodeBound.a[axis];
00258 float l2 = nodeBound.g[axis] - edget;
00259 float belowSA = capArea + l1*capPerim;
00260 float aboveSA = capArea + l2*capPerim;
00261 float rawCosts = (belowSA * nBelow + aboveSA * nAbove);
00262
00263 float eb;
00264 if(nAbove == 0) eb = (0.1f + l2/d[axis])*eBonus*rawCosts;
00265 else if(nBelow == 0) eb = (0.1f + l1/d[axis])*eBonus*rawCosts;
00266 else eb = 0.0f;
00267 float cost = costRatio + invTotalSA * (rawCosts - eb);
00268
00269 if (cost < split.bestCost) {
00270 split.t = edget;
00271 split.bestCost = cost;
00272 split.bestAxis = axis;
00273 split.bestOffset = i;
00274 split.nBelow = nBelow;
00275 split.nAbove = nAbove;
00276 }
00277 }
00278 nBelow += bin[i].c_both + bin[i].c_bleft;
00279 nAbove -= bin[i].c_both;
00280 }
00281 }
00282 if(nBelow != nPrims || nAbove != 0)
00283 {
00284 int c1=0, c2=0, c3=0, c4=0, c5=0;
00285 std::cout << "SCREWED!!\n";
00286 for(int i=0;i<KD_BINS+1;i++){ c1+= bin[i].n; std::cout << bin[i].n << " ";}
00287 std::cout << "\nn total: "<< c1 << "\n";
00288 for(int i=0;i<KD_BINS+1;i++){ c2+= bin[i].c_left; std::cout << bin[i].c_left << " ";}
00289 std::cout << "\nc_left total: "<< c2 << "\n";
00290 for(int i=0;i<KD_BINS+1;i++){ c3+= bin[i].c_bleft; std::cout << bin[i].c_bleft << " ";}
00291 std::cout << "\nc_bleft total: "<< c3 << "\n";
00292 for(int i=0;i<KD_BINS+1;i++){ c4+= bin[i].c_both; std::cout << bin[i].c_both << " ";}
00293 std::cout << "\nc_both total: "<< c4 << "\n";
00294 for(int i=0;i<KD_BINS+1;i++){ c5+= bin[i].c_right; std::cout << bin[i].c_right << " ";}
00295 std::cout << "\nc_right total: "<< c5 << "\n";
00296 std::cout << "\nnPrims: "<<nPrims<<" nBelow: "<<nBelow<<" nAbove: "<<nAbove<<"\n";
00297 std::cout << "total left: " << c2 + c3 + c4 << "\ntotal right: " << c4 + c5 << "\n";
00298 std::cout << "n/2: " << c1/2 << "\n";
00299 throw std::logic_error("cost function mismatch");
00300 }
00301 for(int i=0;i<KD_BINS+1;i++) bin[i].reset();
00302 }
00303 }
00304
00305
00310 void triKdTree_t::minimalCost(u_int32 nPrims, bound_t &nodeBound, u_int32 *primIdx,
00311 const bound_t *pBounds, boundEdge *edges[3], splitCost_t &split)
00312 {
00313 PFLOAT d[3];
00314 d[0] = nodeBound.longX();
00315 d[1] = nodeBound.longY();
00316 d[2] = nodeBound.longZ();
00317 split.oldCost = float(nPrims);
00318 split.bestCost = std::numeric_limits<PFLOAT>::infinity();
00319 float invTotalSA = 1.0f / (d[0]*d[1] + d[0]*d[2] + d[1]*d[2]);
00320 int nEdge;
00321
00322 for(int axis=0;axis<3;axis++)
00323 {
00324
00325 int pn;
00326 nEdge=0;
00327
00328 if(pBounds!=allBounds) for (unsigned int i=0; i < nPrims; i++)
00329 {
00330 pn = primIdx[i];
00331 const bound_t &bbox = pBounds[i];
00332 if(bbox.a[axis] == bbox.g[axis])
00333 {
00334 edges[axis][nEdge] = boundEdge(bbox.a[axis], i , BOTH_B);
00335 ++nEdge;
00336 }
00337 else
00338 {
00339 edges[axis][nEdge] = boundEdge(bbox.a[axis], i , LOWER_B);
00340 edges[axis][nEdge+1] = boundEdge(bbox.g[axis], i , UPPER_B);
00341 nEdge += 2;
00342 }
00343 }
00344 else for (unsigned int i=0; i < nPrims; i++)
00345 {
00346 pn = primIdx[i];
00347 const bound_t &bbox = pBounds[pn];
00348 if(bbox.a[axis] == bbox.g[axis])
00349 {
00350 edges[axis][nEdge] = boundEdge(bbox.a[axis], pn, BOTH_B);
00351 ++nEdge;
00352 }
00353 else
00354 {
00355 edges[axis][nEdge] = boundEdge(bbox.a[axis], pn, LOWER_B);
00356 edges[axis][nEdge+1] = boundEdge(bbox.g[axis], pn, UPPER_B);
00357 nEdge += 2;
00358 }
00359 }
00360 std::sort(&edges[axis][0], &edges[axis][nEdge]);
00361
00362 const int axisLUT[3][3] = { {0,1,2}, {1,2,0}, {2,0,1} };
00363 float capArea = d[ axisLUT[1][axis] ] * d[ axisLUT[2][axis] ];
00364 float capPerim = d[ axisLUT[1][axis] ] + d[ axisLUT[2][axis] ];
00365 unsigned int nBelow = 0, nAbove = nPrims;
00366
00367 if(nPrims>5)
00368 {
00369 PFLOAT edget = edges[axis][0].pos;
00370 float l1 = edget - nodeBound.a[axis];
00371 float l2 = nodeBound.g[axis] - edget;
00372 if(l1 > l2*float(nPrims) && l2 > 0.f)
00373 {
00374 float rawCosts = (capArea + l2*capPerim) * nPrims;
00375 float cost = costRatio + invTotalSA * (rawCosts - eBonus);
00376
00377 if (cost < split.bestCost) {
00378 split.bestCost = cost;
00379 split.bestAxis = axis;
00380 split.bestOffset = 0;
00381 split.nEdge = nEdge;
00382 ++_early_out;
00383 }
00384 continue;
00385 }
00386 edget = edges[axis][nEdge-1].pos;
00387 l1 = edget - nodeBound.a[axis];
00388 l2 = nodeBound.g[axis] - edget;
00389 if(l2 > l1*float(nPrims) && l1 > 0.f)
00390 {
00391 float rawCosts = (capArea + l1*capPerim) * nPrims;
00392 float cost = costRatio + invTotalSA * (rawCosts - eBonus);
00393 if (cost < split.bestCost) {
00394 split.bestCost = cost;
00395 split.bestAxis = axis;
00396 split.bestOffset = nEdge-1;
00397 split.nEdge = nEdge;
00398 ++_early_out;
00399 }
00400 continue;
00401 }
00402 }
00403
00404 for (int i = 0; i < nEdge; ++i) {
00405 if (edges[axis][i].end == UPPER_B) --nAbove;
00406 PFLOAT edget = edges[axis][i].pos;
00407 if (edget > nodeBound.a[axis] &&
00408 edget < nodeBound.g[axis]) {
00409
00410 float l1 = edget - nodeBound.a[axis];
00411 float l2 = nodeBound.g[axis] - edget;
00412 float belowSA = capArea + (l1)*capPerim;
00413 float aboveSA = capArea + (l2)*capPerim;
00414 float rawCosts = (belowSA * nBelow + aboveSA * nAbove);
00415
00416 float eb;
00417 if(nAbove == 0) eb = (0.1f + l2/d[axis])*eBonus*rawCosts;
00418 else if(nBelow == 0) eb = (0.1f + l1/d[axis])*eBonus*rawCosts;
00419 else eb = 0.0f;
00420 float cost = costRatio + invTotalSA * (rawCosts - eb);
00421
00422 if (cost < split.bestCost) {
00423 split.bestCost = cost;
00424 split.bestAxis = axis;
00425 split.bestOffset = i;
00426 split.nEdge = nEdge;
00427
00428 split.nBelow = nBelow;
00429 split.nAbove = nAbove;
00430 }
00431 }
00432 if (edges[axis][i].end != UPPER_B)
00433 {
00434 ++nBelow;
00435 if (edges[axis][i].end == BOTH_B) --nAbove;
00436 }
00437 }
00438 if(nBelow != nPrims || nAbove != 0) std::cout << "you screwed your new idea!\n";
00439
00440 }
00441 }
00442
00443
00451 int triKdTree_t::buildTree(u_int32 nPrims, bound_t &nodeBound, u_int32 *primNums,
00452 u_int32 *leftPrims, u_int32 *rightPrims, boundEdge *edges[3],
00453 u_int32 rightMemSize, int depth, int badRefines )
00454 {
00455
00456 if (nextFreeNode == allocatedNodesCount) {
00457 int newCount = 2*allocatedNodesCount;
00458 newCount = (newCount > 0x100000) ? allocatedNodesCount+0x80000 : newCount;
00459 kdTreeNode *n = (kdTreeNode *) y_memalign(64, newCount * sizeof(kdTreeNode));
00460 memcpy(n, nodes, allocatedNodesCount * sizeof(kdTreeNode));
00461 y_free(nodes);
00462 nodes = n;
00463 allocatedNodesCount = newCount;
00464 }
00465
00466 #if _TRI_CLIP > 0
00467 if(nPrims <= TRI_CLIP_THRESH)
00468 {
00469
00470 int oPrims[TRI_CLIP_THRESH], nOverl=0;
00471 double bHalfSize[3];
00472 double b_ext[2][3];
00473 for(int i=0; i<3; ++i)
00474 {
00475
00476 bHalfSize[i] = ((double)nodeBound.g[i] - (double)nodeBound.a[i]);
00477 double temp = ((double)treeBound.g[i] - (double)treeBound.a[i]);
00478 b_ext[0][i] = nodeBound.a[i] - 0.021*bHalfSize[i] - 0.00001*temp;
00479 b_ext[1][i] = nodeBound.g[i] + 0.021*bHalfSize[i] + 0.00001*temp;
00480
00481 }
00482 char *c_old = cdata + (TRI_CLIP_THRESH * CLIP_DATA_SIZE * depth);
00483 char *c_new = cdata + (TRI_CLIP_THRESH * CLIP_DATA_SIZE * (depth+1));
00484 for(unsigned int i=0; i<nPrims; ++i)
00485 {
00486 const triangle_t *ct = prims[ primNums[i] ];
00487 u_int32 old_idx=0;
00488 if(clip[depth] >= 0) old_idx = primNums[i+nPrims];
00489
00490
00491 if( ct->clipToBound(b_ext, clip[depth], allBounds[totalPrims+nOverl],
00492 c_old + old_idx*CLIP_DATA_SIZE, c_new + nOverl*CLIP_DATA_SIZE) )
00493 {
00494 ++_clip;
00495 oPrims[nOverl] = primNums[i]; nOverl++;
00496 }
00497 else ++_null_clip;
00498 }
00499
00500 memcpy(primNums, oPrims, nOverl*sizeof(u_int32));
00501 nPrims = nOverl;
00502 }
00503 #endif
00504
00505 if(nPrims <= maxLeafSize || depth >= maxDepth)
00506 {
00507
00508 nodes[nextFreeNode].createLeaf(primNums, nPrims, prims, primsArena);
00509 nextFreeNode++;
00510 if( depth >= maxDepth ) depthLimitReached++;
00511 return 0;
00512 }
00513
00514
00515 splitCost_t split;
00516 float baseBonus=eBonus;
00517 eBonus *= 1.1 - (float)depth/(float)maxDepth;
00518 if(nPrims > 128) pigeonMinCost(nPrims, nodeBound, primNums, split);
00519 #if _TRI_CLIP > 0
00520 else if (nPrims > TRI_CLIP_THRESH) minimalCost(nPrims, nodeBound, primNums, allBounds, edges, split);
00521 else minimalCost(nPrims, nodeBound, primNums, allBounds+totalPrims, edges, split);
00522 #else
00523 else minimalCost(nPrims, nodeBound, primNums, allBounds, edges, split);
00524 #endif
00525 eBonus=baseBonus;
00526
00527 if (split.bestCost > split.oldCost) ++badRefines;
00528 if ((split.bestCost > 1.6f * split.oldCost && nPrims < 16) ||
00529 split.bestAxis == -1 || badRefines == 2) {
00530 nodes[nextFreeNode].createLeaf(primNums, nPrims, prims, primsArena);
00531 nextFreeNode++;
00532 if( badRefines == 2) ++NumBadSplits;
00533 return 0;
00534 }
00535
00536
00537 u_int32 remainingMem, *morePrims = 0, *nRightPrims;
00538 u_int32 *oldRightPrims = rightPrims;
00539 if(nPrims > rightMemSize || 2*TRI_CLIP_THRESH > rightMemSize )
00540 {
00541
00542 remainingMem = nPrims * 3;
00543 morePrims = new u_int32[remainingMem];
00544 nRightPrims = morePrims;
00545 }
00546 else
00547 {
00548 nRightPrims = oldRightPrims;
00549 remainingMem = rightMemSize;
00550 }
00551
00552
00553 PFLOAT splitPos;
00554 int n0 = 0, n1 = 0;
00555 if(nPrims > 128)
00556 {
00557 int pn;
00558 for (unsigned int i=0; i<nPrims; i++)
00559 {
00560 pn = primNums[i];
00561 if(allBounds[ pn ].a[split.bestAxis] >= split.t) nRightPrims[n1++] = pn;
00562 else
00563 {
00564 leftPrims[n0++] = pn;
00565 if(allBounds[ pn ].g[split.bestAxis] > split.t) nRightPrims[n1++] = pn;
00566 }
00567 }
00568 splitPos = split.t;
00569 if (n0!= split.nBelow || n1 != split.nAbove) std::cout << "oops!\n";
00570
00571
00572
00573
00574
00575
00576
00577 }
00578 else if(nPrims <= TRI_CLIP_THRESH)
00579 {
00580 int cindizes[TRI_CLIP_THRESH];
00581 u_int32 oldPrims[TRI_CLIP_THRESH];
00582
00583 memcpy(oldPrims, primNums, nPrims*sizeof(int));
00584
00585 for (int i=0; i<split.bestOffset; ++i)
00586 if (edges[split.bestAxis][i].end != UPPER_B)
00587 {
00588 cindizes[n0] = edges[split.bestAxis][i].primNum;
00589
00590 leftPrims[n0] = oldPrims[cindizes[n0]];
00591 ++n0;
00592 }
00593
00594 for(int i=0; i<n0; ++i){ leftPrims[n0+i] = cindizes[i]; }
00595 if (edges[split.bestAxis][split.bestOffset].end == BOTH_B)
00596 {
00597 cindizes[n1] = edges[split.bestAxis][split.bestOffset].primNum;
00598
00599 nRightPrims[n1] = oldPrims[cindizes[n1]];
00600 ++n1;
00601 }
00602 for (int i=split.bestOffset+1; i<split.nEdge; ++i)
00603 if (edges[split.bestAxis][i].end != LOWER_B)
00604 {
00605 cindizes[n1] = edges[split.bestAxis][i].primNum;
00606
00607 nRightPrims[n1] = oldPrims[cindizes[n1]];
00608 ++n1;
00609 }
00610
00611 for(int i=0; i<n1; ++i){ nRightPrims[n1+i] = cindizes[i]; }
00612 splitPos = edges[split.bestAxis][split.bestOffset].pos;
00613
00614 }
00615 else
00616 {
00617 for (int i=0; i<split.bestOffset; ++i)
00618 if (edges[split.bestAxis][i].end != UPPER_B)
00619 leftPrims[n0++] = edges[split.bestAxis][i].primNum;
00620 if (edges[split.bestAxis][split.bestOffset].end == BOTH_B)
00621 nRightPrims[n1++] = edges[split.bestAxis][split.bestOffset].primNum;
00622 for (int i=split.bestOffset+1; i<split.nEdge; ++i)
00623 if (edges[split.bestAxis][i].end != LOWER_B)
00624 nRightPrims[n1++] = edges[split.bestAxis][i].primNum;
00625 splitPos = edges[split.bestAxis][split.bestOffset].pos;
00626 }
00627
00628
00629 remainingMem -= n1;
00630
00631
00632 u_int32 curNode = nextFreeNode;
00633 nodes[curNode].createInterior(split.bestAxis, splitPos);
00634 ++nextFreeNode;
00635 bound_t boundL = nodeBound, boundR = nodeBound;
00636 switch(split.bestAxis){
00637 case 0: boundL.setMaxX(splitPos); boundR.setMinX(splitPos); break;
00638 case 1: boundL.setMaxY(splitPos); boundR.setMinY(splitPos); break;
00639 case 2: boundL.setMaxZ(splitPos); boundR.setMinZ(splitPos); break;
00640 }
00641
00642 #if _TRI_CLIP > 0
00643 if(nPrims <= TRI_CLIP_THRESH)
00644 {
00645 remainingMem -= n1;
00646
00647 clip[depth+1] = split.bestAxis;
00648 buildTree(n0, boundL, leftPrims, leftPrims, nRightPrims+2*n1, edges, remainingMem, depth+1, badRefines);
00649 clip[depth+1] |= 1<<2;
00650
00651 nodes[curNode].setRightChild (nextFreeNode);
00652 buildTree(n1, boundR, nRightPrims, leftPrims, nRightPrims+2*n1, edges, remainingMem, depth+1, badRefines);
00653 clip[depth+1] = -1;
00654 }
00655 else
00656 {
00657 #endif
00658
00659 buildTree(n0, boundL, leftPrims, leftPrims, nRightPrims+n1, edges, remainingMem, depth+1, badRefines);
00660
00661 nodes[curNode].setRightChild (nextFreeNode);
00662 buildTree(n1, boundR, nRightPrims, leftPrims, nRightPrims+n1, edges, remainingMem, depth+1, badRefines);
00663 #if _TRI_CLIP > 0
00664 }
00665 #endif
00666
00667 if(morePrims) delete[] morePrims;
00668 return 1;
00669 }
00670
00671
00672
00673
00678 bool triKdTree_t::Intersect(const ray_t &ray, PFLOAT dist, triangle_t **tr, PFLOAT &Z, void *udat) const
00679 {
00680 Z=dist;
00681
00682 PFLOAT a, b, t;
00683 PFLOAT t_hit;
00684
00685 if (!treeBound.cross(ray, a, b, dist))
00686 { return false; }
00687
00688 unsigned char udat1[PRIM_DAT_SIZE], udat2[PRIM_DAT_SIZE];
00689 void *c_udat=(void*)&udat1[0], *t_udat=(void*)&udat2[0];
00690 vector3d_t invDir(1.0/ray.dir.x, 1.0/ray.dir.y, 1.0/ray.dir.z);
00691
00692 bool hit = false;
00693
00694 KdStack stack[KD_MAX_STACK];
00695 const kdTreeNode *farChild, *currNode;
00696 currNode = nodes;
00697
00698 int enPt = 0;
00699 stack[enPt].t = a;
00700
00701
00702 if(a >= 0.0)
00703 stack[enPt].pb = ray.from + ray.dir * a;
00704 else
00705 stack[enPt].pb = ray.from;
00706
00707
00708 int exPt = 1;
00709 stack[exPt].t = b;
00710 stack[exPt].pb = ray.from + ray.dir * b;
00711 stack[exPt].node = 0;
00712
00713
00714 while (currNode != NULL)
00715 {
00716 if (dist < stack[enPt].t) break;
00717
00718 while( !currNode->IsLeaf() )
00719 {
00720 int axis = currNode->SplitAxis();
00721 PFLOAT splitVal = currNode->SplitPos();
00722
00723 if(stack[enPt].pb[axis] <= splitVal){
00724 if(stack[exPt].pb[axis] <= splitVal)
00725 {
00726 currNode++;
00727 continue;
00728 }
00729 if(stack[exPt].pb[axis] == splitVal)
00730 {
00731 currNode = &nodes[currNode->getRightChild()];
00732 continue;
00733 }
00734
00735 farChild = &nodes[currNode->getRightChild()];
00736 currNode ++;
00737 }
00738 else
00739 {
00740 if(splitVal < stack[exPt].pb[axis])
00741 {
00742 currNode = &nodes[currNode->getRightChild()];
00743 continue;
00744 }
00745 farChild = currNode+1;
00746 currNode = &nodes[currNode->getRightChild()];
00747 }
00748
00749
00750 t = (splitVal - ray.from[axis]) * invDir[axis];
00751
00752
00753 int tmp = exPt;
00754 exPt++;
00755
00756
00757 if (exPt == enPt) exPt++;
00758
00759 static const int npAxis[2][3] = { {1, 2, 0}, {2, 0, 1} };
00760 int nextAxis = npAxis[0][axis];
00761 int prevAxis = npAxis[1][axis];
00762 stack[exPt].prev = tmp;
00763 stack[exPt].t = t;
00764 stack[exPt].node = farChild;
00765 stack[exPt].pb[axis] = splitVal;
00766 stack[exPt].pb[nextAxis] = ray.from[nextAxis] + t * ray.dir[nextAxis];
00767 stack[exPt].pb[prevAxis] = ray.from[prevAxis] + t * ray.dir[prevAxis];
00768 }
00769
00770
00771 u_int32 nPrimitives = currNode->nPrimitives();
00772 if (nPrimitives == 1) {
00773 triangle_t *mp = currNode->onePrimitive;
00774
00775
00776 if (mp->intersect(ray, &t_hit, t_udat))
00777 {
00778
00779 if(t_hit < Z && t_hit >= ray.tmin )
00780 {
00781 Z = t_hit;
00782 *tr = mp;
00783 std::swap(t_udat, c_udat);
00784 hit = true;
00785 }
00786 }
00787
00788 }
00789 else {
00790 triangle_t **prims = currNode->primitives;
00791 for (u_int32 i = 0; i < nPrimitives; ++i) {
00792 triangle_t *mp = prims[i];
00793
00794
00795 if (mp->intersect(ray, &t_hit, t_udat))
00796 {
00797
00798 if(t_hit < Z && t_hit >= ray.tmin )
00799 {
00800 Z = t_hit;
00801 *tr = mp;
00802 std::swap(t_udat, c_udat);
00803 hit = true;
00804 }
00805 }
00806
00807 }
00808 }
00809
00810 if(hit && Z <= stack[exPt].t){ memcpy(udat, c_udat, PRIM_DAT_SIZE); return true;}
00811
00812 enPt = exPt;
00813 currNode = stack[exPt].node;
00814 exPt = stack[enPt].prev;
00815
00816 }
00817
00818 memcpy(udat, c_udat, PRIM_DAT_SIZE);
00819 return hit;
00820 }
00821
00822
00823 bool triKdTree_t::IntersectS(const ray_t &ray, PFLOAT dist, triangle_t **tr) const
00824 {
00825 PFLOAT a, b, t;
00826 PFLOAT t_hit;
00827
00828 if (!treeBound.cross(ray, a, b, dist))
00829 return false;
00830
00831 unsigned char udat[PRIM_DAT_SIZE];
00832 vector3d_t invDir(1.f/ray.dir.x, 1.f/ray.dir.y, 1.f/ray.dir.z);
00833
00834
00835
00836 KdStack stack[KD_MAX_STACK];
00837 const kdTreeNode *farChild, *currNode;
00838 currNode = nodes;
00839
00840 int enPt = 0;
00841 stack[enPt].t = a;
00842
00843
00844 if(a >= 0.0)
00845 stack[enPt].pb = ray.from + ray.dir * a;
00846 else
00847 stack[enPt].pb = ray.from;
00848
00849
00850 int exPt = 1;
00851 stack[exPt].t = b;
00852 stack[exPt].pb = ray.from + ray.dir * b;
00853 stack[exPt].node = 0;
00854
00855
00856 while (currNode != NULL)
00857 {
00858 if (dist < stack[enPt].t ) break;
00859
00860 while( !currNode->IsLeaf() )
00861 {
00862 int axis = currNode->SplitAxis();
00863 PFLOAT splitVal = currNode->SplitPos();
00864
00865 if(stack[enPt].pb[axis] <= splitVal){
00866 if(stack[exPt].pb[axis] <= splitVal)
00867 {
00868 currNode++;
00869 continue;
00870 }
00871 if(stack[exPt].pb[axis] == splitVal)
00872 {
00873 currNode = &nodes[currNode->getRightChild()];
00874 continue;
00875 }
00876
00877 farChild = &nodes[currNode->getRightChild()];
00878 currNode ++;
00879 }
00880 else
00881 {
00882 if(splitVal < stack[exPt].pb[axis])
00883 {
00884 currNode = &nodes[currNode->getRightChild()];
00885 continue;
00886 }
00887 farChild = currNode+1;
00888 currNode = &nodes[currNode->getRightChild()];
00889 }
00890
00891
00892 t = (splitVal - ray.from[axis]) * invDir[axis];
00893
00894
00895 int tmp = exPt;
00896 exPt++;
00897
00898
00899 if (exPt == enPt) exPt++;
00900
00901 static const int npAxis[2][3] = { {1, 2, 0}, {2, 0, 1} };
00902 int nextAxis = npAxis[0][axis];
00903 int prevAxis = npAxis[1][axis];
00904 stack[exPt].prev = tmp;
00905 stack[exPt].t = t;
00906 stack[exPt].node = farChild;
00907 stack[exPt].pb[axis] = splitVal;
00908 stack[exPt].pb[nextAxis] = ray.from[nextAxis] + t * ray.dir[nextAxis];
00909 stack[exPt].pb[prevAxis] = ray.from[prevAxis] + t * ray.dir[prevAxis];
00910 }
00911
00912
00913 u_int32 nPrimitives = currNode->nPrimitives();
00914 if (nPrimitives == 1) {
00915 triangle_t *mp = currNode->onePrimitive;
00916
00917
00918 if (mp->intersect(ray, &t_hit, (void*)udat))
00919 {
00920
00921 if(t_hit < dist && t_hit >= 0.f )
00922 {
00923 *tr = mp;
00924 return true;
00925 }
00926 }
00927
00928 }
00929 else {
00930 triangle_t **prims = currNode->primitives;
00931 for (u_int32 i = 0; i < nPrimitives; ++i) {
00932 triangle_t *mp = prims[i];
00933
00934
00935 if (mp->intersect(ray, &t_hit, (void*)udat))
00936 {
00937 if(t_hit < dist && t_hit >= 0.f )
00938 {
00939
00940 *tr = mp;
00941 return true;
00942 }
00943 }
00944
00945 }
00946 }
00947
00948
00949
00950 enPt = exPt;
00951 currNode = stack[exPt].node;
00952 exPt = stack[enPt].prev;
00953
00954 }
00955
00956 return false;
00957 }
00958
00959
00960
00961
00962
00963 bool triKdTree_t::IntersectTS(renderState_t &state, const ray_t &ray, int maxDepth, PFLOAT dist, triangle_t **tr, color_t &filt) const
00964 {
00965 PFLOAT a, b, t;
00966 PFLOAT t_hit;
00967
00968 if (!treeBound.cross(ray, a, b, dist))
00969 return false;
00970
00971 double udat[PRIM_DAT_SIZE];
00972 vector3d_t invDir(1.f/ray.dir.x, 1.f/ray.dir.y, 1.f/ray.dir.z);
00973
00974
00975 int depth=0;
00976
00977 #if ( HAVE_PTHREAD && defined (__GNUC__) )
00978 std::set<const triangle_t *, std::less<const triangle_t *>, __gnu_cxx::__mt_alloc<const triangle_t *> > filtered;
00979 #else
00980 std::set<const triangle_t *> filtered;
00981 #endif
00982 KdStack stack[KD_MAX_STACK];
00983 const kdTreeNode *farChild, *currNode;
00984 currNode = nodes;
00985
00986 int enPt = 0;
00987 stack[enPt].t = a;
00988
00989
00990 if(a >= 0.0)
00991 stack[enPt].pb = ray.from + ray.dir * a;
00992 else
00993 stack[enPt].pb = ray.from;
00994
00995
00996 int exPt = 1;
00997 stack[exPt].t = b;
00998 stack[exPt].pb = ray.from + ray.dir * b;
00999 stack[exPt].node = 0;
01000
01001
01002 while (currNode != NULL)
01003 {
01004 if (dist < stack[enPt].t ) break;
01005
01006 while( !currNode->IsLeaf() )
01007 {
01008 int axis = currNode->SplitAxis();
01009 PFLOAT splitVal = currNode->SplitPos();
01010
01011 if(stack[enPt].pb[axis] <= splitVal){
01012 if(stack[exPt].pb[axis] <= splitVal)
01013 {
01014 currNode++;
01015 continue;
01016 }
01017 if(stack[exPt].pb[axis] == splitVal)
01018 {
01019 currNode = &nodes[currNode->getRightChild()];
01020 continue;
01021 }
01022
01023 farChild = &nodes[currNode->getRightChild()];
01024 currNode ++;
01025 }
01026 else
01027 {
01028 if(splitVal < stack[exPt].pb[axis])
01029 {
01030 currNode = &nodes[currNode->getRightChild()];
01031 continue;
01032 }
01033 farChild = currNode+1;
01034 currNode = &nodes[currNode->getRightChild()];
01035 }
01036
01037
01038 t = (splitVal - ray.from[axis]) * invDir[axis];
01039
01040
01041 int tmp = exPt;
01042 exPt++;
01043
01044
01045 if (exPt == enPt) exPt++;
01046
01047 static const int npAxis[2][3] = { {1, 2, 0}, {2, 0, 1} };
01048 int nextAxis = npAxis[0][axis];
01049 int prevAxis = npAxis[1][axis];
01050 stack[exPt].prev = tmp;
01051 stack[exPt].t = t;
01052 stack[exPt].node = farChild;
01053 stack[exPt].pb[axis] = splitVal;
01054 stack[exPt].pb[nextAxis] = ray.from[nextAxis] + t * ray.dir[nextAxis];
01055 stack[exPt].pb[prevAxis] = ray.from[prevAxis] + t * ray.dir[prevAxis];
01056 }
01057
01058
01059 u_int32 nPrimitives = currNode->nPrimitives();
01060
01061
01062 if (nPrimitives == 1) {
01063 triangle_t *mp = currNode->onePrimitive;
01064 if (mp->intersect(ray, &t_hit, (void*)&udat[0]))
01065 {
01066 if(t_hit < /* tmax */ dist && t_hit >= ray.tmin )
01067 {
01068
01069 const material_t *mat = mp->getMaterial();
01070 if(!mat->isTransparent() ) return true;
01071 if(filtered.insert(mp).second)
01072 {
01073 if(depth>=maxDepth) return true;
01074 point3d_t h=ray.from + t_hit*ray.dir;
01075 surfacePoint_t sp;
01076 mp->getSurface(sp, h, (void*)&udat[0]);
01077 filt *= mat->getTransparency(state, sp, ray.dir);
01078 ++depth;
01079 }
01080 }
01081 }
01082 }
01083 else {
01084 triangle_t **prims = currNode->primitives;
01085 for (u_int32 i = 0; i < nPrimitives; ++i) {
01086 triangle_t *mp = prims[i];
01087 if (mp->intersect(ray, &t_hit, (void*)&udat[0]))
01088 {
01089 if(t_hit < /* tmax */ dist && t_hit >= ray.tmin )
01090 {
01091
01092 const material_t *mat = mp->getMaterial();
01093 if(!mat->isTransparent() ) return true;
01094 if(filtered.insert(mp).second)
01095 {
01096 if(depth>=maxDepth) return true;
01097 point3d_t h=ray.from + t_hit*ray.dir;
01098 surfacePoint_t sp;
01099 mp->getSurface(sp, h, (void*)&udat[0]);
01100 filt *= mat->getTransparency(state, sp, ray.dir);
01101 ++depth;
01102 }
01103 }
01104 }
01105 }
01106 }
01107
01108
01109
01110 enPt = exPt;
01111 currNode = stack[exPt].node;
01112 exPt = stack[enPt].prev;
01113
01114 }
01115
01116 return false;
01117 }
01118
01119
01120 __END_YAFRAY