MRTK的package在MRTK\Examples\StandardShader 路径下提供了模型切割例程ClippingExamples。切割效果如下:(例程中原效果灰色部分是透明的)
实现切割主要分为两部分:切割算法以及不同模型之间的变量传递。
1、 切割算法
切割例程中主要用到了Assets/MRTK/Core/Utilities/StandardShader路径下的CilpingPlaner.cs、ClippingBox.cs、ClippingSphere.cs、ClippingPrimitive.cs三个脚本文件以及Assets/MRTK/Core/StandardAssets/Shaders路径下的MixedRealityStandard.shader着色器。
例程中实现了三种切割:平面切割(plane)、球切割(sphere)以及立方体切割(cube)。
//位置关系计算的实现位于D:\JCS\project\2_AR\HZtoCS\HoloLensMRTK\Assets\MRTK\Core\StandardAssets\Shaders\MixedRealityShaderUtils.cginc文件中
#if defined(_CLIPPING_PLANE)
inline float PointVsPlane(float3 worldPosition, float4 plane)
{
float3 planePosition = plane.xyz * plane.w;//得到平面中心点的位置
return dot(worldPosition - planePosition, plane.xyz);//plane.xyz是平面的法向量
}
#endif
#if defined(_CLIPPING_SPHERE)
inline float PointVsSphere(float3 worldPosition, float4 sphere)
{
return distance(worldPosition, sphere.xyz) - sphere.w;//计算世界空间下点的位置距离球心的距离
}
#endif
#if defined(_CLIPPING_BOX)
inline float PointVsBox(float3 worldPosition, float3 boxSize, float4x4 boxInverseTransform)
{
float3 distance = abs(mul(boxInverseTransform, float4(worldPosition, 1.0))) - boxSize;//abs返回向量每个成员的绝对值,正方形内的所有坐标都是小于等于boxsize的。
return length(max(distance, 0.0)) + min(max(distance.x, max(distance.y, distance.z)), 0.0);//length返回向量的模
}
#endif
面切割算法:对于心脏模型的每一个片元,在世界坐标系下,使用平面的法线向量n与平面中心点到待渲染点的方向向量d做点乘。根据计算结果的正负号将模型划分为平面的内侧和外侧两部分。
球切割算法:对于心脏模型的每一个片元,计算其到球心的距离,如果小于半径,则位于内侧,反之,位于外侧。
立方体切割算法:对于心脏模型的每一个片元,将片元坐标变换到立方体的模型坐标系下得到坐标position,用position的每个坐标分量取绝对值再减去立方形大小。最终得到的坐标中最大值大于零的,说明在立方体外,最大值小于零的说明在立方体内。
2、变量传递
变量传递主要是通过场景中的Renderer实现的,以Plane为例说明,传递关系如下图所示:
传递过程设计的主要代码如下: