dividePoly

在RecastNavigation将三角形转为高度场过程中,有个很重要的函数,就是切割三角形,将三角形用一根轴切割成左右或是上下两部分,这个函数就是dividePoly,源码如下:

/*
参数:
in : 待切割多边形的顶点坐标
nin :待切割多边形的顶点个数
out1 : 切割后的多边形顶点坐标
nout1 : 切割后的多边形顶点个数
out2 : 切割后的多边形顶点坐标
nout2 : 切割后的多边形顶点个数
两个out,分别对应切割后,切割轴两边的多边形顶点坐标
x: 切割轴
axis : 0代表竖轴,2代表横轴
*/
static void dividePoly(const float* in, int nin,
					  float* out1, int* nout1,
					  float* out2, int* nout2,
					  float x, int axis)
{
    //d数组,表示各个顶点距离切割轴的顶点距离
    //大于0表示在切割轴的左边或是下边,小于0表示在切割轴的右边或是上边
	float d[12];
	for (int i = 0; i < nin; ++i)
		d[i] = x - in[i*3+axis];

    //m和n是后割后的两个多边形的顶点个数
	int m = 0, n = 0;
    
    //for循环的方式是每一次循环对应多边形的一条边
	for (int i = 0, j = nin-1; i < nin; j=i, ++i)
	{
		bool ina = d[j] >= 0;
		bool inb = d[i] >= 0;

        //如果d[j],d[i]这条边在切割轴的两边,则距离切割轴肯定一个是正一个是负,此时符号不同
		if (ina != inb)
		{
            //通过相似三角形原理, 算出切割轴与d[j],d[i]这条边的交点
            //与切割轴的交点肯定是切割后的两个多边形共有的

			float s = d[j] / (d[j] - d[i]);
			out1[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s;
			out1[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s;
			out1[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s;
			rcVcopy(out2 + n*3, out1 + m*3);
			m++;
			n++;

            //>0表示在切割轴左边或下边,则将d[i]保存到out1
            //说明out1保存的是切割轴左边或下边的多边形顶点

            //反之, < 0则保存到out2
            //说明out2保存的是切割轴右边或上边的多边形顶点
			if (d[i] > 0)
			{
				rcVcopy(out1 + m*3, in + i*3);
				m++;
			}
			else if (d[i] < 0)
			{
				rcVcopy(out2 + n*3, in + i*3);
				n++;
			}
		}
		else
		{
            //符号相同,说明d[j],d[i]这条边在切割轴的一侧,此时与切割轴无交点
			if (d[i] >= 0)
			{
				rcVcopy(out1 + m*3, in + i*3);
				m++;
				if (d[i] != 0)
					continue;
			}
            //如果d[i] < 0,则保存到out2
			rcVcopy(out2 + n*3, in + i*3);
			n++;
		}
	}
	*nout1 = m;
	*nout2 = n;
}

以上,切割轴可能是x轴或是z轴,如果切割轴是x轴,则切割后的多边形分别位于切割轴的上下

且切割轴上面的部分保存在out2,下面的部分保存在out1

如下图所示:

 如果切割轴是z轴,则切割后的多边形位于切割轴的左右,且切割轴右边的部分保存在out2,左边的部分保存在out1

如下图所示

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值