Further progress: texturing, compiling animations.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4020 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -29,13 +30,19 @@ import java.io.ObjectInput;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.jme.math.Quaternion;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.scene.Spatial;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
/**
|
||||
@@ -43,6 +50,97 @@ import com.threerings.jme.Log;
|
||||
*/
|
||||
public class Model extends ModelNode
|
||||
{
|
||||
/** An animation for the model. */
|
||||
public static class Animation
|
||||
implements Serializable
|
||||
{
|
||||
/** The transformation targets of the animation. */
|
||||
public Spatial[] transformTargets;
|
||||
|
||||
/** The animation transforms (one transform per target per frame). */
|
||||
public transient Transform[][] transforms;
|
||||
|
||||
private void writeObject (ObjectOutputStream out)
|
||||
throws IOException
|
||||
{
|
||||
out.defaultWriteObject();
|
||||
out.writeInt(transforms.length);
|
||||
for (int ii = 0; ii < transforms.length; ii++) {
|
||||
for (int jj = 0; jj < transformTargets.length; jj++) {
|
||||
transforms[ii][jj].writeExternal(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readObject (ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
in.defaultReadObject();
|
||||
transforms = new Transform[in.readInt()][transformTargets.length];
|
||||
for (int ii = 0; ii < transforms.length; ii++) {
|
||||
for (int jj = 0; jj < transformTargets.length; jj++) {
|
||||
transforms[ii][jj] = new Transform(new Vector3f(),
|
||||
new Quaternion(), new Vector3f());
|
||||
transforms[ii][jj].readExternal(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
/** A frame element that manipulates the target's transform. */
|
||||
public static final class Transform
|
||||
implements Externalizable
|
||||
{
|
||||
public Transform (
|
||||
Vector3f translation, Quaternion rotation, Vector3f scale)
|
||||
{
|
||||
_translation = translation;
|
||||
_rotation = rotation;
|
||||
_scale = scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blends between this transform and the next, applying the result to
|
||||
* the given target.
|
||||
*
|
||||
* @param alpha the blend factor: 0.0 for entirely this frame, 1.0 for
|
||||
* entirely the next
|
||||
*/
|
||||
public void blend (Transform next, float alpha, Spatial target)
|
||||
{
|
||||
target.getLocalTranslation().interpolate(_translation,
|
||||
next._translation, alpha);
|
||||
target.getLocalRotation().slerp(_rotation, next._rotation, alpha);
|
||||
target.getLocalScale().interpolate(_scale, next._scale, alpha);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
public void writeExternal (ObjectOutput out)
|
||||
throws IOException
|
||||
{
|
||||
_translation.writeExternal(out);
|
||||
_rotation.writeExternal(out);
|
||||
_scale.writeExternal(out);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
public void readExternal (ObjectInput in)
|
||||
throws IOException, ClassNotFoundException
|
||||
{
|
||||
_translation.readExternal(in);
|
||||
_rotation.readExternal(in);
|
||||
_scale.readExternal(in);
|
||||
}
|
||||
|
||||
/** The transform at this frame. */
|
||||
protected Vector3f _translation, _scale;
|
||||
protected Quaternion _rotation;
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to read a model from the specified file.
|
||||
*
|
||||
@@ -102,6 +200,48 @@ public class Model extends ModelNode
|
||||
return _props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an animation to the model's library.
|
||||
*/
|
||||
public void addAnimation (String name, Animation anim)
|
||||
{
|
||||
if (_anims == null) {
|
||||
_anims = new HashMap<String, Animation>();
|
||||
}
|
||||
_anims.put(name, anim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the model's animations.
|
||||
*/
|
||||
public String[] getAnimations ()
|
||||
{
|
||||
return (_anims == null) ? new String[0] :
|
||||
_anims.keySet().toArray(new String[_anims.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the named animation.
|
||||
*/
|
||||
public void startAnimation (String name)
|
||||
{
|
||||
_anim = _anims.get(name);
|
||||
if (_anim == null) {
|
||||
Log.warning("Requested unknown animation [name=" +
|
||||
name + "].");
|
||||
return;
|
||||
}
|
||||
_fidx = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the currently running animation.
|
||||
*/
|
||||
public void stopAnimation ()
|
||||
{
|
||||
_anim = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes this model out to a file.
|
||||
*/
|
||||
@@ -125,6 +265,7 @@ public class Model extends ModelNode
|
||||
{
|
||||
super.writeExternal(out);
|
||||
out.writeObject(_props);
|
||||
out.writeObject(_anims);
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
@@ -133,10 +274,45 @@ public class Model extends ModelNode
|
||||
{
|
||||
super.readExternal(in);
|
||||
_props = (Properties)in.readObject();
|
||||
_anims = (HashMap<String, Animation>)in.readObject();
|
||||
}
|
||||
|
||||
@Override // documentation inherited
|
||||
public void updateWorldData (float time)
|
||||
{
|
||||
if (_anim != null) {
|
||||
updateAnimation(time);
|
||||
}
|
||||
|
||||
// update children
|
||||
super.updateWorldData(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the model's state according to the current animation.
|
||||
*/
|
||||
protected void updateAnimation (float time)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** The model properties. */
|
||||
protected Properties _props;
|
||||
|
||||
/** The model animations. */
|
||||
protected HashMap<String, Animation> _anims;
|
||||
|
||||
/** The currently running animation, or <code>null</code> for none. */
|
||||
protected Animation _anim;
|
||||
|
||||
/** The last frame index. */
|
||||
protected int _fidx;
|
||||
|
||||
/** The time corresponding to the last frame. */
|
||||
protected float _ftime;
|
||||
|
||||
/** Identifies a transform frame element. */
|
||||
protected static final byte TRANSFORM_ELEMENT = 0;
|
||||
|
||||
private static final long serialVersionUID = 1;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,13 @@ import com.jme.bounding.BoundingBox;
|
||||
import com.jme.bounding.BoundingSphere;
|
||||
import com.jme.math.Quaternion;
|
||||
import com.jme.math.Vector3f;
|
||||
import com.jme.renderer.Renderer;
|
||||
import com.jme.scene.TriMesh;
|
||||
import com.jme.scene.state.AlphaState;
|
||||
import com.jme.scene.state.CullState;
|
||||
import com.jme.scene.state.TextureState;
|
||||
import com.jme.scene.state.ZBufferState;
|
||||
import com.jme.system.DisplaySystem;
|
||||
|
||||
import com.threerings.jme.Log;
|
||||
|
||||
@@ -82,11 +88,15 @@ public class ModelMesh extends TriMesh
|
||||
{
|
||||
_boundingType = "sphere".equals(props.getProperty("bound")) ?
|
||||
SPHERE_BOUND : BOX_BOUND;
|
||||
_texture = props.getProperty("texture");
|
||||
_solid = !"false".equals(props.getProperty("solid"));
|
||||
_transparent = "true".equals(props.getProperty("transparent"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the buffers as {@link ByteBuffer}s, because we can't create byte
|
||||
* views of non-byte buffers.
|
||||
* views of non-byte buffers. This method is where the model is
|
||||
* initialized after loading.
|
||||
*/
|
||||
public void reconstruct (
|
||||
ByteBuffer vertices, ByteBuffer normals, ByteBuffer colors,
|
||||
@@ -104,12 +114,28 @@ public class ModelMesh extends TriMesh
|
||||
_textureByteBuffer = textures;
|
||||
_indexByteBuffer = indices;
|
||||
|
||||
// initialize the model if we're displaying
|
||||
if (DisplaySystem.getDisplaySystem() == null) {
|
||||
return;
|
||||
}
|
||||
if (_boundingType == BOX_BOUND) {
|
||||
setModelBound(new BoundingBox());
|
||||
} else { // _boundingType == SPHERE_BOUND
|
||||
setModelBound(new BoundingSphere());
|
||||
}
|
||||
updateModelBound();
|
||||
|
||||
if (_backCull == null) {
|
||||
initSharedStates();
|
||||
}
|
||||
if (_solid) {
|
||||
setRenderState(_backCull);
|
||||
}
|
||||
if (_transparent) {
|
||||
setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
|
||||
setRenderState(_blendAlpha);
|
||||
setRenderState(_overlayZBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
@@ -153,6 +179,9 @@ public class ModelMesh extends TriMesh
|
||||
out.writeInt(_textureBufferSize);
|
||||
out.writeInt(_indexBufferSize);
|
||||
out.writeInt(_boundingType);
|
||||
out.writeObject(_texture);
|
||||
out.writeBoolean(_solid);
|
||||
out.writeBoolean(_transparent);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Externalizable
|
||||
@@ -169,6 +198,20 @@ public class ModelMesh extends TriMesh
|
||||
_textureBufferSize = in.readInt();
|
||||
_indexBufferSize = in.readInt();
|
||||
_boundingType = in.readInt();
|
||||
_texture = (String)in.readObject();
|
||||
_solid = in.readBoolean();
|
||||
_transparent = in.readBoolean();
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void resolveTextures (TextureProvider tprov)
|
||||
{
|
||||
if (_texture != null) {
|
||||
TextureState tstate = tprov.getTexture(_texture);
|
||||
if (tstate != null) {
|
||||
setRenderState(tstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
@@ -289,7 +332,7 @@ public class ModelMesh extends TriMesh
|
||||
/**
|
||||
* Imposes the specified order on the given buffer of 32 bit values.
|
||||
*/
|
||||
protected void convertOrder (ByteBuffer buf, ByteOrder order)
|
||||
protected static void convertOrder (ByteBuffer buf, ByteOrder order)
|
||||
{
|
||||
if (buf.order() == order) {
|
||||
return;
|
||||
@@ -301,6 +344,22 @@ public class ModelMesh extends TriMesh
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the states shared between all models. Requires an active
|
||||
* display.
|
||||
*/
|
||||
protected static void initSharedStates ()
|
||||
{
|
||||
Renderer renderer = DisplaySystem.getDisplaySystem().getRenderer();
|
||||
_backCull = renderer.createCullState();
|
||||
_backCull.setCullMode(CullState.CS_BACK);
|
||||
_blendAlpha = renderer.createAlphaState();
|
||||
_blendAlpha.setBlendEnabled(true);
|
||||
_overlayZBuffer = renderer.createZBufferState();
|
||||
_overlayZBuffer.setFunction(ZBufferState.CF_LEQUAL);
|
||||
_overlayZBuffer.setWritable(false);
|
||||
}
|
||||
|
||||
/** The sizes of the various buffers (zero for <code>null</code>). */
|
||||
protected int _vertexBufferSize, _normalBufferSize, _colorBufferSize,
|
||||
_textureBufferSize, _indexBufferSize;
|
||||
@@ -312,6 +371,24 @@ 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;
|
||||
|
||||
/** Whether or not this mesh can enable back-face culling. */
|
||||
protected boolean _solid;
|
||||
|
||||
/** Whether or not this mesh must be rendered as transparent. */
|
||||
protected boolean _transparent;
|
||||
|
||||
/** The shared state for back-face culling. */
|
||||
protected static CullState _backCull;
|
||||
|
||||
/** The shared state for alpha blending. */
|
||||
protected static AlphaState _blendAlpha;
|
||||
|
||||
/** The shared state for checking, but not writing to, the z buffer. */
|
||||
protected static ZBufferState _overlayZBuffer;
|
||||
|
||||
/** Indicates that this mesh should use a bounding box. */
|
||||
protected static final int BOX_BOUND = 0;
|
||||
|
||||
|
||||
@@ -98,7 +98,17 @@ public class ModelNode extends Node
|
||||
attachChild((Spatial)children.get(ii));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void resolveTextures (TextureProvider tprov)
|
||||
{
|
||||
for (Object child : getChildren()) {
|
||||
if (child instanceof ModelSpatial) {
|
||||
((ModelSpatial)child).resolveTextures(tprov);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ModelSpatial
|
||||
public void writeBuffers (FileChannel out)
|
||||
throws IOException
|
||||
|
||||
@@ -32,6 +32,11 @@ import java.nio.channels.FileChannel;
|
||||
*/
|
||||
public interface ModelSpatial
|
||||
{
|
||||
/**
|
||||
* Recursively resolves texture references using the given provider.
|
||||
*/
|
||||
public void resolveTextures (TextureProvider tprov);
|
||||
|
||||
/**
|
||||
* Recursively writes any data buffers to the output channel.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.jme.model;
|
||||
|
||||
import com.jme.scene.state.TextureState;
|
||||
|
||||
/**
|
||||
* Provides a means for models to resolve their texture references.
|
||||
*/
|
||||
public interface TextureProvider
|
||||
{
|
||||
/**
|
||||
* Returns a texture state containing the named texture.
|
||||
*/
|
||||
public TextureState getTexture (String name);
|
||||
}
|
||||
Reference in New Issue
Block a user