通常,当我进行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内容分开。例如,某人可能想要将网格存储为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)

但是,现在渲染系统必须进行大量的簿记工作才能将Mesh映射到相应的GlMesh,这只是自找麻烦。

有没有解决此问题的好方法?

最佳答案

我不是OpenGL程序员,所以我不知道这方面的所有问题,因此可能会使您误入歧途,但是根据您的描述,这听起来像您在寻找Factory模式。

如果需要像使用o​​jit_code一样使用GLMesh对象,则显然需要扩展Mesh(或者在Mesh前面需要有一个Facade类,使其看起来像GLMesh)。

同时,将存在您编写的知道需要使用Mesh的代码。该代码可以将GLMesh传递给不知道将与GLMeshFactory一起使用的代码,但确实知道需要与GLMesh一起使用。它将从Mesh中获取其Mesh实例-通常称为MeshFactory的方法,采用您期望任何getInstance()所需的任何参数以返回实例(您需要提前考虑-最坏的情况是,将它传递给MeshFactory除了您知道需要的Map之外,还添加了其他数据。
Mesh可以生成MeshFactory实例,无论您现在正在执行哪种方式。 Mesh可以一遍又一遍地返回相同的实例(您暗示它们创建起来很昂贵)。通常认为工厂在适当的时候会返回共享实例。

09-04 19:31