void Tree<ElementContainer>::TraversePacket(Context<1,flags> &c,const Selector<1> &selector) const { int bitMask=selector[0]; const Vec3q &dir=c.Dir(0); bool split=1; if(Selector<1>::full||bitMask==0x0f) { if(!filterSigns||GetVecSign(c.Dir(0))!=8) { if(separateFirstElement) elements[0].Collide(c,0); TraversePacket0(c); split=0; } } if(split) { if(bitMask==0) return; for(int q=0;q<4;q++) { if(!(bitMask&(1<<q))) continue; FContext<flags> fc(c,q); if(separateFirstElement) elements[0].Collide(fc,0); TraverseMono(fc); } } }
void Tree<ElementContainer>::TraversePacket(Context<size,flags> &c,const Selector<size> &selector) const { bool split=1; enum { reflected=!(flags&(isct::fPrimary|isct::fShadow)) }; bool selectorsFiltered=size<=(reflected?4:isComplex?64:16); if(!Selector<size>::full) for(int n=0;n<size/4;n++) if(selector.Mask4(n)!=0x0f0f0f0f) { selectorsFiltered=0; break; } if((Selector<size>::full||selectorsFiltered) && size <= (reflected?4 : isComplex? 64 : 16)) { const Vec3q &dir=c.Dir(0); bool signsFiltered=1; int msk=_mm_movemask_ps(_mm_shuffle_ps(_mm_shuffle_ps(dir.x.m,dir.y.m,0),dir.z.m,0+(2<<2)))&7; if(filterSigns) { for(int n=0;n<size;n++) if(GetVecSign(c.Dir(n))!=msk) { signsFiltered=0; break; } } if(signsFiltered) { bool primary = (flags & (isct::fPrimary|isct::fShadow)) && gVals[1]; if((flags & isct::fShadow) &&!isComplex) { floatq dot=1.0f; for(int q=1;q<size;q++) dot=Min(dot,c.Dir(0)|c.Dir(q)); if(ForAny(dot<0.9998f)) primary=0; } if(separateFirstElement) elements[0].Collide(c,0); if(primary) TraversePrimary(c); else TraversePacket0(c); // if(primary && (flags & isct::fShadow)) c.stats.Skip(); split=0; } } if(split) { for(int q=0;q<4;q++) { Context<size/4,flags> subC(c.Split(q)); if(flags & isct::fShadow) subC.shadowCache=c.shadowCache; TraversePacket(subC,selector.SubSelector(q)); if(flags & isct::fShadow) c.shadowCache=subC.shadowCache; } } }
void DBVH::TraversePrimary0(Context<sharedOrigin, hasMask> &c, int firstNode) const { const int size = c.Size(); StackElem stack[maxDepth + 2]; int stackPos = 0; stack[stackPos++] = StackElem(firstNode, 0, size - 1); TreeStats stats; int sign[3] = { c.Dir(0).x[0] < 0.0f, c.Dir(0).y[0] < 0.0f, c.Dir(0).z[0] < 0.0f }; CornerRays crays(c.rays); RayInterval interval(c.rays); while(stackPos) { int nNode = stack[--stackPos].node; int firstActive = stack[stackPos].firstActive; int lastActive = stack[stackPos].lastActive; CONTINUE: stats.LoopIteration(); if(nodes[nNode].IsLeaf()) { int count = nodes[nNode].count, first = nodes[nNode].first & 0x7fffffff; const BBox &box = nodes[nNode].bbox; if(!box.TestInterval(interval)) continue; if(box.Test(c, firstActive, lastActive)) for(int n = 0; n < count; n++) { const ObjectInstance &obj = elements[first + n]; obj.CollidePrimary(c, first + n, firstActive, lastActive); stats.Intersection(lastActive - firstActive + 1); } continue; } int child = nodes[nNode].subNode; #ifdef VECLIB_SSE_VER _mm_prefetch(&nodes[child + 0], _MM_HINT_T0); _mm_prefetch(&nodes[child + 1], _MM_HINT_T0); #endif bool test = 1; { const BBox &box = nodes[nNode].bbox; if(!box.TestInterval(interval)) continue; test = box.Test(c, firstActive, lastActive); } if(test) { int firstNode = nodes[nNode].firstNode ^ sign[nodes[nNode].axis]; stack[stackPos++] = StackElem(child + (firstNode ^ 1), firstActive, lastActive); nNode = child + firstNode; goto CONTINUE; } } if(c.stats) (*c.stats) += stats; }
void DBVH::TraversePrimary(Context<sharedOrigin, hasMask> &c) const { return TraversePrimary0(c); const int size = c.Size(); bool split = 1; RaySelector selector(c.MaskPtr(), c.Size()); bool selectorsFiltered = 1; if(hasMask) { const int size4 = size / 4; //TODO: ... bool any = 0; for(int n = 0; n < size4; n++) { int mask = selector.Mask4(n); selectorsFiltered &= mask == 0x0f0f0f0f; any |= mask; } if(!any) return; } if(!hasMask || selectorsFiltered) { //TODO distant origins floatq dot = 1.0f; for(int q = 1; q < size; q++) dot = Min(dot, c.Dir(0) | c.Dir(q)); split = ForAny(dot < 0.99); if(!split) TraversePrimary0(c); } if(split) { // if(gVals[0]) { char tempData[size + 4]; RaySelector temp(tempData, size); for(int n = 0; n < temp.Size(); n++) temp[n] = c.Mask(n); int start = 0; while(true) { char buf[c.Size() + 4]; RaySelector newSel(buf, c.Size()); newSel.Clear(); for(;start < size; start++) if(temp[start]) break; if(start == size) break; Vec3q lead; for(int i = 0; i < 4; i++) if(temp[start] & (1 << i)) { lead = (Vec3q)ExtractN(c.Dir(start), i); break; } for(int q = start; q < size; q++) { int mask = ForWhich((c.Dir(q) | lead) >= 0.9) & temp[q]; temp[q] &= ~mask; newSel[q] = mask; } Context<sharedOrigin, 1> splitCtx(RayGroup<sharedOrigin, 1>(c.rays.OriginPtr(), c.rays.DirPtr(), c.rays.IDirPtr(), size, buf), c.distance, c.object, c.element, c.barycentric); TraversePrimary0(splitCtx); } // } // else { //TODO: split // for(int q = 0; q < 4; q++) { // Context<size/4,flags> subC(c.Split(q)); // TraversePrimary0(subC, selector.SubSelector(q)); // } // } if(c.stats) c.stats->Skip(); } }