- WIP : Added new batching system : GeometryBatch, that allow batched geometries to be transformed git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8128 75d07b2b-3a1a-0410-a2c5-0572b91ccdca3.0
parent
aec40c2741
commit
cd474b2be9
@ -0,0 +1,135 @@ |
|||||||
|
/* |
||||||
|
* To change this template, choose Tools | Templates and open the template in |
||||||
|
* the editor. |
||||||
|
*/ |
||||||
|
package com.jme3.scene; |
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingVolume; |
||||||
|
import com.jme3.collision.Collidable; |
||||||
|
import com.jme3.collision.CollisionResults; |
||||||
|
import com.jme3.collision.UnsupportedCollisionException; |
||||||
|
import com.jme3.math.Matrix4f; |
||||||
|
import com.jme3.math.Transform; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
import java.util.Queue; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author Nehon |
||||||
|
*/ |
||||||
|
public class BatchedGeometry extends Spatial { |
||||||
|
|
||||||
|
private GeometryBatch batch; |
||||||
|
protected int startIndex; |
||||||
|
protected int vertexCount; |
||||||
|
protected int triangleCount; |
||||||
|
protected Transform prevLocalTransform = new Transform(); |
||||||
|
protected Matrix4f cachedOffsetMat = new Matrix4f(); |
||||||
|
protected Matrix4f tmpMat = new Matrix4f(); |
||||||
|
|
||||||
|
|
||||||
|
protected BatchedGeometry(GeometryBatch batch, Geometry geom) { |
||||||
|
this.batch = batch; |
||||||
|
vertexCount = geom.getVertexCount(); |
||||||
|
triangleCount = geom.getTriangleCount(); |
||||||
|
name = geom.getName(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Should only be called from updateGeometricState(). |
||||||
|
* In most cases should not be subclassed. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
protected void updateWorldTransforms() { |
||||||
|
if (batch == null) { |
||||||
|
worldTransform.set(localTransform); |
||||||
|
refreshFlags &= ~RF_TRANSFORM; |
||||||
|
} else { |
||||||
|
// check if transform for parent is updated
|
||||||
|
assert ((batch.refreshFlags & RF_TRANSFORM) == 0); |
||||||
|
worldTransform.set(localTransform); |
||||||
|
worldTransform.combineWithParent(batch.worldTransform); |
||||||
|
computeOffsetTransform(); |
||||||
|
batch.updateSubBatch(this); |
||||||
|
prevLocalTransform.set(localTransform); |
||||||
|
refreshFlags &= ~RF_TRANSFORM; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Node getParent() { |
||||||
|
return batch.getParent(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Recomputes the matrix returned by {@link Geometry#getWorldMatrix() }. |
||||||
|
* This will require a localized transform update for this geometry. |
||||||
|
*/ |
||||||
|
public void computeOffsetTransform() { |
||||||
|
|
||||||
|
|
||||||
|
// Compute the cached world matrix
|
||||||
|
cachedOffsetMat.loadIdentity(); |
||||||
|
cachedOffsetMat.setRotationQuaternion(prevLocalTransform.getRotation()); |
||||||
|
cachedOffsetMat.setTranslation(prevLocalTransform.getTranslation()); |
||||||
|
|
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Matrix4f scaleMat = vars.tempMat4; |
||||||
|
scaleMat.loadIdentity(); |
||||||
|
scaleMat.scale(prevLocalTransform.getScale()); |
||||||
|
cachedOffsetMat.multLocal(scaleMat); |
||||||
|
cachedOffsetMat.invertLocal(); |
||||||
|
|
||||||
|
tmpMat.loadIdentity(); |
||||||
|
tmpMat.setRotationQuaternion(localTransform.getRotation()); |
||||||
|
tmpMat.setTranslation(localTransform.getTranslation()); |
||||||
|
scaleMat.loadIdentity(); |
||||||
|
scaleMat.scale(localTransform.getScale()); |
||||||
|
tmpMat.multLocal(scaleMat); |
||||||
|
|
||||||
|
tmpMat.mult(cachedOffsetMat,cachedOffsetMat); |
||||||
|
|
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateModelBound() { |
||||||
|
throw new UnsupportedOperationException("Not supported."); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setModelBound(BoundingVolume modelBound) { |
||||||
|
throw new UnsupportedOperationException("Not supported."); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getVertexCount() { |
||||||
|
return vertexCount; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getTriangleCount() { |
||||||
|
return triangleCount; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Spatial deepClone() { |
||||||
|
throw new UnsupportedOperationException("Not supported."); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void depthFirstTraversal(SceneGraphVisitor visitor) { |
||||||
|
throw new UnsupportedOperationException("Not supported."); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void breadthFirstTraversal(SceneGraphVisitor visitor, Queue<Spatial> queue) { |
||||||
|
throw new UnsupportedOperationException("Not supported."); |
||||||
|
} |
||||||
|
|
||||||
|
public int collideWith(Collidable other, CollisionResults results) throws UnsupportedCollisionException { |
||||||
|
throw new UnsupportedOperationException("Not supported yet."); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,398 @@ |
|||||||
|
/* |
||||||
|
* To change this template, choose Tools | Templates and open the template in |
||||||
|
* the editor. |
||||||
|
*/ |
||||||
|
package com.jme3.scene; |
||||||
|
|
||||||
|
import com.jme3.math.Matrix4f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.scene.control.AbstractControl; |
||||||
|
import com.jme3.scene.mesh.IndexBuffer; |
||||||
|
import com.jme3.util.IntMap.Entry; |
||||||
|
import com.jme3.util.SafeArrayList; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
import java.nio.Buffer; |
||||||
|
import java.nio.FloatBuffer; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author Nehon |
||||||
|
*/ |
||||||
|
public class GeometryBatch extends Geometry { |
||||||
|
|
||||||
|
private SafeArrayList<BatchedGeometry> children = new SafeArrayList<BatchedGeometry>(BatchedGeometry.class); |
||||||
|
private List<Geometry> tmpList = new ArrayList<Geometry>(); |
||||||
|
private boolean needMeshUpdate = false; |
||||||
|
|
||||||
|
public GeometryBatch() { |
||||||
|
this("GeometryBatch"); |
||||||
|
} |
||||||
|
|
||||||
|
public GeometryBatch(String name) { |
||||||
|
this.name = name; |
||||||
|
addControl(new ControlUpdate()); |
||||||
|
} |
||||||
|
|
||||||
|
public BatchedGeometry batch(Geometry geom) { |
||||||
|
|
||||||
|
tmpList.clear(); |
||||||
|
Mesh m = new Mesh(); |
||||||
|
if (mesh != null) { |
||||||
|
|
||||||
|
tmpList.add(this); |
||||||
|
} |
||||||
|
tmpList.add(geom); |
||||||
|
List<BatchedGeometry> l = mergeGeometries(m, tmpList); |
||||||
|
mesh = m; |
||||||
|
mesh.updateCounts(); |
||||||
|
mesh.updateBound(); |
||||||
|
return l.get(0); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public List<BatchedGeometry> batch(List<Geometry> geom) { |
||||||
|
if (mesh != null) { |
||||||
|
geom.add(0, this); |
||||||
|
} |
||||||
|
|
||||||
|
Mesh m = new Mesh(); |
||||||
|
List<BatchedGeometry> l = mergeGeometries(m, geom); |
||||||
|
mesh = m; |
||||||
|
mesh.updateCounts(); |
||||||
|
mesh.updateBound(); |
||||||
|
return l; |
||||||
|
} |
||||||
|
|
||||||
|
public List<BatchedGeometry> batch(Geometry... geoms) { |
||||||
|
tmpList.clear(); |
||||||
|
Mesh m = new Mesh(); |
||||||
|
if (mesh != null) { |
||||||
|
tmpList.add(this); |
||||||
|
|
||||||
|
} |
||||||
|
for (Geometry geometry : geoms) { |
||||||
|
tmpList.add(geometry); |
||||||
|
} |
||||||
|
|
||||||
|
List<BatchedGeometry> l = mergeGeometries(m, tmpList); |
||||||
|
mesh = m; |
||||||
|
mesh.updateCounts(); |
||||||
|
mesh.updateBound(); |
||||||
|
return l; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void updateGeometricState() { |
||||||
|
if ((refreshFlags & RF_LIGHTLIST) != 0) { |
||||||
|
updateWorldLightList(); |
||||||
|
} |
||||||
|
|
||||||
|
if ((refreshFlags & RF_TRANSFORM) != 0) { |
||||||
|
// combine with parent transforms- same for all spatial
|
||||||
|
// subclasses.
|
||||||
|
updateWorldTransforms(); |
||||||
|
} |
||||||
|
|
||||||
|
if (!children.isEmpty()) { |
||||||
|
// the important part- make sure child geometric state is refreshed
|
||||||
|
// first before updating own world bound. This saves
|
||||||
|
// a round-trip later on.
|
||||||
|
// NOTE 9/19/09
|
||||||
|
// Although it does save a round trip,
|
||||||
|
for (Spatial child : children.getArray()) { |
||||||
|
child.updateGeometricState(); |
||||||
|
} |
||||||
|
if (needMeshUpdate) { |
||||||
|
updateModelBound(); |
||||||
|
needMeshUpdate = false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if ((refreshFlags & RF_BOUND) != 0) { |
||||||
|
updateWorldBound(); |
||||||
|
} |
||||||
|
|
||||||
|
assert refreshFlags == 0; |
||||||
|
} |
||||||
|
|
||||||
|
protected void updateSubBatch(BatchedGeometry bg) { |
||||||
|
FloatBuffer buf = (FloatBuffer) mesh.getBuffer(VertexBuffer.Type.Position).getData(); |
||||||
|
doTransformVerts(buf, 0, bg.startIndex, bg.startIndex + bg.getVertexCount(), buf, bg.cachedOffsetMat); |
||||||
|
mesh.getBuffer(VertexBuffer.Type.Position).updateData(buf); |
||||||
|
|
||||||
|
buf = (FloatBuffer) mesh.getBuffer(VertexBuffer.Type.Normal).getData(); |
||||||
|
doTransformNorm(buf, 0, bg.startIndex, bg.startIndex + bg.getVertexCount(), buf, bg.cachedOffsetMat); |
||||||
|
mesh.getBuffer(VertexBuffer.Type.Normal).updateData(buf); |
||||||
|
|
||||||
|
|
||||||
|
if (mesh.getBuffer(VertexBuffer.Type.Tangent) != null) { |
||||||
|
buf = (FloatBuffer) mesh.getBuffer(VertexBuffer.Type.Tangent).getData(); |
||||||
|
doTransformNorm(buf, 0, bg.startIndex, bg.startIndex + bg.getVertexCount(), buf, bg.cachedOffsetMat); |
||||||
|
mesh.getBuffer(VertexBuffer.Type.Tangent).updateData(buf); |
||||||
|
} |
||||||
|
|
||||||
|
needMeshUpdate = true; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* <code>getChild</code> returns the first child found with exactly the |
||||||
|
* given name (case sensitive.) |
||||||
|
* |
||||||
|
* @param name |
||||||
|
* the name of the child to retrieve. If null, we'll return null. |
||||||
|
* @return the child if found, or null. |
||||||
|
*/ |
||||||
|
public Spatial getChild(String name) { |
||||||
|
if (name == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
for (Spatial child : children.getArray()) { |
||||||
|
if (name.equals(child.getName())) { |
||||||
|
return child; |
||||||
|
} else if (child instanceof Node) { |
||||||
|
Spatial out = ((Node) child).getChild(name); |
||||||
|
if (out != null) { |
||||||
|
return out; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Merges all geometries in the collection into |
||||||
|
* the output mesh. Does not take into account materials. |
||||||
|
* |
||||||
|
* @param geometries |
||||||
|
* @param outMesh |
||||||
|
*/ |
||||||
|
private List<BatchedGeometry> mergeGeometries(Mesh outMesh, List<Geometry> geometries) { |
||||||
|
int[] compsForBuf = new int[VertexBuffer.Type.values().length]; |
||||||
|
VertexBuffer.Format[] formatForBuf = new VertexBuffer.Format[compsForBuf.length]; |
||||||
|
List<BatchedGeometry> batchedGeoms = new ArrayList<BatchedGeometry>(); |
||||||
|
|
||||||
|
int totalVerts = 0; |
||||||
|
int totalTris = 0; |
||||||
|
int totalLodLevels = 0; |
||||||
|
|
||||||
|
Mesh.Mode mode = null; |
||||||
|
for (Geometry geom : geometries) { |
||||||
|
totalVerts += geom.getVertexCount(); |
||||||
|
totalTris += geom.getTriangleCount(); |
||||||
|
totalLodLevels = Math.min(totalLodLevels, geom.getMesh().getNumLodLevels()); |
||||||
|
|
||||||
|
Mesh.Mode listMode; |
||||||
|
int components; |
||||||
|
switch (geom.getMesh().getMode()) { |
||||||
|
case Points: |
||||||
|
listMode = Mesh.Mode.Points; |
||||||
|
components = 1; |
||||||
|
break; |
||||||
|
case LineLoop: |
||||||
|
case LineStrip: |
||||||
|
case Lines: |
||||||
|
listMode = Mesh.Mode.Lines; |
||||||
|
components = 2; |
||||||
|
break; |
||||||
|
case TriangleFan: |
||||||
|
case TriangleStrip: |
||||||
|
case Triangles: |
||||||
|
listMode = Mesh.Mode.Triangles; |
||||||
|
components = 3; |
||||||
|
break; |
||||||
|
default: |
||||||
|
throw new UnsupportedOperationException(); |
||||||
|
} |
||||||
|
|
||||||
|
for (Entry<VertexBuffer> entry : geom.getMesh().getBuffers()) { |
||||||
|
compsForBuf[entry.getKey()] = entry.getValue().getNumComponents(); |
||||||
|
formatForBuf[entry.getKey()] = entry.getValue().getFormat(); |
||||||
|
} |
||||||
|
|
||||||
|
if (mode != null && mode != listMode) { |
||||||
|
throw new UnsupportedOperationException("Cannot combine different" |
||||||
|
+ " primitive types: " + mode + " != " + listMode); |
||||||
|
} |
||||||
|
mode = listMode; |
||||||
|
compsForBuf[VertexBuffer.Type.Index.ordinal()] = components; |
||||||
|
} |
||||||
|
|
||||||
|
outMesh.setMode(mode); |
||||||
|
if (totalVerts >= 65536) { |
||||||
|
// make sure we create an UnsignedInt buffer so
|
||||||
|
// we can fit all of the meshes
|
||||||
|
formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedInt; |
||||||
|
} else { |
||||||
|
formatForBuf[VertexBuffer.Type.Index.ordinal()] = VertexBuffer.Format.UnsignedShort; |
||||||
|
} |
||||||
|
|
||||||
|
// generate output buffers based on retrieved info
|
||||||
|
for (int i = 0; i < compsForBuf.length; i++) { |
||||||
|
if (compsForBuf[i] == 0) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
Buffer data; |
||||||
|
if (i == VertexBuffer.Type.Index.ordinal()) { |
||||||
|
data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalTris); |
||||||
|
} else { |
||||||
|
data = VertexBuffer.createBuffer(formatForBuf[i], compsForBuf[i], totalVerts); |
||||||
|
} |
||||||
|
|
||||||
|
VertexBuffer vb = new VertexBuffer(VertexBuffer.Type.values()[i]); |
||||||
|
vb.setupData(VertexBuffer.Usage.Static, compsForBuf[i], formatForBuf[i], data); |
||||||
|
outMesh.setBuffer(vb); |
||||||
|
} |
||||||
|
|
||||||
|
int globalVertIndex = 0; |
||||||
|
int globalTriIndex = 0; |
||||||
|
|
||||||
|
for (Geometry geom : geometries) { |
||||||
|
if (geom != this) { |
||||||
|
BatchedGeometry bg = new BatchedGeometry(this, geom); |
||||||
|
bg.startIndex = globalVertIndex; |
||||||
|
bg.setLocalTransform(geom.getLocalTransform()); |
||||||
|
children.add(bg); |
||||||
|
batchedGeoms.add(bg); |
||||||
|
} |
||||||
|
Mesh inMesh = geom.getMesh(); |
||||||
|
|
||||||
|
int geomVertCount = inMesh.getVertexCount(); |
||||||
|
int geomTriCount = inMesh.getTriangleCount(); |
||||||
|
|
||||||
|
for (int bufType = 0; bufType < compsForBuf.length; bufType++) { |
||||||
|
VertexBuffer inBuf = inMesh.getBuffer(VertexBuffer.Type.values()[bufType]); |
||||||
|
VertexBuffer outBuf = outMesh.getBuffer(VertexBuffer.Type.values()[bufType]); |
||||||
|
|
||||||
|
if (outBuf == null) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (VertexBuffer.Type.Index.ordinal() == bufType) { |
||||||
|
int components = compsForBuf[bufType]; |
||||||
|
|
||||||
|
IndexBuffer inIdx = inMesh.getIndicesAsList(); |
||||||
|
IndexBuffer outIdx = outMesh.getIndexBuffer(); |
||||||
|
|
||||||
|
for (int tri = 0; tri < geomTriCount; tri++) { |
||||||
|
for (int comp = 0; comp < components; comp++) { |
||||||
|
int idx = inIdx.get(tri * components + comp) + globalVertIndex; |
||||||
|
outIdx.put((globalTriIndex + tri) * components + comp, idx); |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (VertexBuffer.Type.Position.ordinal() == bufType) { |
||||||
|
FloatBuffer inPos = (FloatBuffer) inBuf.getData(); |
||||||
|
FloatBuffer outPos = (FloatBuffer) outBuf.getData(); |
||||||
|
doCopyBuffer(inPos, globalVertIndex, outPos); |
||||||
|
} else if (VertexBuffer.Type.Normal.ordinal() == bufType || VertexBuffer.Type.Tangent.ordinal() == bufType) { |
||||||
|
FloatBuffer inPos = (FloatBuffer) inBuf.getData(); |
||||||
|
FloatBuffer outPos = (FloatBuffer) outBuf.getData(); |
||||||
|
doCopyBuffer(inPos, globalVertIndex, outPos); |
||||||
|
} else { |
||||||
|
for (int vert = 0; vert < geomVertCount; vert++) { |
||||||
|
int curGlobalVertIndex = globalVertIndex + vert; |
||||||
|
inBuf.copyElement(vert, outBuf, curGlobalVertIndex); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
globalVertIndex += geomVertCount; |
||||||
|
globalTriIndex += geomTriCount; |
||||||
|
} |
||||||
|
return batchedGeoms; |
||||||
|
} |
||||||
|
|
||||||
|
private void doTransformVerts(FloatBuffer inBuf, int offset, int start, int end, FloatBuffer outBuf, Matrix4f transform) { |
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Vector3f pos = vars.vect1; |
||||||
|
|
||||||
|
// offset is given in element units
|
||||||
|
// convert to be in component units
|
||||||
|
offset *= 3; |
||||||
|
|
||||||
|
for (int i = start; i < end; i++) { |
||||||
|
pos.x = inBuf.get(i * 3 + 0); |
||||||
|
pos.y = inBuf.get(i * 3 + 1); |
||||||
|
pos.z = inBuf.get(i * 3 + 2); |
||||||
|
|
||||||
|
transform.mult(pos, pos); |
||||||
|
|
||||||
|
outBuf.put(offset + i * 3 + 0, pos.x); |
||||||
|
outBuf.put(offset + i * 3 + 1, pos.y); |
||||||
|
outBuf.put(offset + i * 3 + 2, pos.z); |
||||||
|
} |
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
private void doTransformNorm(FloatBuffer inBuf, int offset, int start, int end, FloatBuffer outBuf, Matrix4f transform) { |
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Vector3f pos = vars.vect1; |
||||||
|
|
||||||
|
// offset is given in element units
|
||||||
|
// convert to be in component units
|
||||||
|
offset *= 3; |
||||||
|
|
||||||
|
for (int i = start; i < end; i++) { |
||||||
|
pos.x = inBuf.get(i * 3 + 0); |
||||||
|
pos.y = inBuf.get(i * 3 + 1); |
||||||
|
pos.z = inBuf.get(i * 3 + 2); |
||||||
|
|
||||||
|
transform.multNormal(pos, pos); |
||||||
|
|
||||||
|
outBuf.put(offset + i * 3 + 0, pos.x); |
||||||
|
outBuf.put(offset + i * 3 + 1, pos.y); |
||||||
|
outBuf.put(offset + i * 3 + 2, pos.z); |
||||||
|
} |
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
private void doCopyBuffer(FloatBuffer inBuf, int offset, FloatBuffer outBuf) { |
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
Vector3f pos = vars.vect1; |
||||||
|
|
||||||
|
// offset is given in element units
|
||||||
|
// convert to be in component units
|
||||||
|
offset *= 3; |
||||||
|
|
||||||
|
for (int i = 0; i < inBuf.capacity() / 3; i++) { |
||||||
|
pos.x = inBuf.get(i * 3 + 0); |
||||||
|
pos.y = inBuf.get(i * 3 + 1); |
||||||
|
pos.z = inBuf.get(i * 3 + 2); |
||||||
|
|
||||||
|
outBuf.put(offset + i * 3 + 0, pos.x); |
||||||
|
outBuf.put(offset + i * 3 + 1, pos.y); |
||||||
|
outBuf.put(offset + i * 3 + 2, pos.z); |
||||||
|
} |
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
public class ControlUpdate extends AbstractControl { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void controlUpdate(float tpf) { |
||||||
|
for (BatchedGeometry batchedGeometry : children) { |
||||||
|
for (int i = 0; i < batchedGeometry.getNumControls(); i++) { |
||||||
|
batchedGeometry.getControl(i).update(tpf); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void controlRender(RenderManager rm, ViewPort vp) { |
||||||
|
for (BatchedGeometry batchedGeometry : children) { |
||||||
|
for (int i = 0; i < batchedGeometry.getNumControls(); i++) { |
||||||
|
batchedGeometry.getControl(i).render(rm, vp); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public com.jme3.scene.control.Control cloneForSpatial(Spatial spatial) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,246 @@ |
|||||||
|
/* |
||||||
|
* To change this template, choose Tools | Templates and open the template in |
||||||
|
* the editor. |
||||||
|
*/ |
||||||
|
package jme3test.batching; |
||||||
|
|
||||||
|
/* |
||||||
|
* Copyright (c) 2009-2010 jMonkeyEngine All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are met: |
||||||
|
* * * Redistributions of source code must retain the above copyright notice, |
||||||
|
* this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||||||
|
* POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
import com.jme3.bullet.BulletAppState; |
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.asset.TextureKey; |
||||||
|
import com.jme3.bullet.PhysicsSpace; |
||||||
|
import com.jme3.bullet.collision.shapes.BoxCollisionShape; |
||||||
|
import com.jme3.bullet.collision.shapes.SphereCollisionShape; |
||||||
|
import com.jme3.bullet.control.RigidBodyControl; |
||||||
|
import com.jme3.font.BitmapText; |
||||||
|
import com.jme3.input.MouseInput; |
||||||
|
import com.jme3.input.controls.ActionListener; |
||||||
|
import com.jme3.input.controls.MouseButtonTrigger; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.Vector2f; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.queue.RenderQueue.ShadowMode; |
||||||
|
import com.jme3.scene.BatchedGeometry; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.GeometryBatch; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.scene.shape.Sphere; |
||||||
|
import com.jme3.scene.shape.Sphere.TextureMode; |
||||||
|
import com.jme3.shadow.PssmShadowRenderer; |
||||||
|
import com.jme3.shadow.PssmShadowRenderer.CompareMode; |
||||||
|
import com.jme3.shadow.PssmShadowRenderer.FilterMode; |
||||||
|
import com.jme3.texture.Texture; |
||||||
|
import com.jme3.texture.Texture.WrapMode; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import jme3test.bullet.BombControl; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author double1984 (tower mod by atom) |
||||||
|
*/ |
||||||
|
public class TestBatchedTower extends SimpleApplication { |
||||||
|
|
||||||
|
int bricksPerLayer = 8; |
||||||
|
int brickLayers = 30; |
||||||
|
static float brickWidth = .75f, brickHeight = .25f, brickDepth = .25f; |
||||||
|
float radius = 3f; |
||||||
|
float angle = 0; |
||||||
|
List<Geometry> geoms = new ArrayList<Geometry>(); |
||||||
|
Material mat; |
||||||
|
Material mat2; |
||||||
|
Material mat3; |
||||||
|
PssmShadowRenderer bsr; |
||||||
|
private Sphere bullet; |
||||||
|
private Box brick; |
||||||
|
private SphereCollisionShape bulletCollisionShape; |
||||||
|
private GeometryBatch batch = new GeometryBatch(); |
||||||
|
private BulletAppState bulletAppState; |
||||||
|
|
||||||
|
public static void main(String args[]) { |
||||||
|
TestBatchedTower f = new TestBatchedTower(); |
||||||
|
f.start(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
bulletAppState = new BulletAppState(); |
||||||
|
bulletAppState.setThreadingType(BulletAppState.ThreadingType.PARALLEL); |
||||||
|
// bulletAppState.setEnabled(false);
|
||||||
|
stateManager.attach(bulletAppState); |
||||||
|
bullet = new Sphere(32, 32, 0.4f, true, false); |
||||||
|
bullet.setTextureMode(TextureMode.Projected); |
||||||
|
bulletCollisionShape = new SphereCollisionShape(0.4f); |
||||||
|
|
||||||
|
brick = new Box(Vector3f.ZERO, brickWidth, brickHeight, brickDepth); |
||||||
|
brick.scaleTextureCoordinates(new Vector2f(1f, .5f)); |
||||||
|
// bulletAppState.getPhysicsSpace().enableDebug(assetManager);
|
||||||
|
initMaterial(); |
||||||
|
initTower(); |
||||||
|
initFloor(); |
||||||
|
initCrossHairs(); |
||||||
|
|
||||||
|
List<BatchedGeometry> bgs = batch.batch(geoms); |
||||||
|
for (BatchedGeometry bg : bgs) { |
||||||
|
RigidBodyControl rb = new RigidBodyControl(1.5f); |
||||||
|
rb.setCollisionShape(new BoxCollisionShape(new Vector3f(brick.getXExtent(), brick.getYExtent(), brick.getZExtent()))); |
||||||
|
rb.setFriction(1.6f); |
||||||
|
bg.addControl(rb); |
||||||
|
this.getPhysicsSpace().add(bg); |
||||||
|
} |
||||||
|
|
||||||
|
batch.setMaterial(mat); |
||||||
|
batch.setShadowMode(ShadowMode.CastAndReceive); |
||||||
|
|
||||||
|
this.cam.setLocation(new Vector3f(0, 25f, 8f)); |
||||||
|
cam.lookAt(Vector3f.ZERO, new Vector3f(0, 1, 0)); |
||||||
|
cam.setFrustumFar(80); |
||||||
|
inputManager.addMapping("shoot", new MouseButtonTrigger(MouseInput.BUTTON_LEFT)); |
||||||
|
inputManager.addListener(actionListener, "shoot"); |
||||||
|
rootNode.setShadowMode(ShadowMode.Off); |
||||||
|
bsr = new PssmShadowRenderer(assetManager, 1024, 2); |
||||||
|
bsr.setDirection(new Vector3f(-1, -1, -1).normalizeLocal()); |
||||||
|
bsr.setLambda(0.50f); |
||||||
|
bsr.setShadowIntensity(0.6f); |
||||||
|
bsr.setCompareMode(CompareMode.Hardware); |
||||||
|
bsr.setFilterMode(FilterMode.PCF4); |
||||||
|
viewPort.addProcessor(bsr); |
||||||
|
flyCam.setMoveSpeed(50); |
||||||
|
rootNode.attachChild(batch); |
||||||
|
} |
||||||
|
|
||||||
|
private PhysicsSpace getPhysicsSpace() { |
||||||
|
return bulletAppState.getPhysicsSpace(); |
||||||
|
} |
||||||
|
private ActionListener actionListener = new ActionListener() { |
||||||
|
|
||||||
|
public void onAction(String name, boolean keyPressed, float tpf) { |
||||||
|
if (name.equals("shoot") && !keyPressed) { |
||||||
|
Geometry bulletg = new Geometry("bullet", bullet); |
||||||
|
bulletg.setMaterial(mat2); |
||||||
|
bulletg.setShadowMode(ShadowMode.CastAndReceive); |
||||||
|
bulletg.setLocalTranslation(cam.getLocation()); |
||||||
|
RigidBodyControl bulletNode = new BombControl(assetManager, bulletCollisionShape, 1); |
||||||
|
// RigidBodyControl bulletNode = new RigidBodyControl(bulletCollisionShape, 1);
|
||||||
|
bulletNode.setLinearVelocity(cam.getDirection().mult(25)); |
||||||
|
bulletg.addControl(bulletNode); |
||||||
|
rootNode.attachChild(bulletg); |
||||||
|
getPhysicsSpace().add(bulletNode); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public void initTower() { |
||||||
|
double tempX = 0; |
||||||
|
double tempY = 0; |
||||||
|
double tempZ = 0; |
||||||
|
angle = 0f; |
||||||
|
for (int i = 0; i < brickLayers; i++) { |
||||||
|
// Increment rows
|
||||||
|
if (i != 0) { |
||||||
|
tempY += brickHeight * 2; |
||||||
|
} else { |
||||||
|
tempY = brickHeight; |
||||||
|
} |
||||||
|
// Alternate brick seams
|
||||||
|
angle = 360.0f / bricksPerLayer * i / 2f; |
||||||
|
for (int j = 0; j < bricksPerLayer; j++) { |
||||||
|
tempZ = Math.cos(Math.toRadians(angle)) * radius; |
||||||
|
tempX = Math.sin(Math.toRadians(angle)) * radius; |
||||||
|
System.out.println("x=" + ((float) (tempX)) + " y=" + ((float) (tempY)) + " z=" + (float) (tempZ)); |
||||||
|
Vector3f vt = new Vector3f((float) (tempX), (float) (tempY), (float) (tempZ)); |
||||||
|
// Add crenelation
|
||||||
|
if (i == brickLayers - 1) { |
||||||
|
if (j % 2 == 0) { |
||||||
|
addBrick(vt); |
||||||
|
} |
||||||
|
} // Create main tower
|
||||||
|
else { |
||||||
|
addBrick(vt); |
||||||
|
} |
||||||
|
angle += 360.0 / bricksPerLayer; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public void initFloor() { |
||||||
|
Box floorBox = new Box(Vector3f.ZERO, 10f, 0.1f, 5f); |
||||||
|
floorBox.scaleTextureCoordinates(new Vector2f(3, 6)); |
||||||
|
|
||||||
|
Geometry floor = new Geometry("floor", floorBox); |
||||||
|
floor.setMaterial(mat3); |
||||||
|
floor.setShadowMode(ShadowMode.Receive); |
||||||
|
floor.setLocalTranslation(0, 0, 0); |
||||||
|
floor.addControl(new RigidBodyControl(0)); |
||||||
|
this.rootNode.attachChild(floor); |
||||||
|
this.getPhysicsSpace().add(floor); |
||||||
|
} |
||||||
|
|
||||||
|
public void initMaterial() { |
||||||
|
mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
TextureKey key = new TextureKey("Textures/Terrain/BrickWall/BrickWall.jpg"); |
||||||
|
key.setGenerateMips(true); |
||||||
|
Texture tex = assetManager.loadTexture(key); |
||||||
|
mat.setTexture("ColorMap", tex); |
||||||
|
|
||||||
|
mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
TextureKey key2 = new TextureKey("Textures/Terrain/Rock/Rock.PNG"); |
||||||
|
key2.setGenerateMips(true); |
||||||
|
Texture tex2 = assetManager.loadTexture(key2); |
||||||
|
mat2.setTexture("ColorMap", tex2); |
||||||
|
|
||||||
|
mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
TextureKey key3 = new TextureKey("Textures/Terrain/Pond/Pond.jpg"); |
||||||
|
key3.setGenerateMips(true); |
||||||
|
Texture tex3 = assetManager.loadTexture(key3); |
||||||
|
tex3.setWrap(WrapMode.Repeat); |
||||||
|
mat3.setTexture("ColorMap", tex3); |
||||||
|
} |
||||||
|
|
||||||
|
public void addBrick(Vector3f ori) { |
||||||
|
Geometry reBoxg = new Geometry("brick", brick); |
||||||
|
reBoxg.setLocalTranslation(ori); |
||||||
|
reBoxg.rotate(0f, (float) Math.toRadians(angle), 0f); |
||||||
|
geoms.add(reBoxg); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
protected void initCrossHairs() { |
||||||
|
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); |
||||||
|
BitmapText ch = new BitmapText(guiFont, false); |
||||||
|
ch.setSize(guiFont.getCharSet().getRenderedSize() * 2); |
||||||
|
ch.setText("+"); // crosshairs
|
||||||
|
ch.setLocalTranslation( // center
|
||||||
|
settings.getWidth() / 2 - guiFont.getCharSet().getRenderedSize() / 3 * 2, |
||||||
|
settings.getHeight() / 2 + ch.getLineHeight() / 2, 0); |
||||||
|
guiNode.attachChild(ch); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,399 @@ |
|||||||
|
/* |
||||||
|
* To change this template, choose Tools | Templates and open the template in |
||||||
|
* the editor. |
||||||
|
*/ |
||||||
|
package jme3test.batching; |
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.font.BitmapText; |
||||||
|
import com.jme3.input.KeyInput; |
||||||
|
import com.jme3.input.controls.ActionListener; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.RenderManager; |
||||||
|
import com.jme3.renderer.ViewPort; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.system.AppSettings; |
||||||
|
import com.jme3.input.controls.KeyTrigger; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Random; |
||||||
|
import com.jme3.light.DirectionalLight; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Matrix3f; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.post.FilterPostProcessor; |
||||||
|
import com.jme3.post.filters.BloomFilter; |
||||||
|
import com.jme3.post.ssao.SSAOFilter; |
||||||
|
import com.jme3.scene.BatchedGeometry; |
||||||
|
import com.jme3.scene.GeometryBatch; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import com.jme3.scene.Spatial; |
||||||
|
import com.jme3.scene.control.AbstractControl; |
||||||
|
import com.jme3.scene.control.Control; |
||||||
|
import com.jme3.scene.debug.Arrow; |
||||||
|
import java.util.List; |
||||||
|
import jme3test.post.SSAOUI; |
||||||
|
|
||||||
|
public class TestCubeCluster extends SimpleApplication { |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
TestCubeCluster app = new TestCubeCluster(); |
||||||
|
settingst = new AppSettings(true); |
||||||
|
//settingst.setFrameRate(75);
|
||||||
|
settingst.setResolution(640, 480); |
||||||
|
settingst.setVSync(false); |
||||||
|
settingst.setFullscreen(false); |
||||||
|
app.setSettings(settingst); |
||||||
|
app.setShowSettings(false); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
private ActionListener al = new ActionListener() { |
||||||
|
|
||||||
|
public void onAction(String name, boolean isPressed, float tpf) { |
||||||
|
if (name.equals("Start Game")) { |
||||||
|
// randomGenerator();
|
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
protected Random rand = new Random(); |
||||||
|
protected int maxCubes = 2000; |
||||||
|
protected int startAt = 0; |
||||||
|
protected static int xPositions = 0, yPositions = 0, zPositions = 0; |
||||||
|
protected int returner = 0; |
||||||
|
protected ArrayList<Integer> xPosition = new ArrayList<Integer>(); |
||||||
|
protected ArrayList<Integer> yPosition = new ArrayList<Integer>(); |
||||||
|
protected ArrayList<Integer> zPosition = new ArrayList<Integer>(); |
||||||
|
protected int xLimitf = 60, xLimits = -60, yLimitf = 60, yLimits = -20, zLimitf = 60, zLimits = -60; |
||||||
|
protected int circ = 8;//increases by 8 every time.
|
||||||
|
protected int dynamic = 4; |
||||||
|
protected static AppSettings settingst; |
||||||
|
protected boolean isTrue = true; |
||||||
|
private BitmapText helloText2; |
||||||
|
private int lineLength = 50; |
||||||
|
protected GeometryBatch blue; |
||||||
|
protected GeometryBatch brown; |
||||||
|
protected GeometryBatch pink; |
||||||
|
protected GeometryBatch orange; |
||||||
|
protected List<Geometry> blueList = new ArrayList<Geometry>(); |
||||||
|
protected List<Geometry> brownList = new ArrayList<Geometry>(); |
||||||
|
protected List<Geometry> pinkList = new ArrayList<Geometry>(); |
||||||
|
protected List<Geometry> orangeList = new ArrayList<Geometry>(); |
||||||
|
Material mat1; |
||||||
|
Material mat2; |
||||||
|
Material mat3; |
||||||
|
Material mat4; |
||||||
|
Node terrain; |
||||||
|
//protected
|
||||||
|
// protected Geometry player;
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
|
||||||
|
|
||||||
|
blue = new GeometryBatch("blue"); |
||||||
|
brown = new GeometryBatch("brown"); |
||||||
|
pink = new GeometryBatch("pink"); |
||||||
|
orange = new GeometryBatch("orange"); |
||||||
|
mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat1.setColor("Color", ColorRGBA.White); |
||||||
|
mat1.setColor("GlowColor", ColorRGBA.Blue.mult(10)); |
||||||
|
blue.setMaterial(mat1); |
||||||
|
mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat2.setColor("Color", ColorRGBA.White); |
||||||
|
mat2.setColor("GlowColor", ColorRGBA.Red.mult(10)); |
||||||
|
brown.setMaterial(mat2); |
||||||
|
mat3 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat3.setColor("Color", ColorRGBA.White); |
||||||
|
mat3.setColor("GlowColor", ColorRGBA.Yellow.mult(10)); |
||||||
|
pink.setMaterial(mat3); |
||||||
|
mat4 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
mat4.setColor("Color", ColorRGBA.White); |
||||||
|
mat4.setColor("GlowColor", ColorRGBA.Orange.mult(10)); |
||||||
|
orange.setMaterial(mat4); |
||||||
|
//rootNode.attachChild(SkyFactory.createSky(
|
||||||
|
// assetManager, "Textures/SKY02.zip", false));
|
||||||
|
inputManager.addMapping("Start Game", new KeyTrigger(KeyInput.KEY_J)); |
||||||
|
inputManager.addListener(al, new String[]{"Start Game"}); |
||||||
|
|
||||||
|
|
||||||
|
cam.setLocation(new Vector3f(-34.403286f, 126.65158f, 434.791f)); |
||||||
|
cam.setRotation(new Quaternion(0.022630932f, 0.9749435f, -0.18736298f, 0.11776358f)); |
||||||
|
|
||||||
|
|
||||||
|
//ChaseCamera c = new ChaseCamera();
|
||||||
|
//flyCam.setEnabled(false);
|
||||||
|
xPosition.add(0); |
||||||
|
yPosition.add(0); |
||||||
|
zPosition.add(0); |
||||||
|
|
||||||
|
|
||||||
|
randomGenerator(); |
||||||
|
|
||||||
|
|
||||||
|
List<BatchedGeometry> l = blue.batch(blueList); |
||||||
|
// for (Iterator<BatchedGeometry> it = l.iterator(); it.hasNext();) {
|
||||||
|
// BatchedGeometry batchedGeometry = it.next();
|
||||||
|
// batchedGeometry.addControl(new MyControl());
|
||||||
|
// }
|
||||||
|
l = brown.batch(brownList); |
||||||
|
// for (Iterator<BatchedGeometry> it = l.iterator(); it.hasNext();) {
|
||||||
|
// BatchedGeometry batchedGeometry = it.next();
|
||||||
|
// batchedGeometry.addControl(new MyControl());
|
||||||
|
// }
|
||||||
|
l = pink.batch(pinkList); |
||||||
|
// for (Iterator<BatchedGeometry> it = l.iterator(); it.hasNext();) {
|
||||||
|
// BatchedGeometry batchedGeometry = it.next();
|
||||||
|
// batchedGeometry.addControl(new MyControl());
|
||||||
|
// }
|
||||||
|
|
||||||
|
l = orange.batch(orangeList); |
||||||
|
// for (Iterator<BatchedGeometry> it = l.iterator(); it.hasNext();) {
|
||||||
|
// BatchedGeometry batchedGeometry = it.next();
|
||||||
|
// batchedGeometry.addControl(new MyControl());
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// GeometryBatchFactory.optimize(terrain);
|
||||||
|
terrain = new Node("terrain"); |
||||||
|
terrain.setLocalTranslation(50, 0, 50); |
||||||
|
terrain.attachChild(blue); |
||||||
|
terrain.attachChild(brown); |
||||||
|
terrain.attachChild(pink); |
||||||
|
terrain.attachChild(orange); |
||||||
|
flyCam.setMoveSpeed(100); |
||||||
|
rootNode.attachChild(terrain); |
||||||
|
Vector3f pos = new Vector3f(-40, 0, -40); |
||||||
|
blue.setLocalTranslation(pos); |
||||||
|
brown.setLocalTranslation(pos); |
||||||
|
pink.setLocalTranslation(pos); |
||||||
|
orange.setLocalTranslation(pos); |
||||||
|
|
||||||
|
|
||||||
|
Arrow a = new Arrow(new Vector3f(0, 50, 0)); |
||||||
|
Geometry g = new Geometry("a", a); |
||||||
|
g.setLocalTranslation(terrain.getLocalTranslation()); |
||||||
|
Material m = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
||||||
|
m.setColor("Color", ColorRGBA.Blue); |
||||||
|
g.setMaterial(m); |
||||||
|
// rootNode.attachChild(g);
|
||||||
|
|
||||||
|
|
||||||
|
FilterPostProcessor fpp = new FilterPostProcessor(assetManager); |
||||||
|
fpp.addFilter(new BloomFilter(BloomFilter.GlowMode.Objects)); |
||||||
|
// SSAOFilter ssao = new SSAOFilter(8.630104f,22.970434f,2.9299977f,0.2999997f);
|
||||||
|
// fpp.addFilter(ssao);
|
||||||
|
viewPort.addProcessor(fpp); |
||||||
|
// viewPort.setBackgroundColor(ColorRGBA.DarkGray);
|
||||||
|
} |
||||||
|
|
||||||
|
public void randomGenerator() { |
||||||
|
for (int i = startAt; i < maxCubes - 1; i++) { |
||||||
|
randomize(); |
||||||
|
Geometry box = new Geometry("Box" + i, new Box(Vector3f.ZERO, 1, 1, 1)); |
||||||
|
box.setLocalTranslation(new Vector3f(xPosition.get(xPosition.size() - 1), |
||||||
|
yPosition.get(yPosition.size() - 1), |
||||||
|
zPosition.get(zPosition.size() - 1))); |
||||||
|
|
||||||
|
if (i < 500) { |
||||||
|
blueList.add(box); |
||||||
|
} else if (i < 1000) { |
||||||
|
brownList.add(box); |
||||||
|
} else if (i < 1500) { |
||||||
|
pinkList.add(box); |
||||||
|
} else { |
||||||
|
orangeList.add(box); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public GeometryBatch randomBatch() { |
||||||
|
|
||||||
|
int randomn = rand.nextInt(4); |
||||||
|
if (randomn == 0) { |
||||||
|
return blue; |
||||||
|
} else if (randomn == 1) { |
||||||
|
return brown; |
||||||
|
} else if (randomn == 2) { |
||||||
|
return pink; |
||||||
|
} else if (randomn == 3) { |
||||||
|
return orange; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public ColorRGBA randomColor() { |
||||||
|
ColorRGBA color = ColorRGBA.Black; |
||||||
|
int randomn = rand.nextInt(4); |
||||||
|
if (randomn == 0) { |
||||||
|
color = ColorRGBA.Orange; |
||||||
|
} else if (randomn == 1) { |
||||||
|
color = ColorRGBA.Blue; |
||||||
|
} else if (randomn == 2) { |
||||||
|
color = ColorRGBA.Brown; |
||||||
|
} else if (randomn == 3) { |
||||||
|
color = ColorRGBA.Magenta; |
||||||
|
} |
||||||
|
return color; |
||||||
|
} |
||||||
|
|
||||||
|
public void randomize() { |
||||||
|
int xpos = xPosition.get(xPosition.size() - 1); |
||||||
|
int ypos = yPosition.get(yPosition.size() - 1); |
||||||
|
int zpos = zPosition.get(zPosition.size() - 1); |
||||||
|
int x = 0; |
||||||
|
int y = 0; |
||||||
|
int z = 0; |
||||||
|
boolean unTrue = true; |
||||||
|
while (unTrue) { |
||||||
|
unTrue = false; |
||||||
|
boolean xChanged = false; |
||||||
|
x = 0; |
||||||
|
y = 0; |
||||||
|
z = 0; |
||||||
|
if (xpos >= lineLength * 2) { |
||||||
|
x = 2; |
||||||
|
xChanged = true; |
||||||
|
} else { |
||||||
|
x = xPosition.get(xPosition.size() - 1) + 2; |
||||||
|
} |
||||||
|
if (xChanged) { |
||||||
|
//y = yPosition.get(yPosition.size() - lineLength) + 2;
|
||||||
|
} else { |
||||||
|
y = rand.nextInt(3); |
||||||
|
if (yPosition.size() > lineLength) { |
||||||
|
if (yPosition.size() > 51) { |
||||||
|
if (y == 0 && ypos < yLimitf && getym(lineLength) > ypos - 2) { |
||||||
|
y = ypos + 2; |
||||||
|
} else if (y == 1 && ypos > yLimits && getym(lineLength) < ypos + 2) { |
||||||
|
y = ypos - 2; |
||||||
|
} else if (y == 2 && getym(lineLength) > ypos - 2 && getym(lineLength) < ypos + 2) { |
||||||
|
y = ypos; |
||||||
|
} else { |
||||||
|
if (ypos >= yLimitf) { |
||||||
|
y = ypos - 2; |
||||||
|
} else if (ypos <= yLimits) { |
||||||
|
y = ypos + 2; |
||||||
|
} else if (y == 0 && getym(lineLength) >= ypos - 4) { |
||||||
|
y = ypos - 2; |
||||||
|
} else if (y == 0 && getym(lineLength) >= ypos - 2) { |
||||||
|
y = ypos; |
||||||
|
} else if (y == 1 && getym(lineLength) >= ypos + 4) { |
||||||
|
y = ypos + 2; |
||||||
|
} else if (y == 1 && getym(lineLength) >= ypos + 2) { |
||||||
|
y = ypos; |
||||||
|
} else if (y == 2 && getym(lineLength) <= ypos - 2) { |
||||||
|
y = ypos - 2; |
||||||
|
} else if (y == 2 && getym(lineLength) >= ypos + 2) { |
||||||
|
y = ypos + 2; |
||||||
|
} else { |
||||||
|
System.out.println("wtf"); |
||||||
|
} |
||||||
|
} |
||||||
|
} else if (yPosition.size() == lineLength) { |
||||||
|
if (y == 0 && ypos < yLimitf) { |
||||||
|
y = getym(lineLength) + 2; |
||||||
|
} else if (y == 1 && ypos > yLimits) { |
||||||
|
y = getym(lineLength) - 2; |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (y == 0 && ypos < yLimitf) { |
||||||
|
y = ypos + 2; |
||||||
|
} else if (y == 1 && ypos > yLimits) { |
||||||
|
y = ypos - 2; |
||||||
|
} else if (y == 2) { |
||||||
|
y = ypos; |
||||||
|
} else if (y == 0 && ypos >= yLimitf) { |
||||||
|
y = ypos - 2; |
||||||
|
} else if (y == 1 && ypos <= yLimits) { |
||||||
|
y = ypos + 2; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (xChanged) { |
||||||
|
z = zpos + 2; |
||||||
|
} else { |
||||||
|
z = zpos; |
||||||
|
} |
||||||
|
// for (int i = 0; i < xPosition.size(); i++)
|
||||||
|
// {
|
||||||
|
// if (x - xPosition.get(i) <= 1 && x - xPosition.get(i) >= -1 &&
|
||||||
|
// y - yPosition.get(i) <= 1 && y - yPosition.get(i) >= -1
|
||||||
|
// &&z - zPosition.get(i) <= 1 && z - zPosition.get(i) >=
|
||||||
|
// -1)
|
||||||
|
// {
|
||||||
|
// unTrue = true;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
} |
||||||
|
xPosition.add(x); |
||||||
|
yPosition.add(y); |
||||||
|
zPosition.add(z); |
||||||
|
} |
||||||
|
|
||||||
|
public int getxm(int i) { |
||||||
|
return xPosition.get(xPosition.size() - i); |
||||||
|
} |
||||||
|
|
||||||
|
public int getym(int i) { |
||||||
|
return yPosition.get(yPosition.size() - i); |
||||||
|
} |
||||||
|
|
||||||
|
public int getzm(int i) { |
||||||
|
return zPosition.get(zPosition.size() - i); |
||||||
|
} |
||||||
|
|
||||||
|
public int getx(int i) { |
||||||
|
return xPosition.get(i); |
||||||
|
} |
||||||
|
|
||||||
|
public int gety(int i) { |
||||||
|
return yPosition.get(i); |
||||||
|
} |
||||||
|
|
||||||
|
public int getz(int i) { |
||||||
|
return zPosition.get(i); |
||||||
|
} |
||||||
|
long nbFrames = 0; |
||||||
|
long cullTime = 0; |
||||||
|
float time = 0; |
||||||
|
Vector3f lookAtPos = new Vector3f(0, 0, 0); |
||||||
|
float xpos = 0; |
||||||
|
Spatial box; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
time += tpf; |
||||||
|
int random = rand.nextInt(2000); |
||||||
|
float mult1 = 1.0f; |
||||||
|
float mult2 = 1.0f; |
||||||
|
GeometryBatch b = null; |
||||||
|
if (random < 500) { |
||||||
|
b = blue; |
||||||
|
mult1 = 1.0f; |
||||||
|
mult2 = 1.0f; |
||||||
|
} else if (random < 1000) { |
||||||
|
b = brown; |
||||||
|
mult1 = -1.0f; |
||||||
|
mult2 = 1.0f; |
||||||
|
} else if (random < 1500) { |
||||||
|
b = pink; |
||||||
|
mult1 = 1.0f; |
||||||
|
mult2 = -1.0f; |
||||||
|
} else if (random <= 2000) { |
||||||
|
b = orange; |
||||||
|
mult1 = -1.0f; |
||||||
|
mult2 = -1.0f; |
||||||
|
} |
||||||
|
box = b.getChild("Box" + random); |
||||||
|
if (box != null) { |
||||||
|
Vector3f v = box.getLocalTranslation(); |
||||||
|
box.setLocalTranslation(v.x + FastMath.sin(time * mult1) * 20, v.y +( FastMath.sin(time * mult1)* FastMath.cos(time * mult1)* 20), v.z + FastMath.cos(time * mult2) * 20); |
||||||
|
} |
||||||
|
terrain.setLocalRotation(new Quaternion().fromAngleAxis(time, Vector3f.UNIT_Y)); |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
/* |
||||||
|
* To change this template, choose Tools | Templates and open the template in |
||||||
|
* the editor. |
||||||
|
*/ |
||||||
|
package jme3test.batching; |
||||||
|
|
||||||
|
import com.jme3.app.SimpleApplication; |
||||||
|
import com.jme3.light.DirectionalLight; |
||||||
|
import com.jme3.material.Material; |
||||||
|
import com.jme3.math.ColorRGBA; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Quaternion; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.BatchedGeometry; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.GeometryBatch; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.util.TangentBinormalGenerator; |
||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* @author Nehon |
||||||
|
*/ |
||||||
|
public class TestGeometryBatch extends SimpleApplication { |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
|
||||||
|
TestGeometryBatch app = new TestGeometryBatch(); |
||||||
|
app.start(); |
||||||
|
} |
||||||
|
GeometryBatch batch; |
||||||
|
|
||||||
|
@Override |
||||||
|
public void simpleInitApp() { |
||||||
|
batch = new GeometryBatch("MyBatch"); |
||||||
|
|
||||||
|
/** |
||||||
|
* A cube with a color "bleeding" through transparent texture. Uses |
||||||
|
* Texture from jme3-test-data library! |
||||||
|
*/ |
||||||
|
Box boxshape4 = new Box(Vector3f.ZERO, 1f, 1f, 1f); |
||||||
|
Geometry cube = new Geometry("cube1", boxshape4); |
||||||
|
Material mat = assetManager.loadMaterial("Textures/Terrain/Pond/Pond.j3m"); |
||||||
|
// Material mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
|
||||||
|
// mat.setColor("Diffuse", ColorRGBA.Blue);
|
||||||
|
// mat.setBoolean("UseMaterialColors", true);
|
||||||
|
/** |
||||||
|
* A cube with a color "bleeding" through transparent texture. Uses |
||||||
|
* Texture from jme3-test-data library! |
||||||
|
*/ |
||||||
|
Box box = new Box(Vector3f.ZERO, 1f, 1f, 1f); |
||||||
|
cube2 = new Geometry("cube2", box); |
||||||
|
cube.setLocalTranslation(3, 0, 0); |
||||||
|
cube2.setLocalTranslation(0, 3, 0); |
||||||
|
|
||||||
|
TangentBinormalGenerator.generate(cube); |
||||||
|
TangentBinormalGenerator.generate(cube2); |
||||||
|
|
||||||
|
|
||||||
|
batch.batch(cube,cube2); |
||||||
|
|
||||||
|
batchedCube1 = (BatchedGeometry) batch.getChild("cube1"); |
||||||
|
batchedCube2 = (BatchedGeometry) batch.getChild("cube2"); |
||||||
|
|
||||||
|
batch.setMaterial(mat); |
||||||
|
rootNode.attachChild(batch); |
||||||
|
|
||||||
|
|
||||||
|
dl=new DirectionalLight(); |
||||||
|
dl.setColor(ColorRGBA.White.mult(2)); |
||||||
|
dl.setDirection(new Vector3f(1, -1, -1)); |
||||||
|
rootNode.addLight(dl); |
||||||
|
flyCam.setMoveSpeed(10); |
||||||
|
} |
||||||
|
BatchedGeometry batchedCube1; |
||||||
|
BatchedGeometry batchedCube2; |
||||||
|
Geometry cube2; |
||||||
|
float time = 0; |
||||||
|
DirectionalLight dl; |
||||||
|
@Override |
||||||
|
public void simpleUpdate(float tpf) { |
||||||
|
time += tpf; |
||||||
|
dl.setDirection(cam.getDirection()); |
||||||
|
batchedCube2.setLocalTranslation(FastMath.sin(-time)*3, FastMath.cos(time)*3, 0); |
||||||
|
batchedCube2.setLocalRotation(new Quaternion().fromAngleAxis(time, Vector3f.UNIT_Z)); |
||||||
|
batchedCube2.setLocalScale(Math.max(FastMath.sin(time),0.5f)); |
||||||
|
|
||||||
|
batch.setLocalRotation(new Quaternion().fromAngleAxis(time, Vector3f.UNIT_Z)); |
||||||
|
|
||||||
|
} |
||||||
|
//
|
||||||
|
} |
Loading…
Reference in new issue