*
* A model is created from {@link ModelData}, which in turn is loaded by a {@link ModelLoader}.
*
- * @author badlogic
- *
- */
+ * @author badlogic, xoppa */
public class Model implements Disposable {
/** the materials of the model, used by nodes that have a graphical representation FIXME not sure if superfluous, allows modification of materials without having to traverse the nodes **/
public final Array<Material> materials = new Array<Material>();
* Use {@link #manageDisposable(Disposable)} to add resources to be managed by this model. */
public Model() {}
- /**
- * Constructs a new Model based on the {@link ModelData}. Texture files
+ /** Constructs a new Model based on the {@link ModelData}. Texture files
* will be loaded from the internal file storage via an {@link FileTextureProvider}.
- * @param modelData
- */
+ * @param modelData the {@link ModelData} got from e.g. {@link ModelLoader} */
public Model(ModelData modelData) {
this(modelData, new FileTextureProvider());
}
-
+
+ /** Constructs a new Model based on the {@link ModelData}.
+ * @param modelData the {@link ModelData} got from e.g. {@link ModelLoader}
+ * @param textureProvider the {@link TextureProvider} to use for loading the textures */
public Model(ModelData modelData, TextureProvider textureProvider) {
load(modelData, textureProvider);
}
return result;
}
- /**
- * Adds a {@link Disposable} to be managed and disposed by this Model. Can
+ /** Adds a {@link Disposable} to be managed and disposed by this Model. Can
* be used to keep track of manually loaded textures for {@link ModelInstance}.
- * @param disposable the Disposable
- */
+ * @param disposable the Disposable */
public void manageDisposable(Disposable disposable) {
if (!disposables.contains(disposable, true))
disposables.add(disposable);
}
+ /** @return the {@link Disposable} objects that will be disposed when the {@link #dispose()} method is called. */
public Iterable<Disposable> getManagedDisposables() {
return disposables;
}
}
}
- /**
- * Calculates the local and world transform of all {@link Node} instances in this model, recursively.
+ /** Calculates the local and world transform of all {@link Node} instances in this model, recursively.
* First each {@link Node#localTransform} transform is calculated based on the translation, rotation and
* scale of each Node. Then each {@link Node#calculateWorldTransform()}
* is calculated, based on the parent's world transform and the local transform of each Node.
}
/** Calculate the bounding box of this model instance.
- * This is a potential slow operation, it is advised to cache the result. */
+ * This is a potential slow operation, it is advised to cache the result.
+ * @param out the {@link BoundingBox} that will be set with the bounds.
+ * @return the out parameter for chaining */
public BoundingBox calculateBoundingBox(final BoundingBox out) {
out.inf();
return extendBoundingBox(out);
}
/** Extends the bounding box with the bounds of this model instance.
- * This is a potential slow operation, it is advised to cache the result. */
+ * This is a potential slow operation, it is advised to cache the result.
+ * @param out the {@link BoundingBox} that will be extended with the bounds.
+ * @return the out parameter for chaining */
public BoundingBox extendBoundingBox(final BoundingBox out) {
final int n = nodes.size;
for(int i = 0; i < n; i++)
return out;
}
- /** @return The animation with the specified id, or null if not available. */
+ /** @param id The ID of the animation to fetch (case sensitive).
+ * @return The {@link Animation} with the specified id, or null if not available. */
public Animation getAnimation(final String id) {
return getAnimation(id, true);
}
- /** @return The animation with the specified id, or null if not available. */
+ /** @param id The ID of the animation to fetch.
+ * @param ignoreCase whether to use case sensitivity when comparing the animation id.
+ * @return The {@link Animation} with the specified id, or null if not available. */
public Animation getAnimation(final String id, boolean ignoreCase) {
final int n = animations.size;
Animation animation;
return null;
}
- /** @return The material with the specified id, or null if not available. */
+ /** @param id The ID of the material to fetch.
+ * @return The {@link Material} with the specified id, or null if not available. */
public Material getMaterial(final String id) {
return getMaterial(id, true);
}
- /** @return The material with the specified id, or null if not available. */
+ /** @param id The ID of the material to fetch.
+ * @param ignoreCase whether to use case sensitivity when comparing the material id.
+ * @return The {@link Material} with the specified id, or null if not available. */
public Material getMaterial(final String id, boolean ignoreCase) {
final int n = materials.size;
Material material;
return null;
}
- /** @return The node with the specified id, or null if not found. */
+ /** @param id The ID of the node to fetch.
+ * @return The {@link Node} with the specified id, or null if not found. */
public Node getNode(final String id) {
return getNode(id, true);
}
- /** @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
- * @return The node with the specified id, or null if not found. */
+ /** @param id The ID of the node to fetch.
+ * @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
+ * @return The {@link Node} with the specified id, or null if not found. */
public Node getNode(final String id, boolean recursive) {
return getNode(id, recursive, false);
}
- /** @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
- * @return The node with the specified id, or null if not found. */
+ /** @param id The ID of the node to fetch.
+ * @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
+ * @param ignoreCase whether to use case sensitivity when comparing the node id.
+ * @return The {@link Node} with the specified id, or null if not found. */
public Node getNode(final String id, boolean recursive, boolean ignoreCase) {
return Node.getNode(nodes, id, recursive, ignoreCase);
}
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.g3d.lights.Lights;
+import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
import com.badlogic.gdx.graphics.g3d.utils.DefaultRenderableSorter;
import com.badlogic.gdx.graphics.g3d.utils.DefaultShaderProvider;
import com.badlogic.gdx.graphics.g3d.utils.DefaultTextureBinder;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
+import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Pool;
+/** Batches {@link Renderable} instances, fetches {@link Shader}s for them, sorts them and then renders them.
+ * Fetching the shaders is done using a {@link ShaderProvider}, which defaults to {@link DefaultShaderProvider}.
+ * Sorting the renderables is done using a {@link RenderableSorter}, which default to {@link DefaultRenderableSorter}.
+ *
+ * The OpenGL context between the {@link #begin(Camera)} and {@link #end()} call is maintained by the {@link RenderContext}.
+ *
+ * To provide multiple {@link Renderable}s at once a {@link RenderableProvider} can be used, e.g. a {@link ModelInstance}.
+ *
+ * @author xoppa, badlogic */
public class ModelBatch implements Disposable {
protected Camera camera;
protected final Pool<Renderable> renderablesPool = new Pool<Renderable>() {
protected final Array<Renderable> reuseableRenderables = new Array<Renderable>();
/** the {@link RenderContext} **/
protected final RenderContext context;
+ private final boolean ownContext;
/** the {@link ShaderProvider}, provides {@link Shader} instances for Renderables **/
protected final ShaderProvider shaderProvider;
/** the {@link RenderableSorter} **/
protected final RenderableSorter sorter;
- /** Construct a BaseRenderBatch with the specified listener */
- public ModelBatch(RenderContext context, ShaderProvider shaderProvider, RenderableSorter sorter) {
+ private ModelBatch(RenderContext context, boolean ownContext, ShaderProvider shaderProvider, RenderableSorter sorter) {
+ this.ownContext = ownContext;
this.context = context;
this.shaderProvider = shaderProvider;
this.sorter = sorter;
}
- /** Construct a BaseRenderBatch with the default implementation and the specified shader provider*/
+ /** Construct a ModelBatch, using this constructor makes you responsible for calling context.begin() and contact.end() yourself.
+ * @param context The {@link RenderContext} to use.
+ * @param shaderProvider The {@link ShaderProvider} to use.
+ * @param sorter The {@link RenderableSorter} to use. */
+ public ModelBatch(RenderContext context, ShaderProvider shaderProvider, RenderableSorter sorter) {
+ this(context, false, shaderProvider, sorter);
+ }
+
+ /** Construct a ModelBatch, using this constructor makes you responsible for calling context.begin() and contact.end() yourself.
+ * @param shaderProvider The {@link ShaderProvider} to use. */
public ModelBatch(ShaderProvider shaderProvider) {
- this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
- shaderProvider,
- new DefaultRenderableSorter());
+ this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.WEIGHTED, 1)),
+ true,
+ shaderProvider,
+ new DefaultRenderableSorter());
}
- /** Construct a BaseRenderBatch with the default implementation and the specified uber shader*/
+ /** Construct a ModelBatch with the default implementation and the specified ubershader. See {@link DefaultShader} for
+ * more information about using a custom ubershader. Requires OpenGL ES 2.0.
+ * @param vertexShader The {@link FileHandle} of the vertex shader to use.
+ * @param fragmentShader The {@link FileHandle} of the fragment shader to use. */
public ModelBatch(final FileHandle vertexShader, final FileHandle fragmentShader) {
this(new DefaultShaderProvider(vertexShader, fragmentShader));
}
- /** Construct a BaseRenderBatch with the default implementation and the specified uber shader*/
+ /** Construct a ModelBatch with the default implementation and the specified ubershader. See {@link DefaultShader} for
+ * more information about using a custom ubershader. Requires OpenGL ES 2.0.
+ * @param vertexShader The vertex shader to use.
+ * @param fragmentShader The fragment shader to use. */
public ModelBatch(final String vertexShader, final String fragmentShader) {
this(new DefaultShaderProvider(vertexShader, fragmentShader));
}
- /** Construct a BaseRenderBatch with the default implementation */
+ /** Construct a ModelBatch with the default implementation */
public ModelBatch() {
this(new RenderContext(new DefaultTextureBinder(DefaultTextureBinder.ROUNDROBIN, 1)),
- new DefaultShaderProvider(),
- new DefaultRenderableSorter());
+ true,
+ new DefaultShaderProvider(),
+ new DefaultRenderableSorter());
}
- public void begin (Camera cam) {
- this.camera = cam;
+ /** Start rendering one or more {@link Renderable}s. Use one of the render() methods to provide the renderables.
+ * Must be followed by a call to {@link #end()}. The OpenGL context must not be altered between
+ * {@link #begin(Camera)} and {@link #end()}.
+ * @param cam The {@link Camera} to be used when rendering and sorting. */
+ public void begin (final Camera cam) {
+ if (camera != null)
+ throw new GdxRuntimeException("Call end() first.");
+ camera = cam;
+ if (ownContext)
+ context.begin();
}
-
- public void end () {
+
+ /** Change the camera in between {@link #begin(Camera)} and {@link #end()}. This causes the batch to be flushed.
+ * Can only be called after the call to {@link #begin(Camera)} and before the call to {@link #end()}.
+ * @param cam The new camera to use. */
+ public void setCamera(final Camera cam) {
+ if (camera == null)
+ throw new GdxRuntimeException("Call begin() first.");
+ if (renderables.size > 0)
+ flush();
+ camera = cam;
+ }
+
+ /** Flushes the batch, causing all {@link Renderable}s in the batch to be rendered. Can only be called after the
+ * call to {@link #begin(Camera)} and before the call to {@link #end()}. */
+ public void flush() {
sorter.sort(camera, renderables);
- context.begin();
Shader currentShader = null;
for (int i = 0; i < renderables.size; i++) {
final Renderable renderable = renderables.get(i);
}
if (currentShader != null)
currentShader.end();
- context.end();
renderablesPool.freeAll(reuseableRenderables);
reuseableRenderables.clear();
renderables.clear();
+ }
+
+ /** End rendering one or more {@link Renderable}s. Must be called after a call to {@link #begin(Camera)}.
+ * This will flush the batch, causing any renderables provided using one of the render() methods to be rendered.
+ * After a call to this method the OpenGL context can be altered again. */
+ public void end () {
+ flush();
+ if (ownContext)
+ context.end();
camera = null;
}
+ /** Add a single {@link Renderable} to the batch. The {@link ShaderProvider} will be used to fetch a suitable
+ * {@link Shader}. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
+ * @param renderable The {@link Renderable} to be added. */
public void render(final Renderable renderable) {
renderable.shader = shaderProvider.getShader(renderable);
renderable.mesh.setAutoBind(false);
renderables.add(renderable);
}
-
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered.
- * @param renderableProvider the renderable provider
- */
+
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Can only be called after a call to {@link #begin(Camera)}
+ * and before a call to {@link #end()}.
+ * @param renderableProvider the renderable provider */
public void render(final RenderableProvider renderableProvider) {
render(renderableProvider, null, null);
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered.
- * @param renderableProviders one or more renderable providers
- */
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Can only be called after a call to {@link #begin(Camera)}
+ * and before a call to {@link #end()}.
+ * @param renderableProviders one or more renderable providers */
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders) {
render(renderableProviders, null, null);
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered. Any lights set on the returned renderables will be replaced
- * with the given lights
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Any lights set on the returned renderables will be replaced
+ * with the given lights. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProvider the renderable provider
- * @param lights the lights to use for the renderables
- */
+ * @param lights the lights to use for the renderables */
public void render(final RenderableProvider renderableProvider, final Lights lights) {
render(renderableProvider, lights, null);
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered. Any lights set on the returned renderables will be replaced
- * with the given lights
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Any lights set on the returned renderables will be replaced
+ * with the given lights. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProviders one or more renderable providers
- * @param lights the lights to use for the renderables
- */
+ * @param lights the lights to use for the renderables */
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Lights lights) {
render(renderableProviders, lights, null);
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered. Any shaders set on the returned renderables will be replaced
- * with the given {@link Shader}.
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Any shaders set on the returned renderables will be replaced
+ * with the given {@link Shader}. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProvider the renderable provider
- * @param shader the shader to use for the renderables
- */
+ * @param shader the shader to use for the renderables */
public void render(final RenderableProvider renderableProvider, final Shader shader) {
render(renderableProvider, null, shader);
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered. Any shaders set on the returned renderables will be replaced
- * with the given {@link Shader}.
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Any shaders set on the returned renderables will be replaced
+ * with the given {@link Shader}. Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProviders one or more renderable providers
- * @param shader the shader to use for the renderables
- */
+ * @param shader the shader to use for the renderables */
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Shader shader) {
render(renderableProviders, null, shader);
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered. Any lights set on the returned renderables will be replaced
- * with the given lights. Any shaders set on the returned renderables will
- * be replaced by the given {@link Shader}.
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Any lights set on the returned renderables will be replaced
+ * with the given lights. Any shaders set on the returned renderables will be replaced with the given {@link Shader}.
+ * Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProvider the renderable provider
* @param lights the lights to use for the renderables
- * @param shader the shader to use for the renderables
- */
+ * @param shader the shader to use for the renderables */
public void render(final RenderableProvider renderableProvider, final Lights lights, final Shader shader) {
- int offset = renderables.size;
+ final int offset = renderables.size;
renderableProvider.getRenderables(renderables, renderablesPool);
for (int i = offset; i < renderables.size; i++) {
Renderable renderable = renderables.get(i);
}
}
- /**
- * Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds
- * all returned {@link Renderable} instances to the current batch to be
- * rendered. Any lights set on the returned renderables will be replaced
- * with the given lights. Any shaders set on the returned renderables will
- * be replaced by the given {@link Shader}.
+ /** Calls {@link RenderableProvider#getRenderables(Array, Pool)} and adds all returned {@link Renderable}
+ * instances to the current batch to be rendered. Any lights set on the returned renderables will be replaced
+ * with the given lights. Any shaders set on the returned renderables will be replaced with the given {@link Shader}.
+ * Can only be called after a call to {@link #begin(Camera)} and before a call to {@link #end()}.
* @param renderableProviders one or more renderable providers
* @param lights the lights to use for the renderables
- * @param shader the shader to use for the renderables
- */
+ * @param shader the shader to use for the renderables */
public <T extends RenderableProvider> void render(final Iterable<T> renderableProviders, final Lights lights, final Shader shader) {
for (final RenderableProvider renderableProvider : renderableProviders)
render(renderableProvider, lights, shader);
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.Pool;
-/**
- * An instance of a {@link Model}, allows to specify global transform and modify the materials, as it
+/** An instance of a {@link Model}, allows to specify global transform and modify the materials, as it
* has a copy of the model's materials. Multiple instances can be created from the same Model,
* all sharing the meshes and textures of the Model. The Model owns the meshes and textures, to
- * dispose of these, the Model has to be disposed.</p>
+ * dispose of these, the Model has to be disposed. Therefor, the Model must outlive all its ModelInstances</p>
*
- * The ModelInstance creates a full copy of all materials and nodes.
- * @author badlogic
- *
- */
+ * The ModelInstance creates a full copy of all materials, nodes and animations.
+ * @author badlogic, xoppa */
public class ModelInstance implements RenderableProvider {
/** the materials of the model, used by nodes that have a graphical representation FIXME not sure if superfluous, allows modification of materials without having to traverse the nodes **/
public final Array<Material> materials = new Array<Material>();
/** user definable value, which is passed to the shader. */
public Object userData;
- /** Constructs a new ModelInstance with all nodes and materials of the given model. */
- public ModelInstance(Model model) {
+ /** Constructs a new ModelInstance with all nodes and materials of the given model.
+ * @param model The {@link Model} to create an instance of. */
+ public ModelInstance(final Model model) {
this(model, (String[])null);
}
/** @param model The source {@link Model}
* @param nodeId The ID of the root {@link Node} of the {@link Model} for the instance to contain
* @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */
- public ModelInstance(Model model, final String nodeId, boolean mergeTransform) {
+ public ModelInstance(final Model model, final String nodeId, boolean mergeTransform) {
this(model, null, nodeId, false, false, mergeTransform);
}
* @param transform The {@link Matrix4} instance for this ModelInstance to reference or null to create a new matrix.
* @param nodeId The ID of the root {@link Node} of the {@link Model} for the instance to contain
* @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */
- public ModelInstance(Model model, final Matrix4 transform, final String nodeId, boolean mergeTransform) {
+ public ModelInstance(final Model model, final Matrix4 transform, final String nodeId, boolean mergeTransform) {
this(model, transform, nodeId, false, false, mergeTransform);
}
* @param nodeId The ID of the {@link Node} within the {@link Model} for the instance to contain
* @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
* @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */
- public ModelInstance(Model model, final String nodeId, boolean parentTransform, boolean mergeTransform) {
+ public ModelInstance(final Model model, final String nodeId, boolean parentTransform, boolean mergeTransform) {
this(model, null, nodeId, true, parentTransform, mergeTransform);
}
* @param nodeId The ID of the {@link Node} within the {@link Model} for the instance to contain
* @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
* @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */
- public ModelInstance(Model model, final Matrix4 transform, final String nodeId, boolean parentTransform, boolean mergeTransform) {
+ public ModelInstance(final Model model, final Matrix4 transform, final String nodeId, boolean parentTransform, boolean mergeTransform) {
this(model, transform, nodeId, true, parentTransform, mergeTransform);
}
* @param recursive True to recursively search the Model's node tree, false to only search for a root node
* @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
* @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */
- public ModelInstance(Model model, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
+ public ModelInstance(final Model model, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
this(model, null, nodeId, recursive, parentTransform, mergeTransform);
}
* @param recursive True to recursively search the Model's node tree, false to only search for a root node
* @param parentTransform True to apply the parent's node transform to the instance (only applicable if recursive is true).
* @param mergeTransform True to apply the source node transform to the instance transform, resetting the node transform. */
- public ModelInstance(Model model, final Matrix4 transform, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
+ public ModelInstance(final Model model, final Matrix4 transform, final String nodeId, boolean recursive, boolean parentTransform, boolean mergeTransform) {
this.model = model;
this.transform = transform == null ? new Matrix4() : transform;
nodePartBones.clear();
}
/** Constructs a new ModelInstance with only the specified nodes and materials of the given model. */
- public ModelInstance(Model model, final String... rootNodeIds) {
+ public ModelInstance(final Model model, final String... rootNodeIds) {
this(model, null, rootNodeIds);
}
/** Constructs a new ModelInstance with only the specified nodes and materials of the given model. */
- public ModelInstance(Model model, final Matrix4 transform, final String... rootNodeIds) {
+ public ModelInstance(final Model model, final Matrix4 transform, final String... rootNodeIds) {
this.model = model;
this.transform = transform == null ? new Matrix4() : transform;
if (rootNodeIds == null)
}
/** Constructs a new ModelInstance with only the specified nodes and materials of the given model. */
- public ModelInstance(Model model, final Array<String> rootNodeIds) {
+ public ModelInstance(final Model model, final Array<String> rootNodeIds) {
this(model, null, rootNodeIds);
}
/** Constructs a new ModelInstance with only the specified nodes and materials of the given model. */
- public ModelInstance(Model model, final Matrix4 transform, final Array<String> rootNodeIds) {
+ public ModelInstance(final Model model, final Matrix4 transform, final Array<String> rootNodeIds) {
this.model = model;
this.transform = transform == null ? new Matrix4() : transform;
copyNodes(model.nodes, rootNodeIds);
}
/** Constructs a new ModelInstance at the specified position. */
- public ModelInstance(Model model, Vector3 position) {
+ public ModelInstance(final Model model, Vector3 position) {
this(model);
this.transform.setToTranslation(position);
}
/** Constructs a new ModelInstance at the specified position. */
- public ModelInstance(Model model, float x, float y, float z) {
+ public ModelInstance(final Model model, float x, float y, float z) {
this(model);
this.transform.setToTranslation(x, y, z);
}
/** Constructs a new ModelInstance with the specified transform. */
- public ModelInstance(Model model, Matrix4 transform) {
+ public ModelInstance(final Model model, Matrix4 transform) {
this(model, transform, (String[])null);
}
}
}
- /**
- * Calculates the local and world transform of all {@link Node} instances in this model, recursively.
+ /** Calculates the local and world transform of all {@link Node} instances in this model, recursively.
* First each {@link Node#localTransform} transform is calculated based on the translation, rotation and
* scale of each Node. Then each {@link Node#calculateWorldTransform()}
* is calculated, based on the parent's world transform and the local transform of each Node.
}
/** Calculate the bounding box of this model instance.
- * This is a potential slow operation, it is advised to cache the result. */
+ * This is a potential slow operation, it is advised to cache the result.
+ * @param out the {@link BoundingBox} that will be set with the bounds.
+ * @return the out parameter for chaining */
public BoundingBox calculateBoundingBox(final BoundingBox out) {
out.inf();
return extendBoundingBox(out);
}
/** Extends the bounding box with the bounds of this model instance.
- * This is a potential slow operation, it is advised to cache the result. */
+ * This is a potential slow operation, it is advised to cache the result.
+ * @param out the {@link BoundingBox} that will be extended with the bounds.
+ * @return the out parameter for chaining */
public BoundingBox extendBoundingBox(final BoundingBox out) {
final int n = nodes.size;
for(int i = 0; i < n; i++)
return out;
}
- /** @return The animation with the specified id, or null if not available. */
+ /** @param id The ID of the animation to fetch (case sensitive).
+ * @return The {@link Animation} with the specified id, or null if not available. */
public Animation getAnimation(final String id) {
return getAnimation(id, true);
}
- /** @return The animation with the specified id, or null if not available. */
+ /** @param id The ID of the animation to fetch.
+ * @param ignoreCase whether to use case sensitivity when comparing the animation id.
+ * @return The {@link Animation} with the specified id, or null if not available. */
public Animation getAnimation(final String id, boolean ignoreCase) {
final int n = animations.size;
Animation animation;
return null;
}
- /** @return The material with the specified id, or null if not available. */
+ /** @param id The ID of the material to fetch.
+ * @return The {@link Material} with the specified id, or null if not available. */
public Material getMaterial(final String id) {
return getMaterial(id, true);
}
- /** @return The material with the specified id, or null if not available. */
+ /** @param id The ID of the material to fetch.
+ * @param ignoreCase whether to use case sensitivity when comparing the material id.
+ * @return The {@link Material} with the specified id, or null if not available. */
public Material getMaterial(final String id, boolean ignoreCase) {
final int n = materials.size;
Material material;
return null;
}
- /** @return The node with the specified id, or null if not found. */
+ /** @param id The ID of the node to fetch.
+ * @return The {@link Node} with the specified id, or null if not found. */
public Node getNode(final String id) {
return getNode(id, true);
}
- /** @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
- * @return The node with the specified id, or null if not found. */
+ /** @param id The ID of the node to fetch.
+ * @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
+ * @return The {@link Node} with the specified id, or null if not found. */
public Node getNode(final String id, boolean recursive) {
return getNode(id, recursive, false);
}
- /** @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
- * @return The node with the specified id, or null if not found. */
+ /** @param id The ID of the node to fetch.
+ * @param recursive false to fetch a root node only, true to search the entire node tree for the specified node.
+ * @param ignoreCase whether to use case sensitivity when comparing the node id.
+ * @return The {@link Node} with the specified id, or null if not found. */
public Node getNode(final String id, boolean recursive, boolean ignoreCase) {
return Node.getNode(nodes, id, recursive, ignoreCase);
}
import com.badlogic.gdx.graphics.g3d.lights.Lights;
import com.badlogic.gdx.graphics.g3d.materials.Material;
import com.badlogic.gdx.graphics.g3d.model.Node;
+import com.badlogic.gdx.graphics.g3d.utils.ShaderProvider;
import com.badlogic.gdx.math.Matrix4;
+import com.badlogic.gdx.utils.Array;
+import com.badlogic.gdx.utils.Pool;
-/**
- * A renderable defines a world transform, the {@link Mesh} to render
+/** A renderable defines a world transform, the {@link Mesh} to render
* along with the offset into the mesh's indices and the number of indices to use plus the
* primitive type to render the part of the mesh with. Finally, a renderable defines
* a {@link Material} to be applied to the mesh.</p>
*
* Renderables can be rendered via a {@link ModelBatch}, either directly, or by passing a
- * {@link ModelInstance} to the RenderBatch. A Model returns all Renderables via its {@link ModelInstance#getRenderables(com.badlogic.gdx.utils.Array, com.badlogic.gdx.utils.Pool)} method.
- * @author badlogic
- *
- */
+ * {@link RenderableProvider} like {@link ModelInstance} to the RenderBatch.
+ * A ModelInstance returns all Renderables via its {@link ModelInstance#getRenderables(Array, Pool)} method.</p>
+ *
+ * When using a ModelBatch to render a renderable, The renderable and all its values must not be changed
+ * in between the call to {@link ModelBatch#begin(com.badlogic.gdx.graphics.Camera)} and {@link ModelBatch#end()}.</p>
+ *
+ * When the {@link #shader} member of the Renderable is set, the {@link ShaderProvider} of the {@link ModelBatch}
+ * may try to use that shader instead of the default shader. Therefor, to assure the default shader is used, the
+ * {@link #shader} member must be set to null.
+ * @author badlogic, xoppa */
public class Renderable {
/** the model transform **/
public final Matrix4 worldTransform = new Matrix4();
- /** the mesh to render **/
+ /** the {@link Mesh} to render **/
public Mesh mesh;
/** the offset into the mesh's indices **/
public int meshPartOffset;
public int meshPartSize;
/** the primitive type, encoded as an OpenGL constant, like {@link GL20#GL_TRIANGLES} **/
public int primitiveType;
- /** the material to be applied to the mesh **/
+ /** the {@link Material} to be applied to the mesh **/
public Material material;
/** the bones transformations used for skinning, or null if not applicable */
public Matrix4 bones[];
- /** the lights to be used to render this Renderable, may be null **/
+ /** the {@link Lights} to be used to render this Renderable, may be null **/
public Lights lights;
- /** the Shader to be used to render this Renderable, may be null **/
+ /** the {@link Shader} to be used to render this Renderable, may be null.
+ * It is not guaranteed that the shader will be used, the used {@link ShaderProvider} is responsible
+ * for actually choosing the correct shader to use. **/
public Shader shader;
/** user definable value. */
public Object userData;
*
*/
public interface RenderableProvider {
- /**
- * Returns {@link Renderable} instances. Renderables are obtained from the provided
- * pool and added to the provided array. The Renderables in the array will later be
+ /** Returns {@link Renderable} instances. Renderables are obtained from the provided
+ * {@link Pool} and added to the provided array. The Renderables in the array will later be
* put back into the pool, do not store them internally. The resulting array can be rendered via a {@link ModelBatch}.
- *
* @param renderables the output array
- * @param pool the pool to obtain Renderables from
- */
+ * @param pool the pool to obtain Renderables from */
public void getRenderables(Array<Renderable> renderables, Pool<Renderable> pool);
}
}
context.setCullFace(cullFace);
- context.setDepthTest(depthFunc, depthRangeNear, depthRangeFar, depthMask);
+ context.setDepthTest(depthFunc, depthRangeNear, depthRangeFar);
+ context.setDepthMask(depthMask);
}
private final Vector3 tmpV1 = new Vector3();
public void begin (final Camera camera, final RenderContext context) {
this.context = context;
this.camera = camera;
- context.setDepthTest(GL10.GL_LEQUAL, 0, 1, true);
+ context.setDepthTest(GL10.GL_LEQUAL, 0, 1);
+ context.setDepthMask(true);
Gdx.gl10.glMatrixMode(GL10.GL_PROJECTION);
Gdx.gl10.glLoadMatrixf(camera.combined.val, 0);
Gdx.gl10.glMatrixMode(GL10.GL_MODELVIEW);
import com.badlogic.gdx.graphics.g3d.Shader;
import com.badlogic.gdx.graphics.g3d.shaders.DefaultShader;
import com.badlogic.gdx.graphics.g3d.shaders.GLES10Shader;
+import com.badlogic.gdx.utils.GdxRuntimeException;
public class DefaultShaderProvider extends BaseShaderProvider {
public String vertexShader;
*/
public final void end() {
if(depthFunc != 0) Gdx.gl.glDisable(GL10.GL_DEPTH_TEST);
+ if (!depthMask) Gdx.gl.glDepthMask(true);
if(blending) Gdx.gl.glDisable(GL10.GL_BLEND);
if(cullFace>0) Gdx.gl.glDisable(GL10.GL_CULL_FACE);
textureBinder.end();
}
- public final void setDepthTest(final int depthFunction, final float depthRangeNear, final float depthRangeFar, final boolean depthMask) {
+ public final void setDepthMask(final boolean depthMask) {
+ if (this.depthMask != depthMask)
+ Gdx.gl.glDepthMask(this.depthMask = depthMask);
+ }
+
+ public final void setDepthTest(final int depthFunction) {
+ setDepthTest(depthFunction, 0f, 1f);
+ }
+
+ public final void setDepthTest(final int depthFunction, final float depthRangeNear, final float depthRangeFar) {
final boolean wasEnabled = depthFunc != 0;
final boolean enabled = depthFunction != 0;
if (depthFunc != depthFunction) {
if (!wasEnabled || this.depthRangeNear != depthRangeNear || this.depthRangeFar != depthRangeFar)
Gdx.gl.glDepthRangef(this.depthRangeNear = depthRangeNear, this.depthRangeFar = depthRangeFar);
}
- if (this.depthMask != depthMask)
- Gdx.gl.glDepthMask(this.depthMask = depthMask);
}
public final void setBlending(final boolean enabled, final int sFactor, final int dFactor) {