Beispiel #1
0
		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);
				} 
			}
		}
Beispiel #2
0
		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;
				}
			}
		}
Beispiel #3
0
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;
}
Beispiel #4
0
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();
	}
}