Misc. fixes, added random texture selection to models.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4073 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.scene.Geometry;
|
||||
import com.jme.scene.Spatial;
|
||||
@@ -31,6 +33,19 @@ import com.jme.util.geom.BufferUtils;
|
||||
*/
|
||||
public abstract class EmissionController extends ModelController
|
||||
{
|
||||
@Override // documentation inherited
|
||||
public void configure (Properties props, Spatial target)
|
||||
{
|
||||
// substitute underlying mesh for geometry targets
|
||||
if (target instanceof ModelNode) {
|
||||
Spatial mesh = ((ModelNode)target).getChild("mesh");
|
||||
if (mesh != null) {
|
||||
target = mesh;
|
||||
}
|
||||
}
|
||||
super.configure(props, target);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void init (Model model)
|
||||
{
|
||||
@@ -59,4 +74,6 @@ public abstract class EmissionController extends ModelController
|
||||
}
|
||||
_target.getWorldRotation().multLocal(result);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ import com.jme.scene.Controller;
|
||||
import com.jme.scene.Node;
|
||||
import com.jme.scene.Spatial;
|
||||
|
||||
import com.threerings.util.RandomUtil;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
@@ -475,24 +477,7 @@ public class Model extends ModelNode
|
||||
return _prototype.createInstance();
|
||||
}
|
||||
if (_ccreator == null) {
|
||||
// allow adding and removing properties at any time
|
||||
_ccreator = new CloneCreator(this) {
|
||||
public void addProperty (String name) {
|
||||
props.put(name, Boolean.TRUE);
|
||||
}
|
||||
public void removeProperty (String name) {
|
||||
props.remove(name);
|
||||
}
|
||||
};
|
||||
_ccreator.addProperty("vertices");
|
||||
_ccreator.addProperty("colors");
|
||||
_ccreator.addProperty("normals");
|
||||
_ccreator.addProperty("texcoords");
|
||||
_ccreator.addProperty("vboinfo");
|
||||
_ccreator.addProperty("indices");
|
||||
_ccreator.addProperty("obbtree");
|
||||
_ccreator.addProperty("displaylistid");
|
||||
_ccreator.addProperty("bound");
|
||||
_ccreator = new ModelCloneCreator(this);
|
||||
}
|
||||
Model instance = (Model)_ccreator.createCopy();
|
||||
instance.initInstance();
|
||||
@@ -599,7 +584,7 @@ public class Model extends ModelNode
|
||||
|
||||
/** For prototype models, a customized clone creator used to generate
|
||||
* instances. */
|
||||
protected CloneCreator _ccreator;
|
||||
protected ModelCloneCreator _ccreator;
|
||||
|
||||
/** For instances, maps prototype nodes to their corresponding instance
|
||||
* nodes. */
|
||||
@@ -645,6 +630,7 @@ public class Model extends ModelNode
|
||||
_name = name;
|
||||
}
|
||||
|
||||
// documentation inherited from interface ObserverOp
|
||||
public boolean apply (AnimationObserver obs)
|
||||
{
|
||||
return obs.animationStarted(Model.this, _name);
|
||||
@@ -663,6 +649,7 @@ public class Model extends ModelNode
|
||||
_name = name;
|
||||
}
|
||||
|
||||
// documentation inherited from interface ObserverOp
|
||||
public boolean apply (AnimationObserver obs)
|
||||
{
|
||||
return obs.animationCompleted(Model.this, _name);
|
||||
@@ -681,6 +668,7 @@ public class Model extends ModelNode
|
||||
_name = name;
|
||||
}
|
||||
|
||||
// documentation inherited from interface ObserverOp
|
||||
public boolean apply (AnimationObserver obs)
|
||||
{
|
||||
return obs.animationCancelled(Model.this, _name);
|
||||
@@ -690,5 +678,45 @@ public class Model extends ModelNode
|
||||
protected String _name;
|
||||
}
|
||||
|
||||
/** Customized clone creator for models. */
|
||||
protected static class ModelCloneCreator extends CloneCreator
|
||||
{
|
||||
/** A shared seed used to select textures consistently. */
|
||||
public int random;
|
||||
|
||||
public ModelCloneCreator (Model toCopy)
|
||||
{
|
||||
super(toCopy);
|
||||
addProperty("vertices");
|
||||
addProperty("colors");
|
||||
addProperty("normals");
|
||||
addProperty("texcoords");
|
||||
addProperty("vboinfo");
|
||||
addProperty("indices");
|
||||
addProperty("obbtree");
|
||||
addProperty("displaylistid");
|
||||
addProperty("bound");
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void addProperty (String name)
|
||||
{
|
||||
props.put(name, Boolean.TRUE);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void removeProperty (String name)
|
||||
{
|
||||
props.remove(name);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public Spatial createCopy ()
|
||||
{
|
||||
random = RandomUtil.getInt(Integer.MAX_VALUE);
|
||||
return super.createCopy();
|
||||
}
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
@@ -49,12 +49,7 @@ public abstract class ModelController extends Controller
|
||||
*/
|
||||
public void configure (Properties props, Spatial target)
|
||||
{
|
||||
if (target instanceof ModelNode) {
|
||||
_target = ((ModelNode)target).getChild("mesh");
|
||||
}
|
||||
if (_target == null) {
|
||||
_target = target;
|
||||
}
|
||||
_target = target;
|
||||
String[] anims = StringUtil.parseStringArray(
|
||||
props.getProperty("animations", ""));
|
||||
if (anims.length == 0) {
|
||||
@@ -156,4 +151,6 @@ public abstract class ModelController extends Controller
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,8 @@ import com.jme.scene.state.ZBufferState;
|
||||
import com.jme.system.DisplaySystem;
|
||||
import com.jme.util.geom.BufferUtils;
|
||||
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
@@ -80,7 +82,7 @@ public class ModelMesh extends TriMesh
|
||||
* Configures this mesh based on the given parameters and (sub-)properties.
|
||||
*
|
||||
* @param texture the texture specified in the model export, if any (can be
|
||||
* overridden by a texture specified in the properties)
|
||||
* overridden by textures specified in the properties)
|
||||
* @param solid whether or not the mesh allows back face culling
|
||||
* @param transparent whether or not the mesh is (partially) transparent
|
||||
*/
|
||||
@@ -89,8 +91,8 @@ public class ModelMesh extends TriMesh
|
||||
{
|
||||
_boundingType = "sphere".equals(props.getProperty("bound")) ?
|
||||
SPHERE_BOUND : BOX_BOUND;
|
||||
_texture = (texture == null) ? null :
|
||||
props.getProperty(texture, texture);
|
||||
_textures = (texture == null) ? null : StringUtil.parseStringArray(
|
||||
props.getProperty(texture, texture));
|
||||
_solid = solid;
|
||||
_transparent = transparent;
|
||||
}
|
||||
@@ -132,12 +134,19 @@ public class ModelMesh extends TriMesh
|
||||
}
|
||||
if (_solid) {
|
||||
setRenderState(_backCull);
|
||||
} else {
|
||||
setRenderState(_noCull);
|
||||
}
|
||||
if (_transparent) {
|
||||
setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
|
||||
setRenderState(_blendAlpha);
|
||||
setRenderState(_overlayZBuffer);
|
||||
} else {
|
||||
setRenderQueueMode(Renderer.QUEUE_OPAQUE);
|
||||
setRenderState(_noAlpha);
|
||||
setRenderState(_lequalZBuffer);
|
||||
}
|
||||
setTextureCombineMode(TextureState.REPLACE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,14 +155,12 @@ public class ModelMesh extends TriMesh
|
||||
*/
|
||||
public void centerVertices ()
|
||||
{
|
||||
Vector3f offset = getLocalTranslation().subtract(
|
||||
getModelBound().getCenter());
|
||||
FloatBuffer vbuf = getVertexBuffer();
|
||||
for (int ii = 0, nn = getVertexCount(); ii < nn; ii++) {
|
||||
BufferUtils.addInBuffer(offset, vbuf, ii);
|
||||
Vector3f offset = getModelBound().getCenter().negate();
|
||||
if (!offset.equals(Vector3f.ZERO)) {
|
||||
getLocalTranslation().subtractLocal(offset);
|
||||
getModelBound().getCenter().set(Vector3f.ZERO);
|
||||
getBatch().translatePoints(offset);
|
||||
}
|
||||
getLocalTranslation().subtractLocal(offset);
|
||||
getModelBound().getCenter().zero();
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
@@ -199,7 +206,17 @@ public class ModelMesh extends TriMesh
|
||||
if (properties.isSet("bound")) {
|
||||
mstore.setModelBound(getModelBound());
|
||||
}
|
||||
mstore._texture = _texture;
|
||||
if (_textures != null && _textures.length > 1 &&
|
||||
properties instanceof Model.ModelCloneCreator) {
|
||||
int tidx = ((Model.ModelCloneCreator)properties).random %
|
||||
_textures.length;
|
||||
mstore._textures = new String[] { _textures[tidx] };
|
||||
mstore._tstates = new TextureState[] { _tstates[tidx] };
|
||||
mstore.setRenderState(_tstates[tidx]);
|
||||
} else {
|
||||
mstore._textures = _textures;
|
||||
mstore._tstates = _tstates;
|
||||
}
|
||||
return mstore;
|
||||
}
|
||||
|
||||
@@ -217,7 +234,7 @@ public class ModelMesh extends TriMesh
|
||||
out.writeInt(_textureBufferSize);
|
||||
out.writeInt(_indexBufferSize);
|
||||
out.writeInt(_boundingType);
|
||||
out.writeObject(_texture);
|
||||
out.writeObject(_textures);
|
||||
out.writeBoolean(_solid);
|
||||
out.writeBoolean(_transparent);
|
||||
}
|
||||
@@ -236,7 +253,7 @@ public class ModelMesh extends TriMesh
|
||||
_textureBufferSize = in.readInt();
|
||||
_indexBufferSize = in.readInt();
|
||||
_boundingType = in.readInt();
|
||||
_texture = (String)in.readObject();
|
||||
_textures = (String[])in.readObject();
|
||||
_solid = in.readBoolean();
|
||||
_transparent = in.readBoolean();
|
||||
}
|
||||
@@ -264,11 +281,15 @@ public class ModelMesh extends TriMesh
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void resolveTextures (TextureProvider tprov)
|
||||
{
|
||||
if (_texture != null) {
|
||||
TextureState tstate = tprov.getTexture(_texture);
|
||||
if (tstate != null) {
|
||||
setRenderState(tstate);
|
||||
}
|
||||
if (_textures == null) {
|
||||
return;
|
||||
}
|
||||
_tstates = new TextureState[_textures.length];
|
||||
for (int ii = 0; ii < _textures.length; ii++) {
|
||||
_tstates[ii] = tprov.getTexture(_textures[ii]);
|
||||
}
|
||||
if (_tstates[0] != null) {
|
||||
setRenderState(_tstates[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,31 +378,31 @@ public class ModelMesh extends TriMesh
|
||||
if (_vertexBufferSize > 0) {
|
||||
int npos = map.position() + _vertexBufferSize*4;
|
||||
map.limit(npos);
|
||||
vbbuf = map.slice();
|
||||
vbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN);
|
||||
map.position(npos);
|
||||
}
|
||||
if (_normalBufferSize > 0) {
|
||||
int npos = map.position() + _normalBufferSize*4;
|
||||
map.limit(npos);
|
||||
nbbuf = map.slice();
|
||||
nbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN);
|
||||
map.position(npos);
|
||||
}
|
||||
if (_colorBufferSize > 0) {
|
||||
int npos = map.position() + _colorBufferSize*4;
|
||||
map.limit(npos);
|
||||
cbbuf = map.slice();
|
||||
cbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN);
|
||||
map.position(npos);
|
||||
}
|
||||
if (_textureBufferSize > 0) {
|
||||
int npos = map.position() + _textureBufferSize*4;
|
||||
map.limit(npos);
|
||||
tbbuf = map.slice();
|
||||
tbbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN);
|
||||
map.position(npos);
|
||||
}
|
||||
if (_indexBufferSize > 0) {
|
||||
int npos = map.position() + _indexBufferSize*4;
|
||||
map.limit(npos);
|
||||
ibbuf = map.slice();
|
||||
ibbuf = map.slice().order(ByteOrder.LITTLE_ENDIAN);
|
||||
map.position(npos);
|
||||
}
|
||||
reconstruct(vbbuf, nbbuf, cbbuf, tbbuf, ibbuf);
|
||||
@@ -411,11 +432,15 @@ public class ModelMesh extends TriMesh
|
||||
Renderer renderer = DisplaySystem.getDisplaySystem().getRenderer();
|
||||
_backCull = renderer.createCullState();
|
||||
_backCull.setCullMode(CullState.CS_BACK);
|
||||
_noCull = renderer.createCullState();
|
||||
_blendAlpha = renderer.createAlphaState();
|
||||
_blendAlpha.setBlendEnabled(true);
|
||||
_noAlpha = renderer.createAlphaState();
|
||||
_overlayZBuffer = renderer.createZBufferState();
|
||||
_overlayZBuffer.setFunction(ZBufferState.CF_LEQUAL);
|
||||
_overlayZBuffer.setWritable(false);
|
||||
_lequalZBuffer = renderer.createZBufferState();
|
||||
_lequalZBuffer.setFunction(ZBufferState.CF_LEQUAL);
|
||||
}
|
||||
|
||||
/** The sizes of the various buffers (zero for <code>null</code>). */
|
||||
@@ -429,8 +454,8 @@ public class ModelMesh extends TriMesh
|
||||
/** The type of bounding volume that this mesh should use. */
|
||||
protected int _boundingType;
|
||||
|
||||
/** The name of this model's texture, or <code>null</code> for none. */
|
||||
protected String _texture;
|
||||
/** The name of this model's textures, or <code>null</code> for none. */
|
||||
protected String[] _textures;
|
||||
|
||||
/** Whether or not this mesh can enable back-face culling. */
|
||||
protected boolean _solid;
|
||||
@@ -438,15 +463,27 @@ public class ModelMesh extends TriMesh
|
||||
/** Whether or not this mesh must be rendered as transparent. */
|
||||
protected boolean _transparent;
|
||||
|
||||
/** The shared state for back-face culling. */
|
||||
/** For prototype meshes, the resolved texture states. */
|
||||
protected TextureState[] _tstates;
|
||||
|
||||
/** The shared state for back face culling. */
|
||||
protected static CullState _backCull;
|
||||
|
||||
/** The shared state for no back face culling. */
|
||||
protected static CullState _noCull;
|
||||
|
||||
/** The shared state for alpha blending. */
|
||||
protected static AlphaState _blendAlpha;
|
||||
|
||||
/** The shared state for no blending. */
|
||||
protected static AlphaState _noAlpha;
|
||||
|
||||
/** The shared state for checking, but not writing to, the z buffer. */
|
||||
protected static ZBufferState _overlayZBuffer;
|
||||
|
||||
/** The shared state for checking and writing to the z buffer. */
|
||||
protected static ZBufferState _lequalZBuffer;
|
||||
|
||||
/** Indicates that this mesh should use a bounding box. */
|
||||
protected static final int BOX_BOUND = 0;
|
||||
|
||||
|
||||
@@ -123,4 +123,6 @@ public class Rotator extends ModelController
|
||||
|
||||
/** A temporary quaternion. */
|
||||
protected Quaternion _rot = new Quaternion();
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
@@ -287,15 +287,6 @@ public class ModelDef
|
||||
FloatBuffer vbuf, FloatBuffer nbuf, FloatBuffer tbuf)
|
||||
{
|
||||
vbuf.put(location);
|
||||
|
||||
// make sure the normal is normalized
|
||||
float nlen = FastMath.sqrt(normal[0]*normal[0] +
|
||||
normal[1]*normal[1] + normal[2]*normal[2]);
|
||||
if (nlen != 1f) {
|
||||
normal[0] /= nlen;
|
||||
normal[1] /= nlen;
|
||||
normal[2] /= nlen;
|
||||
}
|
||||
nbuf.put(normal);
|
||||
|
||||
if (tbuf != null) {
|
||||
|
||||
@@ -74,6 +74,7 @@ import com.jme.scene.Spatial;
|
||||
import com.jme.scene.state.LightState;
|
||||
import com.jme.scene.state.MaterialState;
|
||||
import com.jme.scene.state.TextureState;
|
||||
import com.jme.scene.state.WireframeState;
|
||||
import com.jme.scene.state.ZBufferState;
|
||||
import com.jme.util.LoggingSystem;
|
||||
import com.jme.util.TextureManager;
|
||||
@@ -153,6 +154,18 @@ public class ModelViewer extends JmeCanvasApp
|
||||
JMenu view = new JMenu(_msg.get("m.view_menu"));
|
||||
view.setMnemonic(KeyEvent.VK_V);
|
||||
menu.add(view);
|
||||
|
||||
Action wireframe = new AbstractAction(_msg.get("m.view_wireframe")) {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
_wfstate.setEnabled(!_wfstate.isEnabled());
|
||||
}
|
||||
};
|
||||
wireframe.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_W);
|
||||
wireframe.putValue(Action.ACCELERATOR_KEY,
|
||||
KeyStroke.getKeyStroke(KeyEvent.VK_W, KeyEvent.CTRL_MASK));
|
||||
view.add(new JCheckBoxMenuItem(wireframe));
|
||||
view.addSeparator();
|
||||
|
||||
_pivots = new JCheckBoxMenuItem(_msg.get("m.view_pivots"));
|
||||
_pivots.setMnemonic(KeyEvent.VK_P);
|
||||
_pivots.setAccelerator(
|
||||
@@ -252,11 +265,14 @@ public class ModelViewer extends JmeCanvasApp
|
||||
{
|
||||
super.initRoot();
|
||||
|
||||
// set a default material
|
||||
// set default states
|
||||
MaterialState mstate = _ctx.getRenderer().createMaterialState();
|
||||
mstate.getDiffuse().set(ColorRGBA.white);
|
||||
mstate.getAmbient().set(ColorRGBA.white);
|
||||
_ctx.getGeometry().setRenderState(mstate);
|
||||
_ctx.getGeometry().setRenderState(
|
||||
_wfstate = _ctx.getRenderer().createWireframeState());
|
||||
_wfstate.setEnabled(false);
|
||||
|
||||
// create a grid on the XY plane to provide some reference
|
||||
Vector3f[] points = new Vector3f[GRID_SIZE*2 + GRID_SIZE*2];
|
||||
@@ -524,6 +540,9 @@ public class ModelViewer extends JmeCanvasApp
|
||||
/** The model file chooser. */
|
||||
protected JFileChooser _chooser;
|
||||
|
||||
/** Used to toggle wireframe rendering. */
|
||||
protected WireframeState _wfstate;
|
||||
|
||||
/** The currently loaded model. */
|
||||
protected Model _model;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user