将单行向量(数组)赋值转换为经典数组,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] 的顶点及其重心坐标uvw == 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的主要内容,如果未能解决你的问题,请参考以下文章

向量不会复制成数组吗?

将 C/C++ 向量快速转换为 Numpy 数组

在 C++ 中将 matlab 矩阵转换为数组的有效方法

如何将 C++ 或 C 中的字符串转换为整数数组?

将 Numpy 数组按列转换为 Pandas DataFrame(作为单行)

如何将静态二维数组转换为特征值