在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
如下图所示