Java OpenGL从x和y计算z坐标
假设我用点a(0,0,a)B(1,0,B)C(1,1,C)和D(0,1,D)画了一个四边形,想找出坐标p(0.6,0.25,p),我该怎么做?我希望我错过了一些处理器不那么重的东西,因为到目前为止,我一直在尝试取A.x和B.x,然后是C.x和D.x的差异,然后找出它们之间的差异,这一切都有点混乱 例如,假设我想找到鼠标在图片中的位置: 是否有一种更简单或不太占用处理器的方法来找到这一点?Java OpenGL从x和y计算z坐标,java,opengl,Java,Opengl,假设我用点a(0,0,a)B(1,0,B)C(1,1,C)和D(0,1,D)画了一个四边形,想找出坐标p(0.6,0.25,p),我该怎么做?我希望我错过了一些处理器不那么重的东西,因为到目前为止,我一直在尝试取A.x和B.x,然后是C.x和D.x的差异,然后找出它们之间的差异,这一切都有点混乱 例如,假设我想找到鼠标在图片中的位置: 是否有一种更简单或不太占用处理器的方法来找到这一点? (不是拾取或光线投射,因为鼠标不会在那里,例如,鼠标只是指向我希望它发生的地方)仅供参考:使用光线投射应该
(不是拾取或光线投射,因为鼠标不会在那里,例如,鼠标只是指向我希望它发生的地方)仅供参考:使用光线投射应该足以完成您所寻找的任务。您需要旋转支点的透视图,以从模型位置的绝对0和绝对1开始聚焦。如果您想用另一种方法快速检查,重心坐标也很有用 使用重心坐标可以确定三角形内的点:
function pointInTriangle(x1, y1, x2, y2, x3, y3, x, y:Number):Boolean
{
var denominator:Number = ((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3));
var a:Number = ((y2 - y3)*(x - x3) + (x3 - x2)*(y - y3)) / denominator;
var b:Number = ((y3 - y1)*(x - x3) + (x1 - x3)*(y - y3)) / denominator;
var c:Number = 1 - a - b;
return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1;
}
函数点三角形(x1,y1,x2,y2,x3,y3,x,y:Number):布尔值
{
var分母:数字=((y2-y3)*(x1-x3)+(x3-x2)*(y1-y3));
变量a:数字=((y2-y3)*(x-x3)+(x3-x2)*(y-y3))/分母;
变量b:数字=((y3-y1)*(x-x3)+(x1-x3)*(y-y3))/分母;
变量c:数值=1-a-b;
return 0这不是最漂亮的读物,但是这里有一些你想要做的事情的示例。一个可下载的项目可能对你更有用,但我不确定我是否可以在这里发布所有这些
(这是基本的光线三角形相交)
使用OpenGL(下面是C++代码)
您希望在OpenGL之外复制的代码的关键部分(如果未使用glaux.lib):
应创建基本碰撞类:
class CCollision
{
public:
CVec vnear; // Where is 0 and where is 100% of fulcrum
CVec vfar;
public:
CCollision(void);
~CCollision(void);
public:
bool checkLine (CVec &v1, CVec &v2,CVec &v3, CVec &p );
bool checkLine( float *triangle, CVec &p );
bool checkLine( float* v1, float* v2, float* v3, CVec &p );
void projectRay ( int x, int y );
};
定义如下:
CCollision::CCollision(void){}
CCollision::~CCollision(void){}
bool CCollision::checkLine( float *triangle, CVec &p )
{
CVec p1 = CVec( triangle[0], triangle[1], triangle[2] );
CVec p2 = CVec( triangle[3], triangle[4], triangle[5] );
CVec p3 = CVec( triangle[6], triangle[7], triangle[8] );
return checkLine( p1, p2, p3, p );
}
bool CCollision::checkLine( float *v1, float *v2, float *v3, CVec &p )
{
CVec p1 = CVec( v1[0], v1[1], v1[2] );
CVec p2 = CVec( v2[0], v2[1], v2[2] );
CVec p3 = CVec( v3[0], v3[1], v3[2] );
return checkLine( p1, p2, p3, p );
}
bool CCollision::checkLine( CVec &v1, CVec &v2, CVec &v3, CVec &p )
{
CVec sect;
// Find Triangle Normal, then normalize it (use Magnitude)
CVec Normal;
Normal = ( v2 - v1 )%( v3 - v1 );
Normal.Normalize(); // Normalize
// Find the distance to the plane, based on the Normal.
float distanceNear = (vnear-v1)^Normal;
float distanceFar = (vfar-v1)^Normal;
if (( (distanceNear * distanceFar) >= 0.0f)||( distanceNear == distanceFar))
return false; // Are they equal?
// Find exact intersection point.
sect = vnear + (vfar-vnear) * ( -distanceNear/(distanceFar-distanceNear) );
// Check all points against the Normalized vector.
CVec v;
// Point 1
v = Normal%( v2-v1 );
if ( (v^( sect-v1 )) < 0.0f )
return false;
// Point 2
v = Normal%( v3-v2 );
if ( (v^( sect-v2 )) < 0.0f )
return false;
// Point 3
v = Normal%( v1-v3 );
if ( (v^( sect-v1 )) < 0.0f )
return false;
// Lastly, lets set the intersection point.
p = sect;
return true;
}
void CCollision::projectRay( int x, int y )
{
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLdouble PosX, PosY, x1, x2, x3;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview );
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
PosX = (float)x;
PosY = (float)viewport[3] - (float)y;
gluUnProject( PosX, PosY, 0, modelview, projection, viewport, &x1, &x2, &x3);
vnear.x = (float)x1; vnear.y = (float)x2; vnear.z = (float)x3;
gluUnProject( PosX, PosY, 1.0, modelview, projection, viewport, &x1, &x2, &x3);
vfar.x = (float)x1; vfar.y = (float)x2; vfar.z = (float)x3;
}
));
}
这将是使用鼠标点击作为捕获,尽管我们希望在所有现实中都从透视矩阵进行捕获
上面的代码来自我在2005年写的一个工作的地形生成器
或者,另一种方法是运行我之前提供的inTriangle代码,然后检测三角形每一侧的坡度。这需要滚动所有点
更好的方法是创建一个透视矩阵,就像我们上面描述的那样。有关所需操作的可视示例:
旋转摄像机,使其直接向下观看播放器
(c) ------>玩家[(地形)
现在,使用我最初发布的相同概念,你可以通过从透视图中创建一个近/远向量来识别相交点。这不需要绘制,但你正在向精确的点投射光线。天哪,看起来很复杂……对,所以我正试着计算出绘制的四边形的z值,该四边形位于一个实体下面,它将移动过去。如果我仍然可以进行光线投射,我很想这样做,因为多年来我一直觉得它很有用,但我会看看我是否可以提取一些旧代码来帮助你。我过去做过。光线投射既快速又准确。但是我如何从世界上的一个点进行光线投射?我无法思考,我目前的光线投射方法也无法思考我使用的生成实体只在屏幕上工作你使用的是什么图形库?LWJGL,但我可以从任何有足够时间的东西进行转换,我已经尝试了大约6个小时,任何帮助都是有帮助的,坦率地说,我将首先尝试这段代码,我在cpp中有cpp和opengl的经验,所以一切都应该顺利。看起来这是完美的,我唯一没有得到的是LOWORD(((LPARAM*)m.LPARAM.ToPointer())、HIWORD((LPARAM*)m.LPARAM.ToPointer())这是什么意思?
CCollision::CCollision(void){}
CCollision::~CCollision(void){}
bool CCollision::checkLine( float *triangle, CVec &p )
{
CVec p1 = CVec( triangle[0], triangle[1], triangle[2] );
CVec p2 = CVec( triangle[3], triangle[4], triangle[5] );
CVec p3 = CVec( triangle[6], triangle[7], triangle[8] );
return checkLine( p1, p2, p3, p );
}
bool CCollision::checkLine( float *v1, float *v2, float *v3, CVec &p )
{
CVec p1 = CVec( v1[0], v1[1], v1[2] );
CVec p2 = CVec( v2[0], v2[1], v2[2] );
CVec p3 = CVec( v3[0], v3[1], v3[2] );
return checkLine( p1, p2, p3, p );
}
bool CCollision::checkLine( CVec &v1, CVec &v2, CVec &v3, CVec &p )
{
CVec sect;
// Find Triangle Normal, then normalize it (use Magnitude)
CVec Normal;
Normal = ( v2 - v1 )%( v3 - v1 );
Normal.Normalize(); // Normalize
// Find the distance to the plane, based on the Normal.
float distanceNear = (vnear-v1)^Normal;
float distanceFar = (vfar-v1)^Normal;
if (( (distanceNear * distanceFar) >= 0.0f)||( distanceNear == distanceFar))
return false; // Are they equal?
// Find exact intersection point.
sect = vnear + (vfar-vnear) * ( -distanceNear/(distanceFar-distanceNear) );
// Check all points against the Normalized vector.
CVec v;
// Point 1
v = Normal%( v2-v1 );
if ( (v^( sect-v1 )) < 0.0f )
return false;
// Point 2
v = Normal%( v3-v2 );
if ( (v^( sect-v2 )) < 0.0f )
return false;
// Point 3
v = Normal%( v1-v3 );
if ( (v^( sect-v1 )) < 0.0f )
return false;
// Lastly, lets set the intersection point.
p = sect;
return true;
}
void CCollision::projectRay( int x, int y )
{
GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];
GLdouble PosX, PosY, x1, x2, x3;
glGetDoublev(GL_MODELVIEW_MATRIX, modelview );
glGetDoublev(GL_PROJECTION_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
PosX = (float)x;
PosY = (float)viewport[3] - (float)y;
gluUnProject( PosX, PosY, 0, modelview, projection, viewport, &x1, &x2, &x3);
vnear.x = (float)x1; vnear.y = (float)x2; vnear.z = (float)x3;
gluUnProject( PosX, PosY, 1.0, modelview, projection, viewport, &x1, &x2, &x3);
vfar.x = (float)x1; vfar.y = (float)x2; vfar.z = (float)x3;
}
case WM_LBUTTONDOWN:
project->scene->bCheckForCollision = true;
project->scene->collision.projectRay(
LOWORD(((LPARAM *)m.LParam.ToPointer())),
HIWORD((LPARAM *)m.LParam.ToPointer())