Ejemplo n.º 1
0
	bool RayTraceDataGenerator::CalcIntersect(const XMVECTOR& p1, const XMVECTOR& n, XMVECTOR* nResult, XMVECTOR* intersectLocation, float* depth)
	{
		/*
		// grid space
		vec3 grid = floor( pos ); //向下取整将坐标在网格中使用
		vec3 grid_step = sign( dir ); //获取dir(方向)的正负符号<-意思就是说获取网格的步进方向,虽然只是正负
		vec3 corner = max( grid_step, vec3( 0.0 ) );//负号->0 //应该是最后在步进方向上产生的偏差值,但是原因不明

		// ray space
		vec3 inv = vec3( 1.0 ) / dir; //取倒数使得各个方向的比值倒过来
		vec3 ratio = ( grid + corner - pos ) * inv;//corn+pos的小数部分
		vec3 ratio_step = grid_step * inv;//不懂
		//于是这个rayspace只是提供一个比值,来决定grid的步进么

		// dda <-数值微分法
		float hit = -1.0;
		for ( int i = 0; i < 128; i++ ) {
		if ( voxel( grid ) > 0.5 ) {

		hit = 1.0;
		break;   //这里应该是可以直接退出循环的,感觉没什么区别
		continue;
		}

		vec3 cp = step( ratio, ratio.yzx );//二维情况的搞清楚了,问题还有就是在三维空间上的扩展

		mask = cp * ( vec3( 1.0 ) - cp.zxy );

		grid  += grid_step  * mask;
		ratio += ratio_step * mask;
		}

		center = grid + vec3( 0.5 );//中心形式表示(跟grid应该没区别吧0 0)
		return dot(ratio - ratio_step,vec3(1.0)) * hit;//dot( ratio - ratio_step, mask ) * hit;
		//这里关心的是hit的深度好像
		*/
		//p1是起点
		XMVECTOR start = p1;
		XMVECTOR dir = n;
		XMVECTOR zero = XMVectorSetBinaryConstant(0, 0, 0, 0);
		XMVECTOR one = XMVectorSetBinaryConstant(1, 1, 1, 1);


		XMVECTOR grid;
		XMVECTOR grid_step;
		XMVECTOR grid_corner;
		grid = XMVectorFloor(start);//实际上w分量为0应该就不影响了吧(
		//好像DirectXMath没有提供Sign的函数(于是用了一个挺别扭的方法- -
		//grid_step 就是 sign_dir
		grid_step = DirectX::XMVectorOrInt(DirectX::XMVectorAndInt(dir, DirectX::XMVectorSplatSignMask()), DirectX::XMVectorSplatOne());
		grid_corner = XMVectorClamp(grid_step, zero, one);

		XMVECTOR inv;
		XMVECTOR ratio;
		XMVECTOR ratio_step;
		inv = XMVectorReciprocal(dir);
		ratio = XMVectorMultiply(XMVectorSubtract(XMVectorAdd(grid, grid_corner), start), inv);
		ratio_step = XMVectorMultiply(grid_step, inv);

		bool hit = false;
		XMVECTOR cp;
		XMVECTOR mask;
		XMVECTOR ratioyzx;
		XMVECTOR cpzxy;
		XMFLOAT4 tmp1;
		XMFLOAT4 tmp2;
		int i;
		for (i = 0; i < 128; ++i)//最大深度为128
		{
			XMStoreFloat4(&tmp1, grid);
			/*
			__try{
			if (map->At(tmp1.x, tmp1.y, tmp1.z).TexType != -1)
			{
			hit = true;
			break;
			}
			}
			__except ((GetExceptionCode() == EXCEPTION_ARRAY_BOUNDS_EXCEEDED)?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH)
			{
			//捕获越界错误作为跳出条件,看看有没有问题...
			break;
			}
			*/
			//理论上来说异常的话处理代价太大,还是判断一下range吧= =
			if ((RangeCheck(tmp1.x, tmp1.y, tmp1.z)))
			{
				if (GetLocInfo(tmp1.x, tmp1.y, tmp1.z) != -1)
				{
					hit = true;
					break;
				}
			}
			/*
			修正:发生越界的时候并不一定就要终止,需要考虑到从值域外射出的射线.....
			不过就算不break效率应该也比原先的算法要高...(除了要限制一下最大遍历深度这方面
			*/


			XMStoreFloat4(&tmp1, ratio);
			tmp2.x = tmp1.y; tmp2.y = tmp1.z; tmp2.z = tmp1.x;
			ratioyzx = XMLoadFloat4(&tmp2);

			cp = XMVectorAndInt(XMVectorGreaterOrEqual(ratioyzx, ratio), XMVectorSplatOne());//1 or 0
			XMStoreFloat4(&tmp1, cp);
			tmp2.x = tmp1.z; tmp2.y = tmp1.x; tmp2.z = tmp1.y;
			cpzxy = XMLoadFloat4(&tmp2);
			mask = XMVectorMultiply(cp, XMVectorSubtract(one, cpzxy));

			grid += XMVectorMultiply(grid_step, mask);
			ratio += XMVectorMultiply(ratio_step, mask);
		}
		if (hit)
		{

			XMFLOAT4 result;
			result = tmp1; //所在方块
			if (i == 0)
			{
				//这是在方块内部的情况
				result.w = -1;
				return false;
			}
			XMVECTOR ftmp;
			ftmp = XMVectorSubtract(ratio, ratio_step);//因为取的只是mask方向的值,所以step在这里没必要乘mask
			*depth = XMVectorGetX(DirectX::XMVector3Dot(ftmp, mask));
			ftmp = XMVectorAdd(XMVectorScale(dir,*depth) , p1);
			XMStoreFloat4(&tmp1, ftmp);
			//需要全部反过来,因为上面的式子没有取反
			*intersectLocation = ftmp;
			result = tmp1;
			result.w = 0;

			XMVECTOR normal;
			normal = XMVectorMultiply(mask, grid_step);
			XMStoreFloat4(&tmp1, normal);
			//需要全部反过来,因为上面的式子没有取反
			if (tmp1.x > 0.5)
			{
				//法向量为1,0,0,后方
				*nResult = XMVectorSetBinaryConstant(1, 0, 0, 0);
			}
			else if (tmp1.x < -0.5)
			{
				//法向量为-1,0,0,前方
				*nResult = XMVectorSetBinaryConstant(-1, 0, 0, 0);
			}
			else if (tmp1.y < -0.5)
			{
				//法向量为0,-1,0,右方
				*nResult = XMVectorSetBinaryConstant(0, -1, 0, 0);
			}
			else if (tmp1.y > 0.5)
			{
				//法向量为0,1,0,左方
				*nResult = XMVectorSetBinaryConstant(0, 1, 0, 0);
			}
			else if (tmp1.z < -0.5)
			{
				//法向量为0,0,-1,上方
				*nResult = XMVectorSetBinaryConstant(0, 0, -1, 0);
			}
			else if (tmp1.z > 0.5)
			{
				//法向量为0,0,1,下方
				*nResult = XMVectorSetBinaryConstant(0, 0, 1, 0);
			}
			return true;
			//return result;
		}
		else
		{
			return false;
		}
		//上面成功的进行了判断,可以得出grid编号了,不过还要算一下相交面(
		return false;
	}
