统一:由四元数的三个点定义的平面

时间:2018-07-02 20:26:46

标签: c# unity3d shader quaternions plane

对于一个研究项目,我正在Unity中处理3D文件。目的是放置三个标记,通过三个标记绘制一个平面,并使用该平面进行切割。 我能够定义标记,添加平面并进行剖面切割。但是,由于剖切需要以四元数来描述平面,因此我必须以某种方式转换我不知道的平面值。

定义平面的标记(样本值):

Vector3 p1 = new Vector3(1.1f, 2.6f, 3.5f);
Vector3 p2 = new Vector3(.4f,  4.5f, 2.5f);
Vector3 p3 = new Vector3(6.1f, 6.9f, 1.4f);
Plane cut  = new Plane(p1, p2, p3);

当前,我使用new Plane定义平面,但我愿意以不同的方式定义它(例如,使用PrimitiveType.Plane)。我仅将此平面用作此参考。 接下来,我使用existing shader添加截面。但是,此着色器需要具有四个值的PlaneNormal和PlanePosition,请参见shader screenshot

简而言之,我的问题是:如何将三个坐标转换为着色器所需的八个值? 另外,如果另一个着色器更适合此处,也可以。

解决方案

借助您的答案,我找到了解决方案。 使用三个点,我定义了一个平面并将其法线存储为Vector4。

Plane finger = new Plane(p1, p2, p3);
Vector3 normal = (finger.normal);
Vector4 planeNormal = Vector4.zero;
planeNormal.x = normal.x;
planeNormal.y = normal.y;
planeNormal.z = normal.z;
digitNormals[digit-1] = planeNormal;

同样,我将位置定义为三点的平均值。因此,我编写了一个函数AvgVector(),该函数采用x,y和z轴的平均值。

Vector3 position = AvgVector(p1, p2, p3);
Vector4 planePosition = Vector4.zero;
planePosition.x = position.x;
planePosition.y = position.y;
planePosition.z = position.z;
Quaternion camNormal = Quaternion.LookRotation(normal);
digitPlanes[digit-1] = planePosition;

我将camPoscamNormal的值存储在新的GameObject中。后来,我获取了这些值并将其应用于我的相机。

rend.material.SetVector("_PlaneNormal", digitNormals[dig-1]);
rend.material.SetVector("_PlanePosition", digitPlanes[dig-1]);
SectionCamera.transform.position = section.transform.position;
SectionCamera.transform.LookAt(clone.transform);
RelocateMarker(c, 3);

我知道我使用了很多变量,这可能会限制这些代码片段的用处。但是,整个代码很快将在https://github.com/TimJohDij/marker-maker上在线。

1 个答案:

答案 0 :(得分:1)

TL; DR:这些字段不解释为四元数。只需将您的平面位置和平面法线插入这些字段,就好像它们是Vector3一样,而忽略w字段。如果您不确定如何获取这些向量,请阅读以下内容。

首先让我们看一下着色器要求的两个四元数。

planeNormal

planeNormal是平面所面向的方向或矢量背离平面的方向。 因此,如果要使用此着色器将对象完全水平地切片,则planeNormal将是表示Vector3.Up的四元数。更深入的解释是平面的法线向量是与该平面上任意两个向量的垂直向量。

planePosition

planePosition是平面的中心点。将其视为切片偏移量。将其设置为Quaternion.identity以外的其他值将使您的飞机四处移动,否则它将始终与对象的中心点相交。

如何解决问题

在得出四元数之前,我们需要将planePositionplaneNormal作为向量。 planePosition由您决定,因此其余答案将集中在planeNormal上。

给出

  1. 平面的法向矢量是该平面上任意两个矢量的垂直矢量
  2. 我们可以通过找到两个向量的叉积来找到一个垂直向量。
  3. 我们可以制作出任意两点的向量。
  4. 您已经有了3个点,我们需要在飞机上绘制两个矢量(我们将重用1个点)。

因此,我们需要从用来定义平面的三个点中得出两个向量,我们将对这两个向量进行叉积,所得的向量将成为我们的法向量。

Vector3 vec1 = p1 - p3;
Vector3 vec2 = p2 - p3;
Vector3 normalVec = Vector3.Cross(vec1, vec2);

现在,在使用了着色器之后,我发现这些字段实际上只是具有额外值的Vector3。据我所知w的值被忽略了,所以一旦找到法线向量,就可以将其值插入x,y和z字段中。

但是要真正回答您的问题,将向量转换为四元数的最简单方法是使用LookRotation()

Quaternion planeNormal = Quaternion.LookRotation(normalVec)