通常,当我进行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)
然而,现在渲染系统必须进行大量的簿记才能将Mesh映射到相应的GlMesh,这只是一个问题。
有没有一种解决这个问题的好方法,我错过了?
答案 0 :(得分:1)
我不是OpenGL程序员,所以我不知道这方面的所有问题,因此可能会让你误入歧途,但鉴于你所描述的内容,听起来像你&# 39;重新寻找工厂模式。
如果您的GLMesh
对象需要像Mesh
一样使用,那么它显然需要扩展Mesh
(或者需要 facade < / {>在GLMesh
前面的类,使其看起来像Mesh
。)
同时,您将编写知道需要使用GLMesh
的代码。该代码可以将GLMeshFactory
传递给不知道它将与GLMesh
一起使用的代码,但可以知道它需要与Mesh
一起使用。它将从Mesh
获取MeshFactory
个实例 - 通常是一个名为getInstance()
的方法,采用您期望任何MeshFactory
所需的任何参数来返回实例(您&# 39;我需要提前思考 - 最糟糕的情况是,除了你所知道的Map
所需的任何额外数据之外,你最后传递Mesh
。
MeshFactory
可以生成Mesh
个实例,无论您现在正在做什么。 GLMeshFactory
可以一遍又一遍地返回相同的实例(您在评论中暗示他们创建起来很昂贵)。工厂通常被理解为在适当的时候返回共享实例。
答案 1 :(得分:0)
这样的事情怎么样:
public class Mesh implements GlMeshSupplier{
private final List<Vector3f> vertices = new ArrayList<>();
private final List<Vector3f> normals = new ArrayList<>();
private final List<Vector2f> texCoords = new ArrayList<>();
private GlMesh glMesh;
@Override
public GlMesh getGlMesh() {
return glMesh;
}
public void createGlMesh(){
glMesh = new GlMesh();
}
public List<Vector3f> getVertices() {
return vertices;
}
public List<Vector3f> getNormals() {
return normals;
}
public List<Vector2f> getTexCoords() {
return texCoords;
}
public class GlMesh extends Mesh{
// OpenGL-specific stuff
protected int ivertices;
protected boolean dirty;
protected int vertexArrayID = -1;
protected int vertexBufferID = -1;
private GlMesh(){}
@Override
public List<Vector3f> getVertices() {
return Mesh.this.vertices;
}
@Override
public List<Vector3f> getNormals() {
return Mesh.this.normals;
}
@Override
public List<Vector2f> getTexCoords() {
return Mesh.this.texCoords;
}
}
}
public interface GlMeshSupplier {
public GlMesh getGlMesh();
}
Mesh和GlMesh之间的替代映射:
//class Mesh
public Mesh(){
this.vertices = new ArrayList<>();
this.normals = new ArrayList<>();
this.texCoords = new ArrayList<>();
}
private Mesh(List<Vector3f> vertices, List<Vector3f> normals, List<Vector2f> texCoords){
this.vertices = vertices;
this.normals = normals;
this.texCoords = texCoords;
}
//class GlMesh
private GlMesh(){
super(Mesh.this.vertices, Mesh.this.normals, Mesh.this.texCoords);
}
你的Mesh
和GlMesh
似乎彼此关系非常密切,这可能是合理制作这样的作品的理由。 Mesh
可以独立于GlMesh
创建。创建GlMesh
后,它会将(Mesh
)映射到封闭Mesh
的属性。
方法getVertices()
,getNormals()
和getTexCoords()
只是如何通过Mesh
及其{{1}的网格方法访问相同属性的示例}}。
如果您要隐藏GlMesh
中不应映射到Mesh
的功能,您还可以使用GlMeshSupplier
等供应商界面屏蔽Mesh
。