You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于线形点集生成偏移顶点以通过GL_TRIANGLE_STRIP绘制多边形轮廓

问题描述

我现有一组呈线形排列的点,如下图所示:
原始线形点集示意图
我需要生成一组与当前点集保持指定偏移距离的新点,最终可以通过GL_TRIANGLE_STRIP绘制出多边形轮廓形态,预期效果如下图:
偏移后多边形轮廓效果示意图
以下是我当前编写的代码,但运行后无法得到预期的有效结果,请问该如何正确实现需求?

// outlineVertices are existing set of points from which we would generate the offsetPoints

for (int i = 0; i < outlineVertices.size() - 3 ; i += 3) {
        finalVertices.push_back(outlineVertices[i]);
        finalVertices.push_back(outlineVertices[i + 1]);
        finalVertices.push_back(outlineVertices[i + 2]);        

        glm::vec3 point1 = glm::vec3(outlineVertices[i], outlineVertices[i + 1], outlineVertices[i + 2]);
        glm::vec3 point2 = glm::vec3(outlineVertices[i + 7], outlineVertices[i + 1 + 7], outlineVertices[i + 2 + 7]);
        glm::vec4 directionVector = GetPerpendicularVectorDirection(point1, point2);
    
        finalVertices.push_back(outlineVertices[i] - (directionVector.x * outlineWidth ));
        finalVertices.push_back(outlineVertices[i + 1] + (directionVector.y * outlineWidth));
        finalVertices.push_back(outlineVertices[i + 2]);
        finalVertices.push_back(outlineVertices[i + 3]);
        
    }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

glm::vec4 RectangleOutline::GetPerpendicularVectorDirection(glm::vec3 point1, glm::vec3 point2) {

    glm::vec3 Direction = glm::normalize(point1 - point2);
    float x, y;
    x = Direction.x;
    Direction.x = -y;
    Direction.y = x;
    return glm::vec4(Direction, 0);
}

问题排查与修复方案

原有代码核心错误

  1. 垂直向量计算逻辑完全错误:GetPerpendicularVectorDirection函数中y变量未初始化就被赋值给Direction.x,得到的是内存垃圾值,方向完全不对。正确的2D向量垂直转换逻辑为:对于方向向量(dx, dy),逆时针垂直向量为(-dy, dx),顺时针垂直向量为(dy, -dx)。
  2. 相邻点取址错误:循环中取下一个点的偏移量写为i+7,但每个点占3个float存储,相邻下一个点的偏移应为i+3,取点错误导致方向计算完全偏离预期。
  3. 顶点组装逻辑混乱:GL_TRIANGLE_STRIP绘制线轮廓需要交替插入正负偏移点,原有逻辑额外插入了无意义的outlineVertices[i+3],且没有处理转角处的法线平均,会导致拐角出现缺口。

修复后的实现代码

1. 修复垂直向量计算函数

// 输入两个点,返回两点方向的单位逆时针垂直向量
glm::vec3 GetPerpendicular(glm::vec3 p1, glm::vec3 p2) {
    glm::vec3 dir = glm::normalize(p2 - p1);
    // 2D垂直向量转换,z值保持不变
    return glm::vec3(-dir.y, dir.x, 0.0f);
}

2. 修正顶点生成逻辑(带转角miter处理)

float halfWidth = outlineWidth * 0.5f;
int pointCount = outlineVertices.size() / 3;
finalVertices.clear();

for (int i = 0; i < pointCount; i++) {
    glm::vec3 cur = glm::vec3(
        outlineVertices[i*3],
        outlineVertices[i*3 + 1],
        outlineVertices[i*3 + 2]
    );
    glm::vec3 normal;
    
    if (i == 0) {
        // 起点只取下一段的垂直向量
        glm::vec3 next = glm::vec3(
            outlineVertices[(i+1)*3],
            outlineVertices[(i+1)*3 + 1],
            outlineVertices[(i+1)*3 + 2]
        );
        normal = GetPerpendicular(cur, next);
    } else if (i == pointCount - 1) {
        // 终点只取上一段的垂直向量
        glm::vec3 prev = glm::vec3(
            outlineVertices[(i-1)*3],
            outlineVertices[(i-1)*3 + 1],
            outlineVertices[(i-1)*3 + 2]
        );
        normal = GetPerpendicular(prev, cur);
    } else {
        // 中间点取前后两段垂直向量的平均,处理转角
        glm::vec3 prev = glm::vec3(
            outlineVertices[(i-1)*3],
            outlineVertices[(i-1)*3 + 1],
            outlineVertices[(i-1)*3 + 2]
        );
        glm::vec3 next = glm::vec3(
            outlineVertices[(i+1)*3],
            outlineVertices[(i+1)*3 + 1],
            outlineVertices[(i+1)*3 + 2]
        );
        glm::vec3 n1 = GetPerpendicular(prev, cur);
        glm::vec3 n2 = GetPerpendicular(cur, next);
        normal = glm::normalize(n1 + n2);
        // 调整miter长度,避免尖角过度延伸
        float miterLen = halfWidth / glm::dot(normal, n1);
        normal *= miterLen / halfWidth;
    }
    
    // 按三角带要求交替插入正负偏移点
    glm::vec3 pLeft = cur + normal * halfWidth;
    glm::vec3 pRight = cur - normal * halfWidth;
    finalVertices.push_back(pLeft.x);
    finalVertices.push_back(pLeft.y);
    finalVertices.push_back(pLeft.z);
    finalVertices.push_back(pRight.x);
    finalVertices.push_back(pRight.y);
    finalVertices.push_back(pRight.z);
}

内容的提问来源于stack exchange,提问作者Summit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:30:02