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:
Andrzej Kapolka
2006-04-28 01:47:49 +00:00
parent d8f7e48cbf
commit 33ab4146c8
8 changed files with 153 additions and 61 deletions
@@ -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;
}
+47 -19
View File
@@ -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;