实施四面体 - 射线相交测试
Implementing a tetrahedra - ray intersection test
我有一个关于四面体 - 射线相交的问题:
我尝试实施四面体射线相交测试,该测试应该 return 出射面的索引。对于交集,我关注了这个博客 post,其中标量三重乘积用于交集测试:
http://realtimecollisiondetection.net/blog/?p=13
但是,我的代码总是 return 与出口面相同的面。在尝试自己找到解决方案但没有成功之后,我将非常感谢任何提示我的交叉测试中可能存在错误的提示。
输入参数为射线原点和方向、节点、面的索引、相邻四面体的索引和最后一个面的索引。出射面和出射四面体的索引是输出值。 ScTP 计算标量三重乘积,并且 sameSign 检查三个浮点数的符号是否相同。
这是代码,感谢您的帮助:
__device__ void GetExitTet(float4 ray_o, float4 ray_d, float4* nodes, int32_t findex[4], int32_t adjtet[4], int32_t lface, int32_t &face, int32_t &tet)
{
face = 0;
tet = 0;
float4 q = ray_d;
float4 v0 = make_float4(nodes[0].x, nodes[0].y, nodes[0].z, 0); // A
float4 v1 = make_float4(nodes[1].x, nodes[1].y, nodes[1].z, 0); // B
float4 v2 = make_float4(nodes[2].x, nodes[2].y, nodes[2].z, 0); // C
float4 v3 = make_float4(nodes[3].x, nodes[3].y, nodes[3].z, 0); // D
float4 p0 = v0 - ray_o;
float4 p1 = v1 - ray_o;
float4 p2 = v2 - ray_o;
float4 p3 = v3 - ray_o;
float u_3 = ScTP(q, p0, p1);
float v_3 = ScTP(q, p1, p2);
float w_3 = ScTP(q, p2, p0);
float u_2 = ScTP(q, p1, p0);
float v_2 = ScTP(q, p0, p3);
float w_2 = ScTP(q, p3, p1);
float u_1 = ScTP(q, p2, p3);
float v_1 = ScTP(q, p3, p0);
float w_1 = ScTP(q, p0, p2);
float u_0 = ScTP(q, p3, p2);
float v_0 = ScTP(q, p2, p1);
float w_0 = ScTP(q, p1, p3);
// ABC
if (lface != findex[3]) { if (sameSign(u_3, v_3, w_3)) { face = findex[3]; tet = adjtet[3]; } }
// BAD
if (lface != findex[2]) { if (sameSign(u_2, v_2, w_2)) { face = findex[2]; tet = adjtet[2]; } }
// CDA
if (lface != findex[1]) { if (sameSign(u_1, v_1, w_1)) { face = findex[1]; tet = adjtet[1]; } }
// DCB
if (lface != findex[0]) { if (sameSign(u_0, v_0, w_0)) { face = findex[0]; tet = adjtet[0]; } }
// No face hit
// if (face == 0 && tet == 0) { printf("Error! No exit tet found. \n"); }
}
所以,我自己想出了解决方案,以防万一有人需要,这里是:
__device__ void GetExitTet(float4 ray_o, float4 ray_d, float4* nodes, int32_t findex[4], int32_t adjtet[4], int32_t lface, int32_t &face, int32_t &tet)
{
face = 0;
tet = 0;
// http://realtimecollisiondetection.net/blog/?p=13
// translate Ray to origin and vertices same as ray
float4 q = ray_d;
float4 v0 = make_float4(nodes[0].x, nodes[0].y, nodes[0].z, 0); // A
float4 v1 = make_float4(nodes[1].x, nodes[1].y, nodes[1].z, 0); // B
float4 v2 = make_float4(nodes[2].x, nodes[2].y, nodes[2].z, 0); // C
float4 v3 = make_float4(nodes[3].x, nodes[3].y, nodes[3].z, 0); // D
float4 p0 = v0 - ray_o;
float4 p1 = v1 - ray_o;
float4 p2 = v2 - ray_o;
float4 p3 = v3 - ray_o;
double QAB = ScTP(q, p0, p1); // A B
double QBC = ScTP(q, p1, p2); // B C
double QAC = ScTP(q, p0, p2); // A C
double QAD = ScTP(q, p0, p3); // A D
double QBD = ScTP(q, p1, p3); // B D
double QCD = ScTP(q, p2, p3); // C D
double sQAB = signf(QAB); // A B
double sQBC = signf(QBC); // B C
double sQAC = signf(QAC); // A C
double sQAD = signf(QAD); // A D
double sQBD = signf(QBD); // B D
double sQCD = signf(QCD); // C D
// ABC
if (sQAB != 0 && sQAC !=0 && sQBC != 0)
{
if (sQAB < 0 && sQAC > 0 && sQBC < 0) { face = findex[3]; tet = adjtet[3]; } // exit face
}
// BAD
if (sQAB != 0 && sQAD != 0 && sQBD != 0)
{
if (sQAB > 0 && sQAD < 0 && sQBD > 0) { face = findex[2]; tet = adjtet[2]; } // exit face
}
// CDA
if (sQAD != 0 && sQAC != 0 && sQCD != 0)
{
if (sQAD > 0 && sQAC < 0 && sQCD < 0) { face = findex[1]; tet = adjtet[1]; } // exit face
}
// DCB
if (sQBC != 0 && sQBD != 0 && sQCD != 0)
{
if (sQBC > 0 && sQBD < 0 && sQCD > 0) { face = findex[0]; tet = adjtet[0]; } // exit face
}
// No face hit
// if (face == 0 && tet == 0) { printf("Error! No exit tet found. \n"); }
}
我有一个关于四面体 - 射线相交的问题:
我尝试实施四面体射线相交测试,该测试应该 return 出射面的索引。对于交集,我关注了这个博客 post,其中标量三重乘积用于交集测试:
http://realtimecollisiondetection.net/blog/?p=13
但是,我的代码总是 return 与出口面相同的面。在尝试自己找到解决方案但没有成功之后,我将非常感谢任何提示我的交叉测试中可能存在错误的提示。
输入参数为射线原点和方向、节点、面的索引、相邻四面体的索引和最后一个面的索引。出射面和出射四面体的索引是输出值。 ScTP 计算标量三重乘积,并且 sameSign 检查三个浮点数的符号是否相同。 这是代码,感谢您的帮助:
__device__ void GetExitTet(float4 ray_o, float4 ray_d, float4* nodes, int32_t findex[4], int32_t adjtet[4], int32_t lface, int32_t &face, int32_t &tet)
{
face = 0;
tet = 0;
float4 q = ray_d;
float4 v0 = make_float4(nodes[0].x, nodes[0].y, nodes[0].z, 0); // A
float4 v1 = make_float4(nodes[1].x, nodes[1].y, nodes[1].z, 0); // B
float4 v2 = make_float4(nodes[2].x, nodes[2].y, nodes[2].z, 0); // C
float4 v3 = make_float4(nodes[3].x, nodes[3].y, nodes[3].z, 0); // D
float4 p0 = v0 - ray_o;
float4 p1 = v1 - ray_o;
float4 p2 = v2 - ray_o;
float4 p3 = v3 - ray_o;
float u_3 = ScTP(q, p0, p1);
float v_3 = ScTP(q, p1, p2);
float w_3 = ScTP(q, p2, p0);
float u_2 = ScTP(q, p1, p0);
float v_2 = ScTP(q, p0, p3);
float w_2 = ScTP(q, p3, p1);
float u_1 = ScTP(q, p2, p3);
float v_1 = ScTP(q, p3, p0);
float w_1 = ScTP(q, p0, p2);
float u_0 = ScTP(q, p3, p2);
float v_0 = ScTP(q, p2, p1);
float w_0 = ScTP(q, p1, p3);
// ABC
if (lface != findex[3]) { if (sameSign(u_3, v_3, w_3)) { face = findex[3]; tet = adjtet[3]; } }
// BAD
if (lface != findex[2]) { if (sameSign(u_2, v_2, w_2)) { face = findex[2]; tet = adjtet[2]; } }
// CDA
if (lface != findex[1]) { if (sameSign(u_1, v_1, w_1)) { face = findex[1]; tet = adjtet[1]; } }
// DCB
if (lface != findex[0]) { if (sameSign(u_0, v_0, w_0)) { face = findex[0]; tet = adjtet[0]; } }
// No face hit
// if (face == 0 && tet == 0) { printf("Error! No exit tet found. \n"); }
}
所以,我自己想出了解决方案,以防万一有人需要,这里是:
__device__ void GetExitTet(float4 ray_o, float4 ray_d, float4* nodes, int32_t findex[4], int32_t adjtet[4], int32_t lface, int32_t &face, int32_t &tet)
{
face = 0;
tet = 0;
// http://realtimecollisiondetection.net/blog/?p=13
// translate Ray to origin and vertices same as ray
float4 q = ray_d;
float4 v0 = make_float4(nodes[0].x, nodes[0].y, nodes[0].z, 0); // A
float4 v1 = make_float4(nodes[1].x, nodes[1].y, nodes[1].z, 0); // B
float4 v2 = make_float4(nodes[2].x, nodes[2].y, nodes[2].z, 0); // C
float4 v3 = make_float4(nodes[3].x, nodes[3].y, nodes[3].z, 0); // D
float4 p0 = v0 - ray_o;
float4 p1 = v1 - ray_o;
float4 p2 = v2 - ray_o;
float4 p3 = v3 - ray_o;
double QAB = ScTP(q, p0, p1); // A B
double QBC = ScTP(q, p1, p2); // B C
double QAC = ScTP(q, p0, p2); // A C
double QAD = ScTP(q, p0, p3); // A D
double QBD = ScTP(q, p1, p3); // B D
double QCD = ScTP(q, p2, p3); // C D
double sQAB = signf(QAB); // A B
double sQBC = signf(QBC); // B C
double sQAC = signf(QAC); // A C
double sQAD = signf(QAD); // A D
double sQBD = signf(QBD); // B D
double sQCD = signf(QCD); // C D
// ABC
if (sQAB != 0 && sQAC !=0 && sQBC != 0)
{
if (sQAB < 0 && sQAC > 0 && sQBC < 0) { face = findex[3]; tet = adjtet[3]; } // exit face
}
// BAD
if (sQAB != 0 && sQAD != 0 && sQBD != 0)
{
if (sQAB > 0 && sQAD < 0 && sQBD > 0) { face = findex[2]; tet = adjtet[2]; } // exit face
}
// CDA
if (sQAD != 0 && sQAC != 0 && sQCD != 0)
{
if (sQAD > 0 && sQAC < 0 && sQCD < 0) { face = findex[1]; tet = adjtet[1]; } // exit face
}
// DCB
if (sQBC != 0 && sQBD != 0 && sQCD != 0)
{
if (sQBC > 0 && sQBD < 0 && sQCD > 0) { face = findex[0]; tet = adjtet[0]; } // exit face
}
// No face hit
// if (face == 0 && tet == 0) { printf("Error! No exit tet found. \n"); }
}