ModelBuilder
ModelBuilder (code) is a utility class to create one or more models on code. It allows you to include one or more nodes, each node consisting of one or more parts. It does, however, not support building a node hierarchy (child nodes). Be aware that building a model on code can be a costly operation and might trigger the garbage collector.
Building one or more models
begin() method, after which you must call the end() when you’re done building the model. The end() method will return the newly created model. You can build multiple models using the same ModelBuilder, but not at the same time. For example:
ModelBuilder modelBuilder = new ModelBuilder();modelBuilder.begin();... //build one or more nodesModel model1 = modelBuilder.end();modelBuilder.begin();... //build one or more nodesModel model2 = modelBuilder.end();
Managing resources
needs to be disposed. A model built via ModelBuilder will always be responsible for disposing all meshes it contains, even if you provide the Mesh yourself. Do not share a Mesh along multiple Models.
materials. You can, however, use the manage(disposable) method to make the model responsible for disposing those resources. For example:
ModelBuilder modelBuilder = new ModelBuilder();modelBuilder.begin();Texture texture = new Texture(...);modelBuilder.manage(texture);... //build one or more nodesModel model = modelBuilder.end();... //use the model and when done:model.dispose(); // this will dispose the texture as well
Creating nodes
nodes. To start building a new node inside the model you can use the node() method. This will add a new node and make it active for building. It will also return the so you can reference it for later use or for example set its id.
ModelBuilder modelBuilder = new ModelBuilder();modelBuilder.begin();Node node1 = modelBuilder.node();node1.id = "node1";node1.translation.set(1, 2, 3);...//build node1Node node2 = modelBuilder.node();node2.id = "node2";...//build node2Model model = modelBuilder.end();
Note that node id’s should unique within the model. A typical use-case would be:
ModelBuilder modelBuilder = new ModelBuilder();modelBuilder.begin();modelBuilder.node().id = "node1";...//build node1modelBuilder.node().id = "node2";...//build node2Model model = modelBuilder.end();
node() method for the first node is optional. For example, for models consisting of only a single node, you can immediately start creating the node parts without having to call the node() method.
Node active for building at a time. Calling the node() method will stop building the previous node (if any) and start building the newly created node. The nodes will only be valid (complete), however, after the Model is completely built (the call to end() is made).
Creating node parts
Node can contain one or more parts. Each part of a node will be rendered at the same location (the node transformation), but can be made up of a different material (e.g. shader uniforms) and/or mesh (e.g. shader (vertex) attributes).
A NodePart is the smallest renderable part of a Model. Every visible NodePart implies a render call (or “draw call” if you prefer). Reducing the number of render calls can help to decrease the time it takes to render the model. Therefore it is advised to try to combine multiple parts to a single part where possible. to the current node you can use one of the
part(...)methods. A NodePart is basically the combination of a and . You must always supply the material when calling one of thepart(...)methods. For theMeshPart, however,ModelBuilderallows you to either specify the (part of the) mesh yourself, or to start building theMeshPartusing aMeshPartBuilder.Modelwill always be made responsible for disposing theMesh, regardless the method used to create part.MeshPartBuilderis an interface (implemented byMeshBuilder, see below) which contains various helper methods to create a mesh. If you use thepart(...)method to construct the MeshPart using a MeshPartBuilder, then ModelBuilder will try to combine multiple parts into the same Mesh. This will in most cases reduce the number of Mesh binds. This is only possible if the parts are made up using the same vertex attributes. For example:
ModelBuilder modelBuilder = new ModelBuilder();modelBuilder.begin();MeshPartBuilder meshBuilder;meshBuilder = modelBuilder.part("part1", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material());meshBuilder.cone(5, 5, 5, 10);Node node = modelBuilder.node();node.translation.set(10,0,0);meshBuilder = modelBuilder.part("part2", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material());meshBuilder.sphere(5, 5, 5, 10, 10);Model model = modelBuilder.end();
ModelBuilderto create default (3D)VertexAttributes. You could also specify the yourself.ModelBuilderreuses theMeshPartBuilderinstances for multiple parts, you cannot build multiple parts at the same time. PerModelBuilderyou can only build oneModel,NodeandMeshPartat any given time. Calling theMeshPartBuilderto create the shape of the part.MeshBuilder
MeshBuilder (code) is a utility class to create one or more meshes, optionally consisting of one or more MeshParts. While a
MeshBuilderis typically constructed and maintained by theModelBuilderusing theModelBuilder#part(...)method, it is possible to useMeshBuilderwithout using aModelBuilder. For this, you can use thebegin(...)method to start building a mesh, after which you must call theend()method when you’re done building the mesh. The begin methods accepts various arguments to specify the vertex attributes and optionally primitive type (required when not creating mesh part(s)). Theend()method will return the newly created . You can build multiple meshes using the sameMeshBuilderinstance, but not at the same time:
MeshBuilder meshBuilder = new MeshBuilder();meshBuilder.begin(Usage.Position | Usage.Normal, GL20.GL_TRIANGLES);...//build the first meshMesh mesh1 = meshBuilder.end();meshBuilder.begin(Usage.Position | Usage.Normal | Usage.ColorPacked, GL20.GL_TRIANGLES);...//build the second meshMesh mesh2 = meshBuilder.end();
Meshmust be disposed when you no longer need it.part(...)method to create a Mesh consisting of multiple parts. This will create a newMeshPartand set it active for building.
MeshBuilder meshBuilder = new MeshBuilder();meshBuilder.begin(Usage.Position | Usage.Normal);MeshPart part1 = meshBuilder.part("part1", GL20.GL_TRIANGLES);... // build the first partMeshPart part2 = meshBuilder.part("part2", GL20.GL_TRIANGLES);... // build the second partMesh mesh = meshBuilder.end();
part(...)method returns theMeshPartso you can reference it for later use, it will not be valid until theend()method is called. You can only create oneMeshPartat a time, calling thepart(...)method will stop building the previous part and start building the new part.Meshshare the sameVertexAttributes. The primitive type can vary among parts though. For example, the following snippet creates two parts each with a different primitive type, but sharing the same mesh:
meshBuilder.begin(Usage.Position | Usage.Normal);MeshPart part1 = meshBuilder.part("part1", GL20.GL_TRIANGLES);... // build the first partMeshPart part2 = meshBuilder.part("part2", GL20.GL_TRIANGLE_STRIP);... // build the second partMesh mesh = meshBuilder.end();
MeshBuilderimplementsMeshPartBuilder. Creating the actual shape of the (part of the) mesh, is described in the MeshPartBuilder section.MeshPartBuilder
MeshPartBuilder (code) is a utility interface which supplies various methods for creating a (part of a) mesh. You can either use
ModelBuilder.part(...)or construct aMeshBuilderto obtain aMeshPartBuilder. All methods of theMeshPartBuilderinterface can only be called as long as theMeshPartis being build (most commonly between the call to thepart(...)method and the call to the nextpart(...)orend()method of eitherModelBuilderorMeshBuilder).getMeshPart()method to obtain theMeshPartcurrently being build. Use thegetAttributes()method to obtain theVertexAttributesof theMeshbeing build.VertexAttributeofUsage.Position(either 2D or 3D) is required. There are no further restriction on the specified vertex attributes. However, most (especially higher level) methods are only implemented for position, normal, color (either packed or unpacked) and texture coordinates attributes. If you use other attributes as well, then a default (commonly zero) value will be used.VertexInfois used to specify these on a per vertex basis. For example therect(...)method accepts aVertexInfofor each corner, instead of using a method with all possible combinations or arguments for the vertex values of each corner. Be aware that theVertexInfokeeps track of whether a specific value has been set, therefor you should always use the setXXX methods. Usenullin case you want to unset a value.setColor(...)method to specify the default color that will be used when theVertexAttributescontain a colorVertexAttribute, but no color is set in e.g. theVertexInfo. For example:
meshPartBuilder.setColor(Color.RED);VertexInfo v1 = new VertexInfo().setPos(0, 0, 0).setNor(0, 0, 1).setCol(null).setUV(0.5f, 0.0f);VertexInfo v2 = new VertexInfo().setPos(3, 0, 0).setNor(0, 0, 1).setCol(null).setUV(0.0f, 0.0f);VertexInfo v3 = new VertexInfo().setPos(3, 3, 0).setNor(0, 0, 1).setCol(null).setUV(0.0f, 0.5f);VertexInfo v4 = new VertexInfo().setPos(0, 3, 0).setNor(0, 0, 1).setCol(null).setUV(0.5f, 0.5f);meshPartBuilder.rect(v1, v2, v3, v4);
VertexInfohas no color set (setCol(null)), the default will be used which is set to a red color.setUVRangeto specify the default texture coordinates range that will be used when no texture coordinates are specified. Along with the default color, this is especially useful for simple shapes where only positions are needed and other vertex information can be derived from the shape. For example:
meshPartBuilder.setColor(Color.RED);meshPartBuilder.setUVRange(0.5f, 0f, 0f, 0.5f);meshPartBuilder.rect(0,0,0, 3,0,0, 3,3,0, 0,3,0, 0,0,1); // the last three arguments specify the normal
setVertexTransform(...)method to supply a transformation matrix that should be applied to all vertices following after that call.
