|
|
@ -42,6 +42,7 @@ import com.jme3.math.Matrix4f; |
|
|
|
import com.jme3.math.Triangle; |
|
|
|
import com.jme3.math.Triangle; |
|
|
|
import com.jme3.math.Vector2f; |
|
|
|
import com.jme3.math.Vector2f; |
|
|
|
import com.jme3.math.Vector3f; |
|
|
|
import com.jme3.math.Vector3f; |
|
|
|
|
|
|
|
import com.jme3.renderer.Renderer; |
|
|
|
import com.jme3.scene.VertexBuffer.Format; |
|
|
|
import com.jme3.scene.VertexBuffer.Format; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Type; |
|
|
|
import com.jme3.scene.VertexBuffer.Usage; |
|
|
|
import com.jme3.scene.VertexBuffer.Usage; |
|
|
@ -49,6 +50,7 @@ import com.jme3.scene.mesh.*; |
|
|
|
import com.jme3.util.BufferUtils; |
|
|
|
import com.jme3.util.BufferUtils; |
|
|
|
import com.jme3.util.IntMap; |
|
|
|
import com.jme3.util.IntMap; |
|
|
|
import com.jme3.util.IntMap.Entry; |
|
|
|
import com.jme3.util.IntMap.Entry; |
|
|
|
|
|
|
|
import com.jme3.util.NativeObject; |
|
|
|
import com.jme3.util.SafeArrayList; |
|
|
|
import com.jme3.util.SafeArrayList; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.IOException; |
|
|
|
import java.nio.*; |
|
|
|
import java.nio.*; |
|
|
@ -71,7 +73,7 @@ import java.util.ArrayList; |
|
|
|
* |
|
|
|
* |
|
|
|
* @author Kirill Vainer |
|
|
|
* @author Kirill Vainer |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class Mesh implements Savable, Cloneable { |
|
|
|
public class Mesh extends NativeObject implements Savable { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* The mode of the Mesh specifies both the type of primitive represented |
|
|
|
* The mode of the Mesh specifies both the type of primitive represented |
|
|
@ -127,19 +129,14 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
TriangleFan(false), |
|
|
|
TriangleFan(false), |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
Reserved(false), |
|
|
|
* A combination of various triangle modes. It is best to avoid |
|
|
|
|
|
|
|
* using this mode as it may not be supported by all renderers. |
|
|
|
|
|
|
|
* The {@link Mesh#setModeStart(int[]) mode start points} and |
|
|
|
|
|
|
|
* {@link Mesh#setElementLengths(int[]) element lengths} must |
|
|
|
|
|
|
|
* be specified for this mode. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Hybrid(false), |
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Used for Tesselation only. Requires to set the number of vertices |
|
|
|
* Used for Tesselation only. Requires to set the number of vertices |
|
|
|
* for each patch (default is 3 for triangle tesselation) |
|
|
|
* for each patch (default is 3 for triangle tesselation) |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
Patch(true); |
|
|
|
Patch(true); |
|
|
|
|
|
|
|
|
|
|
|
private boolean listMode = false; |
|
|
|
private boolean listMode = false; |
|
|
|
|
|
|
|
|
|
|
|
private Mode(boolean listMode){ |
|
|
|
private Mode(boolean listMode){ |
|
|
@ -182,9 +179,6 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
private int patchVertexCount=3; //only used for tesselation
|
|
|
|
private int patchVertexCount=3; //only used for tesselation
|
|
|
|
private int maxNumWeights = -1; // only if using skeletal animation
|
|
|
|
private int maxNumWeights = -1; // only if using skeletal animation
|
|
|
|
|
|
|
|
|
|
|
|
private int[] elementLengths; |
|
|
|
|
|
|
|
private int[] modeStart; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Mode mode = Mode.Triangles; |
|
|
|
private Mode mode = Mode.Triangles; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -193,6 +187,10 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
public Mesh(){ |
|
|
|
public Mesh(){ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
protected Mesh(int id) { |
|
|
|
|
|
|
|
super(id); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Create a shallow clone of this Mesh. The {@link VertexBuffer vertex |
|
|
|
* Create a shallow clone of this Mesh. The {@link VertexBuffer vertex |
|
|
|
* buffers} are shared between this and the clone mesh, the rest |
|
|
|
* buffers} are shared between this and the clone mesh, the rest |
|
|
@ -202,23 +200,12 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public Mesh clone() { |
|
|
|
public Mesh clone() { |
|
|
|
try { |
|
|
|
|
|
|
|
Mesh clone = (Mesh) super.clone(); |
|
|
|
Mesh clone = (Mesh) super.clone(); |
|
|
|
clone.meshBound = meshBound.clone(); |
|
|
|
clone.meshBound = meshBound.clone(); |
|
|
|
clone.collisionTree = collisionTree != null ? collisionTree : null; |
|
|
|
clone.collisionTree = collisionTree != null ? collisionTree : null; |
|
|
|
clone.buffers = buffers.clone(); |
|
|
|
clone.buffers = buffers.clone(); |
|
|
|
clone.buffersList = new SafeArrayList<VertexBuffer>(VertexBuffer.class,buffersList); |
|
|
|
clone.buffersList = new SafeArrayList<VertexBuffer>(VertexBuffer.class,buffersList); |
|
|
|
clone.vertexArrayID = -1; |
|
|
|
|
|
|
|
if (elementLengths != null) { |
|
|
|
|
|
|
|
clone.elementLengths = elementLengths.clone(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (modeStart != null) { |
|
|
|
|
|
|
|
clone.modeStart = modeStart.clone(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return clone; |
|
|
|
return clone; |
|
|
|
} catch (CloneNotSupportedException ex) { |
|
|
|
|
|
|
|
throw new AssertionError(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -229,7 +216,6 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
* @return a deep clone of this mesh. |
|
|
|
* @return a deep clone of this mesh. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public Mesh deepClone(){ |
|
|
|
public Mesh deepClone(){ |
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
@ -245,7 +231,6 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
clone.buffersList.add(bufClone); |
|
|
|
clone.buffersList.add(bufClone); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
clone.vertexArrayID = -1; |
|
|
|
|
|
|
|
clone.vertCount = vertCount; |
|
|
|
clone.vertCount = vertCount; |
|
|
|
clone.elementCount = elementCount; |
|
|
|
clone.elementCount = elementCount; |
|
|
|
clone.instanceCount = instanceCount; |
|
|
|
clone.instanceCount = instanceCount; |
|
|
@ -254,12 +239,7 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
// if the bone weight/index buffers are modified
|
|
|
|
// if the bone weight/index buffers are modified
|
|
|
|
clone.maxNumWeights = maxNumWeights; |
|
|
|
clone.maxNumWeights = maxNumWeights; |
|
|
|
|
|
|
|
|
|
|
|
clone.elementLengths = elementLengths != null ? elementLengths.clone() : null; |
|
|
|
|
|
|
|
clone.modeStart = modeStart != null ? modeStart.clone() : null; |
|
|
|
|
|
|
|
return clone; |
|
|
|
return clone; |
|
|
|
}catch (CloneNotSupportedException ex){ |
|
|
|
|
|
|
|
throw new AssertionError(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
@ -475,40 +455,6 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
return lodLevels[lod]; |
|
|
|
return lodLevels[lod]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Get the element lengths for {@link Mode#Hybrid} mesh mode. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return element lengths |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int[] getElementLengths() { |
|
|
|
|
|
|
|
return elementLengths; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Set the element lengths for {@link Mode#Hybrid} mesh mode. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param elementLengths The element lengths to set |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void setElementLengths(int[] elementLengths) { |
|
|
|
|
|
|
|
this.elementLengths = elementLengths; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Set the mode start indices for {@link Mode#Hybrid} mesh mode. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return mode start indices |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int[] getModeStart() { |
|
|
|
|
|
|
|
return modeStart; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Get the mode start indices for {@link Mode#Hybrid} mesh mode. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void setModeStart(int[] modeStart) { |
|
|
|
|
|
|
|
this.modeStart = modeStart; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Returns the mesh mode |
|
|
|
* Returns the mesh mode |
|
|
|
* |
|
|
|
* |
|
|
@ -899,23 +845,6 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
indices[2] = ib.get(vertIndex+2); |
|
|
|
indices[2] = ib.get(vertIndex+2); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the mesh's VAO ID. Internal use only. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public int getId(){ |
|
|
|
|
|
|
|
return vertexArrayID; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Sets the mesh's VAO ID. Internal use only. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void setId(int id){ |
|
|
|
|
|
|
|
if (vertexArrayID != -1) |
|
|
|
|
|
|
|
throw new IllegalStateException("ID has already been set."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vertexArrayID = id; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Generates a collision tree for the mesh. |
|
|
|
* Generates a collision tree for the mesh. |
|
|
|
* Called automatically by {@link #collideWith(com.jme3.collision.Collidable, |
|
|
|
* Called automatically by {@link #collideWith(com.jme3.collision.Collidable, |
|
|
@ -1109,20 +1038,17 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
* @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) |
|
|
|
|
|
|
|
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); |
|
|
@ -1385,16 +1311,30 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
return patchVertexCount; |
|
|
|
return patchVertexCount; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void resetObject() { |
|
|
|
|
|
|
|
id = -1; |
|
|
|
|
|
|
|
setUpdateNeeded(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void deleteObject(Object rendererObject) { |
|
|
|
|
|
|
|
((Renderer)rendererObject).deleteMesh(this); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public NativeObject createDestructableClone() { |
|
|
|
|
|
|
|
return new Mesh(id); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public long getUniqueId() { |
|
|
|
|
|
|
|
return ((long)OBJTYPE_MESH << 32) | ((long)id); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void write(JmeExporter ex) throws IOException { |
|
|
|
public void write(JmeExporter ex) throws IOException { |
|
|
|
OutputCapsule out = ex.getCapsule(this); |
|
|
|
OutputCapsule out = ex.getCapsule(this); |
|
|
|
|
|
|
|
|
|
|
|
// HashMap<String, VertexBuffer> map = new HashMap<String, VertexBuffer>();
|
|
|
|
|
|
|
|
// for (Entry<VertexBuffer> buf : buffers){
|
|
|
|
|
|
|
|
// if (buf.getValue() != null)
|
|
|
|
|
|
|
|
// map.put(buf.getKey()+"a", buf.getValue());
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// out.writeStringSavableMap(map, "buffers", null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
out.write(meshBound, "modelBound", null); |
|
|
|
out.write(meshBound, "modelBound", null); |
|
|
|
out.write(vertCount, "vertCount", -1); |
|
|
|
out.write(vertCount, "vertCount", -1); |
|
|
|
out.write(elementCount, "elementCount", -1); |
|
|
|
out.write(elementCount, "elementCount", -1); |
|
|
@ -1402,8 +1342,6 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
out.write(maxNumWeights, "max_num_weights", -1); |
|
|
|
out.write(maxNumWeights, "max_num_weights", -1); |
|
|
|
out.write(mode, "mode", Mode.Triangles); |
|
|
|
out.write(mode, "mode", Mode.Triangles); |
|
|
|
out.write(collisionTree, "collisionTree", null); |
|
|
|
out.write(collisionTree, "collisionTree", null); |
|
|
|
out.write(elementLengths, "elementLengths", null); |
|
|
|
|
|
|
|
out.write(modeStart, "modeStart", null); |
|
|
|
|
|
|
|
out.write(pointSize, "pointSize", 1f); |
|
|
|
out.write(pointSize, "pointSize", 1f); |
|
|
|
|
|
|
|
|
|
|
|
//Removing HW skinning buffers to not save them
|
|
|
|
//Removing HW skinning buffers to not save them
|
|
|
@ -1439,21 +1377,16 @@ public class Mesh implements Savable, Cloneable { |
|
|
|
instanceCount = in.readInt("instanceCount", -1); |
|
|
|
instanceCount = in.readInt("instanceCount", -1); |
|
|
|
maxNumWeights = in.readInt("max_num_weights", -1); |
|
|
|
maxNumWeights = in.readInt("max_num_weights", -1); |
|
|
|
mode = in.readEnum("mode", Mode.class, Mode.Triangles); |
|
|
|
mode = in.readEnum("mode", Mode.class, Mode.Triangles); |
|
|
|
elementLengths = in.readIntArray("elementLengths", null); |
|
|
|
|
|
|
|
modeStart = in.readIntArray("modeStart", null); |
|
|
|
|
|
|
|
collisionTree = (BIHTree) in.readSavable("collisionTree", null); |
|
|
|
collisionTree = (BIHTree) in.readSavable("collisionTree", null); |
|
|
|
elementLengths = in.readIntArray("elementLengths", null); |
|
|
|
|
|
|
|
modeStart = in.readIntArray("modeStart", null); |
|
|
|
|
|
|
|
pointSize = in.readFloat("pointSize", 1f); |
|
|
|
pointSize = in.readFloat("pointSize", 1f); |
|
|
|
|
|
|
|
|
|
|
|
// 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); |
|
|
|