Ejemplo n.º 2
0
//-----------------------------------------------------------------------------
// Compute the intersection of a ray (Origin, Direction) with a triangle 
// (V0, V1, V2).  Return TRUE if there is an intersection and also set *pDist 
// to the distance along the ray to the intersection.
// 
// The algorithm is based on Moller, Tomas and Trumbore, "Fast, Minimum Storage 
// Ray-Triangle Intersection", Journal of Graphics Tools, vol. 2, no. 1, 
// pp 21-28, 1997.
//-----------------------------------------------------------------------------
BOOL GLibIntersectRayTriangle( FXMVECTOR Origin, FXMVECTOR Direction, FXMVECTOR V0, CXMVECTOR V1, CXMVECTOR V2,
							  FLOAT* pDist )
{
	XMASSERT( pDist );
	//XMASSERT( XMVector3IsUnit( Direction ) );

	static const XMVECTOR Epsilon =
	{
		1e-20f, 1e-20f, 1e-20f, 1e-20f
	};

	XMVECTOR Zero = XMVectorZero();

	XMVECTOR e1 = V1 - V0;
	XMVECTOR e2 = V2 - V0;

	// p = Direction ^ e2;
	XMVECTOR p = XMVector3Cross( Direction, e2 );

	// det = e1 * p;
	XMVECTOR det = XMVector3Dot( e1, p );

	XMVECTOR u, v, t;

	if( XMVector3GreaterOrEqual( det, Epsilon ) )
	{
		// Determinate is positive (front side of the triangle).
		XMVECTOR s = Origin - V0;

		// u = s * p;
		u = XMVector3Dot( s, p );

		XMVECTOR NoIntersection = XMVectorLess( u, Zero );
		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( u, det ) );

		// q = s ^ e1;
		XMVECTOR q = XMVector3Cross( s, e1 );

		// v = Direction * q;
		v = XMVector3Dot( Direction, q );

		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( v, Zero ) );
		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( u + v, det ) );

		// t = e2 * q;
		t = XMVector3Dot( e2, q );

		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( t, Zero ) );

		if( XMVector4EqualInt( NoIntersection, XMVectorTrueInt() ) )
			return FALSE;
	}
	else if( XMVector3LessOrEqual( det, -Epsilon ) )
	{
		// Determinate is negative (back side of the triangle).
		XMVECTOR s = Origin - V0;

		// u = s * p;
		u = XMVector3Dot( s, p );

		XMVECTOR NoIntersection = XMVectorGreater( u, Zero );
		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( u, det ) );

		// q = s ^ e1;
		XMVECTOR q = XMVector3Cross( s, e1 );

		// v = Direction * q;
		v = XMVector3Dot( Direction, q );

		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( v, Zero ) );
		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( u + v, det ) );

		// t = e2 * q;
		t = XMVector3Dot( e2, q );

		NoIntersection = XMVectorOrInt( NoIntersection, XMVectorGreater( t, Zero ) );

		if ( XMVector4EqualInt( NoIntersection, XMVectorTrueInt() ) )
			return FALSE;
	}
	else
	{
		// Parallel ray.
		return FALSE;
	}

	XMVECTOR inv_det = XMVectorReciprocal( det );

	t *= inv_det;

	// u * inv_det and v * inv_det are the barycentric cooridinates of the intersection.

	// Store the x-component to *pDist
	XMStoreFloat( pDist, t );

	return TRUE;
}
Ejemplo n.º 3
0
//-----------------------------------------------------------------------------
// Compute the intersection of a ray (Origin, Direction) with an axis aligned 
// box using the slabs method.
//-----------------------------------------------------------------------------
BOOL GLibIntersectRayAxisAlignedBox( FXMVECTOR Origin, FXMVECTOR Direction, const XNA::AxisAlignedBox* pVolume, FLOAT* pDist )
{
	XMASSERT( pVolume );
	XMASSERT( pDist );
	//XMASSERT( XMVector3IsUnit( Direction ) );

	static const XMVECTOR Epsilon =
	{
		1e-20f, 1e-20f, 1e-20f, 1e-20f
	};
	static const XMVECTOR FltMin =
	{
		-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX
	};
	static const XMVECTOR FltMax =
	{
		FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX
	};

	// Load the box.
	XMVECTOR Center = XMLoadFloat3( &pVolume->Center );
	XMVECTOR Extents = XMLoadFloat3( &pVolume->Extents );

	// Adjust ray origin to be relative to center of the box.
	XMVECTOR TOrigin = Center - Origin;

	// Compute the dot product againt each axis of the box.
	// Since the axii are (1,0,0), (0,1,0), (0,0,1) no computation is necessary.
	XMVECTOR AxisDotOrigin = TOrigin;
	XMVECTOR AxisDotDirection = Direction;

	// if (fabs(AxisDotDirection) <= Epsilon) the ray is nearly parallel to the slab.
	XMVECTOR IsParallel = XMVectorLessOrEqual( XMVectorAbs( AxisDotDirection ), Epsilon );

	// Test against all three axii simultaneously.
	XMVECTOR InverseAxisDotDirection = XMVectorReciprocal( AxisDotDirection );
	XMVECTOR t1 = ( AxisDotOrigin - Extents ) * InverseAxisDotDirection;
	XMVECTOR t2 = ( AxisDotOrigin + Extents ) * InverseAxisDotDirection;

	// Compute the max of min(t1,t2) and the min of max(t1,t2) ensuring we don't
	// use the results from any directions parallel to the slab.
	XMVECTOR t_min = XMVectorSelect( XMVectorMin( t1, t2 ), FltMin, IsParallel );
	XMVECTOR t_max = XMVectorSelect( XMVectorMax( t1, t2 ), FltMax, IsParallel );

	// t_min.x = maximum( t_min.x, t_min.y, t_min.z );
	// t_max.x = minimum( t_max.x, t_max.y, t_max.z );
	t_min = XMVectorMax( t_min, XMVectorSplatY( t_min ) );  // x = max(x,y)
	t_min = XMVectorMax( t_min, XMVectorSplatZ( t_min ) );  // x = max(max(x,y),z)
	t_max = XMVectorMin( t_max, XMVectorSplatY( t_max ) );  // x = min(x,y)
	t_max = XMVectorMin( t_max, XMVectorSplatZ( t_max ) );  // x = min(min(x,y),z)

	// if ( t_min > t_max ) return FALSE;
	XMVECTOR NoIntersection = XMVectorGreater( XMVectorSplatX( t_min ), XMVectorSplatX( t_max ) );

	// if ( t_max < 0.0f ) return FALSE;
	NoIntersection = XMVectorOrInt( NoIntersection, XMVectorLess( XMVectorSplatX( t_max ), XMVectorZero() ) );

	// if (IsParallel && (-Extents > AxisDotOrigin || Extents < AxisDotOrigin)) return FALSE;
	XMVECTOR ParallelOverlap = XMVectorInBounds( AxisDotOrigin, Extents );
	NoIntersection = XMVectorOrInt( NoIntersection, XMVectorAndCInt( IsParallel, ParallelOverlap ) );

	if(!GLibXMVector3AnyTrue( NoIntersection ) )
	{
		// Store the x-component to *pDist
		XMStoreFloat( pDist, t_min );
		return TRUE;
	}

	return FALSE;
}
Ejemplo n.º 4
0
BSphere ComputeBoundingSphereFromPoints(const XMFLOAT3* points, uint32 numPoints, uint32 stride, BBox *optionalBBoxOut)
{
	BSphere sphere;

	Assert_(numPoints > 0);
	Assert_(points);

	// Find the points with minimum and maximum x, y, and z
	XMVECTOR MinX, MaxX, MinY, MaxY, MinZ, MaxZ;

	MinX = MaxX = MinY = MaxY = MinZ = MaxZ = XMLoadFloat3(points);
	GetBoundCornersFromPoints(points, numPoints, stride, MinX, MaxX, MinY, MaxY, MinZ, MaxZ);

	/*for (uint32 i = 1; i < numPoints; i++)
	{
		XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride));

		float px = XMVectorGetX(Point);
		float py = XMVectorGetY(Point);
		float pz = XMVectorGetZ(Point);

		if (px < XMVectorGetX(MinX))
			MinX = Point;

		if (px > XMVectorGetX(MaxX))
			MaxX = Point;

		if (py < XMVectorGetY(MinY))
			MinY = Point;

		if (py > XMVectorGetY(MaxY))
			MaxY = Point;

		if (pz < XMVectorGetZ(MinZ))
			MinZ = Point;

		if (pz > XMVectorGetZ(MaxZ))
			MaxZ = Point;
	}*/

	if (optionalBBoxOut != NULL)
	{
		float maxx = XMVectorGetX(MaxX);
		float maxy = XMVectorGetY(MaxY);
		float maxz = XMVectorGetZ(MaxZ);

		float minx = XMVectorGetX(MinX);
		float miny = XMVectorGetY(MinY);
		float minz = XMVectorGetZ(MinZ);

		optionalBBoxOut->Max.x = maxx;
		optionalBBoxOut->Max.y = maxy;
		optionalBBoxOut->Max.z = maxz;

		optionalBBoxOut->Min.x = minx;
		optionalBBoxOut->Min.y = miny;
		optionalBBoxOut->Min.z = minz;
	}

	// Use the min/max pair that are farthest apart to form the initial sphere.
	XMVECTOR DeltaX = MaxX - MinX;
	XMVECTOR DistX = XMVector3Length(DeltaX);

	XMVECTOR DeltaY = MaxY - MinY;
	XMVECTOR DistY = XMVector3Length(DeltaY);

	XMVECTOR DeltaZ = MaxZ - MinZ;
	XMVECTOR DistZ = XMVector3Length(DeltaZ);

	XMVECTOR Center;
	XMVECTOR Radius;

	if (XMVector3Greater(DistX, DistY))
	{
		if (XMVector3Greater(DistX, DistZ))
		{
			// Use min/max x.
			Center = (MaxX + MinX) * 0.5f;
			Radius = DistX * 0.5f;
		}
		else
		{
			// Use min/max z.
			Center = (MaxZ + MinZ) * 0.5f;
			Radius = DistZ * 0.5f;
		}
	}
	else // Y >= X
	{
		if (XMVector3Greater(DistY, DistZ))
		{
			// Use min/max y.
			Center = (MaxY + MinY) * 0.5f;
			Radius = DistY * 0.5f;
		}
		else
		{
			// Use min/max z.
			Center = (MaxZ + MinZ) * 0.5f;
			Radius = DistZ * 0.5f;
		}
	}

	// Add any points not inside the sphere.
	for (uint32 i = 0; i < numPoints; i++)
	{
		XMVECTOR Point = XMLoadFloat3((XMFLOAT3*)((BYTE*)points + i * stride));

		XMVECTOR Delta = Point - Center;

		XMVECTOR Dist = XMVector3Length(Delta);

		if (XMVector3Greater(Dist, Radius))
		{
			// Adjust sphere to include the new point.
			Radius = (Radius + Dist) * 0.5f;
			Center += (XMVectorReplicate(1.0f) - Radius * XMVectorReciprocal(Dist)) * Delta;
		}
	}

	XMStoreFloat3(&sphere.Center, Center);
	XMStoreFloat(&sphere.Radius, Radius);

	return sphere;
}