从XYZ计算数组中的索引



我需要一些帮助来制定正确的算法,用数据填充顶点浮点缓冲区数组。。。

由于在我的设置中,每个顶点都有9个属性(XYZ、UV、RGBA),并且我使用四边形进行绘制,因此每个面总共有36个索引。我正在画立方体,所以这是6个面,总共有216(9*4*6)个索引。而不是仅仅迭代缓冲区来填充以下内容:

public void AddVertex(int x, int y, int z, float u, float v, Color4 color)
    {
        if (vCount >= vertex_data.Length)
            return;
        else
        {
            vertex_data[vCount++] = x;
            vertex_data[vCount++] = y;
            vertex_data[vCount++] = z;
            vertex_data[vCount++] = u;
            vertex_data[vCount++] = v;
            vertex_data[vCount++] = color.R;
            vertex_data[vCount++] = color.G;
            vertex_data[vCount++] = color.B;
            vertex_data[vCount++] = color.A;
        }
    }

我想使用偏移量直接针对GPU上要更新的缓冲区中的位置(通过使用BufferSubData)。然而,问题是将立方体(XYZ)的相对位置值转换为缓冲区数组中的位置,这样我就可以更新它的值。

这就是我迭代立方体的方式,以及我试图获得正确位置的方式。。。

for (int x = 0; x < Chunk.DEFAULT_SIZE; x++)
        {
            for (int y = 0; y < Chunk.DEFAULT_SIZE; y++)
            {
                for (int z = 0; z < Chunk.DEFAULT_SIZE; z++)
                {
                    <...>
                    offset = (x + size * (y + size * z)) * 216;
                    SetVertex(offset, face_i.X + absX, face_i.Y + absY, face_i.Z + -absZ, u, v, color);
                    //SetVertex (...) would be called 3 more times, and "offset" would be supplemented by 0,9,18, and 27 (totalling 36 indices).
                    <...>
                }
            }
        }

我甚至尝试过对XYZ值进行位偏移:

int offset = 216 * (x<<10) + 216 * (y<<5) + 216*z;

这只在某些情况下有效。我是不是走错了路?上面代码的结果只创建了多维数据集的底面,但它确实以所有正确的间隔创建了它们。

我要做的第一件事是编写代码,在给定坐标、面和顶点的情况下,为您提供要修改的顶点地址的偏移量。这将为您在寻址数据指针时省去很多麻烦。这可能看起来像这样:

size_t get_offset(int x, int y, int z, face_enum face, vertex_enum vertex) {
    size_t x_offset = x * Chunk.DEFAULT_SIZE * Chunk.DEFAULT_SIZE;
    size_t y_offset = y * Chunk.DEFAULT_SIZE;
    size_t z_offset = z;
    size_t cube_offset = x_offset + y_offset + z_offset;
    size_t face_offset = convert_face_enum_to_index(face); //I'm here assuming that all the possible enums map to indexes in the range [0,5]
    size_t quad_offset = cube_offset * 6 + face_offset; //Multiplied by six for six faces
    size_t vertex_offset = convert_vertex_enum_to_index(vertex); //I'm here assuming that all the possible enums map to indexes in the range [0,3]
    size_t vertex_location = quad_offset * 4 + vertex_offset; //Multiplied by four for four vertices per quad.
    const size_t num_of_floats_per_vertex = 9; //Based on your problem description, this should be correct
    return vertex_location * num_of_floats_per_vertex;
}
public void modify_vertex(float * location, float x, float y, float z, float u, float v, Color4 color) {
    location[0] = x;
    location[1] = y;
    location[2] = z;
    location[3] = u;
    location[4] = v;
    location[5] = color.R;
    location[6] = color.G;
    location[7] = color.B;
    location[8] = color.A;
}

如果所有添加或修改顶点数据的尝试都是以这种方式完成的,这将使您的生活更加简单。一旦你完成了这项工作,你就可以编写这样的代码:

for(cube qube : cubes) { //Depends on your implementation. If you've literally stored all the cubes in a cube[][][] array, then the triple-nested code you wrote above would be adequate.
    for(face_enum face = FACE0; face <= FACE5; face++) { //I'm assuming that face_enum has an increment operator; this may need to be adjusted depending on what you write.
        for(vertex_enum vertex = VERTEX0; vertex <= VERTEX3; vertex++) { //same deal here.
            size_t vertex_offset = get_offset(qube.x, qube.y, qube.z, face, vertex);
            float * data_offset = my_mapped_vertex_buffer + vertex_offset;
            modify_vertex(data_offset, /*insert appropriate data here*/);
        }
    }
}

然后,只要正确设置了顶点缓冲区对象(以及所有相关的属性指针),这将以一致且易于修改的方式(从程序员的角度来看)存储所有相关的渲染数据。

当然,您必须确保顶点缓冲区足够大,可以存储每个多维数据集,但这仍然是旧代码的问题。

最新更新