在iOS上使用OpenGL ES 2.0,如何在两点之间绘制圆柱体?

时间:2013-12-05 21:25:48

标签: ios opengl-es-2.0

我有两个GLKVector3代表圆柱体的起点和终点。使用这些点和半径,我需要构建并渲染一个圆柱体。我可以建立一个圆柱体,它们之间的距离正确,但是在一个固定的方向上(目前总是在y(0,1,0)向上方向)。我不确定需要做什么样的计算才能将气缸放在两点之间的正确平面上,以便一条线穿过两个端点。我想我可以应用某种计算,因为我使用方向矢量或角度创建顶点数据,这将创建指向正确方向的圆柱体。有没有人会有一个算法,或者知道哪一个会有所帮助?

2 个答案:

答案 0 :(得分:0)

检查这个真棒article;它已经过时了,但在调整算法后,它就像一个魅力。一个提示,OpenGL ES 2.0仅支持三角形,因此不使用GL_QUAD_STRIP,而是使用GL_TRIANGLE_STRIP,结果相同。 site还包含一些关于OpenGL几何的其他有用信息。

请参阅以下代码以获取解决方案。 Self表示网格,包含顶点,索引等。

- (instancetype)initWithOriginRadius:(CGFloat)originRadius
                   atOriginPoint:(GLKVector3)originPoint
                    andEndRadius:(CGFloat)endRadius
                      atEndPoint:(GLKVector3)endPoint
                   withPrecision:(NSInteger)precision
                        andColor:(GLKVector4)color
{
self = [super init];

if (self) {
    // normal pointing from origin point to end point
    GLKVector3 normal = GLKVector3Make(originPoint.x - endPoint.x,
                                       originPoint.y - endPoint.y,
                                       originPoint.z - endPoint.z);

    // create two perpendicular vectors - perp and q
    GLKVector3 perp = normal;
    if (normal.x == 0 && normal.z == 0) {
        perp.x += 1;
    } else {
        perp.y += 1;
    }

    // cross product
    GLKVector3 q = GLKVector3CrossProduct(perp, normal);
    perp = GLKVector3CrossProduct(normal, q);

    // normalize vectors
    perp = GLKVector3Normalize(perp);
    q = GLKVector3Normalize(q);

    // calculate vertices
    CGFloat twoPi = 2 * PI;        
    NSInteger index = 0;
    for (NSInteger i = 0; i < precision + 1; i++) {
        CGFloat theta = ((CGFloat) i) / precision * twoPi; // go around circle and get points

        // normals
        normal.x = cosf(theta) * perp.x + sinf(theta) * q.x;
        normal.y = cosf(theta) * perp.y + sinf(theta) * q.y;
        normal.z = cosf(theta) * perp.z + sinf(theta) * q.z;

        AGLKMeshVertex meshVertex;
        AGLKMeshVertexDynamic colorVertex;

        // top vertex
        meshVertex.position.x = endPoint.x + endRadius * normal.x;
        meshVertex.position.y = endPoint.y + endRadius * normal.y;
        meshVertex.position.z = endPoint.z + endRadius * normal.z;
        meshVertex.normal = normal;
        meshVertex.originalColor = color;

        // append vertex
        [self appendVertex:meshVertex];

        // append color vertex
        colorVertex.colors = color;
        [self appendColorVertex:colorVertex];

        // append index
        [self appendIndex:index++];

        // bottom vertex
        meshVertex.position.x = originPoint.x + originRadius * normal.x;
        meshVertex.position.y = originPoint.y + originRadius * normal.y;
        meshVertex.position.z = originPoint.z + originRadius * normal.z;
        meshVertex.normal = normal;
        meshVertex.originalColor = color;

        // append vertex
        [self appendVertex:meshVertex];

        // append color vertex
        [self appendColorVertex:colorVertex];

        // append index
        [self appendIndex:index++];
    }

    // draw command
    [self appendCommand:GL_TRIANGLE_STRIP firstIndex:0 numberOfIndices:self.numberOfIndices materialName:@""];
}

return self;
}

答案 1 :(得分:0)

您是否正在绘制多个这些气瓶?或者曾经把它拉到不同的位置?如果是这样,使用来自这篇精彩文章的算法是一个不太可怕的想法。每次将几何数据上传到GPU时,都会产生性能成本。

更好的方法是计算单个基本圆柱体的几何形状 - 例如,具有单位半径和高度的圆柱体 - 以及stuff that vertex data into a VBO。然后,在绘制时,使用模型到世界的变换矩阵进行缩放(如果需要,可以独立地在半径和长度上)并将圆柱体旋转到位。这样,每次绘制调用时发送到GPU的唯一新数据是4x4矩阵,而不是您绘制的任何多个圆柱体的所有顶点数据。