我基本上是在尝试根据贝塞尔曲线上的点创建二维线。 贝塞尔曲线的所有点都放置得很好,一切看起来都井然有序。 从这些点开始,我在 z 轴上创建另外 2 个点,它们将作为线的边界:
glm::vec3 p1 = pos[i];
p1.z = p1.z + (size / 2);
glm::vec3 p2 = pos[i];
p2.z = p2.z - (size / 2);
然后我通过围绕主要点旋转这些点来更改它们的位置:
pm 是移动点绕固定点pf
旋转 glm::vec3 rotP = glm::vec3(0.0f, 0.5f, 0.0f);
float co = cos(angle);
float si = sin(angle);
// CLOCKWISE
rotP.x = (pf.x - pm.x) * co + (pf.z - pm.z) * si + pm.x;
rotP.z = -(pf.x - pm.x) * si + (pf.z - pm.z) * co + pm.z;
angle 是贝塞尔曲线上向后点和向前点之间的角度:
depForward 是 x, glm::vec3(1.0f, 0.0f, 0.0f)
glm::vec3 normForwardUnit = normalize(p2 - p1);
float angle = (acos(dot(depForward, normForwardUnit)));
我遇到的问题是旋转错误。我的一些线条是正确的,但它似乎取决于线条的方向。
我认为问题出在轮换的格式上,但我仍然无法理解。 我尝试将角度标准化为不同的范围:
//0 to 2PI
if (angle < 0) { angle += 2 * PI; }
//-PI to PI
if (angle > PI) { angle -= 2 * PI; }
else if (angle <= -PI) { angle += 2 * PI; }
其他计算角度的方法:
float angle = atan2(p2.z - p1.z, p2.x - p1.x);
逆时针旋转点:
//COUNTER CLOCKWISE
rotP.x = (pf.x - pm.x) * co - (pf.z - pm.z) * si + pm.x;
rotP.z = (pf.x - pm.x) * si + (pf.z - pm.z) * co + pm.z;
如果有人需要,这里是 paddy 方法的实现。 您可以使用 backP 和 nextP 之间的点而不是 midPoint 来放置新点。
backP 和 nextP 是 b 曲线的前后点
// VEC FORWARD VECTOR
glm::vec3 forwardVec = normalize(backP - nextP);
//PERPENDICULAR VEC
glm::vec3 perpVec = cross(forwardVec, glm::vec3(0.0f, 1.0f, 0.0f));
perpVec = normalize(perpVec);
//MID POINT
glm::vec3 midP = midPoint(backP, nextP);
// GEN POINTS
glm::vec3 p1 = midP + (width * perpVec);
glm::vec3 p2 = midP - (width * perpVec);
我认为你绝对应该看看这个:
如果您坚持自己的方式,则不需要使用任何角度或旋转......
您有从多项式曲线中采样的线
p0,p1
,因此:
tangent = p1-p0
但是,最好有更好的切线近似值,因此可以通过曲线的一阶导数来获取它,或者使用 2 条后续线
(p0,p1) , (p1,p2)
那么点 p1
处的切线是:
tangent = p2-p1
欲了解更多信息,请参阅:
现在取
bitangent
(相机的z轴,可以从相机矩阵中提取)并使用叉积得到normal
normal = normalize(cross(tangent,binormal))
现在你只需将
p1
替换为正常即可:
p1' = p1 + 0.5*curve_thickness*normal
p1'' = p1 - 0.5*curve_thickness*normal
对曲线的所有点执行相同的操作...之后,您只需使用
p'
和 p''
点渲染四边形...
但是,使用这种方法,您可能会遇到可能需要进一步调整的问题,请参阅: