我正在寻找在一个圆锥体(底部是圆的。所以它基本上是一个球体的一部分)和一个盒子之间实现碰撞检测。我不太在意它是 AABB 还是 OBB,因为转换应该足够简单。我找到的每个解决方案都使用三角形锥体,但我的锥体更像是一个具有角度和距离的“弧”。
是否有一个简单的解决方案来进行这种碰撞检测?还是进行多种类型的测试? IE。比如在一个球体上获取交点,r 是我的圆锥距离,然后测试它们是否在一个角度内相交或其他什么?
最佳答案
无论如何,我很好奇并计划以 GLSL 数学风格做这件事所需的东西。所以这里有不同的方法。让我们考虑一下圆锥的定义:
您需要支持点、线、三角形、凸三角网格、球面(圆锥)。
对于
triangle
任何边和点之间的交叉结果 - 边原点应该指向三角形的同一侧(如正常)。如果不是点在外面。对于
convex mesh
对于所有面,点面原点和面法线指向之间的点积应 <= 0。对于
cone
该点应在球体半径内,锥轴与点锥原点之间的角度应<= ang。再次点积可用于此。这就像在形成一条线的每个图元上找到最近的点。它类似于垂直距离。
point-point
这很容易,因为它们是最近的线路。point-line
可以使用将点投影到线上(点积)来完成。但是,您需要限制结果,使其位于行内,而不是外推。point-triangle
可以作为所有圆周线与点组合的最小值以及到表面的垂直距离(与三角形法线的点积)获得。所有其他原语组合都可以从这些基本组合构建。
只需在圆锥球体中心和网格之间使用最近的线。如果线位于圆锥内,则将其缩短球体半径 R。这将考虑所有帽相互作用。
然后在锥体表面上测试线,沿其圆周取样,从锥体球心开始,到最外圈(锥体和盖子之间的边缘)结束。如果您需要更好的精度,您也可以测试三角形。
这很容易,只需计算网格和圆锥之间的最近留置权。然后测试它在网格侧的点是否在圆锥内。
检查
`bool intersect(convex_mesh m0,spherical_sector s0);`
在下面的代码中实现。这里是小的 C++/OpenGL 示例(使用 GLSL 风格的数学) :
//---------------------------------------------------------------------------
//--- GL geometry -----------------------------------------------------------
//---------------------------------------------------------------------------
#ifndef _gl_geometry_h
#define _gl_geometry_h
//---------------------------------------------------------------------------
const float deg=M_PI/180.0;
const float rad=180.0/M_PI;
float divide(float a,float b){ if (fabs(b)<1e-10) return 0.0; else return a/b; }
double divide(double a,double b){ if (fabs(b)<1e-10) return 0.0; else return a/b; }
#include "GLSL_math.h"
#include "List.h"
//---------------------------------------------------------------------------
class point
{
public:
// cfg
vec3 p0;
point() {}
point(point& a) { *this=a; }
~point() {}
point* operator = (const point *a) { *this=*a; return this; }
//point* operator = (const point &a) { ...copy... return this; }
point(vec3 _p0)
{
p0=_p0;
compute();
}
void compute(){};
void draw()
{
glBegin(GL_POINTS);
glVertex3fv(p0.dat);
glEnd();
}
};
//---------------------------------------------------------------------------
class axis
{
public:
// cfg
vec3 p0,dp;
axis() {}
axis(axis& a) { *this=a; }
~axis() {}
axis* operator = (const axis *a) { *this=*a; return this; }
//axis* operator = (const axis &a) { ...copy... return this; }
axis(vec3 _p0,vec3 _dp)
{
p0=_p0;
dp=_dp;
compute();
}
void compute()
{
dp=normalize(dp);
}
void draw()
{
vec3 p; p=p0+100.0*dp;
glBegin(GL_LINES);
glVertex3fv(p0.dat);
glVertex3fv(p .dat);
glEnd();
}
};
//---------------------------------------------------------------------------
class line
{
public:
// cfg
vec3 p0,p1;
// computed
float l;
vec3 dp;
line() {}
line(line& a) { *this=a; }
~line() {}
line* operator = (const line *a) { *this=*a; return this; }
//line* operator = (const line &a) { ...copy... return this; }
line(vec3 _p0,vec3 _p1)
{
p0=_p0;
p1=_p1;
compute();
}
void swap()
{
vec3 p=p0; p0=p1; p1=p;
}
void compute()
{
dp=p1-p0;
l=length(dp);
}
void draw()
{
glBegin(GL_LINES);
glVertex3fv(p0.dat);
glVertex3fv(p1.dat);
glEnd();
}
};
//---------------------------------------------------------------------------
class triangle
{
public:
// cfg
vec3 p0,p1,p2;
// computed
vec3 n;
triangle() {}
triangle(triangle& a) { *this=a; }
~triangle() {}
triangle* operator = (const triangle *a) { *this=*a; return this; }
//triangle* operator = (const triangle &a) { ...copy... return this; }
triangle(vec3 _p0,vec3 _p1,vec3 _p2)
{
p0=_p0;
p1=_p1;
p2=_p2;
compute();
}
void swap()
{
vec3 p=p1; p1=p2; p2=p;
n=-n;
}
void compute()
{
n=normalize(cross(p1-p0,p2-p1));
}
void draw()
{
glBegin(GL_TRIANGLES);
glNormal3fv(n.dat);
glVertex3fv(p0.dat);
glVertex3fv(p1.dat);
glVertex3fv(p2.dat);
glEnd();
}
};
//---------------------------------------------------------------------------
class convex_mesh
{
public:
// cfg
List<triangle> tri;
// computed
vec3 p0; // center
convex_mesh() { tri.num=0; }
convex_mesh(convex_mesh& a) { *this=a; }
~convex_mesh() {}
convex_mesh* operator = (const convex_mesh *a) { *this=*a; return this; }
//convex_mesh* operator = (const convex_mesh &a) { ...copy... return this; }
void init_box(vec3 _p0,vec3 _u,vec3 _v,vec3 _w) // center, half sizes
{
const vec3 p[8]=
{
_p0-_u+_v-_w,
_p0+_u+_v-_w,
_p0+_u-_v-_w,
_p0-_u-_v-_w,
_p0-_u-_v+_w,
_p0+_u-_v+_w,
_p0+_u+_v+_w,
_p0-_u+_v+_w,
};
const int ix[36]=
{
0,1,2,0,2,3,
4,5,6,4,6,7,
3,2,5,3,5,4,
2,1,6,2,6,5,
1,0,7,1,7,6,
0,3,4,0,4,7,
};
tri.num=0;
for (int i=0;i<36;i+=3) tri.add(triangle(p[ix[i+0]],p[ix[i+1]],p[ix[i+2]]));
compute();
}
void compute()
{
int i,n;
p0=vec3(0.0,0.0,0.0);
if (!tri.num) return;
for (i=0,n=0;i<tri.num;i++,n+=3)
{
p0+=tri.dat[i].p0;
p0+=tri.dat[i].p1;
p0+=tri.dat[i].p2;
} p0/=float(n);
for (i=0;i<tri.num;i++)
if (dot(tri.dat[i].p0-p0,tri.dat[i].n)<0.0)
tri.dat[i].swap();
}
void draw()
{
int i;
glBegin(GL_TRIANGLES);
for (i=0;i<tri.num;i++) tri.dat[i].draw();
glEnd();
}
};
//---------------------------------------------------------------------------
class spherical_sector
{
public:
// cfg
vec3 p0,p1;
float ang;
// computed
vec3 dp;
float r,R;
spherical_sector() {}
spherical_sector(spherical_sector& a) { *this=a; }
~spherical_sector() {}
spherical_sector* operator = (const spherical_sector *a) { *this=*a; return this; }
//spherical_sector* operator = (const spherical_sector &a) { ...copy... return this; }
spherical_sector(vec3 _p0,vec3 _p1,float _ang)
{
p0=_p0;
p1=_p1;
ang=_ang;
compute();
}
void compute()
{
dp=p1-p0;
R=length(dp);
r=R*tan(ang);
}
void draw()
{
const int N=32;
const int M=16;
vec3 pnt[M][N]; // points
vec3 n0[N]; // normals for cine
vec3 n1[M][N]; // normals for cap
int i,j;
float a,b,da,db,ca,sa,cb,sb;
vec3 q,u,v,w;
// basis vectors
w=normalize(dp); u=vec3(1.0,0.0,0.0);
if (fabs(dot(u,w))>0.75) u=vec3(0.0,1.0,0.0);
v=cross(u,w);
u=cross(v,w);
u=normalize(u);
v=normalize(v);
// compute tables
da=2.0*M_PI/float(N-1);
db=ang/float(M-1);
for (a=0.0,i=0;i<N;i++,a+=da)
{
ca=cos(a);
sa=sin(a);
n0[i]=u*ca+v*sa;
for (b=0.0,j=0;j<M;j++,b+=db)
{
cb=cos(b);
sb=sin(b);
q=vec3(ca*sb,sa*sb,cb);
pnt[j][i]=p0+((q.x*u+q.y*v+q.z*w)*R);
n1[j][i]=normalize(pnt[j][i]);
}
}
// render
glBegin(GL_TRIANGLES);
for (i=1,j=M-1;i<N;i++)
{
glNormal3fv(n0[i].dat); // p0 should have average 0.5*(n0[i]+n0[i-1]) as nomal
glVertex3fv(p0.dat);
glVertex3fv(pnt[j][i+0].dat);
glNormal3fv(n0[i-1].dat);
glVertex3fv(pnt[j][i-1].dat);
glNormal3fv( n1[0][0].dat);
glVertex3fv(pnt[0][0].dat);
glNormal3fv( n1[1][i-1].dat);
glVertex3fv(pnt[1][i-1].dat);
glNormal3fv( n1[1][i+0].dat);
glVertex3fv(pnt[1][i+0].dat);
}
glEnd();
glBegin(GL_QUADS);
for (i=0;i<N;i++)
for (j=2;j<M;j++)
{
glNormal3fv( n1[j-1][i+0].dat);
glVertex3fv(pnt[j-1][i+0].dat);
glNormal3fv( n1[j-1][i-1].dat);
glVertex3fv(pnt[j-1][i-1].dat);
glNormal3fv( n1[j+0][i-1].dat);
glVertex3fv(pnt[j+0][i-1].dat);
glNormal3fv( n1[j+0][i+0].dat);
glVertex3fv(pnt[j+0][i+0].dat);
}
glEnd();
}
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
bool inside(point p0,triangle t0);
bool inside(point p0,convex_mesh m0);
bool inside(point p0,spherical_sector s0);
//---------------------------------------------------------------------------
line closest(point p0,axis a0);
line closest(point p0,line l0);
line closest(point p0,triangle t0);
line closest(point p0,convex_mesh m0);
//---------------------------------------------------------------------------
line closest(axis a0,point p0);
line closest(axis a0,axis a1);
line closest(axis a0,line l1);
line closest(axis a0,triangle t0);
line closest(axis a0,convex_mesh m0);
//---------------------------------------------------------------------------
line closest(line l0,point p0);
line closest(line l0,axis a0);
line closest(line l0,line l1);
line closest(line l0,triangle t0);
line closest(line l0,convex_mesh m0);
//---------------------------------------------------------------------------
line closest(triangle t0,point p0);
line closest(triangle t0,axis a0);
line closest(triangle t0,line l0);
line closest(triangle t0,triangle t1);
line closest(triangle t0,convex_mesh m0);
//---------------------------------------------------------------------------
line closest(convex_mesh m0,point p0);
line closest(convex_mesh m0,axis a0);
line closest(convex_mesh m0,line l0);
line closest(convex_mesh m0,triangle t0);
line closest(convex_mesh m0,spherical_sector s0);
//---------------------------------------------------------------------------
bool intersect(convex_mesh m0,spherical_sector s0);
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
bool inside(point p0,triangle t0)
{
if (fabs(dot(p0.p0-t0.p0,t0.n))>1e-6) return false;
float d0,d1,d2;
d0=dot(t0.n,cross(p0.p0-t0.p0,t0.p1-t0.p0));
d1=dot(t0.n,cross(p0.p0-t0.p1,t0.p2-t0.p1));
d2=dot(t0.n,cross(p0.p0-t0.p2,t0.p0-t0.p2));
if (d0*d1<-1e-6) return false;
if (d0*d2<-1e-6) return false;
if (d1*d2<-1e-6) return false;
return true;
}
bool inside(point p0,convex_mesh m0)
{
for (int i=0;i<m0.tri.num;i++)
if (dot(p0.p0-m0.tri.dat[i].p0,m0.tri.dat[i].n)>0.0)
return false;
return true;
}
bool inside(point p0,spherical_sector s0)
{
float t,l;
vec3 u;
u=p0.p0-s0.p0;
l=length(u);
if (l>s0.R) return false;
t=divide(dot(u,s0.dp),(l*s0.R));
if (t<cos(s0.ang)) return false;
return true;
}
//---------------------------------------------------------------------------
line closest(point p0,axis a0){ return line(p0.p0,a0.p0+(a0.dp*dot(p0.p0-a0.p0,a0.dp))); }
line closest(point p0,line l0)
{
float t=dot(p0.p0-l0.p0,l0.dp);
if (t<0.0) t=0.0;
if (t>1.0) t=1.0;
return line(p0.p0,l0.p0+(l0.dp*t));
}
line closest(point p0,triangle t0)
{
float t;
point p;
line cl,ll;
cl.l=1e300;
t=dot(p0.p0-t0.p0,t0.n); p=p0.p0-t*t0.n; if ((fabs(t)>1e-6)&&(inside(p,t0))){ ll=line(p0.p0,p.p0); if (cl.l>ll.l) cl=ll; }
ll=closest(p0,line(t0.p0,t0.p1)); if (cl.l>ll.l) cl=ll;
ll=closest(p0,line(t0.p1,t0.p2)); if (cl.l>ll.l) cl=ll;
ll=closest(p0,line(t0.p2,t0.p0)); if (cl.l>ll.l) cl=ll;
return cl;
}
line closest(point p0,convex_mesh m0)
{
int i;
line cl,ll;
cl=line(vec3(0.0,0.0,0.0),vec3(0.0,0.0,0.0)); cl.l=1e300;
for (i=0;i<m0.tri.num;i++)
{
ll=closest(p0,m0.tri.dat[i]);
if (cl.l>ll.l) cl=ll;
}
return cl;
}
//---------------------------------------------------------------------------
line closest(axis a0,point p0){ line cl; cl=closest(p0,a0); cl.swap(); return cl; }
line closest(axis a0,axis a1)
{
vec3 u=a0.dp;
vec3 v=a1.dp;
vec3 w=a0.p0-a1.p0;
float a=dot(u,u); // always >= 0
float b=dot(u,v);
float c=dot(v,v); // always >= 0
float d=dot(u,w);
float e=dot(v,w);
float D=a*c-b*b; // always >= 0
float t0,t1;
// compute the line parameters of the two closest points
if (D<1e-6) // the lines are almost parallel
{
t0=0.0;
t1=(b>c ? d/b : e/c); // use the largest denominator
}
else{
t0=(b*e-c*d)/D;
t1=(a*e-b*d)/D;
}
return line(a0.p0+(a0.dp*t0),a1.p0+(a1.dp*t1));
}
line closest(axis a0,line l1)
{
vec3 u=a0.dp;
vec3 v=l1.dp;
vec3 w=a0.p0-l1.p0;
float a=dot(u,u); // always >= 0
float b=dot(u,v);
float c=dot(v,v); // always >= 0
float d=dot(u,w);
float e=dot(v,w);
float D=a*c-b*b; // always >= 0
float t0,t1;
// compute the line parameters of the two closest points
if (D<1e-6) // the lines are almost parallel
{
t0=0.0;
t1=(b>c ? d/b : e/c); // use the largest denominator
}
else{
t0=(b*e-c*d)/D;
t1=(a*e-b*d)/D;
}
if (t1<0.0) t1=0.0;
if (t1>1.0) t1=1.0;
return line(a0.p0+(a0.dp*t0),l1.p0+(l1.dp*t1));
}
line closest(axis a0,triangle t0)
{
line cl,ll;
cl=closest(a0,line(t0.p0,t0.p1));
ll=closest(a0,line(t0.p1,t0.p2)); if (cl.l>ll.l) cl=ll;
ll=closest(a0,line(t0.p2,t0.p0)); if (cl.l>ll.l) cl=ll;
return cl;
}
line closest(axis a0,convex_mesh m0)
{
int i;
line cl,ll;
cl=line(vec3(0.0,0.0,0.0),vec3(0.0,0.0,0.0)); cl.l=1e300;
for (i=0;i<m0.tri.num;i++)
{
ll=closest(a0,m0.tri.dat[i]);
if (cl.l>ll.l) cl=ll;
}
return cl;
}
//---------------------------------------------------------------------------
line closest(line l0,point p0){ line cl; cl=closest(p0,l0); cl.swap(); return cl; }
line closest(line l0,axis a0) { line cl; cl=closest(a0,l0); cl.swap(); return cl; }
line closest(line l0,line l1)
{
vec3 u=l0.p1-l0.p0;
vec3 v=l1.p1-l1.p0;
vec3 w=l0.p0-l1.p0;
float a=dot(u,u); // always >= 0
float b=dot(u,v);
float c=dot(v,v); // always >= 0
float d=dot(u,w);
float e=dot(v,w);
float D=a*c-b*b; // always >= 0
float t0,t1;
// compute the line parameters of the two closest points
if (D<1e-6) // the lines are almost parallel
{
t0=0.0;
t1=(b>c ? d/b : e/c); // use the largest denominator
}
else{
t0=(b*e-c*d)/D;
t1=(a*e-b*d)/D;
}
if (t0<0.0) t0=0.0;
if (t0>1.0) t0=1.0;
if (t1<0.0) t1=0.0;
if (t1>1.0) t1=1.0;
return line(l0.p0+(l0.dp*t0),l1.p0+(l1.dp*t1));
}
line closest(line l0,triangle t0)
{
float t;
point p;
line cl,ll;
cl.l=1e300;
t=dot(l0.p0-t0.p0,t0.n); p=l0.p0-t*t0.n; if ((fabs(t)>1e-6)&&(inside(p,t0))){ ll=line(l0.p0,p.p0); if (cl.l>ll.l) cl=ll; }
t=dot(l0.p1-t0.p0,t0.n); p=l0.p1-t*t0.n; if ((fabs(t)>1e-6)&&(inside(p,t0))){ ll=line(l0.p1,p.p0); if (cl.l>ll.l) cl=ll; }
ll=closest(l0,line(t0.p0,t0.p1)); if (cl.l>ll.l) cl=ll;
ll=closest(l0,line(t0.p1,t0.p2)); if (cl.l>ll.l) cl=ll;
ll=closest(l0,line(t0.p2,t0.p0)); if (cl.l>ll.l) cl=ll;
return cl;
}
line closest(line l0,convex_mesh m0)
{
int i;
line cl,ll;
cl=line(vec3(0.0,0.0,0.0),vec3(0.0,0.0,0.0)); cl.l=1e300;
for (i=0;i<m0.tri.num;i++)
{
ll=closest(l0,m0.tri.dat[i]);
if (cl.l>ll.l) cl=ll;
}
return cl;
}
//---------------------------------------------------------------------------
line closest(triangle t0,point p0){ line cl; cl=closest(p0,t0); cl.swap(); return cl; }
line closest(triangle t0,axis a0) { line cl; cl=closest(a0,t0); cl.swap(); return cl; }
line closest(triangle t0,line l0) { line cl; cl=closest(l0,t0); cl.swap(); return cl; }
line closest(triangle t0,triangle t1)
{
float t;
point p;
line l0,l1,l2,l3,l4,l5,cl,ll;
l0=line(t0.p0,t0.p1); l3=line(t1.p0,t1.p1);
l1=line(t0.p1,t0.p2); l4=line(t1.p1,t1.p2);
l2=line(t0.p2,t0.p0); l5=line(t1.p2,t1.p0);
cl.l=1e300;
t=dot(t0.p0-t1.p0,t1.n); p=t0.p0-t*t1.n; if ((fabs(t)>1e-6)&&(inside(p,t1))){ ll=line(t0.p0,p.p0); if (cl.l>ll.l) cl=ll; }
t=dot(t0.p1-t1.p0,t1.n); p=t0.p1-t*t1.n; if ((fabs(t)>1e-6)&&(inside(p,t1))){ ll=line(t0.p1,p.p0); if (cl.l>ll.l) cl=ll; }
t=dot(t0.p2-t1.p0,t1.n); p=t0.p2-t*t1.n; if ((fabs(t)>1e-6)&&(inside(p,t1))){ ll=line(t0.p2,p.p0); if (cl.l>ll.l) cl=ll; }
t=dot(t1.p0-t0.p0,t0.n); p=t1.p0-t*t0.n; if ((fabs(t)>1e-6)&&(inside(p,t0))){ ll=line(p.p0,t1.p0); if (cl.l>ll.l) cl=ll; }
t=dot(t1.p1-t0.p0,t0.n); p=t1.p1-t*t0.n; if ((fabs(t)>1e-6)&&(inside(p,t0))){ ll=line(p.p0,t1.p1); if (cl.l>ll.l) cl=ll; }
t=dot(t1.p2-t0.p0,t0.n); p=t1.p2-t*t0.n; if ((fabs(t)>1e-6)&&(inside(p,t0))){ ll=line(p.p0,t1.p2); if (cl.l>ll.l) cl=ll; }
ll=closest(l0,l3); if (cl.l>ll.l) cl=ll;
ll=closest(l0,l4); if (cl.l>ll.l) cl=ll;
ll=closest(l0,l5); if (cl.l>ll.l) cl=ll;
ll=closest(l1,l3); if (cl.l>ll.l) cl=ll;
ll=closest(l1,l4); if (cl.l>ll.l) cl=ll;
ll=closest(l1,l5); if (cl.l>ll.l) cl=ll;
ll=closest(l2,l3); if (cl.l>ll.l) cl=ll;
ll=closest(l2,l4); if (cl.l>ll.l) cl=ll;
ll=closest(l2,l5); if (cl.l>ll.l) cl=ll;
return cl;
}
line closest(triangle t0,convex_mesh m0)
{
int i;
line cl,ll;
cl=line(vec3(0.0,0.0,0.0),vec3(0.0,0.0,0.0)); cl.l=1e300;
for (i=0;i<m0.tri.num;i++)
{
ll=closest(m0.tri.dat[i],t0);
if (cl.l>ll.l) cl=ll;
}
return cl;
}
//---------------------------------------------------------------------------
line closest(convex_mesh m0,point p0) { line cl; cl=closest(p0,m0); cl.swap(); return cl; }
line closest(convex_mesh m0,axis a0) { line cl; cl=closest(a0,m0); cl.swap(); return cl; }
line closest(convex_mesh m0,line l0) { line cl; cl=closest(l0,m0); cl.swap(); return cl; }
line closest(convex_mesh m0,triangle t0){ line cl; cl=closest(t0,m0); cl.swap(); return cl; }
line closest(convex_mesh m0,convex_mesh m1)
{
int i0,i1;
line cl,ll;
cl=line(vec3(0.0,0.0,0.0),vec3(0.0,0.0,0.0)); cl.l=1e300;
for (i0=0;i0<m0.tri.num;i0++)
for (i1=0;i1<m1.tri.num;i1++)
{
ll=closest(m0.tri.dat[i0],m1.tri.dat[i1]);
if (cl.l>ll.l) cl=ll;
}
return cl;
}
line closest(convex_mesh m0,spherical_sector s0)
{
int i,N=18;
float a,da,ca,sa,cb,sb;
vec3 u,v,w,q;
line cl,ll;
// cap
ll=closest(m0,point(s0.p0)); // sphere
if (dot(ll.dp,s0.dp)/(ll.l*s0.R)>=cos(s0.ang)) // cap
ll=line(ll.p0,ll.p1+(ll.dp*s0.R/ll.l));
cl=ll;
// cone
w=normalize(s0.dp); u=vec3(1.0,0.0,0.0);
if (fabs(dot(u,w))>0.75) u=vec3(0.0,1.0,0.0);
v=cross(u,w);
u=cross(v,w);
u=normalize(u)*s0.r;
v=normalize(v)*s0.r;
da=2.0*M_PI/float(N-1);
cb=cos(s0.ang);
sb=sin(s0.ang);
for (a=0.0,i=0;i<N;i++)
{
ca=cos(a);
sa=sin(a);
q=vec3(ca*sb,sa*sb,cb);
q=s0.p0+((q.x*u+q.y*v+q.z*w)*s0.R);
ll=line(s0.p0,q);
ll=closest(m0,ll);
if (cl.l>ll.l) cl=ll;
}
return cl;
}
//---------------------------------------------------------------------------
bool intersect(convex_mesh m0,spherical_sector s0)
{
line cl;
cl=closest(m0,s0);
if (cl.l<=1e-6) return true;
if (inside(cl.p0,s0)) return true;
return false;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
GLSL 数学可以由 this 创建或使用 GLM 或其他任何东西。我还使用了我的动态列表模板(只是将三角形列表存储在网格中),所以:
List<double> xxx;
与 double xxx[];
相同xxx.add(5);
添加 5
到列表末尾xxx[7]
访问数组元素(安全)xxx.dat[7]
访问数组元素(不安全但快速的直接访问)xxx.num
是数组的实际使用大小xxx.reset()
清除数组并设置 xxx.num=0
xxx.allocate(100)
为 100
预分配空间项目您可以使用您可以使用的任何列表。
在这里测试预览测试这个的正确性:
锥体根据相交测试的结果旋转并改变颜色。黄线是最近的线结果。
我在这个周末为了好玩而破坏了它,所以它还没有经过广泛的测试,并且可能仍然存在未处理的边缘情况。
我希望代码尽可能可读,所以它根本没有优化。我也没有过多评论(因为低级原语和基本向量数学应该足够明显,如果不是你应该在实现这样的东西之前先学习)
[编辑1]
看来我搞砸了
closest
测试忽略一些边缘情况..它需要重大返工(对所有相关功能应用修复)我现在没有足够的时间(一旦完成将更新代码)所以现在这里快速修复线与线仅最接近的测试:line3D closest(line3D l0,line3D l1)
{
vec3 u=l0.p1-l0.p0;
vec3 v=l1.p1-l1.p0;
vec3 w=l0.p0-l1.p0;
float a=dot(u,u); // always >= 0
float b=dot(u,v);
float c=dot(v,v); // always >= 0
float d=dot(u,w);
float e=dot(v,w);
float D=a*c-b*b; // always >= 0
float t0,t1;
point3D p;
line3D r,rr;
int f; // check distance perpendicular to: 1: l0, 2: l1
f=0; r.l=-1.0;
// compute the line3D parameters of the two closest points
if (D<acc_dot) f=3; // the lines are almost parallel
else{
t0=(b*e-c*d)/D;
t1=(a*e-b*d)/D;
if (t0<0.0){ f|=1; t0=0.0; }
if (t0>1.0){ f|=1; t0=1.0; }
if (t1<0.0){ f|=2; t1=0.0; }
if (t1>1.0){ f|=2; t1=1.0; }
r=line3D(l0.p0+(l0.dp*t0),l1.p0+(l1.dp*t1));
}
// check perpendicular distance from each endpoint marked in f
if (int(f&1))
{
t0=0.0;
t1=divide(dot(l0.p0-l1.p0,l1.dp),l1.l*l1.l);
if (t1<0.0) t1=0.0;
if (t1>1.0) t1=1.0;
rr=line3D(l0.p0+(l0.dp*t0),l1.p0+(l1.dp*t1));
if ((r.l<0.0)||(r.l>rr.l)) r=rr;
t0=1.0;
t1=divide(dot(l0.p1-l1.p0,l1.dp),l1.l*l1.l);
if (t1<0.0) t1=0.0;
if (t1>1.0) t1=1.0;
rr=line3D(l0.p0+(l0.dp*t0),l1.p0+(l1.dp*t1));
if ((r.l<0.0)||(r.l>rr.l)) r=rr;
}
if (int(f&2))
{
t1=0.0;
t0=divide(dot(l1.p0-l0.p0,l0.dp),l0.l*l0.l);
if (t0<0.0) t0=0.0;
if (t0>1.0) t0=1.0;
rr=line3D(l0.p0+(l0.dp*t0),l1.p0+(l1.dp*t1));
if ((r.l<0.0)||(r.l>rr.l)) r=rr;
t1=1.0;
t0=divide(dot(l1.p1-l0.p0,l0.dp),l0.l*l0.l);
if (t0<0.0) t0=0.0;
if (t0>1.0) t0=1.0;
rr=line3D(l0.p0+(l0.dp*t0),l1.p0+(l1.dp*t1));
if ((r.l<0.0)||(r.l>rr.l)) r=rr;
}
return r;
}
关于math - 锥盒碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62145967/