通常,当我进行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模式。
如果需要像使用ojit_code一样使用GLMesh
对象,则显然需要扩展Mesh
(或者在Mesh
前面需要有一个Facade类,使其看起来像GLMesh
)。
同时,将存在您编写的知道需要使用Mesh
的代码。该代码可以将GLMesh
传递给不知道将与GLMeshFactory
一起使用的代码,但确实知道需要与GLMesh
一起使用。它将从Mesh
中获取其Mesh
实例-通常称为MeshFactory
的方法,采用您期望任何getInstance()
所需的任何参数以返回实例(您需要提前考虑-最坏的情况是,将它传递给MeshFactory
除了您知道需要的Map
之外,还添加了其他数据。Mesh
可以生成MeshFactory
实例,无论您现在正在执行哪种方式。 Mesh
可以一遍又一遍地返回相同的实例(您暗示它们创建起来很昂贵)。通常认为工厂在适当的时候会返回共享实例。