将单行向量(数组)赋值转换为经典数组,C++ 转换为 C
Posted
技术标签:
【中文标题】将单行向量(数组)赋值转换为经典数组,C++ 转换为 C【英文标题】:Convert a one line vector (array) assignation to classical array, C++ translation to C 【发布时间】:2020-04-28 06:21:19 【问题描述】:我正在尝试转换 Moller Trumbore 算法,如 here 所示。
这段代码的目的是寻找一个向量与一个三角形的交点,同时返回U和V纹理点。
但是,我坚持这一行:
Vector uvHit = uvVectors[0] * u + uvVectors[1] * v + uvVectors[2] * (1 - u - v);
谁也可以看作:
*uvHit = u * uvVectors[0] + v * uvVectors[1] + (1 - u - v) * uvVectors[2];
这是我的代码:
typedef float vec_t;
typedef vec_t vec3_t[3];
qboolean GetIntersection(vec3_t rayOrigin, vec3_t rayDirection, float hitDistance, vec3_t *uv)
vec3_t pvec;
float det = 0.0f;
vec3_t tvec;
vec3_t qvec;
vec3_t uvHit;
// begin calculating determinant - also used to calculate U parameter
CrossProduct(rayDirection, edge2, pvec);
// if determinant is near zero, ray lies in plane of triangle
det = DotProduct(edge1, pvec);
const float EPSILON = 0.000001f;
if ((det > -EPSILON) && (det < EPSILON))
return qfalse;
float inv_det = 1.0f / det;
// calculate distance from vertex 0 to ray origin
tvec = rayOrigin - verts[0];
// calculate U parameter and test bounds
u = DotProduct(tvec, pvec) * inv_det;
if ((u < 0.0f) || (u > 1.0f))
return false;
// prepare to test V parameter
CrossProduct(tvec, edge1, qvec);
// calculate V parameter and test bounds
float v = DotProduct(rayDirection, qvec) * inv_det;
if ((v < 0.0f) || (u + v > 1.0f))
return false;
Vector uvHit = uvVectors[0] * u + uvVectors[1] * v + uvVectors[2] * (1 - u - v);// This is the line I don't understand
uv[0] = uvHit[0];
uv[1] = uvHit[1];
uv[2] = 0;
// calculate t, ray intersects triangle
hitDistance = DotProduct(edge2, qvec) * inv_det;
// only allow intersections in the forward ray direction
return hitDistance >= 0.0f;
【问题讨论】:
你为什么认为是矩阵乘法?它看起来像普通的算术。 你需要展示Vector
类型是如何定义的,以及所有变量的声明。
这里没有任何东西看起来像 C++ std::vector
。
Vector
类与 C++ std::vector
完全无关。它代表矢量图形。
好吧,我的错。但是无论如何请如何转换它?
【参考方案1】:
您正在根据表示为Vector uvVectors[3]
的顶点及其重心坐标u
、v
和w == 1 - u - v
计算三角形中的一个点。
在您展示的 C++ 代码中,Vector
可能是一个类或结构。乘法运算符 *
已重载,在本例中为向量与标量的乘法:
Vector uvHit = uvVectors[0] * u + uvVectors[1] * v + uvVectors[2] * (1 - u - v);
在 C 中,您不能重载运算符,因此您必须明确地编写此计算。假设您的向量是 3D 空间中的向量:
typedef struct Vector Vector;
struct Vector
double x, y, z;
;
那么当你初始化一个向量时,你的乘法是这样的:
Vector uvHit =
uvVectors[0].x * u + uvVectors[1].x * v + uvVectors[2].x * (1 - u - v),
uvVectors[0].y * u + uvVectors[1].y * v + uvVectors[2].y * (1 - u - v),
uvVectors[0].z * u + uvVectors[1].z * v + uvVectors[2].z * (1 - u - v)
;
或者当你稍后分配它的值时像这样:
uvHit.x = uvVectors[0].x * u + uvVectors[1].x * v + uvVectors[2].x * (1 - u - v);
uvHit.y = uvVectors[0].y * u + uvVectors[1].y * v + uvVectors[2].y * (1 - u - v);
uvHit.z = uvVectors[0].z * u + uvVectors[1].z * v + uvVectors[2].z * (1 - u - v);
【讨论】:
我没有得到 uvVectors[0].x,因为它不是数组也不是指针? 但是uvVectors[0]
就在您的原始 C++ 代码中,所以它一定是一个向量数组,不是吗?我的猜测是这个向量数组是三角形顶点的三个位置向量的数组。是的,我猜在这里,因为您在帖子中没有提供足够的信息。
(在您发布的链接的代码中,没有显示uvVector
的定义。那里的函数可能是一个类的方法,其中定义了uvVector
。)
我已经回答了您的问题,这实际上是如何实现向量与标量的乘法,该标量是 C 中 C++ 中的单个操作。我对您的纹理内容并不感兴趣'正在尝试做。我的印象是,您可以从更抽象的层次理解算法中受益,而不是通过查看具体的实现。如果您正在查看具体的实现,则必须查看所有内容,而不仅仅是摘录,还必须了解数据的表示方式。
@GUNNM 这不是一个 3x3 矩阵,它是一个由 3 个点组成的数组,它们共同定义了一个三角形。以上是关于将单行向量(数组)赋值转换为经典数组,C++ 转换为 C的主要内容,如果未能解决你的问题,请参考以下文章