improve formatting & rm trailing whitespace (5 files in com.jme3.scene)

master
Stephen Gold 5 years ago
parent bee3d36f16
commit 851793cde6
  1. 51
      jme3-core/src/main/java/com/jme3/scene/Geometry.java
  2. 263
      jme3-core/src/main/java/com/jme3/scene/Mesh.java
  3. 175
      jme3-core/src/main/java/com/jme3/scene/Node.java
  4. 77
      jme3-core/src/main/java/com/jme3/scene/Spatial.java
  5. 339
      jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java

@ -61,7 +61,6 @@ import java.util.logging.Logger;
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public class Geometry extends Spatial { public class Geometry extends Spatial {
// Version #1: removed shared meshes. // Version #1: removed shared meshes.
// models loaded with shared mesh will be automatically fixed. // models loaded with shared mesh will be automatically fixed.
public static final int SAVABLE_VERSION = 1; public static final int SAVABLE_VERSION = 1;
@ -74,19 +73,16 @@ public class Geometry extends Spatial {
*/ */
protected boolean ignoreTransform = false; protected boolean ignoreTransform = false;
protected transient Matrix4f cachedWorldMat = new Matrix4f(); protected transient Matrix4f cachedWorldMat = new Matrix4f();
/** /**
* Specifies which {@link GeometryGroupNode} this <code>Geometry</code> * Specifies which {@link GeometryGroupNode} this <code>Geometry</code>
* is managed by. * is managed by.
*/ */
protected GeometryGroupNode groupNode; protected GeometryGroupNode groupNode;
/** /**
* The start index of this <code>Geometry's</code> inside * The start index of this <code>Geometry's</code> inside
* the {@link GeometryGroupNode}. * the {@link GeometryGroupNode}.
*/ */
protected int startIndex = -1; protected int startIndex = -1;
/** /**
* Morph state variable for morph animation * Morph state variable for morph animation
*/ */
@ -391,8 +387,7 @@ public class Geometry extends Spatial {
} }
} }
/*
/**
* Indicate that the transform of this spatial has changed and that * Indicate that the transform of this spatial has changed and that
* a refresh is required. * a refresh is required.
*/ */
@ -519,7 +514,7 @@ public class Geometry extends Spatial {
*/ */
@Override @Override
public Geometry clone(boolean cloneMaterial) { public Geometry clone(boolean cloneMaterial) {
return (Geometry)super.clone(cloneMaterial); return (Geometry) super.clone(cloneMaterial);
} }
/** /**
@ -553,13 +548,13 @@ public class Geometry extends Spatial {
* Called internally by com.jme3.util.clone.Cloner. Do not call directly. * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/ */
@Override @Override
public void cloneFields( Cloner cloner, Object original ) { public void cloneFields(Cloner cloner, Object original) {
super.cloneFields(cloner, original); super.cloneFields(cloner, original);
// If this is a grouped node and if our group node is // If this is a grouped node and if our group node is
// also cloned then we'll grab its reference. // also cloned then we'll grab its reference.
if( groupNode != null ) { if (groupNode != null) {
if( cloner.isCloned(groupNode) ) { if (cloner.isCloned(groupNode)) {
// Then resolve the reference // Then resolve the reference
this.groupNode = cloner.clone(groupNode); this.groupNode = cloner.clone(groupNode);
} else { } else {
@ -581,7 +576,7 @@ public class Geometry extends Spatial {
// See if we clone the mesh using the special animation // See if we clone the mesh using the special animation
// semi-deep cloning // semi-deep cloning
if( shallowClone && mesh != null && mesh.getBuffer(Type.BindPosePosition) != null ) { if (shallowClone && mesh != null && mesh.getBuffer(Type.BindPosePosition) != null) {
// Then we need to clone the mesh a little deeper // Then we need to clone the mesh a little deeper
this.mesh = mesh.cloneForAnim(); this.mesh = mesh.cloneForAnim();
} else { } else {
@ -593,7 +588,7 @@ public class Geometry extends Spatial {
} }
public void setMorphState(float[] state) { public void setMorphState(float[] state) {
if (mesh == null || mesh.getMorphTargets().length == 0){ if (mesh == null || mesh.getMorphTargets().length == 0) {
return; return;
} }
@ -608,9 +603,9 @@ public class Geometry extends Spatial {
/** /**
* Set the state of the morph with the given name. * Set the state of the morph with the given name.
* *
* If the name of the morph is not found, no state will be set. * If the name of the morph is not found, no state will be set.
* *
* @param morphTarget The name of the morph to set the state of * @param morphTarget The name of the morph to set the state of
* @param state The state to set the morph to * @param state The state to set the morph to
*/ */
@ -624,6 +619,7 @@ public class Geometry extends Spatial {
/** /**
* returns true if the morph state has changed on the last frame. * returns true if the morph state has changed on the last frame.
*
* @return true if changed, otherwise false * @return true if changed, otherwise false
*/ */
public boolean isDirtyMorph() { public boolean isDirtyMorph() {
@ -633,6 +629,7 @@ public class Geometry extends Spatial {
/** /**
* Seting this to true will stop this geometry morph buffer to be updated, * Seting this to true will stop this geometry morph buffer to be updated,
* unless the morph state changes * unless the morph state changes
*
* @param dirtyMorph * @param dirtyMorph
*/ */
public void setDirtyMorph(boolean dirtyMorph) { public void setDirtyMorph(boolean dirtyMorph) {
@ -642,6 +639,7 @@ public class Geometry extends Spatial {
/** /**
* returns the morph state of this Geometry. * returns the morph state of this Geometry.
* Used internally by the MorphControl. * Used internally by the MorphControl.
*
* @return an array * @return an array
*/ */
public float[] getMorphState() { public float[] getMorphState() {
@ -650,9 +648,10 @@ public class Geometry extends Spatial {
} }
return morphState; return morphState;
} }
/** /**
* Get the state of a morph * Get the state of a morph
*
* @param morphTarget the name of the morph to get the state of * @param morphTarget the name of the morph to get the state of
* @return the state of the morph, or -1 if the morph is not found * @return the state of the morph, or -1 if the morph is not found
*/ */
@ -660,16 +659,19 @@ public class Geometry extends Spatial {
int index = mesh.getMorphIndex(morphTarget); int index = mesh.getMorphIndex(morphTarget);
if (index < 0) { if (index < 0) {
return -1; return -1;
} else { } else {
return morphState[index]; return morphState[index];
} }
} }
/** /**
* Return the number of morph targets that can be handled on the GPU simultaneously for this geometry. * Return the number of morph targets that can be handled
* on the GPU simultaneously for this geometry.
* Note that it depends on the material set on this geometry. * Note that it depends on the material set on this geometry.
* This number is computed and set by the MorphControl, so it might be available only after the first frame. * This number is computed and set by the MorphControl,
* so it might be available only after the first frame.
* Else it's set to -1. * Else it's set to -1.
*
* @return the number of simultaneous morph targets handled on the GPU * @return the number of simultaneous morph targets handled on the GPU
*/ */
public int getNbSimultaneousGPUMorph() { public int getNbSimultaneousGPUMorph() {
@ -677,11 +679,15 @@ public class Geometry extends Spatial {
} }
/** /**
* Sets the number of morph targets that can be handled on the GPU simultaneously for this geometry. * Sets the number of morph targets that can be handled
* on the GPU simultaneously for this geometry.
* Note that it depends on the material set on this geometry. * Note that it depends on the material set on this geometry.
* This number is computed and set by the MorphControl, so it might be available only after the first frame. * This number is computed and set by the MorphControl,
* so it might be available only after the first frame.
* Else it's set to -1. * Else it's set to -1.
* WARNING: setting this manually might crash the shader compilation if set too high. Do it at your own risk. * WARNING: setting this manually might crash the shader compilation if set too high.
* Do it at your own risk.
*
* @param nbSimultaneousGPUMorph the number of simultaneous morph targets to be handled on the GPU. * @param nbSimultaneousGPUMorph the number of simultaneous morph targets to be handled on the GPU.
*/ */
public void setNbSimultaneousGPUMorph(int nbSimultaneousGPUMorph) { public void setNbSimultaneousGPUMorph(int nbSimultaneousGPUMorph) {
@ -723,7 +729,8 @@ public class Geometry extends Spatial {
material = im.getAssetManager().loadMaterial(matName); material = im.getAssetManager().loadMaterial(matName);
} catch (AssetNotFoundException ex) { } catch (AssetNotFoundException ex) {
// Cannot find J3M file. // Cannot find J3M file.
logger.log(Level.FINE, "Cannot locate {0} for geometry {1}", new Object[]{matName, key}); logger.log(Level.FINE, "Cannot locate {0} for geometry {1}",
new Object[]{matName, key});
} }
} }
// If material is NULL, try to load it from the geometry // If material is NULL, try to load it from the geometry

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2019 jMonkeyEngine * Copyright (c) 2009-2020 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -46,7 +46,6 @@ import com.jme3.util.*;
import com.jme3.util.IntMap.Entry; import com.jme3.util.IntMap.Entry;
import com.jme3.util.clone.Cloner; import com.jme3.util.clone.Cloner;
import com.jme3.util.clone.JmeCloneable; import com.jme3.util.clone.JmeCloneable;
import java.io.IOException; import java.io.IOException;
import java.nio.*; import java.nio.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -79,50 +78,46 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* determined via the vertex shader's <code>gl_PointSize</code> output. * determined via the vertex shader's <code>gl_PointSize</code> output.
*/ */
Points(true), Points(true),
/** /**
* A primitive is a line segment. Every two vertices specify * A primitive is a line segment. Every two vertices specify
* a single line. {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} can be used * a single line. {@link Material#getAdditionalRenderState()}
* and {@link RenderState#setLineWidth(float)} can be used
* to set the width of the lines. * to set the width of the lines.
*/ */
Lines(true), Lines(true),
/** /**
* A primitive is a line segment. The first two vertices specify * A primitive is a line segment. The first two vertices specify
* a single line, while subsequent vertices are combined with the * a single line, while subsequent vertices are combined with the
* previous vertex to make a line. {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} can * previous vertex to make a line. {@link Material#getAdditionalRenderState()}
* and {@link RenderState#setLineWidth(float)} can
* be used to set the width of the lines. * be used to set the width of the lines.
*/ */
LineStrip(false), LineStrip(false),
/** /**
* Identical to {@link #LineStrip} except that at the end * Identical to {@link #LineStrip} except that at the end
* the last vertex is connected with the first to form a line. * the last vertex is connected with the first to form a line.
* {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} can be used * {@link Material#getAdditionalRenderState()}
* and {@link RenderState#setLineWidth(float)} can be used
* to set the width of the lines. * to set the width of the lines.
*/ */
LineLoop(false), LineLoop(false),
/** /**
* A primitive is a triangle. Each 3 vertices specify a single * A primitive is a triangle. Each 3 vertices specify a single
* triangle. * triangle.
*/ */
Triangles(true), Triangles(true),
/** /**
* Similar to {@link #Triangles}, the first 3 vertices * Similar to {@link #Triangles}, the first 3 vertices
* specify a triangle, while subsequent vertices are combined with * specify a triangle, while subsequent vertices are combined with
* the previous two to form a triangle. * the previous two to form a triangle.
*/ */
TriangleStrip(false), TriangleStrip(false),
/** /**
* Similar to {@link #Triangles}, the first 3 vertices * Similar to {@link #Triangles}, the first 3 vertices
* specify a triangle, each 2 subsequent vertices are combined * specify a triangle, each 2 subsequent vertices are combined
* with the very first vertex to make a triangle. * with the very first vertex to make a triangle.
*/ */
TriangleFan(false), TriangleFan(false),
/** /**
* A combination of various triangle modes. It is best to avoid * A combination of various triangle modes. It is best to avoid
* using this mode as it may not be supported by all renderers. * using this mode as it may not be supported by all renderers.
@ -138,7 +133,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
Patch(true); Patch(true);
private boolean listMode = false; private boolean listMode = false;
private Mode(boolean listMode){ private Mode(boolean listMode) {
this.listMode = listMode; this.listMode = listMode;
} }
@ -151,7 +146,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return true if the mode is a list type mode * @return true if the mode is a list type mode
*/ */
public boolean isListMode(){ public boolean isListMode() {
return listMode; return listMode;
} }
} }
@ -160,7 +155,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* The bounding volume that contains the mesh entirely. * The bounding volume that contains the mesh entirely.
* By default a BoundingBox (AABB). * By default a BoundingBox (AABB).
*/ */
private BoundingVolume meshBound = new BoundingBox(); private BoundingVolume meshBound = new BoundingBox();
private CollisionData collisionTree = null; private CollisionData collisionTree = null;
@ -175,7 +170,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
private int vertCount = -1; private int vertCount = -1;
private int elementCount = -1; private int elementCount = -1;
private int instanceCount = -1; private int instanceCount = -1;
private int patchVertexCount=3; //only used for tessellation private int patchVertexCount = 3; //only used for tessellation
private int maxNumWeights = -1; // only if using skeletal animation private int maxNumWeights = -1; // only if using skeletal animation
private int[] elementLengths; private int[] elementLengths;
@ -188,7 +183,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
/** /**
* Creates a new mesh with no {@link VertexBuffer vertex buffers}. * Creates a new mesh with no {@link VertexBuffer vertex buffers}.
*/ */
public Mesh(){ public Mesh() {
} }
/** /**
@ -226,8 +221,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return a deep clone of this mesh. * @return a deep clone of this mesh.
*/ */
public Mesh deepClone(){ public Mesh deepClone() {
try{ try {
Mesh clone = (Mesh) super.clone(); Mesh clone = (Mesh) super.clone();
clone.meshBound = meshBound != null ? meshBound.clone() : null; clone.meshBound = meshBound != null ? meshBound.clone() : null;
@ -237,7 +232,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
clone.buffers = new IntMap<>(); clone.buffers = new IntMap<>();
clone.buffersList = new SafeArrayList<>(VertexBuffer.class); clone.buffersList = new SafeArrayList<>(VertexBuffer.class);
for (VertexBuffer vb : buffersList.getArray()){ for (VertexBuffer vb : buffersList.getArray()) {
VertexBuffer bufClone = vb.clone(); VertexBuffer bufClone = vb.clone();
clone.buffers.put(vb.getBufferType().ordinal(), bufClone); clone.buffers.put(vb.getBufferType().ordinal(), bufClone);
clone.buffersList.add(bufClone); clone.buffersList.add(bufClone);
@ -255,7 +250,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
clone.elementLengths = elementLengths != null ? elementLengths.clone() : null; clone.elementLengths = elementLengths != null ? elementLengths.clone() : null;
clone.modeStart = modeStart != null ? modeStart.clone() : null; clone.modeStart = modeStart != null ? modeStart.clone() : null;
return clone; return clone;
}catch (CloneNotSupportedException ex){ } catch (CloneNotSupportedException ex) {
throw new AssertionError(); throw new AssertionError();
} }
} }
@ -269,9 +264,9 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return A clone of the mesh for animation use. * @return A clone of the mesh for animation use.
*/ */
public Mesh cloneForAnim(){ public Mesh cloneForAnim() {
Mesh clone = clone(); Mesh clone = clone();
if (getBuffer(Type.BindPosePosition) != null){ if (getBuffer(Type.BindPosePosition) != null) {
VertexBuffer oldPos = getBuffer(Type.Position); VertexBuffer oldPos = getBuffer(Type.Position);
// NOTE: creates deep clone // NOTE: creates deep clone
@ -279,13 +274,13 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
clone.clearBuffer(Type.Position); clone.clearBuffer(Type.Position);
clone.setBuffer(newPos); clone.setBuffer(newPos);
if (getBuffer(Type.BindPoseNormal) != null){ if (getBuffer(Type.BindPoseNormal) != null) {
VertexBuffer oldNorm = getBuffer(Type.Normal); VertexBuffer oldNorm = getBuffer(Type.Normal);
VertexBuffer newNorm = oldNorm.clone(); VertexBuffer newNorm = oldNorm.clone();
clone.clearBuffer(Type.Normal); clone.clearBuffer(Type.Normal);
clone.setBuffer(newNorm); clone.setBuffer(newNorm);
if (getBuffer(Type.BindPoseTangent) != null){ if (getBuffer(Type.BindPoseTangent) != null) {
VertexBuffer oldTang = getBuffer(Type.Tangent); VertexBuffer oldTang = getBuffer(Type.Tangent);
VertexBuffer newTang = oldTang.clone(); VertexBuffer newTang = oldTang.clone();
clone.clearBuffer(Type.Tangent); clone.clearBuffer(Type.Tangent);
@ -302,7 +297,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
@Override @Override
public Mesh jmeClone() { public Mesh jmeClone() {
try { try {
Mesh clone = (Mesh)super.clone(); Mesh clone = (Mesh) super.clone();
clone.vertexArrayID = -1; clone.vertexArrayID = -1;
return clone; return clone;
} catch (CloneNotSupportedException ex) { } catch (CloneNotSupportedException ex) {
@ -314,8 +309,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* Called internally by com.jme3.util.clone.Cloner. Do not call directly. * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/ */
@Override @Override
public void cloneFields( Cloner cloner, Object original ) { public void cloneFields(Cloner cloner, Object original) {
// Probably could clone this now but it will get regenerated anyway. // Probably could clone this now but it will get regenerated anyway.
this.collisionTree = null; this.collisionTree = null;
@ -393,7 +387,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @param forSoftwareAnim Should be true to enable the conversion. * @param forSoftwareAnim Should be true to enable the conversion.
*/ */
public void prepareForAnim(boolean forSoftwareAnim){ public void prepareForAnim(boolean forSoftwareAnim) {
if (forSoftwareAnim) { if (forSoftwareAnim) {
// convert indices to ubytes on the heap // convert indices to ubytes on the heap
VertexBuffer indices = getBuffer(Type.BoneIndex); VertexBuffer indices = getBuffer(Type.BoneIndex);
@ -445,29 +439,34 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
VertexBuffer indices = getBuffer(Type.BoneIndex); VertexBuffer indices = getBuffer(Type.BoneIndex);
if (indices.getFormat() == Format.UnsignedByte) { if (indices.getFormat() == Format.UnsignedByte) {
ByteBuffer originalIndex = (ByteBuffer) indices.getData(); ByteBuffer originalIndex = (ByteBuffer) indices.getData();
ByteBuffer directIndex = BufferUtils.createByteBuffer(originalIndex.capacity()); ByteBuffer directIndex
= BufferUtils.createByteBuffer(originalIndex.capacity());
originalIndex.clear(); originalIndex.clear();
directIndex.put(originalIndex); directIndex.put(originalIndex);
result = directIndex; result = directIndex;
} else { } else {
//bone indices can be stored in an UnsignedShort buffer //bone indices can be stored in an UnsignedShort buffer
ShortBuffer originalIndex = (ShortBuffer) indices.getData(); ShortBuffer originalIndex = (ShortBuffer) indices.getData();
ShortBuffer directIndex = BufferUtils.createShortBuffer(originalIndex.capacity()); ShortBuffer directIndex
= BufferUtils.createShortBuffer(originalIndex.capacity());
originalIndex.clear(); originalIndex.clear();
directIndex.put(originalIndex); directIndex.put(originalIndex);
result = directIndex; result = directIndex;
} }
indicesHW.setupData(Usage.Static, indices.getNumComponents(), indices.getFormat(), result); indicesHW.setupData(Usage.Static, indices.getNumComponents(),
indices.getFormat(), result);
} }
VertexBuffer weightsHW = getBuffer(Type.HWBoneWeight); VertexBuffer weightsHW = getBuffer(Type.HWBoneWeight);
if (weightsHW.getData() == null) { if (weightsHW.getData() == null) {
VertexBuffer weights = getBuffer(Type.BoneWeight); VertexBuffer weights = getBuffer(Type.BoneWeight);
FloatBuffer originalWeight = (FloatBuffer) weights.getData(); FloatBuffer originalWeight = (FloatBuffer) weights.getData();
FloatBuffer directWeight = BufferUtils.createFloatBuffer(originalWeight.capacity()); FloatBuffer directWeight
= BufferUtils.createFloatBuffer(originalWeight.capacity());
originalWeight.clear(); originalWeight.clear();
directWeight.put(originalWeight); directWeight.put(originalWeight);
weightsHW.setupData(Usage.Static, weights.getNumComponents(), weights.getFormat(), directWeight); weightsHW.setupData(Usage.Static, weights.getNumComponents(),
weights.getFormat(), directWeight);
} }
// position, normal, and tanget buffers to be in "Static" mode // position, normal, and tanget buffers to be in "Static" mode
@ -502,7 +501,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @param lodLevels The LOD levels to set * @param lodLevels The LOD levels to set
*/ */
public void setLodLevels(VertexBuffer[] lodLevels){ public void setLodLevels(VertexBuffer[] lodLevels) {
this.lodLevels = lodLevels; this.lodLevels = lodLevels;
} }
@ -510,7 +509,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @return The number of LOD levels set on this mesh, including the main * @return The number of LOD levels set on this mesh, including the main
* index buffer, returns zero if there are no lod levels. * index buffer, returns zero if there are no lod levels.
*/ */
public int getNumLodLevels(){ public int getNumLodLevels() {
return lodLevels != null ? lodLevels.length : 0; return lodLevels != null ? lodLevels.length : 0;
} }
@ -526,7 +525,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @see #setLodLevels(com.jme3.scene.VertexBuffer[]) * @see #setLodLevels(com.jme3.scene.VertexBuffer[])
*/ */
public VertexBuffer getLodLevel(int lod){ public VertexBuffer getLodLevel(int lod) {
return lodLevels[lod]; return lodLevels[lod];
} }
@ -636,7 +635,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* Returns the line width for line meshes. * Returns the line width for line meshes.
* *
* @return the line width * @return the line width
* @deprecated use {@link Material#getAdditionalRenderState()} and {@link RenderState#getLineWidth()} * @deprecated use {@link Material#getAdditionalRenderState()}
* and {@link RenderState#getLineWidth()}
*/ */
@Deprecated @Deprecated
public float getLineWidth() { public float getLineWidth() {
@ -649,7 +649,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* the default value is 1.0. * the default value is 1.0.
* *
* @param lineWidth The line width * @param lineWidth The line width
* @deprecated use {@link Material#getAdditionalRenderState()} and {@link RenderState#setLineWidth(float)} * @deprecated use {@link Material#getAdditionalRenderState()}
* and {@link RenderState#setLineWidth(float)}
*/ */
@Deprecated @Deprecated
public void setLineWidth(float lineWidth) { public void setLineWidth(float lineWidth) {
@ -665,7 +666,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* for all {@link VertexBuffer vertex buffers} on this Mesh. * for all {@link VertexBuffer vertex buffers} on this Mesh.
*/ */
public void setStatic() { public void setStatic() {
for (VertexBuffer vb : buffersList.getArray()){ for (VertexBuffer vb : buffersList.getArray()) {
vb.setUsage(Usage.Static); vb.setUsage(Usage.Static);
} }
} }
@ -676,7 +677,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* for all {@link VertexBuffer vertex buffers} on this Mesh. * for all {@link VertexBuffer vertex buffers} on this Mesh.
*/ */
public void setDynamic() { public void setDynamic() {
for (VertexBuffer vb : buffersList.getArray()){ for (VertexBuffer vb : buffersList.getArray()) {
vb.setUsage(Usage.Dynamic); vb.setUsage(Usage.Dynamic);
} }
} }
@ -686,8 +687,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* Sets the usage mode to {@link Usage#Stream} * Sets the usage mode to {@link Usage#Stream}
* for all {@link VertexBuffer vertex buffers} on this Mesh. * for all {@link VertexBuffer vertex buffers} on this Mesh.
*/ */
public void setStreamed(){ public void setStreamed() {
for (VertexBuffer vb : buffersList.getArray()){ for (VertexBuffer vb : buffersList.getArray()) {
vb.setUsage(Usage.Stream); vb.setUsage(Usage.Stream);
} }
} }
@ -698,7 +699,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* to <em>avoid</em> using this method as it disables some engine features. * to <em>avoid</em> using this method as it disables some engine features.
*/ */
@Deprecated @Deprecated
public void setInterleaved(){ public void setInterleaved() {
ArrayList<VertexBuffer> vbs = new ArrayList<>(); ArrayList<VertexBuffer> vbs = new ArrayList<>();
vbs.addAll(buffersList); vbs.addAll(buffersList);
@ -707,7 +708,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
vbs.remove(getBuffer(Type.Index)); vbs.remove(getBuffer(Type.Index));
int stride = 0; // aka bytes per vertex int stride = 0; // aka bytes per vertex
for (int i = 0; i < vbs.size(); i++){ for (int i = 0; i < vbs.size(); i++) {
VertexBuffer vb = vbs.get(i); VertexBuffer vb = vbs.get(i);
// if (vb.getFormat() != Format.Float){ // if (vb.getFormat() != Format.Float){
// throw new UnsupportedOperationException("Cannot interleave vertex buffer.\n" + // throw new UnsupportedOperationException("Cannot interleave vertex buffer.\n" +
@ -725,20 +726,20 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
buffers.put(Type.InterleavedData.ordinal(), allData); buffers.put(Type.InterleavedData.ordinal(), allData);
buffersList.add(allData); buffersList.add(allData);
for (int vert = 0; vert < getVertexCount(); vert++){ for (int vert = 0; vert < getVertexCount(); vert++) {
for (int i = 0; i < vbs.size(); i++){ for (int i = 0; i < vbs.size(); i++) {
VertexBuffer vb = vbs.get(i); VertexBuffer vb = vbs.get(i);
switch (vb.getFormat()){ switch (vb.getFormat()) {
case Float: case Float:
FloatBuffer fb = (FloatBuffer) vb.getData(); FloatBuffer fb = (FloatBuffer) vb.getData();
for (int comp = 0; comp < vb.components; comp++){ for (int comp = 0; comp < vb.components; comp++) {
dataBuf.putFloat(fb.get()); dataBuf.putFloat(fb.get());
} }
break; break;
case Byte: case Byte:
case UnsignedByte: case UnsignedByte:
ByteBuffer bb = (ByteBuffer) vb.getData(); ByteBuffer bb = (ByteBuffer) vb.getData();
for (int comp = 0; comp < vb.components; comp++){ for (int comp = 0; comp < vb.components; comp++) {
dataBuf.put(bb.get()); dataBuf.put(bb.get());
} }
break; break;
@ -746,20 +747,20 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
case Short: case Short:
case UnsignedShort: case UnsignedShort:
ShortBuffer sb = (ShortBuffer) vb.getData(); ShortBuffer sb = (ShortBuffer) vb.getData();
for (int comp = 0; comp < vb.components; comp++){ for (int comp = 0; comp < vb.components; comp++) {
dataBuf.putShort(sb.get()); dataBuf.putShort(sb.get());
} }
break; break;
case Int: case Int:
case UnsignedInt: case UnsignedInt:
IntBuffer ib = (IntBuffer) vb.getData(); IntBuffer ib = (IntBuffer) vb.getData();
for (int comp = 0; comp < vb.components; comp++){ for (int comp = 0; comp < vb.components; comp++) {
dataBuf.putInt(ib.get()); dataBuf.putInt(ib.get());
} }
break; break;
case Double: case Double:
DoubleBuffer db = (DoubleBuffer) vb.getData(); DoubleBuffer db = (DoubleBuffer) vb.getData();
for (int comp = 0; comp < vb.components; comp++){ for (int comp = 0; comp < vb.components; comp++) {
dataBuf.putDouble(db.get()); dataBuf.putDouble(db.get());
} }
break; break;
@ -768,7 +769,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
} }
int offset = 0; int offset = 0;
for (VertexBuffer vb : vbs){ for (VertexBuffer vb : vbs) {
vb.setOffset(offset); vb.setOffset(offset);
vb.setStride(stride); vb.setStride(stride);
@ -778,8 +779,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
} }
} }
private int computeNumElements(int bufSize){ private int computeNumElements(int bufSize) {
switch (mode){ switch (mode) {
case Triangles: case Triangles:
return bufSize / 3; return bufSize / 3;
case TriangleFan: case TriangleFan:
@ -794,7 +795,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
case LineStrip: case LineStrip:
return bufSize - 1; return bufSize - 1;
case Patch: case Patch:
return bufSize/patchVertexCount; return bufSize / patchVertexCount;
default: default:
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -803,8 +804,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
private int computeInstanceCount() { private int computeInstanceCount() {
// Whatever the max of the base instance counts // Whatever the max of the base instance counts
int max = 0; int max = 0;
for( VertexBuffer vb : buffersList ) { for (VertexBuffer vb : buffersList) {
if( vb.getBaseInstanceCount() > max ) { if (vb.getBaseInstanceCount() > max) {
max = vb.getBaseInstanceCount(); max = vb.getBaseInstanceCount();
} }
} }
@ -821,19 +822,19 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @throws IllegalStateException If this mesh is in * @throws IllegalStateException If this mesh is in
* {@link #setInterleaved() interleaved} format. * {@link #setInterleaved() interleaved} format.
*/ */
public void updateCounts(){ public void updateCounts() {
if (getBuffer(Type.InterleavedData) != null) { if (getBuffer(Type.InterleavedData) != null) {
throw new IllegalStateException("Should update counts before interleave"); throw new IllegalStateException("Should update counts before interleave");
} }
VertexBuffer pb = getBuffer(Type.Position); VertexBuffer pb = getBuffer(Type.Position);
VertexBuffer ib = getBuffer(Type.Index); VertexBuffer ib = getBuffer(Type.Index);
if (pb != null){ if (pb != null) {
vertCount = pb.getData().limit() / pb.getNumComponents(); vertCount = pb.getData().limit() / pb.getNumComponents();
} }
if (ib != null){ if (ib != null) {
elementCount = computeNumElements(ib.getData().limit()); elementCount = computeNumElements(ib.getData().limit());
}else{ } else {
elementCount = computeNumElements(vertCount); elementCount = computeNumElements(vertCount);
} }
instanceCount = computeInstanceCount(); instanceCount = computeInstanceCount();
@ -845,8 +846,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @param lod The lod level to look up * @param lod The lod level to look up
* @return The triangle count for that LOD level * @return The triangle count for that LOD level
*/ */
public int getTriangleCount(int lod){ public int getTriangleCount(int lod) {
if (lodLevels != null){ if (lodLevels != null) {
if (lod < 0) { if (lod < 0) {
throw new IllegalArgumentException("LOD level cannot be < 0"); throw new IllegalArgumentException("LOD level cannot be < 0");
} }
@ -856,9 +857,9 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
} }
return computeNumElements(lodLevels[lod].getData().limit()); return computeNumElements(lodLevels[lod].getData().limit());
}else if (lod == 0){ } else if (lod == 0) {
return elementCount; return elementCount;
}else{ } else {
throw new IllegalArgumentException("There are no LOD levels on the mesh!"); throw new IllegalArgumentException("There are no LOD levels on the mesh!");
} }
} }
@ -872,7 +873,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return how many triangles/elements are on this Mesh. * @return how many triangles/elements are on this Mesh.
*/ */
public int getTriangleCount(){ public int getTriangleCount() {
return elementCount; return elementCount;
} }
@ -883,7 +884,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return Number of vertices on the mesh * @return Number of vertices on the mesh
*/ */
public int getVertexCount(){ public int getVertexCount() {
return vertCount; return vertCount;
} }
@ -906,24 +907,24 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @param v2 Vector to contain second vertex position * @param v2 Vector to contain second vertex position
* @param v3 Vector to contain third vertex position * @param v3 Vector to contain third vertex position
*/ */
public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3){ public void getTriangle(int index, Vector3f v1, Vector3f v2, Vector3f v3) {
VertexBuffer pb = getBuffer(Type.Position); VertexBuffer pb = getBuffer(Type.Position);
IndexBuffer ib = getIndicesAsList(); IndexBuffer ib = getIndicesAsList();
if (pb != null && pb.getFormat() == Format.Float && pb.getNumComponents() == 3){ if (pb != null && pb.getFormat() == Format.Float && pb.getNumComponents() == 3) {
FloatBuffer fpb = (FloatBuffer) pb.getData(); FloatBuffer fpb = (FloatBuffer) pb.getData();
// aquire triangle's vertex indices // aquire triangle's vertex indices
int vertIndex = index * 3; int vertIndex = index * 3;
int vert1 = ib.get(vertIndex); int vert1 = ib.get(vertIndex);
int vert2 = ib.get(vertIndex+1); int vert2 = ib.get(vertIndex + 1);
int vert3 = ib.get(vertIndex+2); int vert3 = ib.get(vertIndex + 2);
BufferUtils.populateFromBuffer(v1, fpb, vert1); BufferUtils.populateFromBuffer(v1, fpb, vert1);
BufferUtils.populateFromBuffer(v2, fpb, vert2); BufferUtils.populateFromBuffer(v2, fpb, vert2);
BufferUtils.populateFromBuffer(v3, fpb, vert3); BufferUtils.populateFromBuffer(v3, fpb, vert3);
}else{ } else {
throw new UnsupportedOperationException("Position buffer not set or " throw new UnsupportedOperationException("Position buffer not set or "
+ " has incompatible format"); + " has incompatible format");
} }
} }
@ -937,7 +938,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @param tri The triangle to store the positions in * @param tri The triangle to store the positions in
*/ */
public void getTriangle(int index, Triangle tri){ public void getTriangle(int index, Triangle tri) {
getTriangle(index, tri.get1(), tri.get2(), tri.get3()); getTriangle(index, tri.get1(), tri.get2(), tri.get3());
tri.setIndex(index); tri.setIndex(index);
tri.setNormal(null); tri.setNormal(null);
@ -952,27 +953,27 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @param indices Indices of the triangle's vertices * @param indices Indices of the triangle's vertices
*/ */
public void getTriangle(int index, int[] indices){ public void getTriangle(int index, int[] indices) {
IndexBuffer ib = getIndicesAsList(); IndexBuffer ib = getIndicesAsList();
// acquire triangle's vertex indices // acquire triangle's vertex indices
int vertIndex = index * 3; int vertIndex = index * 3;
indices[0] = ib.get(vertIndex); indices[0] = ib.get(vertIndex);
indices[1] = ib.get(vertIndex+1); indices[1] = ib.get(vertIndex + 1);
indices[2] = ib.get(vertIndex+2); indices[2] = ib.get(vertIndex + 2);
} }
/** /**
* Returns the mesh's VAO ID. Internal use only. * Returns the mesh's VAO ID. Internal use only.
*/ */
public int getId(){ public int getId() {
return vertexArrayID; return vertexArrayID;
} }
/** /**
* Sets the mesh's VAO ID. Internal use only. * Sets the mesh's VAO ID. Internal use only.
*/ */
public void setId(int id){ public void setId(int id) {
if (vertexArrayID != -1) { if (vertexArrayID != -1) {
throw new IllegalStateException("ID has already been set."); throw new IllegalStateException("ID has already been set.");
} }
@ -987,7 +988,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* com.jme3.bounding.BoundingVolume, * com.jme3.bounding.BoundingVolume,
* com.jme3.collision.CollisionResults) }. * com.jme3.collision.CollisionResults) }.
*/ */
public void createCollisionData(){ public void createCollisionData() {
BIHTree tree = new BIHTree(this); BIHTree tree = new BIHTree(this);
tree.construct(); tree.construct();
collisionTree = tree; collisionTree = tree;
@ -1008,9 +1009,9 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* graph elements such as {@link Spatial}s. * graph elements such as {@link Spatial}s.
*/ */
public int collideWith(Collidable other, public int collideWith(Collidable other,
Matrix4f worldMatrix, Matrix4f worldMatrix,
BoundingVolume worldBound, BoundingVolume worldBound,
CollisionResults results){ CollisionResults results) {
switch (mode) { switch (mode) {
case Points: case Points:
@ -1028,7 +1029,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
return 0; return 0;
} }
if (collisionTree == null){ if (collisionTree == null) {
createCollisionData(); createCollisionData();
} }
@ -1042,7 +1043,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @param vb The buffer to set * @param vb The buffer to set
* @throws IllegalArgumentException If the buffer type is already set * @throws IllegalArgumentException If the buffer type is already set
*/ */
public void setBuffer(VertexBuffer vb){ public void setBuffer(VertexBuffer vb) {
if (buffers.containsKey(vb.getBufferType().ordinal())) { if (buffers.containsKey(vb.getBufferType().ordinal())) {
throw new IllegalArgumentException("Buffer type already set: " + vb.getBufferType()); throw new IllegalArgumentException("Buffer type already set: " + vb.getBufferType());
} }
@ -1059,9 +1060,9 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @param type The buffer type to remove * @param type The buffer type to remove
*/ */
public void clearBuffer(VertexBuffer.Type type){ public void clearBuffer(VertexBuffer.Type type) {
VertexBuffer vb = buffers.remove(type.ordinal()); VertexBuffer vb = buffers.remove(type.ordinal());
if (vb != null){ if (vb != null) {
buffersList.remove(vb); buffersList.remove(vb);
updateCounts(); updateCounts();
} }
@ -1079,14 +1080,14 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @throws UnsupportedOperationException If the buffer already set is * @throws UnsupportedOperationException If the buffer already set is
* incompatible with the parameters given. * incompatible with the parameters given.
*/ */
public void setBuffer(Type type, int components, Format format, Buffer buf){ public void setBuffer(Type type, int components, Format format, Buffer buf) {
VertexBuffer vb = buffers.get(type.ordinal()); VertexBuffer vb = buffers.get(type.ordinal());
if (vb == null){ if (vb == null) {
vb = new VertexBuffer(type); vb = new VertexBuffer(type);
vb.setupData(Usage.Dynamic, components, format, buf); vb.setupData(Usage.Dynamic, components, format, buf);
setBuffer(vb); setBuffer(vb);
}else{ } else {
if (vb.getNumComponents() != components || vb.getFormat() != format){ if (vb.getNumComponents() != components || vb.getFormat() != format) {
throw new UnsupportedOperationException("The buffer already set " throw new UnsupportedOperationException("The buffer already set "
+ "is incompatible with the given parameters"); + "is incompatible with the given parameters");
} }
@ -1110,7 +1111,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
setBuffer(type, components, Format.Float, buf); setBuffer(type, components, Format.Float, buf);
} }
public void setBuffer(Type type, int components, float[] buf){ public void setBuffer(Type type, int components, float[] buf) {
setBuffer(type, components, BufferUtils.createFloatBuffer(buf)); setBuffer(type, components, BufferUtils.createFloatBuffer(buf));
} }
@ -1118,7 +1119,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
setBuffer(type, components, Format.UnsignedInt, buf); setBuffer(type, components, Format.UnsignedInt, buf);
} }
public void setBuffer(Type type, int components, int[] buf){ public void setBuffer(Type type, int components, int[] buf) {
setBuffer(type, components, BufferUtils.createIntBuffer(buf)); setBuffer(type, components, BufferUtils.createIntBuffer(buf));
} }
@ -1126,7 +1127,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
setBuffer(type, components, Format.UnsignedShort, buf); setBuffer(type, components, Format.UnsignedShort, buf);
} }
public void setBuffer(Type type, int components, byte[] buf){ public void setBuffer(Type type, int components, byte[] buf) {
setBuffer(type, components, BufferUtils.createByteBuffer(buf)); setBuffer(type, components, BufferUtils.createByteBuffer(buf));
} }
@ -1134,7 +1135,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
setBuffer(type, components, Format.UnsignedByte, buf); setBuffer(type, components, Format.UnsignedByte, buf);
} }
public void setBuffer(Type type, int components, short[] buf){ public void setBuffer(Type type, int components, short[] buf) {
setBuffer(type, components, BufferUtils.createShortBuffer(buf)); setBuffer(type, components, BufferUtils.createShortBuffer(buf));
} }
@ -1145,7 +1146,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @param type The type of VertexBuffer * @param type The type of VertexBuffer
* @return the VertexBuffer data, or null if not set * @return the VertexBuffer data, or null if not set
*/ */
public VertexBuffer getBuffer(Type type){ public VertexBuffer getBuffer(Type type) {
return buffers.get(type.ordinal()); return buffers.get(type.ordinal());
} }
@ -1187,22 +1188,22 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return A virtual or wrapped index buffer to read the data as a list * @return A virtual or wrapped index buffer to read the data as a list
*/ */
public IndexBuffer getIndicesAsList(){ public IndexBuffer getIndicesAsList() {
if (mode == Mode.Hybrid) { if (mode == Mode.Hybrid) {
throw new UnsupportedOperationException("Hybrid mode not supported"); throw new UnsupportedOperationException("Hybrid mode not supported");
} }
IndexBuffer ib = getIndexBuffer(); IndexBuffer ib = getIndexBuffer();
if (ib != null){ if (ib != null) {
if (mode.isListMode()){ if (mode.isListMode()) {
// already in list mode // already in list mode
return ib; return ib;
}else{ } else {
// not in list mode but it does have an index buffer // not in list mode but it does have an index buffer
// wrap it so the data is converted to list format // wrap it so the data is converted to list format
return new WrappedIndexBuffer(this); return new WrappedIndexBuffer(this);
} }
}else{ } else {
// return a virtual index buffer that will supply // return a virtual index buffer that will supply
// "fake" indices in list format // "fake" indices in list format
return new VirtualIndexBuffer(vertCount, mode); return new VirtualIndexBuffer(vertCount, mode);
@ -1289,9 +1290,9 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
VertexBuffer newIdxBuf = new VertexBuffer(Type.Index); VertexBuffer newIdxBuf = new VertexBuffer(Type.Index);
newIdxBuf.setupData(oldIdxBuf.getUsage(), newIdxBuf.setupData(oldIdxBuf.getUsage(),
oldIdxBuf.getNumComponents(), oldIdxBuf.getNumComponents(),
newIndexBuf instanceof IndexIntBuffer ? Format.UnsignedInt : Format.UnsignedShort, newIndexBuf instanceof IndexIntBuffer ? Format.UnsignedInt : Format.UnsignedShort,
newIndexBuf.getBuffer()); newIndexBuf.getBuffer());
clearBuffer(Type.Index); clearBuffer(Type.Index);
setBuffer(newIdxBuf); setBuffer(newIdxBuf);
@ -1308,11 +1309,13 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
//check for data before copying, some buffers are just empty shells //check for data before copying, some buffers are just empty shells
//for caching purpose (HW skinning buffers), and will be filled when //for caching purpose (HW skinning buffers), and will be filled when
//needed //needed
if(oldVb.getData()!=null){ if (oldVb.getData() != null) {
// Create a new vertex buffer with similar configuration, but // Create a new vertex buffer with similar configuration, but
// with the capacity of number of unique vertices // with the capacity of number of unique vertices
Buffer buffer = VertexBuffer.createBuffer(oldVb.getFormat(), oldVb.getNumComponents(), newNumVerts); Buffer buffer = VertexBuffer.createBuffer(oldVb.getFormat(),
newVb.setupData(oldVb.getUsage(), oldVb.getNumComponents(), oldVb.getFormat(), buffer); oldVb.getNumComponents(), newNumVerts);
newVb.setupData(oldVb.getUsage(), oldVb.getNumComponents(),
oldVb.getFormat(), buffer);
// Copy the vertex data from the old buffer into the new buffer // Copy the vertex data from the old buffer into the new buffer
for (int i = 0; i < newNumVerts; i++) { for (int i = 0; i < newNumVerts; i++) {
@ -1338,8 +1341,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
} }
/** /**
* Scales the texture coordinate buffer on this mesh by the given * Scales the texture coordinate buffer on this mesh by the given scale
* scale factor. * factor.
* <p> * <p>
* Note that values above 1 will cause the * Note that values above 1 will cause the
* texture to tile, while values below 1 will cause the texture * texture to tile, while values below 1 will cause the texture
@ -1354,7 +1357,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @throws UnsupportedOperationException If the texture coordinate * @throws UnsupportedOperationException If the texture coordinate
* buffer is not in 2D float format. * buffer is not in 2D float format.
*/ */
public void scaleTextureCoordinates(Vector2f scaleFactor){ public void scaleTextureCoordinates(Vector2f scaleFactor) {
VertexBuffer tc = getBuffer(Type.TexCoord); VertexBuffer tc = getBuffer(Type.TexCoord);
if (tc == null) { if (tc == null) {
throw new IllegalStateException("The mesh has no texture coordinates"); throw new IllegalStateException("The mesh has no texture coordinates");
@ -1370,10 +1373,10 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
FloatBuffer fb = (FloatBuffer) tc.getData(); FloatBuffer fb = (FloatBuffer) tc.getData();
fb.clear(); fb.clear();
for (int i = 0; i < fb.limit() / 2; i++){ for (int i = 0; i < fb.limit() / 2; i++) {
float x = fb.get(); float x = fb.get();
float y = fb.get(); float y = fb.get();
fb.position(fb.position()-2); fb.position(fb.position() - 2);
x *= scaleFactor.getX(); x *= scaleFactor.getX();
y *= scaleFactor.getY(); y *= scaleFactor.getY();
fb.put(x).put(y); fb.put(x).put(y);
@ -1387,10 +1390,10 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* The method does nothing if the mesh has no {@link Type#Position} buffer. * The method does nothing if the mesh has no {@link Type#Position} buffer.
* It is expected that the position buffer is a float buffer with 3 components. * It is expected that the position buffer is a float buffer with 3 components.
*/ */
public void updateBound(){ public void updateBound() {
VertexBuffer posBuf = getBuffer(VertexBuffer.Type.Position); VertexBuffer posBuf = getBuffer(VertexBuffer.Type.Position);
if (meshBound != null && posBuf != null){ if (meshBound != null && posBuf != null) {
meshBound.computeFromPoints((FloatBuffer)posBuf.getData()); meshBound.computeFromPoints((FloatBuffer) posBuf.getData());
} }
} }
@ -1423,7 +1426,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return map of vertex buffers on this mesh. * @return map of vertex buffers on this mesh.
*/ */
public IntMap<VertexBuffer> getBuffers(){ public IntMap<VertexBuffer> getBuffers() {
return buffers; return buffers;
} }
@ -1436,7 +1439,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* *
* @return list of vertex buffers on this mesh. * @return list of vertex buffers on this mesh.
*/ */
public SafeArrayList<VertexBuffer> getBufferList(){ public SafeArrayList<VertexBuffer> getBufferList() {
return buffersList; return buffersList;
} }
@ -1449,8 +1452,8 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
* @return true if the mesh uses bone animation, false otherwise * @return true if the mesh uses bone animation, false otherwise
*/ */
public boolean isAnimated() { public boolean isAnimated() {
return getBuffer(Type.BoneIndex) != null || return getBuffer(Type.BoneIndex) != null
getBuffer(Type.HWBoneIndex) != null; || getBuffer(Type.HWBoneIndex) != null;
} }
/** /**
@ -1504,6 +1507,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
/** /**
* Sets the count of vertices used for each tessellation patch * Sets the count of vertices used for each tessellation patch
*
* @param patchVertexCount * @param patchVertexCount
*/ */
public void setPatchVertexCount(int patchVertexCount) { public void setPatchVertexCount(int patchVertexCount) {
@ -1512,13 +1516,13 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
/** /**
* Gets the amount of vertices used for each patch; * Gets the amount of vertices used for each patch;
*
* @return the count (&ge;0) * @return the count (&ge;0)
*/ */
public int getPatchVertexCount() { public int getPatchVertexCount() {
return patchVertexCount; return patchVertexCount;
} }
public void addMorphTarget(MorphTarget target) { public void addMorphTarget(MorphTarget target) {
if (morphTargets == null) { if (morphTargets == null) {
morphTargets = new SafeArrayList<>(MorphTarget.class); morphTargets = new SafeArrayList<>(MorphTarget.class);
@ -1533,14 +1537,13 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
return morphTargets.getArray(); return morphTargets.getArray();
} }
} }
/** /**
* Get the name of all morphs in order. * Get the name of all morphs in order.
* Morphs without names will be null * Morphs without names will be null
* @return an array * @return an array
*/ */
public String[] getMorphTargetNames() { public String[] getMorphTargetNames() {
MorphTarget[] nbMorphTargets = getMorphTargets(); MorphTarget[] nbMorphTargets = getMorphTargets();
if (nbMorphTargets.length == 0) { if (nbMorphTargets.length == 0) {
return new String[0]; return new String[0];
@ -1556,11 +1559,12 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
public boolean hasMorphTargets() { public boolean hasMorphTargets() {
return morphTargets != null && !morphTargets.isEmpty(); return morphTargets != null && !morphTargets.isEmpty();
} }
/** /**
* Get the index of the morph that has the given name. * Get the index of the morph that has the given name.
*
* @param morphName The name of the morph to search for * @param morphName The name of the morph to search for
* @return The index of the morph, or -1 if not found. * @return The index of the morph, or -1 if not found.
*/ */
public int getMorphIndex(String morphName) { public int getMorphIndex(String morphName) {
int index = -1; int index = -1;
@ -1637,12 +1641,12 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
// in.readStringSavableMap("buffers", null); // in.readStringSavableMap("buffers", null);
buffers = (IntMap<VertexBuffer>) in.readIntSavableMap("buffers", null); buffers = (IntMap<VertexBuffer>) in.readIntSavableMap("buffers", null);
for (Entry<VertexBuffer> entry : buffers){ for (Entry<VertexBuffer> entry : buffers) {
buffersList.add(entry.getValue()); buffersList.add(entry.getValue());
} }
//creating hw animation buffers empty so that they are put in the cache //creating hw animation buffers empty so that they are put in the cache
if(isAnimated()){ if (isAnimated()) {
VertexBuffer hwBoneIndex = new VertexBuffer(Type.HWBoneIndex); VertexBuffer hwBoneIndex = new VertexBuffer(Type.HWBoneIndex);
hwBoneIndex.setUsage(Usage.CpuOnly); hwBoneIndex.setUsage(Usage.CpuOnly);
setBuffer(hwBoneIndex); setBuffer(hwBoneIndex);
@ -1654,7 +1658,7 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
Savable[] lodLevelsSavable = in.readSavableArray("lodLevels", null); Savable[] lodLevelsSavable = in.readSavableArray("lodLevels", null);
if (lodLevelsSavable != null) { if (lodLevelsSavable != null) {
lodLevels = new VertexBuffer[lodLevelsSavable.length]; lodLevels = new VertexBuffer[lodLevelsSavable.length];
System.arraycopy( lodLevelsSavable, 0, lodLevels, 0, lodLevels.length); System.arraycopy(lodLevelsSavable, 0, lodLevels, 0, lodLevels.length);
} }
ArrayList<Savable> l = in.readSavableArrayList("morphTargets", null); ArrayList<Savable> l = in.readSavableArrayList("morphTargets", null);
@ -1662,5 +1666,4 @@ public class Mesh implements Savable, Cloneable, JmeCloneable {
morphTargets = new SafeArrayList(MorphTarget.class, l); morphTargets = new SafeArrayList(MorphTarget.class, l);
} }
} }
} }

@ -47,7 +47,6 @@ import java.util.Queue;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* <code>Node</code> defines an internal node of a scene graph. The internal * <code>Node</code> defines an internal node of a scene graph. The internal
* node maintains a collection of children and handles merging said children * node maintains a collection of children and handles merging said children
@ -59,14 +58,11 @@ import java.util.logging.Logger;
* @author Joshua Slack * @author Joshua Slack
*/ */
public class Node extends Spatial { public class Node extends Spatial {
private static final Logger logger = Logger.getLogger(Node.class.getName()); private static final Logger logger = Logger.getLogger(Node.class.getName());
/** /**
* This node's children. * This node's children.
*/ */
protected SafeArrayList<Spatial> children = new SafeArrayList<Spatial>(Spatial.class); protected SafeArrayList<Spatial> children = new SafeArrayList<Spatial>(Spatial.class);
/** /**
* If this node is a root, this list will contain the current * If this node is a root, this list will contain the current
* set of children (and children of children) that require * set of children (and children of children) that require
@ -105,7 +101,6 @@ public class Node extends Spatial {
} }
/** /**
*
* <code>getQuantity</code> returns the number of children this node * <code>getQuantity</code> returns the number of children this node
* maintains. * maintains.
* *
@ -116,22 +111,24 @@ public class Node extends Spatial {
} }
@Override @Override
protected void setTransformRefresh(){ protected void setTransformRefresh() {
super.setTransformRefresh(); super.setTransformRefresh();
for (Spatial child : children.getArray()){ for (Spatial child : children.getArray()) {
if ((child.refreshFlags & RF_TRANSFORM) != 0) if ((child.refreshFlags & RF_TRANSFORM) != 0) {
continue; continue;
}
child.setTransformRefresh(); child.setTransformRefresh();
} }
} }
@Override @Override
protected void setLightListRefresh(){ protected void setLightListRefresh() {
super.setLightListRefresh(); super.setLightListRefresh();
for (Spatial child : children.getArray()){ for (Spatial child : children.getArray()) {
if ((child.refreshFlags & RF_LIGHTLIST) != 0) if ((child.refreshFlags & RF_LIGHTLIST) != 0) {
continue; continue;
}
child.setLightListRefresh(); child.setLightListRefresh();
} }
@ -150,7 +147,7 @@ public class Node extends Spatial {
} }
@Override @Override
protected void updateWorldBound(){ protected void updateWorldBound() {
super.updateWorldBound(); super.updateWorldBound();
// for a node, the world bound is a combination of all its children // for a node, the world bound is a combination of all its children
// bounds // bounds
@ -176,7 +173,7 @@ public class Node extends Spatial {
@Override @Override
protected void setParent(Node parent) { protected void setParent(Node parent) {
if( this.parent == null && parent != null ) { if (this.parent == null && parent != null) {
// We were a root before and now we aren't... make sure if // We were a root before and now we aren't... make sure if
// we had an updateList then we clear it completely to // we had an updateList then we clear it completely to
// avoid holding the dead array. // avoid holding the dead array.
@ -186,13 +183,13 @@ public class Node extends Spatial {
super.setParent(parent); super.setParent(parent);
} }
private void addUpdateChildren( SafeArrayList<Spatial> results ) { private void addUpdateChildren(SafeArrayList<Spatial> results) {
for( Spatial child : children.getArray() ) { for (Spatial child : children.getArray()) {
if( child.requiresUpdates() ) { if (child.requiresUpdates()) {
results.add(child); results.add(child);
} }
if( child instanceof Node ) { if (child instanceof Node) {
((Node)child).addUpdateChildren(results); ((Node) child).addUpdateChildren(results);
} }
} }
} }
@ -205,16 +202,16 @@ public class Node extends Spatial {
*/ */
void invalidateUpdateList() { void invalidateUpdateList() {
updateListValid = false; updateListValid = false;
if ( parent != null ) { if (parent != null) {
parent.invalidateUpdateList(); parent.invalidateUpdateList();
} }
} }
private SafeArrayList<Spatial> getUpdateList() { private SafeArrayList<Spatial> getUpdateList() {
if( updateListValid ) { if (updateListValid) {
return updateList; return updateList;
} }
if( updateList == null ) { if (updateList == null) {
updateList = new SafeArrayList<Spatial>(Spatial.class); updateList = new SafeArrayList<Spatial>(Spatial.class);
} else { } else {
updateList.clear(); updateList.clear();
@ -227,32 +224,32 @@ public class Node extends Spatial {
} }
@Override @Override
public void updateLogicalState(float tpf){ public void updateLogicalState(float tpf) {
super.updateLogicalState(tpf); super.updateLogicalState(tpf);
// Only perform updates on children if we are the // Only perform updates on children if we are the
// root and then only peform updates on children we // root and then only peform updates on children we
// know to require updates. // know to require updates.
// So if this isn't the root, abort. // So if this isn't the root, abort.
if( parent != null ) { if (parent != null) {
return; return;
} }
for( Spatial s : getUpdateList().getArray() ) { for (Spatial s : getUpdateList().getArray()) {
s.updateLogicalState(tpf); s.updateLogicalState(tpf);
} }
} }
@Override @Override
public void updateGeometricState(){ public void updateGeometricState() {
if (refreshFlags == 0) { if (refreshFlags == 0) {
// This branch has no geometric state that requires updates. // This branch has no geometric state that requires updates.
return; return;
} }
if ((refreshFlags & RF_LIGHTLIST) != 0){ if ((refreshFlags & RF_LIGHTLIST) != 0) {
updateWorldLightList(); updateWorldLightList();
} }
if ((refreshFlags & RF_TRANSFORM) != 0){ if ((refreshFlags & RF_TRANSFORM) != 0) {
// combine with parent transforms- same for all spatial // combine with parent transforms- same for all spatial
// subclasses. // subclasses.
updateWorldTransforms(); updateWorldTransforms();
@ -273,7 +270,7 @@ public class Node extends Spatial {
} }
} }
if ((refreshFlags & RF_BOUND) != 0){ if ((refreshFlags & RF_BOUND) != 0) {
updateWorldBound(); updateWorldBound();
} }
@ -289,14 +286,15 @@ public class Node extends Spatial {
@Override @Override
public int getTriangleCount() { public int getTriangleCount() {
int count = 0; int count = 0;
if(children != null) { if (children != null) {
for(int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) {
count += children.get(i).getTriangleCount(); count += children.get(i).getTriangleCount();
} }
} }
return count; return count;
} }
/** /**
* <code>getVertexCount</code> returns the number of vertices contained * <code>getVertexCount</code> returns the number of vertices contained
* in all sub-branches of this node that contain geometry. * in all sub-branches of this node that contain geometry.
@ -306,9 +304,9 @@ public class Node extends Spatial {
@Override @Override
public int getVertexCount() { public int getVertexCount() {
int count = 0; int count = 0;
if(children != null) { if (children != null) {
for(int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) {
count += children.get(i).getVertexCount(); count += children.get(i).getVertexCount();
} }
} }
@ -330,8 +328,8 @@ public class Node extends Spatial {
public int attachChild(Spatial child) { public int attachChild(Spatial child) {
return attachChildAt(child, children.size()); return attachChildAt(child, children.size());
} }
/** /**
*
* <code>attachChildAt</code> attaches a child to this node at an index. This node * <code>attachChildAt</code> attaches a child to this node at an index. This node
* becomes the child's parent. The current number of children maintained is * becomes the child's parent. The current number of children maintained is
* returned. * returned.
@ -349,7 +347,7 @@ public class Node extends Spatial {
} }
if (child == this) { if (child == this) {
throw new IllegalArgumentException("Cannot add child to itself"); throw new IllegalArgumentException("Cannot add child to itself");
} }
if (child.getParent() != this) { if (child.getParent() != this) {
if (child.getParent() != null) { if (child.getParent() != null) {
child.getParent().detachChild(child); child.getParent().detachChild(child);
@ -363,7 +361,7 @@ public class Node extends Spatial {
child.setLightListRefresh(); child.setLightListRefresh();
child.setMatParamOverrideRefresh(); child.setMatParamOverrideRefresh();
if (logger.isLoggable(Level.FINE)) { if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE,"Child ({0}) attached to this node ({1})", logger.log(Level.FINE, "Child ({0}) attached to this node ({1})",
new Object[]{child.getName(), getName()}); new Object[]{child.getName(), getName()});
} }
invalidateUpdateList(); invalidateUpdateList();
@ -380,8 +378,9 @@ public class Node extends Spatial {
* @return the index the child was at. -1 if the child was not in the list. * @return the index the child was at. -1 if the child was not in the list.
*/ */
public int detachChild(Spatial child) { public int detachChild(Spatial child) {
if (child == null) if (child == null) {
throw new NullPointerException(); throw new NullPointerException();
}
if (child.getParent() == this) { if (child.getParent() == this) {
int index = children.indexOf(child); int index = children.indexOf(child);
@ -404,13 +403,14 @@ public class Node extends Spatial {
* @return the index the child was at. -1 if the child was not in the list. * @return the index the child was at. -1 if the child was not in the list.
*/ */
public int detachChildNamed(String childName) { public int detachChildNamed(String childName) {
if (childName == null) if (childName == null) {
throw new NullPointerException(); throw new NullPointerException();
}
for (int x = 0, max = children.size(); x < max; x++) { for (int x = 0, max = children.size(); x < max; x++) {
Spatial child = children.get(x); Spatial child = children.get(x);
if (childName.equals(child.getName())) { if (childName.equals(child.getName())) {
detachChildAt( x ); detachChildAt(x);
return x; return x;
} }
} }
@ -418,7 +418,6 @@ public class Node extends Spatial {
} }
/** /**
*
* <code>detachChildAt</code> removes a child at a given index. That child * <code>detachChildAt</code> removes a child at a given index. That child
* is returned for saving purposes. * is returned for saving purposes.
* *
@ -427,9 +426,9 @@ public class Node extends Spatial {
* @return the child at the supplied index. * @return the child at the supplied index.
*/ */
public Spatial detachChildAt(int index) { public Spatial detachChildAt(int index) {
Spatial child = children.remove(index); Spatial child = children.remove(index);
if ( child != null ) { if (child != null) {
child.setParent( null ); child.setParent(null);
logger.log(Level.FINE, "{0}: Child removed.", this.toString()); logger.log(Level.FINE, "{0}: Child removed.", this.toString());
// since a child with a bound was detached; // since a child with a bound was detached;
@ -443,14 +442,13 @@ public class Node extends Spatial {
// lights are also inherited from parent // lights are also inherited from parent
child.setLightListRefresh(); child.setLightListRefresh();
child.setMatParamOverrideRefresh(); child.setMatParamOverrideRefresh();
invalidateUpdateList(); invalidateUpdateList();
} }
return child; return child;
} }
/** /**
*
* <code>detachAllChildren</code> removes all children attached to this * <code>detachAllChildren</code> removes all children attached to this
* node. * node.
*/ */
@ -458,7 +456,7 @@ public class Node extends Spatial {
// Note: this could be a bit more efficient if it delegated // Note: this could be a bit more efficient if it delegated
// to a private method that avoided setBoundRefresh(), etc. // to a private method that avoided setBoundRefresh(), etc.
// for every child and instead did one in here at the end. // for every child and instead did one in here at the end.
for ( int i = children.size() - 1; i >= 0; i-- ) { for (int i = children.size() - 1; i >= 0; i--) {
detachChildAt(i); detachChildAt(i);
} }
logger.log(Level.FINE, "{0}: All children removed.", this.toString()); logger.log(Level.FINE, "{0}: All children removed.", this.toString());
@ -469,8 +467,7 @@ public class Node extends Spatial {
* in this node's list of children. * in this node's list of children.
* @param sp * @param sp
* The spatial to look up * The spatial to look up
* @return * @return The index of the spatial in the node's children, or -1
* The index of the spatial in the node's children, or -1
* if the spatial is not attached to this node * if the spatial is not attached to this node
*/ */
public int getChildIndex(Spatial sp) { public int getChildIndex(Spatial sp) {
@ -484,19 +481,17 @@ public class Node extends Spatial {
* @param index2 The index of the second child to swap * @param index2 The index of the second child to swap
*/ */
public void swapChildren(int index1, int index2) { public void swapChildren(int index1, int index2) {
Spatial c2 = children.get(index2); Spatial c2 = children.get(index2);
Spatial c1 = children.remove(index1); Spatial c1 = children.remove(index1);
children.add(index1, c2); children.add(index1, c2);
children.remove(index2); children.remove(index2);
children.add(index2, c1); children.add(index2, c1);
} }
/** /**
*
* <code>getChild</code> returns a child at a given index. * <code>getChild</code> returns a child at a given index.
* *
* @param i * @param i the index to retrieve the child from.
* the index to retrieve the child from.
* @return the child at a specified index. * @return the child at a specified index.
*/ */
public Spatial getChild(int i) { public Spatial getChild(int i) {
@ -514,21 +509,23 @@ public class Node extends Spatial {
* @return the child if found, or null. * @return the child if found, or null.
*/ */
public Spatial getChild(String name) { public Spatial getChild(String name) {
if (name == null) if (name == null) {
return null; return null;
}
for (Spatial child : children.getArray()) { for (Spatial child : children.getArray()) {
if (name.equals(child.getName())) { if (name.equals(child.getName())) {
return child; return child;
} else if(child instanceof Node) { } else if (child instanceof Node) {
Spatial out = ((Node)child).getChild(name); Spatial out = ((Node) child).getChild(name);
if(out != null) { if (out != null) {
return out; return out;
} }
} }
} }
return null; return null;
} }
/** /**
* determines if the provided Spatial is contained in the children list of * determines if the provided Spatial is contained in the children list of
* this node. * this node.
@ -538,12 +535,14 @@ public class Node extends Spatial {
* @return true if the object is contained, false otherwise. * @return true if the object is contained, false otherwise.
*/ */
public boolean hasChild(Spatial spat) { public boolean hasChild(Spatial spat) {
if (children.contains(spat)) if (children.contains(spat)) {
return true; return true;
}
for (Spatial child : children.getArray()) { for (Spatial child : children.getArray()) {
if (child instanceof Node && ((Node) child).hasChild(spat)) if (child instanceof Node && ((Node) child).hasChild(spat)) {
return true; return true;
}
} }
return false; return false;
@ -560,14 +559,14 @@ public class Node extends Spatial {
} }
@Override @Override
public void setMaterial(Material mat){ public void setMaterial(Material mat) {
for (int i = 0; i < children.size(); i++){ for (int i = 0; i < children.size(); i++) {
children.get(i).setMaterial(mat); children.get(i).setMaterial(mat);
} }
} }
@Override @Override
public void setLodLevel(int lod){ public void setLodLevel(int lod) {
super.setLodLevel(lod); super.setLodLevel(lod);
for (Spatial child : children.getArray()) { for (Spatial child : children.getArray()) {
child.setLodLevel(lod); child.setLodLevel(lod);
@ -575,11 +574,13 @@ public class Node extends Spatial {
} }
@Override @Override
public int collideWith(Collidable other, CollisionResults results){ public int collideWith(Collidable other, CollisionResults results) {
int total = 0; int total = 0;
// optimization: try collideWith BoundingVolume to avoid possibly redundant tests on children // optimization: try collideWith BoundingVolume to avoid possibly redundant tests on children
// number 4 in condition is somewhat arbitrary. When there is only one child, the boundingVolume test is redundant at all. // number 4 in condition is somewhat arbitrary.
// The idea is when there are few children, it can be too expensive to test boundingVolume first. // When there is only one child, the boundingVolume test is redundant at all.
// The idea is when there are few children,
// it can be too expensive to test boundingVolume first.
/* /*
I'm removing this change until some issues can be addressed and I really I'm removing this change until some issues can be addressed and I really
think it needs to be implemented a better way anyway. think it needs to be implemented a better way anyway.
@ -612,7 +613,7 @@ public class Node extends Spatial {
if (bv.collideWith(other) == 0) return 0; if (bv.collideWith(other) == 0) return 0;
} }
*/ */
for (Spatial child : children.getArray()){ for (Spatial child : children.getArray()) {
total += child.collideWith(other, results); total += child.collideWith(other, results);
} }
return total; return total;
@ -643,22 +644,27 @@ public class Node extends Spatial {
* Null causes all Spatials to qualify. * Null causes all Spatials to qualify.
* @param nameRegex Regular expression to match Spatial name against. * @param nameRegex Regular expression to match Spatial name against.
* Null causes all Names to qualify. * Null causes all Names to qualify.
* @return Non-null, but possibly 0-element, list of matching Spatials (also Instances extending Spatials). * @return Non-null, but possibly 0-element, list of matching Spatials
* (also Instances extending Spatials).
* *
* @see java.util.regex.Pattern * @see java.util.regex.Pattern
* @see Spatial#matches(java.lang.Class, java.lang.String) * @see Spatial#matches(java.lang.Class, java.lang.String)
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Spatial>List<T> descendantMatches( public <T extends Spatial> List<T> descendantMatches(
Class<T> spatialSubclass, String nameRegex) { Class<T> spatialSubclass, String nameRegex) {
List<T> newList = new ArrayList<T>(); List<T> newList = new ArrayList<T>();
if (getQuantity() < 1) return newList; if (getQuantity() < 1) {
return newList;
}
for (Spatial child : getChildren()) { for (Spatial child : getChildren()) {
if (child.matches(spatialSubclass, nameRegex)) if (child.matches(spatialSubclass, nameRegex)) {
newList.add((T)child); newList.add((T) child);
if (child instanceof Node) }
if (child instanceof Node) {
newList.addAll(((Node) child).descendantMatches( newList.addAll(((Node) child).descendantMatches(
spatialSubclass, nameRegex)); spatialSubclass, nameRegex));
}
} }
return newList; return newList;
} }
@ -668,7 +674,7 @@ public class Node extends Spatial {
* *
* @see #descendantMatches(java.lang.Class, java.lang.String) * @see #descendantMatches(java.lang.Class, java.lang.String)
*/ */
public <T extends Spatial>List<T> descendantMatches( public <T extends Spatial> List<T> descendantMatches(
Class<T> spatialSubclass) { Class<T> spatialSubclass) {
return descendantMatches(spatialSubclass, null); return descendantMatches(spatialSubclass, null);
} }
@ -678,12 +684,12 @@ public class Node extends Spatial {
* *
* @see #descendantMatches(java.lang.Class, java.lang.String) * @see #descendantMatches(java.lang.Class, java.lang.String)
*/ */
public <T extends Spatial>List<T> descendantMatches(String nameRegex) { public <T extends Spatial> List<T> descendantMatches(String nameRegex) {
return descendantMatches(null, nameRegex); return descendantMatches(null, nameRegex);
} }
@Override @Override
public Node clone(boolean cloneMaterials){ public Node clone(boolean cloneMaterials) {
Node nodeClone = (Node) super.clone(cloneMaterials); Node nodeClone = (Node) super.clone(cloneMaterials);
// nodeClone.children = new ArrayList<Spatial>(); // nodeClone.children = new ArrayList<Spatial>();
// for (Spatial child : children){ // for (Spatial child : children){
@ -700,7 +706,7 @@ public class Node extends Spatial {
@Override @Override
public Spatial deepClone() { public Spatial deepClone() {
Node nodeClone = (Node)super.deepClone(); Node nodeClone = (Node) super.deepClone();
// Reset the fields of the clone that should be in a 'new' state. // Reset the fields of the clone that should be in a 'new' state.
nodeClone.updateList = null; nodeClone.updateList = null;
@ -709,10 +715,10 @@ public class Node extends Spatial {
return nodeClone; return nodeClone;
} }
public Spatial oldDeepClone(){ public Spatial oldDeepClone() {
Node nodeClone = (Node) super.clone(); Node nodeClone = (Node) super.clone();
nodeClone.children = new SafeArrayList<Spatial>(Spatial.class); nodeClone.children = new SafeArrayList<Spatial>(Spatial.class);
for (Spatial child : children){ for (Spatial child : children) {
Spatial childClone = child.deepClone(); Spatial childClone = child.deepClone();
childClone.parent = nodeClone; childClone.parent = nodeClone;
nodeClone.children.add(childClone); nodeClone.children.add(childClone);
@ -724,7 +730,7 @@ public class Node extends Spatial {
* Called internally by com.jme3.util.clone.Cloner. Do not call directly. * Called internally by com.jme3.util.clone.Cloner. Do not call directly.
*/ */
@Override @Override
public void cloneFields( Cloner cloner, Object original ) { public void cloneFields(Cloner cloner, Object original) {
super.cloneFields(cloner, original); super.cloneFields(cloner, original);
this.children = cloner.clone(children); this.children = cloner.clone(children);
@ -734,6 +740,7 @@ public class Node extends Spatial {
// cloning this list is fine. // cloning this list is fine.
this.updateList = cloner.clone(updateList); this.updateList = cloner.clone(updateList);
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void write(JmeExporter e) throws IOException { public void write(JmeExporter e) throws IOException {
@ -747,8 +754,8 @@ public class Node extends Spatial {
// XXX: Load children before loading itself!! // XXX: Load children before loading itself!!
// This prevents empty children list if controls query // This prevents empty children list if controls query
// it in Control.setSpatial(). // it in Control.setSpatial().
children = new SafeArrayList( Spatial.class, children = new SafeArrayList(Spatial.class,
e.getCapsule(this).readSavableArrayList("children", null) ); e.getCapsule(this).readSavableArrayList("children", null));
// go through children and set parent to this node // go through children and set parent to this node
if (children != null) { if (children != null) {
@ -761,7 +768,7 @@ public class Node extends Spatial {
@Override @Override
public void setModelBound(BoundingVolume modelBound) { public void setModelBound(BoundingVolume modelBound) {
if(children != null) { if (children != null) {
for (Spatial child : children.getArray()) { for (Spatial child : children.getArray()) {
child.setModelBound(modelBound != null ? modelBound.clone(null) : null); child.setModelBound(modelBound != null ? modelBound.clone(null) : null);
} }
@ -770,7 +777,7 @@ public class Node extends Spatial {
@Override @Override
public void updateModelBound() { public void updateModelBound() {
if(children != null) { if (children != null) {
for (Spatial child : children.getArray()) { for (Spatial child : children.getArray()) {
child.updateModelBound(); child.updateModelBound();
} }

@ -68,8 +68,8 @@ import java.util.logging.Logger;
* @author Joshua Slack * @author Joshua Slack
* @version $Revision: 4075 $, $Data$ * @version $Revision: 4075 $, $Data$
*/ */
public abstract class Spatial implements Savable, Cloneable, Collidable, CloneableSmartAsset, JmeCloneable, HasLocalTransform { public abstract class Spatial implements Savable, Cloneable, Collidable,
CloneableSmartAsset, JmeCloneable, HasLocalTransform {
private static final Logger logger = Logger.getLogger(Spatial.class.getName()); private static final Logger logger = Logger.getLogger(Spatial.class.getName());
/** /**
@ -77,7 +77,6 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* this spatial. * this spatial.
*/ */
public enum CullHint { public enum CullHint {
/** /**
* Do whatever our parent does. If no parent, default to {@link #Dynamic}. * Do whatever our parent does. If no parent, default to {@link #Dynamic}.
*/ */
@ -104,7 +103,6 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* Specifies if this spatial should be batched * Specifies if this spatial should be batched
*/ */
public enum BatchHint { public enum BatchHint {
/** /**
* Do whatever our parent does. If no parent, default to {@link #Always}. * Do whatever our parent does. If no parent, default to {@link #Always}.
*/ */
@ -121,12 +119,13 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
/** /**
* Refresh flag types * Refresh flag types
*/ */
protected static final int RF_TRANSFORM = 0x01, // need light resort + combine transforms protected static final int
RF_BOUND = 0x02, RF_TRANSFORM = 0x01, // need light resort + combine transforms
RF_LIGHTLIST = 0x04, // changes in light lists RF_BOUND = 0x02,
RF_CHILD_LIGHTLIST = 0x08, // some child need geometry update RF_LIGHTLIST = 0x04, // changes in light lists
RF_MATPARAM_OVERRIDE = 0x10; RF_CHILD_LIGHTLIST = 0x08, // some child need geometry update
RF_MATPARAM_OVERRIDE = 0x10;
protected CullHint cullHint = CullHint.Inherit; protected CullHint cullHint = CullHint.Inherit;
protected BatchHint batchHint = BatchHint.Inherit; protected BatchHint batchHint = BatchHint.Inherit;
/** /**
@ -147,7 +146,8 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
*/ */
protected String name; protected String name;
// scale values // scale values
protected transient Camera.FrustumIntersect frustrumIntersects = Camera.FrustumIntersect.Intersects; protected transient Camera.FrustumIntersect frustrumIntersects
= Camera.FrustumIntersect.Intersects;
protected RenderQueue.Bucket queueBucket = RenderQueue.Bucket.Inherit; protected RenderQueue.Bucket queueBucket = RenderQueue.Bucket.Inherit;
protected ShadowMode shadowMode = RenderQueue.ShadowMode.Inherit; protected ShadowMode shadowMode = RenderQueue.ShadowMode.Inherit;
public transient float queueDistance = Float.NEGATIVE_INFINITY; public transient float queueDistance = Float.NEGATIVE_INFINITY;
@ -232,6 +232,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
boolean requiresUpdates() { boolean requiresUpdates() {
return requiresUpdates | !controls.isEmpty(); return requiresUpdates | !controls.isEmpty();
} }
/** /**
* Subclasses can call this with true to denote that they require * Subclasses can call this with true to denote that they require
* updateLogicalState() to be called even if they contain no controls. * updateLogicalState() to be called even if they contain no controls.
@ -247,7 +248,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* optimal behavior if they don't require updateLogicalState() to be * optimal behavior if they don't require updateLogicalState() to be
* called even if there are no controls. * called even if there are no controls.
*/ */
protected void setRequiresUpdates( boolean f ) { protected void setRequiresUpdates(boolean f) {
// Note to explorers, the reason this was done as a protected setter // Note to explorers, the reason this was done as a protected setter
// instead of passed on construction is because it frees all subclasses // instead of passed on construction is because it frees all subclasses
// from having to make sure to always pass the value up in case they // from having to make sure to always pass the value up in case they
@ -264,7 +265,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// it to false if the class is Node.class or Geometry.class. // it to false if the class is Node.class or Geometry.class.
// This means that all subclasses will default to the old behavior // This means that all subclasses will default to the old behavior
// unless they opt in. // unless they opt in.
if( parent != null ) { if (parent != null) {
throw new IllegalStateException("setRequiresUpdates() cannot be called once attached."); throw new IllegalStateException("setRequiresUpdates() cannot be called once attached.");
} }
this.requiresUpdates = f; this.requiresUpdates = f;
@ -325,6 +326,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
p = p.parent; p = p.parent;
} }
} }
/** /**
* (Internal use only) Forces a refresh of the given types of data. * (Internal use only) Forces a refresh of the given types of data.
* *
@ -556,9 +558,9 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
Vector3f compVecA = vars.vect4; Vector3f compVecA = vars.vect4;
compVecA.set(position).subtractLocal(worldTranslation); compVecA.set(position).subtractLocal(worldTranslation);
getLocalRotation().lookAt(compVecA, upVector); getLocalRotation().lookAt(compVecA, upVector);
if ( getParent() != null ) { if (getParent() != null) {
Quaternion rot=vars.quat1; Quaternion rot = vars.quat1;
rot = rot.set(parent.getWorldRotation()).inverseLocal().multLocal(getLocalRotation()); rot = rot.set(parent.getWorldRotation()).inverseLocal().multLocal(getLocalRotation());
rot.normalizeLocal(); rot.normalizeLocal();
setLocalRotation(rot); setLocalRotation(rot);
} }
@ -762,6 +764,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
/** /**
* Add a control to the list of controls. * Add a control to the list of controls.
*
* @param control The control to add. * @param control The control to add.
* *
* @see Spatial#removeControl(java.lang.Class) * @see Spatial#removeControl(java.lang.Class)
@ -774,7 +777,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// If the requirement to be updated has changed // If the requirement to be updated has changed
// then we need to let the parent node know so it // then we need to let the parent node know so it
// can rebuild its update list. // can rebuild its update list.
if( parent != null && before != after ) { if (parent != null && before != after) {
parent.invalidateUpdateList(); parent.invalidateUpdateList();
} }
} }
@ -797,7 +800,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// If the requirement to be updated has changed // If the requirement to be updated has changed
// then we need to let the parent node know so it // then we need to let the parent node know so it
// can rebuild its update list. // can rebuild its update list.
if( parent != null && before != after ) { if (parent != null && before != after) {
parent.invalidateUpdateList(); parent.invalidateUpdateList();
} }
} }
@ -822,7 +825,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// If the requirement to be updated has changed // If the requirement to be updated has changed
// then we need to let the parent node know so it // then we need to let the parent node know so it
// can rebuild its update list. // can rebuild its update list.
if( parent != null && before != after ) { if (parent != null && before != after) {
parent.invalidateUpdateList(); parent.invalidateUpdateList();
} }
return result; return result;
@ -1229,6 +1232,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
/** /**
* Centers the spatial in the origin of the world bound. * Centers the spatial in the origin of the world bound.
*
* @return The spatial on which this method is called, e.g <code>this</code>. * @return The spatial on which this method is called, e.g <code>this</code>.
*/ */
public Spatial center() { public Spatial center() {
@ -1341,8 +1345,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
* *
* @see Mesh#cloneForAnim() * @see Mesh#cloneForAnim()
*/ */
public Spatial clone( boolean cloneMaterial ) { public Spatial clone(boolean cloneMaterial) {
// Setup the cloner for the type of cloning we want to do. // Setup the cloner for the type of cloning we want to do.
Cloner cloner = new Cloner(); Cloner cloner = new Cloner();
@ -1351,7 +1354,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// If we aren't cloning materials then we will make sure those // If we aren't cloning materials then we will make sure those
// aren't cloned also // aren't cloned also
if( !cloneMaterial ) { if (!cloneMaterial) {
cloner.setCloneFunction(Material.class, new IdentityCloneFunction<Material>()); cloner.setCloneFunction(Material.class, new IdentityCloneFunction<Material>());
} }
@ -1425,7 +1428,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
@Override @Override
public Spatial jmeClone() { public Spatial jmeClone() {
try { try {
Spatial clone = (Spatial)super.clone(); Spatial clone = (Spatial) super.clone();
return clone; return clone;
} catch (CloneNotSupportedException ex) { } catch (CloneNotSupportedException ex) {
throw new AssertionError(); throw new AssertionError();
@ -1437,8 +1440,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
*/ */
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void cloneFields( Cloner cloner, Object original ) { public void cloneFields(Cloner cloner, Object original) {
// Clone all of the fields that need fix-ups and/or potential // Clone all of the fields that need fix-ups and/or potential
// sharing. // sharing.
this.parent = cloner.clone(parent); this.parent = cloner.clone(parent);
@ -1457,11 +1459,11 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
// to avoid all of the nasty cloneForSpatial() fixup style code that // to avoid all of the nasty cloneForSpatial() fixup style code that
// used to inject stuff into the clone's user data. By using cloner // used to inject stuff into the clone's user data. By using cloner
// to clone the user data we get this automatically. // to clone the user data we get this automatically.
if( userData != null ) { if (userData != null) {
userData = (HashMap<String, Savable>)userData.clone(); userData = (HashMap<String, Savable>) userData.clone();
for( Map.Entry<String, Savable> e : userData.entrySet() ) { for (Map.Entry<String, Savable> e : userData.entrySet()) {
Savable value = e.getValue(); Savable value = e.getValue();
if( value instanceof Cloneable ) { if (value instanceof Cloneable) {
// Note: all JmeCloneable objects are also Cloneable so this // Note: all JmeCloneable objects are also Cloneable so this
// catches both cases. // catches both cases.
e.setValue(cloner.clone(value)); e.setValue(cloner.clone(value));
@ -1474,7 +1476,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
if (data == null) { if (data == null) {
if (userData != null) { if (userData != null) {
userData.remove(key); userData.remove(key);
if(userData.isEmpty()) { if (userData.isEmpty()) {
userData = null; userData = null;
} }
} }
@ -1588,9 +1590,11 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
} }
worldOverrides = new SafeArrayList<>(MatParamOverride.class); worldOverrides = new SafeArrayList<>(MatParamOverride.class);
//changed for backward compatibility with j3o files generated before the AnimControl/SkeletonControl split //changed for backward compatibility with j3o files
//generated before the AnimControl/SkeletonControl split
//the AnimControl creates the SkeletonControl for old files and add it to the spatial. //the AnimControl creates the SkeletonControl for old files and add it to the spatial.
//The SkeletonControl must be the last in the stack so we add the list of all other control before it. //The SkeletonControl must be the last in the stack
//so we add the list of all other control before it.
//When backward compatibility won't be needed anymore this can be replaced by : //When backward compatibility won't be needed anymore this can be replaced by :
//controls = ic.readSavableArrayList("controlsList", null)); //controls = ic.readSavableArrayList("controlsList", null));
controls.addAll(0, ic.readSavableArrayList("controlsList", null)); controls.addAll(0, ic.readSavableArrayList("controlsList", null));
@ -1759,13 +1763,14 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
/** /**
* Visit each scene graph element ordered by DFS with the default post order mode. * Visit each scene graph element ordered by DFS with the default post order mode.
*
* @param visitor * @param visitor
* @see #depthFirstTraversal(com.jme3.scene.SceneGraphVisitor, com.jme3.scene.Spatial.DFSMode) * @see #depthFirstTraversal(com.jme3.scene.SceneGraphVisitor, com.jme3.scene.Spatial.DFSMode)
*/ */
public void depthFirstTraversal(SceneGraphVisitor visitor) { public void depthFirstTraversal(SceneGraphVisitor visitor) {
depthFirstTraversal(visitor, DFSMode.POST_ORDER); depthFirstTraversal(visitor, DFSMode.POST_ORDER);
} }
/** /**
* Specifies the mode of the depth first search. * Specifies the mode of the depth first search.
*/ */
@ -1779,10 +1784,11 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
*/ */
POST_ORDER; POST_ORDER;
} }
/** /**
* Visit each scene graph element ordered by DFS. * Visit each scene graph element ordered by DFS.
* There are two modes: pre order and post order. * There are two modes: pre order and post order.
*
* @param visitor * @param visitor
* @param mode the traversal mode: pre order or post order * @param mode the traversal mode: pre order or post order
*/ */
@ -1790,6 +1796,7 @@ public abstract class Spatial implements Savable, Cloneable, Collidable, Cloneab
/** /**
* Visit each scene graph element ordered by BFS * Visit each scene graph element ordered by BFS
*
* @param visitor * @param visitor
*/ */
public void breadthFirstTraversal(SceneGraphVisitor visitor) { public void breadthFirstTraversal(SceneGraphVisitor visitor) {

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2009-2019 jMonkeyEngine * Copyright (c) 2009-2020 jMonkeyEngine
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -49,12 +49,11 @@ import java.nio.*;
* <li>Element - A single element is the largest individual object * <li>Element - A single element is the largest individual object
* inside a VertexBuffer. E.g. if the VertexBuffer is used to store 3D position * inside a VertexBuffer. E.g. if the VertexBuffer is used to store 3D position
* data, then an element will be a single 3D vector.</li> * data, then an element will be a single 3D vector.</li>
* <li>Component - A component represents the parts inside an element. * <li>Component - A component represents the parts inside an element.
* For a 3D vector, a single component is one of the dimensions, X, Y or Z.</li> * For a 3D vector, a single component is one of the dimensions, X, Y or Z.</li>
* </ul> * </ul>
*/ */
public class VertexBuffer extends NativeObject implements Savable, Cloneable { public class VertexBuffer extends NativeObject implements Savable, Cloneable {
/** /**
* Type of buffer. Specifies the actual attribute it defines. * Type of buffer. Specifies the actual attribute it defines.
*/ */
@ -63,27 +62,22 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* Position of the vertex (3 floats) * Position of the vertex (3 floats)
*/ */
Position, Position,
/** /**
* The size of the point when using point buffers (float). * The size of the point when using point buffers (float).
*/ */
Size, Size,
/** /**
* Normal vector, normalized (3 floats). * Normal vector, normalized (3 floats).
*/ */
Normal, Normal,
/** /**
* Texture coordinate (2 float) * Texture coordinate (2 float)
*/ */
TexCoord, TexCoord,
/** /**
* Color and Alpha (4 floats) * Color and Alpha (4 floats)
*/ */
Color, Color,
/** /**
* Tangent vector, normalized (4 floats) (x,y,z,w). The w component is * Tangent vector, normalized (4 floats) (x,y,z,w). The w component is
* called the binormal parity, is not normalized, and is either 1f or * called the binormal parity, is not normalized, and is either 1f or
@ -91,19 +85,16 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* GPU at render time. * GPU at render time.
*/ */
Tangent, Tangent,
/** /**
* Binormal vector, normalized (3 floats, optional) * Binormal vector, normalized (3 floats, optional)
*/ */
Binormal, Binormal,
/** /**
* Specifies the source data for various vertex buffers * Specifies the source data for various vertex buffers
* when interleaving is used. By default the format is * when interleaving is used. By default the format is
* byte. * byte.
*/ */
InterleavedData, InterleavedData,
/** /**
* Do not use. * Do not use.
*/ */
@ -114,106 +105,90 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* (ubyte, ushort, or uint). * (ubyte, ushort, or uint).
*/ */
Index, Index,
/**
/**
* Initial vertex position, used with animation. * Initial vertex position, used with animation.
* Should have the same format and size as {@link Type#Position}. * Should have the same format and size as {@link Type#Position}.
* If used with software skinning, the usage should be * If used with software skinning, the usage should be
* {@link Usage#CpuOnly}, and the buffer should be allocated * {@link Usage#CpuOnly}, and the buffer should be allocated
* on the heap. * on the heap.
*/ */
BindPosePosition, BindPosePosition,
/**
/**
* Initial vertex normals, used with animation. * Initial vertex normals, used with animation.
* Should have the same format and size as {@link Type#Normal}. * Should have the same format and size as {@link Type#Normal}.
* If used with software skinning, the usage should be * If used with software skinning, the usage should be
* {@link Usage#CpuOnly}, and the buffer should be allocated * {@link Usage#CpuOnly}, and the buffer should be allocated
* on the heap. * on the heap.
*/ */
BindPoseNormal, BindPoseNormal,
/**
/**
* Bone weights, used with animation (4 floats). * Bone weights, used with animation (4 floats).
* Only used for software skinning, the usage should be * Only used for software skinning, the usage should be
* {@link Usage#CpuOnly}, and the buffer should be allocated * {@link Usage#CpuOnly}, and the buffer should be allocated
* on the heap. * on the heap.
*/ */
BoneWeight, BoneWeight,
/**
/**
* Bone indices, used with animation (4 ubytes). * Bone indices, used with animation (4 ubytes).
* Only used for software skinning, the usage should be * Only used for software skinning, the usage should be
* {@link Usage#CpuOnly}, and the buffer should be allocated * {@link Usage#CpuOnly}, and the buffer should be allocated
* on the heap as a ubytes buffer. * on the heap as a ubytes buffer.
*/ */
BoneIndex, BoneIndex,
/** /**
* Texture coordinate #2 * Texture coordinate #2
*/ */
TexCoord2, TexCoord2,
/** /**
* Texture coordinate #3 * Texture coordinate #3
*/ */
TexCoord3, TexCoord3,
/** /**
* Texture coordinate #4 * Texture coordinate #4
*/ */
TexCoord4, TexCoord4,
/** /**
* Texture coordinate #5 * Texture coordinate #5
*/ */
TexCoord5, TexCoord5,
/** /**
* Texture coordinate #6 * Texture coordinate #6
*/ */
TexCoord6, TexCoord6,
/** /**
* Texture coordinate #7 * Texture coordinate #7
*/ */
TexCoord7, TexCoord7,
/** /**
* Texture coordinate #8 * Texture coordinate #8
*/ */
TexCoord8, TexCoord8,
/**
/**
* Initial vertex tangents, used with animation. * Initial vertex tangents, used with animation.
* Should have the same format and size as {@link Type#Tangent}. * Should have the same format and size as {@link Type#Tangent}.
* If used with software skinning, the usage should be * If used with software skinning, the usage should be
* {@link Usage#CpuOnly}, and the buffer should be allocated * {@link Usage#CpuOnly}, and the buffer should be allocated
* on the heap. * on the heap.
*/ */
BindPoseTangent, BindPoseTangent,
/**
/**
* Bone weights, used with animation (4 floats). * Bone weights, used with animation (4 floats).
* for Hardware Skinning only * for Hardware Skinning only
*/ */
HWBoneWeight, HWBoneWeight,
/**
/**
* Bone indices, used with animation (4 ubytes). * Bone indices, used with animation (4 ubytes).
* for Hardware Skinning only * for Hardware Skinning only
* either an int or float buffer due to shader attribute types restrictions. * either an int or float buffer due to shader attribute types restrictions.
*/ */
HWBoneIndex, HWBoneIndex,
/** /**
* Information about this instance. * Information about this instance.
* *
* Format should be {@link Format#Float} and number of components * Format should be {@link Format#Float} and number of components
* should be 16. * should be 16.
*/ */
InstanceData, InstanceData,
/** /**
* Morph animations targets. * Morph animations targets.
* Supports up tp 14 morph target buffers at the same time * Supports up tp 14 morph target buffers at the same time
@ -225,11 +200,15 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* 7 simultaneous POSITION and NORMAL targets * 7 simultaneous POSITION and NORMAL targets
* 4 simultaneous POSTION, NORMAL and TANGENT targets. * 4 simultaneous POSTION, NORMAL and TANGENT targets.
* <p> * <p>
* Note that the MorphControl will find how many buffers can be supported for each mesh/material combination. * Note that the MorphControl will find how many buffers
* Note that all buffers have 3 components (Vector3f) even the Tangent buffer that * can be supported for each mesh/material combination.
* does not contain the w (handedness) component that will not be interpolated for morph animation. * Note that all buffers have 3 components (Vector3f)
* even the Tangent buffer that
* does not contain the w (handedness) component
* that will not be interpolated for morph animation.
* <p> * <p>
* Note that those buffers contain the difference between the base buffer (POSITION, NORMAL or TANGENT) and the target value * Note that those buffers contain the difference between
* the base buffer (POSITION, NORMAL or TANGENT) and the target value
* So that you can interpolate with a MADD operation in the vertex shader * So that you can interpolate with a MADD operation in the vertex shader
* position = weight * diffPosition + basePosition; * position = weight * diffPosition + basePosition;
*/ */
@ -247,7 +226,6 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
MorphTarget11, MorphTarget11,
MorphTarget12, MorphTarget12,
MorphTarget13, MorphTarget13,
} }
/** /**
@ -256,22 +234,18 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* or held in video memory, but no guarantees are made- it's only a hint. * or held in video memory, but no guarantees are made- it's only a hint.
*/ */
public static enum Usage { public static enum Usage {
/** /**
* Mesh data is sent once and very rarely updated. * Mesh data is sent once and very rarely updated.
*/ */
Static, Static,
/** /**
* Mesh data is updated occasionally (once per frame or less). * Mesh data is updated occasionally (once per frame or less).
*/ */
Dynamic, Dynamic,
/** /**
* Mesh data is updated every frame. * Mesh data is updated every frame.
*/ */
Stream, Stream,
/** /**
* Mesh data is <em>not</em> sent to GPU at all. It is only * Mesh data is <em>not</em> sent to GPU at all. It is only
* used by the CPU. * used by the CPU.
@ -289,49 +263,38 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
*/ */
public static enum Format { public static enum Format {
/** /**
* Half precision floating point. * Half precision floating point. 2 bytes, signed.
* 2 bytes, signed.
*/ */
Half(2), Half(2),
/** /**
* Single precision floating point. * Single precision floating point. 4 bytes, signed
* 4 bytes, signed
*/ */
Float(4), Float(4),
/** /**
* Double precision floating point. * Double precision floating point. 8 bytes, signed. May not be
* 8 bytes, signed. May not * supported by all GPUs.
* be supported by all GPUs.
*/ */
Double(8), Double(8),
/** /**
* 1 byte integer, signed. * 1 byte integer, signed.
*/ */
Byte(1), Byte(1),
/** /**
* 1 byte integer, unsigned. * 1 byte integer, unsigned.
*/ */
UnsignedByte(1), UnsignedByte(1),
/** /**
* 2 byte integer, signed. * 2 byte integer, signed.
*/ */
Short(2), Short(2),
/** /**
* 2 byte integer, unsigned. * 2 byte integer, unsigned.
*/ */
UnsignedShort(2), UnsignedShort(2),
/** /**
* 4 byte integer, signed. * 4 byte integer, signed.
*/ */
Int(4), Int(4),
/** /**
* 4 byte integer, unsigned. * 4 byte integer, unsigned.
*/ */
@ -339,16 +302,16 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
private int componentSize = 0; private int componentSize = 0;
Format(int componentSize){ Format(int componentSize) {
this.componentSize = componentSize; this.componentSize = componentSize;
} }
/** /**
* Returns the size in bytes of this data type. * Returns the size in bytes of this data type.
* *
* @return Size in bytes of this data type. * @return Size in bytes of this data type.
*/ */
public int getComponentSize(){ public int getComponentSize() {
return componentSize; return componentSize;
} }
} }
@ -374,7 +337,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* Creates an empty, uninitialized buffer. * Creates an empty, uninitialized buffer.
* Must call setupData() to initialize. * Must call setupData() to initialize.
*/ */
public VertexBuffer(Type type){ public VertexBuffer(Type type) {
super(); super();
this.bufType = type; this.bufType = type;
} }
@ -382,11 +345,11 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
/** /**
* Serialization only. Do not use. * Serialization only. Do not use.
*/ */
protected VertexBuffer(){ protected VertexBuffer() {
super(); super();
} }
protected VertexBuffer(int id){ protected VertexBuffer(int id) {
super(id); super(id);
} }
@ -408,7 +371,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
throw new AssertionError(); throw new AssertionError();
} }
// Are components between 1 and 4? // Are components between 1 and 4?
// Are components between 1 and 4 and not InstanceData? // Are components between 1 and 4 and not InstanceData?
if (bufType != Type.InstanceData) { if (bufType != Type.InstanceData) {
if (components < 1 || components > 4) { if (components < 1 || components > 4) {
@ -442,11 +405,11 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
} }
return true; return true;
} }
/** /**
* @return The offset after which the data is sent to the GPU. * @return The offset after which the data is sent to the GPU.
* *
* @see #setOffset(int) * @see #setOffset(int)
*/ */
public int getOffset() { public int getOffset() {
return offset; return offset;
@ -461,21 +424,21 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
} }
/** /**
* @return The stride (in bytes) for the data. * @return The stride (in bytes) for the data.
* *
* @see #setStride(int) * @see #setStride(int)
*/ */
public int getStride() { public int getStride() {
return stride; return stride;
} }
/** /**
* Set the stride (in bytes) for the data. * Set the stride (in bytes) for the data.
* <p> * <p>
* If the data is packed in the buffer, then stride is 0, if there's other * If the data is packed in the buffer, then stride is 0, if there's other
* data that is between the current component and the next component in the * data that is between the current component and the next component in the
* buffer, then this specifies the size in bytes of that additional data. * buffer, then this specifies the size in bytes of that additional data.
* *
* @param stride the stride (in bytes) for the data * @param stride the stride (in bytes) for the data
*/ */
public void setStride(int stride) { public void setStride(int stride) {
@ -486,17 +449,17 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* Returns the raw internal data buffer used by this VertexBuffer. * Returns the raw internal data buffer used by this VertexBuffer.
* This buffer is not safe to call from multiple threads since buffers * This buffer is not safe to call from multiple threads since buffers
* have their own internal position state that cannot be shared. * have their own internal position state that cannot be shared.
* Call getData().duplicate(), getData().asReadOnlyBuffer(), or * Call getData().duplicate(), getData().asReadOnlyBuffer(), or
* the more convenient getDataReadOnly() if the buffer may be accessed * the more convenient getDataReadOnly() if the buffer may be accessed
* from multiple threads. * from multiple threads.
* *
* @return A native buffer, in the specified {@link Format format}. * @return A native buffer, in the specified {@link Format format}.
*/ */
public Buffer getData(){ public Buffer getData() {
return data; return data;
} }
/** /**
* Returns a safe read-only version of this VertexBuffer's data. The * Returns a safe read-only version of this VertexBuffer's data. The
* contents of the buffer will reflect whatever changes are made on * contents of the buffer will reflect whatever changes are made on
* other threads (eventually) but these should not be used in that way. * other threads (eventually) but these should not be used in that way.
@ -504,38 +467,36 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* a separate thread since it has its own book-keeping state (position, limit, etc.) * a separate thread since it has its own book-keeping state (position, limit, etc.)
* *
* @return A rewound native buffer in the specified {@link Format format} * @return A rewound native buffer in the specified {@link Format format}
* that is safe to read from a separate thread from other readers. * that is safe to read from a separate thread from other readers.
*/ */
public Buffer getDataReadOnly() { public Buffer getDataReadOnly() {
if (data == null) { if (data == null) {
return null; return null;
} }
// Create a read-only duplicate(). Note: this does not copy // Create a read-only duplicate(). Note: this does not copy
// the underlying memory, it just creates a new read-only wrapper // the underlying memory, it just creates a new read-only wrapper
// with its own buffer position state. // with its own buffer position state.
// Unfortunately, this is not 100% straight forward since Buffer // Unfortunately, this is not 100% straight forward since Buffer
// does not have an asReadOnlyBuffer() method. // does not have an asReadOnlyBuffer() method.
Buffer result; Buffer result;
if( data instanceof ByteBuffer ) { if (data instanceof ByteBuffer) {
result = ((ByteBuffer)data).asReadOnlyBuffer(); result = ((ByteBuffer) data).asReadOnlyBuffer();
} else if( data instanceof FloatBuffer ) { } else if (data instanceof FloatBuffer) {
result = ((FloatBuffer)data).asReadOnlyBuffer(); result = ((FloatBuffer) data).asReadOnlyBuffer();
} else if( data instanceof ShortBuffer ) { } else if (data instanceof ShortBuffer) {
result = ((ShortBuffer)data).asReadOnlyBuffer(); result = ((ShortBuffer) data).asReadOnlyBuffer();
} else if( data instanceof IntBuffer ) { } else if (data instanceof IntBuffer) {
result = ((IntBuffer)data).asReadOnlyBuffer(); result = ((IntBuffer) data).asReadOnlyBuffer();
} else { } else {
throw new UnsupportedOperationException( "Cannot get read-only view of buffer type:" + data ); throw new UnsupportedOperationException("Cannot get read-only view of buffer type:" + data);
} }
// Make sure the caller gets a consistent view since we may // Make sure the caller gets a consistent view since we may
// have grabbed this buffer while another thread was reading // have grabbed this buffer while another thread was reading
// the raw data. // the raw data.
result.rewind(); result.rewind();
return result; return result;
} }
@ -543,7 +504,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* @return The usage of this buffer. See {@link Usage} for more * @return The usage of this buffer. See {@link Usage} for more
* information. * information.
*/ */
public Usage getUsage(){ public Usage getUsage() {
return usage; return usage;
} }
@ -551,7 +512,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* @param usage The usage of this buffer. See {@link Usage} for more * @param usage The usage of this buffer. See {@link Usage} for more
* information. * information.
*/ */
public void setUsage(Usage usage){ public void setUsage(Usage usage) {
// if (id != -1) // if (id != -1)
// throw new UnsupportedOperationException("Data has already been sent. Cannot set usage."); // throw new UnsupportedOperationException("Data has already been sent. Cannot set usage.");
@ -567,15 +528,15 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* the components will be converted to the range 0.0 - 1.0 by dividing * the components will be converted to the range 0.0 - 1.0 by dividing
* every integer by 2^32. * every integer by 2^32.
*/ */
public void setNormalized(boolean normalized){ public void setNormalized(boolean normalized) {
this.normalized = normalized; this.normalized = normalized;
} }
/** /**
* @return True if integer components should be converted to the range 0-1. * @return True if integer components should be converted to the range 0-1.
* @see VertexBuffer#setNormalized(boolean) * @see VertexBuffer#setNormalized(boolean)
*/ */
public boolean isNormalized(){ public boolean isNormalized() {
return normalized; return normalized;
} }
@ -585,9 +546,9 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* instanceSpan. * instanceSpan.
*/ */
public void setInstanced(boolean instanced) { public void setInstanced(boolean instanced) {
if( instanced && instanceSpan == 0 ) { if (instanced && instanceSpan == 0) {
instanceSpan = 1; instanceSpan = 1;
} else if( !instanced ) { } else if (!instanced) {
instanceSpan = 0; instanceSpan = 0;
} }
} }
@ -599,7 +560,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
public boolean isInstanced() { public boolean isInstanced() {
return instanceSpan > 0; return instanceSpan > 0;
} }
/** /**
* Sets how this vertex buffer matches with rendered instances * Sets how this vertex buffer matches with rendered instances
* where 0 means no instancing at all, ie: all elements are * where 0 means no instancing at all, ie: all elements are
@ -610,22 +571,22 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
public void setInstanceSpan(int i) { public void setInstanceSpan(int i) {
this.instanceSpan = i; this.instanceSpan = i;
} }
public int getInstanceSpan() { public int getInstanceSpan() {
return instanceSpan; return instanceSpan;
} }
/** /**
* @return The type of information that this buffer has. * @return The type of information that this buffer has.
*/ */
public Type getBufferType(){ public Type getBufferType() {
return bufType; return bufType;
} }
/** /**
* @return The {@link Format format}, or data type of the data. * @return The {@link Format format}, or data type of the data.
*/ */
public Format getFormat(){ public Format getFormat() {
return format; return format;
} }
@ -633,15 +594,15 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* @return The number of components of the given {@link Format format} per * @return The number of components of the given {@link Format format} per
* element. * element.
*/ */
public int getNumComponents(){ public int getNumComponents() {
return components; return components;
} }
/** /**
* @return The total number of data elements in the data buffer. * @return The total number of data elements in the data buffer.
*/ */
public int getNumElements(){ public int getNumElements() {
if( data == null ) { if (data == null) {
return 0; return 0;
} }
int elements = data.limit() / components; int elements = data.limit() / components;
@ -659,7 +620,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* but the instance data begins to repeat. * but the instance data begins to repeat.
*/ */
public int getBaseInstanceCount() { public int getBaseInstanceCount() {
if( instanceSpan == 0 ) { if (instanceSpan == 0) {
return 1; return 1;
} }
return getNumElements() * instanceSpan; return getNumElements() * instanceSpan;
@ -668,7 +629,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
/** /**
* Called to initialize the data in the <code>VertexBuffer</code>. Must only * Called to initialize the data in the <code>VertexBuffer</code>. Must only
* be called once. * be called once.
* *
* @param usage The usage for the data, or how often will the data * @param usage The usage for the data, or how often will the data
* be updated per frame. See the {@link Usage} enum. * be updated per frame. See the {@link Usage} enum.
* @param components The number of components per element. * @param components The number of components per element.
@ -677,7 +638,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* @param data A native buffer, the format of which matches the {@link Format} * @param data A native buffer, the format of which matches the {@link Format}
* argument. * argument.
*/ */
public void setupData(Usage usage, int components, Format format, Buffer data){ public void setupData(Usage usage, int components, Format format, Buffer data) {
if (id != -1) { if (id != -1) {
throw new UnsupportedOperationException("Data has already been sent. Cannot setupData again."); throw new UnsupportedOperationException("Data has already been sent. Cannot setupData again.");
} }
@ -695,7 +656,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
throw new IllegalArgumentException("components must be between 1 and 4"); throw new IllegalArgumentException("components must be between 1 and 4");
} }
} }
this.data = data; this.data = data;
this.components = components; this.components = components;
this.usage = usage; this.usage = usage;
@ -707,7 +668,8 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
/** /**
* Called to update the data in the buffer with new data. Can only * Called to update the data in the buffer with new data. Can only
* be called after {@link VertexBuffer#setupData(com.jme3.scene.VertexBuffer.Usage, int, com.jme3.scene.VertexBuffer.Format, java.nio.Buffer) } * be called after {@link VertexBuffer#setupData(
* com.jme3.scene.VertexBuffer.Usage, int, com.jme3.scene.VertexBuffer.Format, java.nio.Buffer) }
* has been called. Note that it is fine to call this method on the * has been called. Note that it is fine to call this method on the
* data already set, e.g. vb.updateData(vb.getData()), this will just * data already set, e.g. vb.updateData(vb.getData()), this will just
* set the proper update flag indicating the data should be sent to the GPU * set the proper update flag indicating the data should be sent to the GPU
@ -716,26 +678,26 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* It is allowed to specify a buffer with different capacity than the * It is allowed to specify a buffer with different capacity than the
* originally set buffer, HOWEVER, if you do so, you must * originally set buffer, HOWEVER, if you do so, you must
* call Mesh.updateCounts() otherwise bizarre errors can occur. * call Mesh.updateCounts() otherwise bizarre errors can occur.
* *
* @param data The data buffer to set * @param data The data buffer to set
*/ */
public void updateData(Buffer data){ public void updateData(Buffer data) {
if (id != -1){ if (id != -1) {
// request to update data is okay // request to update data is okay
} }
// Check if the data buffer is read-only which is a sign // Check if the data buffer is read-only which is a sign
// of a bug on the part of the caller // of a bug on the part of the caller
if (data != null && data.isReadOnly()) { if (data != null && data.isReadOnly()) {
throw new IllegalArgumentException( "VertexBuffer data cannot be read-only." ); throw new IllegalArgumentException("VertexBuffer data cannot be read-only.");
} }
// will force renderer to call glBufferData again // will force renderer to call glBufferData again
if (data != null && (this.data.getClass() != data.getClass() || data.limit() != lastLimit)){ if (data != null && (this.data.getClass() != data.getClass() || data.limit() != lastLimit)) {
dataSizeChanged = true; dataSizeChanged = true;
lastLimit = data.limit(); lastLimit = data.limit();
} }
this.data = data; this.data = data;
setUpdateNeeded(); setUpdateNeeded();
} }
@ -743,6 +705,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
/** /**
* Returns true if the data size of the VertexBuffer has changed. * Returns true if the data size of the VertexBuffer has changed.
* Internal use only. * Internal use only.
*
* @return true if the data size has changed * @return true if the data size has changed
*/ */
public boolean hasDataSizeChanged() { public boolean hasDataSizeChanged() {
@ -750,7 +713,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
} }
@Override @Override
public void clearUpdateNeeded(){ public void clearUpdateNeeded() {
super.clearUpdateNeeded(); super.clearUpdateNeeded();
dataSizeChanged = false; dataSizeChanged = false;
} }
@ -758,7 +721,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
/** /**
* Converts single floating-point data to {@link Format#Half half} floating-point data. * Converts single floating-point data to {@link Format#Half half} floating-point data.
*/ */
public void convertToHalf(){ public void convertToHalf() {
if (id != -1) { if (id != -1) {
throw new UnsupportedOperationException("Data has already been sent."); throw new UnsupportedOperationException("Data has already been sent.");
} }
@ -770,14 +733,14 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
int numElements = data.limit() / components; int numElements = data.limit() / components;
format = Format.Half; format = Format.Half;
this.componentsLength = components * format.getComponentSize(); this.componentsLength = components * format.getComponentSize();
ByteBuffer halfData = BufferUtils.createByteBuffer(componentsLength * numElements); ByteBuffer halfData = BufferUtils.createByteBuffer(componentsLength * numElements);
halfData.rewind(); halfData.rewind();
FloatBuffer floatData = (FloatBuffer) data; FloatBuffer floatData = (FloatBuffer) data;
floatData.rewind(); floatData.rewind();
for (int i = 0; i < floatData.limit(); i++){ for (int i = 0; i < floatData.limit(); i++) {
float f = floatData.get(i); float f = floatData.get(i);
short half = FastMath.convertFloatToHalf(f); short half = FastMath.convertFloatToHalf(f);
halfData.putShort(half); halfData.putShort(half);
@ -794,10 +757,10 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* *
* @param numElements The number of elements to reduce to. * @param numElements The number of elements to reduce to.
*/ */
public void compact(int numElements){ public void compact(int numElements) {
int total = components * numElements; int total = components * numElements;
data.clear(); data.clear();
switch (format){ switch (format) {
case Byte: case Byte:
case UnsignedByte: case UnsignedByte:
case Half: case Half:
@ -831,7 +794,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
data = fnewBuf; data = fnewBuf;
break; break;
default: default:
throw new UnsupportedOperationException("Unrecognized buffer format: "+format); throw new UnsupportedOperationException("Unrecognized buffer format: " + format);
} }
data.clear(); data.clear();
setUpdateNeeded(); setUpdateNeeded();
@ -842,69 +805,69 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* Modify a component inside an element. * Modify a component inside an element.
* The <code>val</code> parameter must be in the buffer's format: * The <code>val</code> parameter must be in the buffer's format:
* {@link Format}. * {@link Format}.
* *
* @param elementIndex The element index to modify * @param elementIndex The element index to modify
* @param componentIndex The component index to modify * @param componentIndex The component index to modify
* @param val The value to set, either byte, short, int or float depending * @param val The value to set, either byte, short, int or float depending
* on the {@link Format}. * on the {@link Format}.
*/ */
public void setElementComponent(int elementIndex, int componentIndex, Object val){ public void setElementComponent(int elementIndex, int componentIndex, Object val) {
int inPos = elementIndex * components; int inPos = elementIndex * components;
int elementPos = componentIndex; int elementPos = componentIndex;
if (format == Format.Half){ if (format == Format.Half) {
inPos *= 2; inPos *= 2;
elementPos *= 2; elementPos *= 2;
} }
data.clear(); data.clear();
switch (format){ switch (format) {
case Byte: case Byte:
case UnsignedByte: case UnsignedByte:
case Half: case Half:
ByteBuffer bin = (ByteBuffer) data; ByteBuffer bin = (ByteBuffer) data;
bin.put(inPos + elementPos, (Byte)val); bin.put(inPos + elementPos, (Byte) val);
break; break;
case Short: case Short:
case UnsignedShort: case UnsignedShort:
ShortBuffer sin = (ShortBuffer) data; ShortBuffer sin = (ShortBuffer) data;
sin.put(inPos + elementPos, (Short)val); sin.put(inPos + elementPos, (Short) val);
break; break;
case Int: case Int:
case UnsignedInt: case UnsignedInt:
IntBuffer iin = (IntBuffer) data; IntBuffer iin = (IntBuffer) data;
iin.put(inPos + elementPos, (Integer)val); iin.put(inPos + elementPos, (Integer) val);
break; break;
case Float: case Float:
FloatBuffer fin = (FloatBuffer) data; FloatBuffer fin = (FloatBuffer) data;
fin.put(inPos + elementPos, (Float)val); fin.put(inPos + elementPos, (Float) val);
break; break;
default: default:
throw new UnsupportedOperationException("Unrecognized buffer format: "+format); throw new UnsupportedOperationException("Unrecognized buffer format: " + format);
} }
} }
/** /**
* Get the component inside an element. * Get the component inside an element.
* *
* @param elementIndex The element index * @param elementIndex The element index
* @param componentIndex The component index * @param componentIndex The component index
* @return The component, as one of the primitive types, byte, short, * @return The component, as one of the primitive types, byte, short,
* int or float. * int or float.
*/ */
public Object getElementComponent(int elementIndex, int componentIndex){ public Object getElementComponent(int elementIndex, int componentIndex) {
int inPos = elementIndex * components; int inPos = elementIndex * components;
int elementPos = componentIndex; int elementPos = componentIndex;
if (format == Format.Half){ if (format == Format.Half) {
inPos *= 2; inPos *= 2;
elementPos *= 2; elementPos *= 2;
} }
Buffer srcData = getDataReadOnly(); Buffer srcData = getDataReadOnly();
switch (format){ switch (format) {
case Byte: case Byte:
case UnsignedByte: case UnsignedByte:
case Half: case Half:
@ -922,46 +885,46 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
FloatBuffer fin = (FloatBuffer) srcData; FloatBuffer fin = (FloatBuffer) srcData;
return fin.get(inPos + elementPos); return fin.get(inPos + elementPos);
default: default:
throw new UnsupportedOperationException("Unrecognized buffer format: "+format); throw new UnsupportedOperationException("Unrecognized buffer format: " + format);
} }
} }
/** /**
* Copies a single element of data from this <code>VertexBuffer</code> * Copies a single element of data from this <code>VertexBuffer</code>
* to the given output VertexBuffer. * to the given output VertexBuffer.
* *
* @param inIndex The input element index * @param inIndex The input element index
* @param outVb The buffer to copy to * @param outVb The buffer to copy to
* @param outIndex The output element index * @param outIndex The output element index
* *
* @throws IllegalArgumentException If the formats of the buffers do not * @throws IllegalArgumentException If the formats of the buffers do not
* match. * match.
*/ */
public void copyElement(int inIndex, VertexBuffer outVb, int outIndex){ public void copyElement(int inIndex, VertexBuffer outVb, int outIndex) {
copyElements(inIndex, outVb, outIndex, 1); copyElements(inIndex, outVb, outIndex, 1);
} }
/** /**
* Copies a sequence of elements of data from this <code>VertexBuffer</code> * Copies a sequence of elements of data from this <code>VertexBuffer</code>
* to the given output VertexBuffer. * to the given output VertexBuffer.
* *
* @param inIndex The input element index * @param inIndex The input element index
* @param outVb The buffer to copy to * @param outVb The buffer to copy to
* @param outIndex The output element index * @param outIndex The output element index
* @param len The number of elements to copy * @param len The number of elements to copy
* *
* @throws IllegalArgumentException If the formats of the buffers do not * @throws IllegalArgumentException If the formats of the buffers do not
* match. * match.
*/ */
public void copyElements(int inIndex, VertexBuffer outVb, int outIndex, int len){ public void copyElements(int inIndex, VertexBuffer outVb, int outIndex, int len) {
if (outVb.format != format || outVb.components != components) { if (outVb.format != format || outVb.components != components) {
throw new IllegalArgumentException("Buffer format mismatch. Cannot copy"); throw new IllegalArgumentException("Buffer format mismatch. Cannot copy");
} }
int inPos = inIndex * components; int inPos = inIndex * components;
int outPos = outIndex * components; int outPos = outIndex * components;
int elementSz = components; int elementSz = components;
if (format == Format.Half){ if (format == Format.Half) {
// because half is stored as bytebuf but its 2 bytes long // because half is stored as bytebuf but its 2 bytes long
inPos *= 2; inPos *= 2;
outPos *= 2; outPos *= 2;
@ -974,7 +937,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
Buffer srcData = getDataReadOnly(); Buffer srcData = getDataReadOnly();
outVb.data.clear(); outVb.data.clear();
switch (format){ switch (format) {
case Byte: case Byte:
case UnsignedByte: case UnsignedByte:
case Half: case Half:
@ -982,7 +945,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
ByteBuffer bout = (ByteBuffer) outVb.data; ByteBuffer bout = (ByteBuffer) outVb.data;
bin.position(inPos).limit(inPos + elementSz * len); bin.position(inPos).limit(inPos + elementSz * len);
bout.position(outPos).limit(outPos + elementSz * len); bout.position(outPos).limit(outPos + elementSz * len);
bout.put(bin); bout.put(bin);
break; break;
case Short: case Short:
case UnsignedShort: case UnsignedShort:
@ -1008,7 +971,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
fout.put(fin); fout.put(fin);
break; break;
default: default:
throw new UnsupportedOperationException("Unrecognized buffer format: "+format); throw new UnsupportedOperationException("Unrecognized buffer format: " + format);
} }
// Clear the output buffer to rewind it and reset its // Clear the output buffer to rewind it and reset its
@ -1022,14 +985,14 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
* {@link Format format} and would be able to contain the given number * {@link Format format} and would be able to contain the given number
* of elements with the given number of components in each element. * of elements with the given number of components in each element.
*/ */
public static Buffer createBuffer(Format format, int components, int numElements){ public static Buffer createBuffer(Format format, int components, int numElements) {
if (components < 1 || components > 4) { if (components < 1 || components > 4) {
throw new IllegalArgumentException("Num components must be between 1 and 4"); throw new IllegalArgumentException("Num components must be between 1 and 4");
} }
int total = numElements * components; int total = numElements * components;
switch (format){ switch (format) {
case Byte: case Byte:
case UnsignedByte: case UnsignedByte:
return BufferUtils.createByteBuffer(total); return BufferUtils.createByteBuffer(total);
@ -1046,17 +1009,17 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
case Double: case Double:
return BufferUtils.createDoubleBuffer(total); return BufferUtils.createDoubleBuffer(total);
default: default:
throw new UnsupportedOperationException("Unrecoginized buffer format: "+format); throw new UnsupportedOperationException("Unrecoginized buffer format: " + format);
} }
} }
/** /**
* Creates a deep clone of the {@link VertexBuffer}. * Creates a deep clone of the {@link VertexBuffer}.
* *
* @return Deep clone of this buffer * @return Deep clone of this buffer
*/ */
@Override @Override
public VertexBuffer clone(){ public VertexBuffer clone() {
// NOTE: Superclass GLObject automatically creates shallow clone // NOTE: Superclass GLObject automatically creates shallow clone
// e.g re-use ID. // e.g re-use ID.
VertexBuffer vb = (VertexBuffer) super.clone(); VertexBuffer vb = (VertexBuffer) super.clone();
@ -1069,22 +1032,22 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
// a purely read-only operation. // a purely read-only operation.
vb.updateData(BufferUtils.clone(getDataReadOnly())); vb.updateData(BufferUtils.clone(getDataReadOnly()));
} }
return vb; return vb;
} }
/** /**
* Creates a deep clone of this VertexBuffer but overrides the * Creates a deep clone of this VertexBuffer but overrides the
* {@link Type}. * {@link Type}.
* *
* @param overrideType The type of the cloned VertexBuffer * @param overrideType The type of the cloned VertexBuffer
* @return A deep clone of the buffer * @return A deep clone of the buffer
*/ */
public VertexBuffer clone(Type overrideType){ public VertexBuffer clone(Type overrideType) {
VertexBuffer vb = new VertexBuffer(overrideType); VertexBuffer vb = new VertexBuffer(overrideType);
vb.components = components; vb.components = components;
vb.componentsLength = componentsLength; vb.componentsLength = componentsLength;
// Make sure to pass a read-only buffer to clone so that // Make sure to pass a read-only buffer to clone so that
// the position information doesn't get clobbered by another // the position information doesn't get clobbered by another
// reading thread during cloning (and vice versa) since this is // reading thread during cloning (and vice versa) since this is
@ -1103,15 +1066,15 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
} }
@Override @Override
public String toString(){ public String toString() {
String dataTxt = null; String dataTxt = null;
if (data != null){ if (data != null) {
dataTxt = ", elements="+data.limit(); dataTxt = ", elements=" + data.limit();
} }
return getClass().getSimpleName() + "[fmt="+format.name() return getClass().getSimpleName() + "[fmt=" + format.name()
+", type="+bufType.name() + ", type=" + bufType.name()
+", usage="+usage.name() + ", usage=" + usage.name()
+dataTxt+"]"; + dataTxt + "]";
} }
@Override @Override
@ -1123,29 +1086,28 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
@Override @Override
public void deleteObject(Object rendererObject) { public void deleteObject(Object rendererObject) {
((Renderer)rendererObject).deleteBuffer(this); ((Renderer) rendererObject).deleteBuffer(this);
} }
@Override @Override
protected void deleteNativeBuffers() { protected void deleteNativeBuffers() {
if (data != null) { if (data != null) {
BufferUtils.destroyDirectBuffer(data); BufferUtils.destroyDirectBuffer(data);
} }
} }
@Override @Override
public NativeObject createDestructableClone(){ public NativeObject createDestructableClone() {
return new VertexBuffer(id); return new VertexBuffer(id);
} }
@Override @Override
public long getUniqueId() { public long getUniqueId() {
return ((long)OBJTYPE_VERTEXBUFFER << 32) | ((long)id); return ((long) OBJTYPE_VERTEXBUFFER << 32) | ((long) id);
} }
@Override @Override
public void write(JmeExporter ex) throws IOException { public void write(JmeExporter ex) throws IOException {
OutputCapsule oc = ex.getCapsule(this); OutputCapsule oc = ex.getCapsule(this);
oc.write(components, "components", 0); oc.write(components, "components", 0);
oc.write(usage, "usage", Usage.Dynamic); oc.write(usage, "usage", Usage.Dynamic);
@ -1158,7 +1120,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
String dataName = "data" + format.name(); String dataName = "data" + format.name();
Buffer roData = getDataReadOnly(); Buffer roData = getDataReadOnly();
switch (format){ switch (format) {
case Float: case Float:
oc.write((FloatBuffer) roData, dataName, null); oc.write((FloatBuffer) roData, dataName, null);
break; break;
@ -1176,7 +1138,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
oc.write((IntBuffer) roData, dataName, null); oc.write((IntBuffer) roData, dataName, null);
break; break;
default: default:
throw new IOException("Unsupported export buffer format: "+format); throw new IOException("Unsupported export buffer format: " + format);
} }
} }
@ -1194,7 +1156,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
componentsLength = components * format.getComponentSize(); componentsLength = components * format.getComponentSize();
String dataName = "data" + format.name(); String dataName = "data" + format.name();
switch (format){ switch (format) {
case Float: case Float:
data = ic.readFloatBuffer(dataName, null); data = ic.readFloatBuffer(dataName, null);
break; break;
@ -1212,8 +1174,7 @@ public class VertexBuffer extends NativeObject implements Savable, Cloneable {
data = ic.readIntBuffer(dataName, null); data = ic.readIntBuffer(dataName, null);
break; break;
default: default:
throw new IOException("Unsupported import buffer format: "+format); throw new IOException("Unsupported import buffer format: " + format);
} }
} }
} }

Loading…
Cancel
Save