如何在不修改元素的情况下将数据与集合中的元素相关联?

通常,当我在进行OpenGL编程时,我有一个像这样的Mesh类:

public class Mesh {

    // General 3D stuff
    List<Vector3f> vertices = new ArrayList<>();
    List<Vector3f> normals = new ArrayList<>();
    List<Vector2f> texCoords = new ArrayList<>();

    // OpenGL-specific stuff
    protected int vertices;
    protected boolean dirty;
    protected int vertexArrayID = -1;
    protected int vertexBufferID = -1;

    ...

}

但是,我现在正在处理的应用程序更加通用,我希望将特定于OpenGL的内容与一般的3D内容分开.例如,某人可能希望将Mesh存储为STL文件并将其打印为3D,或将其发送到Raytrace渲染器以使其看起来不错.在这种情况下,特定于OpenGL的数据是无用的.

换句话说,Mesh类的这种实现违反了单一责任原则.

现在,我能想到的一个解决方案如下:

public class Mesh {

    // General 3D stuff
    List<Vector3f> vertices = new ArrayList<>();
    List<Vector3f> normals = new ArrayList<>();
    List<Vector2f> texCoords = new ArrayList<>();
}

public class GlMesh extends Mesh implements GlDrawable {

    // OpenGL-specific stuff
    protected int vertices;
    protected boolean dirty;
    protected int vertexArrayID = -1;
    protected int vertexBufferID = -1;
}

但是,现在数据结构中仍然存在特定于OpenGL的对象,这些对象是从生成它的算法输出的. Mesh生成器需要知道它应该创建一个GlMesh而不是Mesh,因此知道OpenGL渲染模块,我真的宁愿避免.

现在,我们可以这样做:

public class Mesh {

    // General 3D stuff
    List<Vector3f> vertices = new ArrayList<>();
    List<Vector3f> normals = new ArrayList<>();
    List<Vector2f> texCoords = new ArrayList<>();
}

public class GlMesh {

    // OpenGL-specific stuff
    protected int vertices;
    protected boolean dirty;
    protected int vertexArrayID = -1;
    protected int vertexBufferID = -1;
}

Map<Mesh, GlMesh> meshToGlMesh = (whatever)

但是,现在渲染系统必须进行大量的簿记才能将网格映射到相应的GlMesh,这只是一个问题.

有没有一种解决这个问题的好方法,我错过了?

最佳答案 我不是OpenGL程序员,所以我不知道前面的所有问题,因此可能会让你误入歧途,但鉴于你所描述的,听起来你正在寻找一个工厂模式.

如果你的GLMesh对象需要被用作Mesh,那么它显然需要扩展Mesh(或者需要在GLMesh前面有一个Facade类,使它看起来像一个Mesh).

同时,您将编写知道GLMesh需要使用的代码.该代码可以将GLMeshFactory传递给不知道它将与GLMesh一起使用的代码,但确实知道它需要使用Mesh.它将从MeshFactory中获取它的Mesh实例 – 通常是一个名为getInstance()的方法,接受任何MeshFactory所需的参数以返回一个实例(你需要提前考虑 – 最坏的情况是,你传递一个Map最后除了你所知道的Mesh需要的任何额外数据之外.

MeshFactory可以生成Mesh实例,无论你现在正在做什么. GLMeshFactory可以一遍又一遍地返回相同的实例(你在评论中暗示它们创建起来很昂贵).工厂通常被理解为在适当的时候返回共享实例.

点赞