159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene; 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.AssetNotFoundException; 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.bounding.BoundingVolume; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.Collidable; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.collision.CollisionResults; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.InputCapsule; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeExporter; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.JmeImporter; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.export.OutputCapsule; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.material.Material; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Matrix4f; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Transform; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.VertexBuffer.Type; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.TempVars; 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Queue; 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger; 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>Geometry</code> defines a leaf node of the scene graph. The leaf node 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * contains the geometric data for rendering objects. It manages all rendering 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * information such as a {@link Material} object to define how the surface 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * should be shaded and the {@link Mesh} data to contain the actual geometry. 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Kirill Vainer 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class Geometry extends Spatial { 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Version #1: removed shared meshes. 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // models loaded with shared mesh will be automatically fixed. 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int SAVABLE_VERSION = 1; 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final Logger logger = Logger.getLogger(Geometry.class.getName()); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Mesh mesh; 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected transient int lodLevel = 0; 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Material material; 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * When true, the geometry's transform will not be applied. 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected boolean ignoreTransform = false; 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected transient Matrix4f cachedWorldMat = new Matrix4f(); 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * used when geometry is batched 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected BatchNode batchNode = null; 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the start index of this geom's mesh in the batchNode mesh 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected int startIndex; 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the previous transforms of the geometry used to compute world transforms 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Transform prevBatchTransforms = null; 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the cached offset matrix used when the geometry is batched 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected Matrix4f cachedOffsetMat = null; 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Serialization only. Do not use. 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Geometry() { 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Create a geometry node without any mesh data. 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Both the mesh and the material are null, the geometry 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * cannot be rendered until those are set. 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param name The name of this geometry 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Geometry(String name) { 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(name); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Create a geometry node with mesh data. 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * The material of the geometry is null, it cannot 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * be rendered until it is set. 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param name The name of this geometry 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param mesh The mesh data for this geometry 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Geometry(String name, Mesh mesh) { 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this(name); 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh == null) { 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new NullPointerException(); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.mesh = mesh; 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return If ignoreTransform mode is set. 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see Geometry#setIgnoreTransform(boolean) 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isIgnoreTransform() { 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return ignoreTransform; 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param ignoreTransform If true, the geometry's transform will not be applied. 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setIgnoreTransform(boolean ignoreTransform) { 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.ignoreTransform = ignoreTransform; 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Sets the LOD level to use when rendering the mesh of this geometry. 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Level 0 indicates that the default index buffer should be used, 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * levels [1, LodLevels + 1] represent the levels set on the mesh 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * with {@link Mesh#setLodLevels(com.jme3.scene.VertexBuffer[]) }. 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param lod The lod level to set 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setLodLevel(int lod) { 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getNumLodLevels() == 0) { 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("LOD levels are not set on this mesh"); 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (lod < 0 || lod >= mesh.getNumLodLevels()) { 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("LOD level is out of range: " + lod); 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta lodLevel = lod; 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Returns the LOD level set with {@link #setLodLevel(int) }. 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the LOD level set 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getLodLevel() { 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return lodLevel; 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Returns this geometry's mesh vertex count. 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return this geometry's mesh vertex count. 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see Mesh#getVertexCount() 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getVertexCount() { 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return mesh.getVertexCount(); 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Returns this geometry's mesh triangle count. 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return this geometry's mesh triangle count. 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see Mesh#getTriangleCount() 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getTriangleCount() { 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return mesh.getTriangleCount(); 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Sets the mesh to use for this geometry when rendering. 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param mesh the mesh to use for this geometry 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws IllegalArgumentException If mesh is null 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setMesh(Mesh mesh) { 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh == null) { 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException(); 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (isBatched()) { 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Cannot set the mesh of a batched geometry"); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.mesh = mesh; 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setBoundRefresh(); 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Returns the mseh to use for this geometry 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the mseh to use for this geometry 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see #setMesh(com.jme3.scene.Mesh) 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Mesh getMesh() { 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return mesh; 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Sets the material to use for this geometry. 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param material the material to use for this geometry 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setMaterial(Material material) { 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (isBatched()) { 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Cannot set the material of a batched geometry, change the material of the parent BatchNode."); 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.material = material; 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Returns the material that is used for this geometry. 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the material that is used for this geometry 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see #setMaterial(com.jme3.material.Material) 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Material getMaterial() { 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return material; 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return The bounding volume of the mesh, in model space. 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public BoundingVolume getModelBound() { 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return mesh.getBound(); 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Updates the bounding volume of the mesh. Should be called when the 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * mesh has been modified. 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateModelBound() { 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.updateBound(); 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setBoundRefresh(); 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>updateWorldBound</code> updates the bounding volume that contains 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this geometry. The location of the geometry is based on the location of 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * all this node's parents. 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @see Spatial#updateWorldBound() 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void updateWorldBound() { 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.updateWorldBound(); 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh == null) { 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new NullPointerException("Geometry: " + getName() + " has null mesh"); 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh.getBound() != null) { 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ignoreTransform) { 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // we do not transform the model bound by the world transform, 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // just use the model bound as-is 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta worldBound = mesh.getBound().clone(worldBound); 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta worldBound = mesh.getBound().transform(worldTransform, worldBound); 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void updateWorldTransforms() { 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.updateWorldTransforms(); 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta computeWorldMatrix(); 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (isBatched()) { 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta computeOffsetTransform(); 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta batchNode.updateSubBatch(this); 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta prevBatchTransforms.set(batchNode.getTransforms(this)); 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // geometry requires lights to be sorted 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta worldLights.sort(true); 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Batch this geometry, should only be called by the BatchNode. 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param node the batchNode 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param startIndex the starting index of this geometry in the batched mesh 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void batch(BatchNode node, int startIndex) { 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.batchNode = node; 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.startIndex = startIndex; 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta prevBatchTransforms = new Transform(); 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat = new Matrix4f(); 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setCullHint(CullHint.Always); 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * unBatch this geometry. 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void unBatch() { 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.startIndex = 0; 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta prevBatchTransforms = null; 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat = null; 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //once the geometry is removed from the screnegraph the batchNode needs to be rebatched. 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.batchNode.setNeedsFullRebatch(true); 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.batchNode = null; 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setCullHint(CullHint.Dynamic); 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean removeFromParent() { 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean removed = super.removeFromParent(); 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //if the geometry is batched we also have to unbatch it 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (isBatched()) { 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta unBatch(); 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return removed; 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Recomputes the cached offset matrix used when the geometry is batched * 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void computeOffsetTransform() { 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TempVars vars = TempVars.get(); 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Matrix4f tmpMat = vars.tempMat42; 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Compute the cached world matrix 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat.loadIdentity(); 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat.setRotationQuaternion(prevBatchTransforms.getRotation()); 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat.setTranslation(prevBatchTransforms.getTranslation()); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Matrix4f scaleMat = vars.tempMat4; 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scaleMat.loadIdentity(); 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scaleMat.scale(prevBatchTransforms.getScale()); 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat.multLocal(scaleMat); 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedOffsetMat.invertLocal(); 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tmpMat.loadIdentity(); 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tmpMat.setRotationQuaternion(batchNode.getTransforms(this).getRotation()); 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tmpMat.setTranslation(batchNode.getTransforms(this).getTranslation()); 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scaleMat.loadIdentity(); 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scaleMat.scale(batchNode.getTransforms(this).getScale()); 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tmpMat.multLocal(scaleMat); 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta tmpMat.mult(cachedOffsetMat, cachedOffsetMat); 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Indicate that the transform of this spatial has changed and that 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a refresh is required. 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void setTransformRefresh() { 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta refreshFlags |= RF_TRANSFORM; 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setBoundRefresh(); 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Recomputes the matrix returned by {@link Geometry#getWorldMatrix() }. 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This will require a localized transform update for this geometry. 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void computeWorldMatrix() { 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Force a local update of the geometry's transform 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDoTransformUpdate(); 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Compute the cached world matrix 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedWorldMat.loadIdentity(); 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedWorldMat.setRotationQuaternion(worldTransform.getRotation()); 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedWorldMat.setTranslation(worldTransform.getTranslation()); 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta TempVars vars = TempVars.get(); 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Matrix4f scaleMat = vars.tempMat4; 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scaleMat.loadIdentity(); 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scaleMat.scale(worldTransform.getScale()); 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cachedWorldMat.multLocal(scaleMat); 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta vars.release(); 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * A {@link Matrix4f matrix} that transforms the {@link Geometry#getMesh() mesh} 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * from model space to world space. This matrix is computed based on the 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * {@link Geometry#getWorldTransform() world transform} of this geometry. 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * In order to receive updated values, you must call {@link Geometry#computeWorldMatrix() } 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * before using this method. 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return Matrix to transform from local space to world space 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Matrix4f getWorldMatrix() { 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return cachedWorldMat; 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Sets the model bound to use for this geometry. 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This alters the bound used on the mesh as well via 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * {@link Mesh#setBound(com.jme3.bounding.BoundingVolume) } and 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * forces the world bounding volume to be recomputed. 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param modelBound The model bound to set 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setModelBound(BoundingVolume modelBound) { 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.worldBound = null; 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh.setBound(modelBound); 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setBoundRefresh(); 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: Calling updateModelBound() would cause the mesh 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // to recompute the bound based on the geometry thus making 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // this call useless! 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //updateModelBound(); 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int collideWith(Collidable other, CollisionResults results) { 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Force bound to update 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDoBoundUpdate(); 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Update transform, and compute cached world matrix 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta computeWorldMatrix(); 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert (refreshFlags & (RF_BOUND | RF_TRANSFORM)) == 0; 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh != null) { 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: BIHTree in mesh already checks collision with the 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // mesh's bound 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int prevSize = results.size(); 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int added = mesh.collideWith(other, cachedWorldMat, worldBound, results); 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int newSize = results.size(); 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = prevSize; i < newSize; i++) { 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta results.getCollisionDirect(i).setGeometry(this); 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return added; 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return 0; 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void depthFirstTraversal(SceneGraphVisitor visitor) { 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta visitor.visit(this); 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta protected void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue) { 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isBatched() { 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return batchNode != null; 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This version of clone is a shallow clone, in other words, the 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * same mesh is referenced as the original geometry. 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Exception: if the mesh is marked as being a software 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * animated mesh, (bind pose is set) then the positions 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and normals are deep copied. 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Geometry clone(boolean cloneMaterial) { 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry geomClone = (Geometry) super.clone(cloneMaterial); 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomClone.cachedWorldMat = cachedWorldMat.clone(); 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material != null) { 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (cloneMaterial) { 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomClone.material = material.clone(); 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomClone.material = material; 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (mesh != null && mesh.getBuffer(Type.BindPosePosition) != null) { 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomClone.mesh = mesh.cloneForAnim(); 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return geomClone; 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This version of clone is a shallow clone, in other words, the 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * same mesh is referenced as the original geometry. 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Exception: if the mesh is marked as being a software 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * animated mesh, (bind pose is set) then the positions 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * and normals are deep copied. 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Geometry clone() { 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return clone(true); 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Creates a deep clone of the geometry, 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this creates an identical copy of the mesh 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * with the vertexbuffer data duplicated. 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Spatial deepClone() { 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Geometry geomClone = clone(true); 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta geomClone.mesh = mesh.deepClone(); 51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return geomClone; 51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void write(JmeExporter ex) throws IOException { 52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.write(ex); 52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta OutputCapsule oc = ex.getCapsule(this); 52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(mesh, "mesh", null); 52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material != null) { 52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(material.getAssetName(), "materialName", null); 52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(material, "material", null); 53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta oc.write(ignoreTransform, "ignoreTransform", false); 53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void read(JmeImporter im) throws IOException { 53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super.read(im); 53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputCapsule ic = im.getCapsule(this); 53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mesh = (Mesh) ic.readSavable("mesh", null); 53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = null; 54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String matName = ic.readString("materialName", null); 54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (matName != null) { 54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Material name is set, 54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Attempt to load material via J3M 54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = im.getAssetManager().loadMaterial(matName); 54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (AssetNotFoundException ex) { 54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Cannot find J3M file. 54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINE, "Cannot locate {0} for geometry {1}", new Object[]{matName, key}); 54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // If material is NULL, try to load it from the geometry 55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (material == null) { 55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta material = (Material) ic.readSavable("material", null); 55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ignoreTransform = ic.readBoolean("ignoreTransform", false); 55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ic.getSavableVersion(Geometry.class) == 0){ 55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Fix shared mesh (if set) 55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Mesh sharedMesh = getUserData(UserData.JME_SHAREDMESH); 56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (sharedMesh != null){ 56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta getMesh().extractVertexData(sharedMesh); 56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 566