首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >你如何找到一个点在四个顶点之间的Y位置?HLSL

你如何找到一个点在四个顶点之间的Y位置?HLSL
EN

Stack Overflow用户
提问于 2014-08-31 22:25:14
回答 1查看 877关注 0票数 0

假设有一个由两个三角形组成的游戏的网格地形-由四个顶点组成。我们如何找到四个顶点之间的点的Y(向上)位置?

我试过这样做:

代码语言:javascript
复制
float diffZ1    = lerp(heights[0], heights[2], zOffset);
float diffZ2    = lerp(heights[1], heights[3], zOffset);
float yPosition = lerp(diffZ1, diffZ2, xOffset);

其中z/yOffset是与瓷砖的第一个顶点的z/y偏移量(百分比/ 100 )。这种方法适用于平坦的表面,但在崎岖的地形上效果不太好。

我希望这与由三角形构成的地形有关,在这些三角形上,上面的东西可能在平面上工作。我不确定,但有人知道出了什么问题吗?

这也许能更好地解释这里发生的事情:

在上面的代码中,"heights[]“是周围顶点v0-3的Y坐标数组。三角形1由顶点0、2和1组成,三角形2由顶点1、2和3组成。

当p1的x,y坐标在v0-3之间时,我希望找到它的坐标Y.

因此,我尝试通过这个函数来确定点之间的哪个三角形:

代码语言:javascript
复制
bool PointInTriangle(float3 pt, float3 pa, float3 pb, float3 pc)
{
  // Compute vectors        
  float2 v0 = pc.xz - pa.xz;
  float2 v1 = pb.xz - pa.xz;
  float2 v2 = pt.xz - pa.xz;

  // Compute dot products
  float dot00 = dot(v0, v0);
  float dot01 = dot(v0, v1);
  float dot02 = dot(v0, v2);
  float dot11 = dot(v1, v1);
  float dot12 = dot(v1, v2);

  // Compute barycentric coordinates
  float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01);
  float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  float v = (dot00 * dot12 - dot01 * dot02) * invDenom;

  // Check if point is in triangle
  return (u >= 0.0f) && (v >= 0.0f) && (u + v <= 1.0f);
}

这并没有给我预期的结果

然后,我试图在每个三角形中找到点p1的y坐标:

代码语言:javascript
复制
// Position of point p1
float3 pos = input[0].PosI;

// Calculate point and normal for triangles
float3 p1 = tile[0];
float3 n1 = (tile[2] - p1) * (tile[1] - p1); // <-- Error, cross needed
       // = cross(tile[2] - p1, tile[1] - p1);
float3 p2 = tile[3];
float3 n2 = (tile[2] - p2) * (tile[1] - p2);  // <-- Error
       // = cross(tile[2] - p2, tile[1] - p2); 
float newY = 0.0f;

// Determine triangle & get y coordinate inside correct triangle
if(PointInTriangle(pos, tile[0], tile[1], tile[2]))
{
    newY = p1.y - ((pos.x - p1.x) * n1.x + (pos.z - p1.z) * n1.z) / n1.y;
}
else if(PointInTriangle(input[0].PosI, tile[3], tile[2], tile[1]))
{
    newY = p2.y - ((pos.x - p2.x) * n2.x + (pos.z - p2.z) * n2.z) / n2.y;
}

使用以下内容查找正确的三角形:

代码语言:javascript
复制
if((1.0f - xOffset) <= zOffset)
    inTri1 = true;

而纠正上面的代码使用正确的交叉函数似乎解决了这个问题。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-31 23:13:53

因为你的4个顶点可能不在一个平面上,所以你应该分别考虑每个三角形。首先找到点所在的三角形,然后使用下面的StackOverflow讨论来求解Z值(注意轴的不同命名)。我个人更喜欢DanielKO的答案,但接受的答案也应该有效:

Linear interpolation of three 3D points in 3D space

编辑:对于问题的第二部分,(找到点所在的三角形):,因为将瓷砖投影到xz平面上(在定义坐标时)是完美的正方形,找到点所在的三角形是一个非常简单的操作。在这里,我将使用左-右的术语来表示x轴(从x的较低值到更高的值),而自下而上的术语则表示z轴(从z的较低值到更高的值)。

每个瓷砖只能用两种方式之一分割。(A)通过从左下角到右上角的对角线,或(B)通过从右下角到左上角的对角线。

  • 对于分割为A的任何瓷砖:检查x‘> z',其中x’‘是从瓷砖的边缘到点的距离,z’是从瓷砖的底部边缘到点的距离。如果x‘> z’>,那么你的点是右下角三角形,否则是左上角三角形.
  • 对于分割为B的任何瓷砖:检查是否x“> z',其中x”是从瓷砖的右侧边缘到点的距离,z‘是从瓷砖的底部边缘到点的距离。如果x“> z‘,那么你的点是左下角三角形,否则是右上三角形。

(小注意:上面我假设你的瓷砖不是在xz平面上旋转的,也就是说,它们与轴对齐。)如果这是不正确的,只需旋转它们与轴对齐,然后再进行上述检查。)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25596861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档