diff --git a/.classpath b/.classpath index ab1559e9..026b971f 100644 --- a/.classpath +++ b/.classpath @@ -1,14 +1,14 @@ - - + + - - + + diff --git a/build.xml b/build.xml index de051199..9856ff47 100644 --- a/build.xml +++ b/build.xml @@ -73,7 +73,6 @@ - @@ -219,10 +218,6 @@ - - - - diff --git a/etc/depends-incl.xml b/etc/depends-incl.xml index 780b7b93..5000f979 100644 --- a/etc/depends-incl.xml +++ b/etc/depends-incl.xml @@ -9,14 +9,6 @@ classname="org.lwjgl.LWJGLException" classpathref="classpath"/> - - - - - - @@ -29,13 +21,6 @@ classname="com.megginson.sax.DataWriter" classpathref="classpath"/> - - - - - - - diff --git a/etc/libs-incl.xml b/etc/libs-incl.xml index 523fc5f3..6f6bbedf 100644 --- a/etc/libs-incl.xml +++ b/etc/libs-incl.xml @@ -18,16 +18,9 @@ - + - - - - - - - diff --git a/rsrc/media/jme/defaultfont.tga b/rsrc/media/jme/defaultfont.tga deleted file mode 100644 index 563b0968..00000000 Binary files a/rsrc/media/jme/defaultfont.tga and /dev/null differ diff --git a/rsrc/media/jme/skin.frag b/rsrc/media/jme/skin.frag deleted file mode 100644 index 0d44c2ee..00000000 --- a/rsrc/media/jme/skin.frag +++ /dev/null @@ -1,56 +0,0 @@ -// -// $Id: ImageCache.java 158 2007-02-24 00:38:17Z mdb $ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/nenya/ -// -// 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 - -/** The diffuse texture map. */ -uniform sampler2D diffuseMap; - -/** The emissive texture map. */ -#ifdef EMISSIVE_MAPPED - uniform sampler2D emissiveMap; -#endif - -/** The amount of fog. */ -#ifdef FOG - varying float fogAlpha; -#endif - -/** - * Fragment shader for skinned meshes. - */ -void main () -{ - // start with the diffuse color - vec4 fragColor = texture2D(diffuseMap, gl_TexCoord[0].st); - - // modulate by the light color - #ifdef EMISSIVE_MAPPED - fragColor *= (gl_Color + vec4(texture2D(emissiveMap, gl_TexCoord[0].st).rgb, 0.0)); - #else - fragColor *= gl_Color; - #endif - - // blend between the computed color and the fog color - #ifdef FOG - gl_FragColor = mix(gl_Fog.color, fragColor, fogAlpha); - #else - gl_FragColor = fragColor; - #endif -} diff --git a/rsrc/media/jme/skin.vert b/rsrc/media/jme/skin.vert deleted file mode 100644 index 5bee27d8..00000000 --- a/rsrc/media/jme/skin.vert +++ /dev/null @@ -1,67 +0,0 @@ -// -// $Id: ImageCache.java 158 2007-02-24 00:38:17Z mdb $ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://www.threerings.net/code/nenya/ -// -// 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 - -/** The bone transforms. */ -uniform mat4 boneTransforms[MAX_BONE_COUNT]; - -/** The bone indices. */ -attribute vec4 boneIndices; - -/** The bone weights. */ -attribute vec4 boneWeights; - -/** The amount of fog. */ -#ifdef FOG - varying float fogAlpha; -#endif - -/** - * Vertex shader for skinned meshes. - */ -void main () -{ - vec4 normal4 = vec4(gl_Normal, 0.0); - - // add up the vertex as transformed by each bone and scaled by each weight - vec4 modelVertex = vec4(0.0, 0.0, 0.0, 0.0); - vec4 modelNormal = vec4(0.0, 0.0, 0.0, 0.0); - for (int ii = 0; ii < 4; ii++) { - mat4 boneTransform = boneTransforms[int(boneIndices[ii])]; - modelVertex += boneTransform * gl_Vertex * boneWeights[ii]; - modelNormal += boneTransform * normal4 * boneWeights[ii]; - } - - // apply the standard transformation - gl_Position = gl_ModelViewProjectionMatrix * modelVertex; - - // transform the vertex and normal into eye space - vec3 eyeVertex = vec3(gl_ModelViewMatrix * modelVertex); - vec3 eyeNormal = normalize(vec3(gl_ModelViewMatrixInverseTranspose * modelNormal)); - - // set gl_FrontColor based on vertex, normal and light parameters - SET_FRONT_COLOR - - // set the varying texture coordinates - SET_TEX_COORDS - - // set the fog alpha based on the eye space vertex - SET_FOG_ALPHA -} diff --git a/src/java/com/threerings/jme/JmeApp.java b/src/java/com/threerings/jme/JmeApp.java deleted file mode 100644 index eedb9b31..00000000 --- a/src/java/com/threerings/jme/JmeApp.java +++ /dev/null @@ -1,600 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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; - -import java.io.File; - -import java.util.Arrays; - -import com.samskivert.util.Queue; -import com.samskivert.util.RunQueue; -import com.samskivert.util.StringUtil; - -import com.jme.renderer.Camera; -import com.jme.renderer.ColorRGBA; -import com.jme.renderer.Renderer; - -import com.jme.scene.Node; -import com.jme.scene.state.LightState; -import com.jme.scene.state.RenderState; -import com.jme.scene.state.ZBufferState; - -import com.jme.system.DisplaySystem; -import com.jme.system.JmeException; -import com.jme.system.PropertiesIO; -import com.jme.system.lwjgl.LWJGLPropertiesDialog; - -import com.jme.input.InputHandler; -import com.jme.input.KeyInput; -import com.jme.input.MouseInput; -import com.jmex.bui.BRootNode; -import com.jmex.bui.PolledRootNode; - -import com.jme.light.PointLight; -import com.jme.math.Vector3f; -import com.jme.util.Timer; - -import com.threerings.jme.camera.CameraHandler; - -import static com.threerings.jme.Log.log; - -/** - * Defines a basic application framework providing integration with the - * Presents networking system and - * targeting the framerate of the display. - */ -public class JmeApp - implements RunQueue -{ - /** - * Returns a context implementation that provides access to all the - * necessary bits. - */ - public JmeContext getContext () - { - return _ctx; - } - - /** - * Does the main initialization of the application. This method should - * be called first, and then the {@link #run} method should be called - * to begin the rendering/event loop. Derived classes can override - * this, being sure to call super before doing their own - * initalization. - * - * @return true if the application initialized successfully, false if - * initialization failed. (See {@link #reportInitFailure}.) - */ - public boolean init () - { - try { - // initialize the rendering system - initDisplay(); - if (!_display.isCreated()) { - throw new IllegalStateException( - "Failed to initialize display?"); - } - - // create an appropriate timer - _timer = Timer.getTimer(); - - // start with the target FPS equal to the refresh rate (but - // sometimes the refresh rate is reported as zero so don't let that - // freak us out) - setTargetFPS(Math.max(_display.getFrequency(), 60)); - - // initialize our main camera controls and user input handling - initInput(); - - // initialize the root node - initRoot(); - - // initialize the lighting - initLighting(); - - // initialize the UI support stuff - initInterface(); - - // update everything for the zeroth tick - _iface.updateRenderState(); - _geom.updateRenderState(); - _root.updateGeometricState(0f, true); - _root.updateRenderState(); - - return true; - - } catch (Throwable t) { - reportInitFailure(t); - return false; - } - } - - /** - * Configures whether or not we display FPS and other statistics atop the - * display. - */ - public void displayStatistics (boolean display) - { - if (display && (_stats == null)) { - _stats = new StatsDisplay(_display.getRenderer()); - _stats.updateGeometricState(0f, true); - _stats.updateRenderState(); - } else if (!display && (_stats != null)) { - _stats = null; - } - } - - /** - * Returns true if we are displaying statistics, false if not. - */ - public boolean showingStatistics () - { - return (_stats != null); - } - - /** - * Sets the target frames per second. - * - * @return the old target frames per second. - */ - public int setTargetFPS (int targetFPS) - { - int oldTargetFPS = _targetFPS; - _targetFPS = targetFPS; - _ticksPerFrame = _timer.getResolution() / _targetFPS; - return oldTargetFPS; - } - - /** - * Returns the frames per second averaged over the last 32 frames. - */ - public float getRecentFrameRate () - { - return _timer.getFrameRate(); - } - - /** - * Enables or disables the update and render part of the - * update/render/process events application loop. - */ - public void setEnabled (boolean update, boolean render) - { - _updateEnabled = update; - _renderEnabled = render; - } - - /** - * Starts up the main rendering and event processing loop. This method - * will not return until the application is terminated with a call to - * {@link #stop}. - */ - public void run () - { - synchronized (this) { - _dispatchThread = Thread.currentThread(); - } - - // enter the main rendering and event processing loop - while (!_finished) { - try { - // render the current frame - long frameStart = processFrame(); - - // and process events until it's time to render the next - PROCESS_EVENTS: - do { - Runnable r = _evqueue.getNonBlocking(); - if (r != null) { - r.run(); - } - if (_timer.getTime() - frameStart >= _ticksPerFrame) { - break PROCESS_EVENTS; - } else { - try { - Thread.sleep(1); - } catch (InterruptedException ie) { - } - } - } while (!_finished); - _failures = 0; - - } catch (Throwable t) { - log.warning(t); - // stick a fork in things if we fail too many times in a row - if (++_failures > MAX_SUCCESSIVE_FAILURES) { - stop(); - } - } - if (_display.isClosing()) { - stop(); - } - } - - try { - cleanup(); - } catch (Throwable t) { - log.warning(t); - } finally { - exit(); - } - } - - /** - * Returns the duration (in seconds) between the previous frame and the - * current frame. - */ - public float getFrameTime () - { - return _frameTime; - } - - /** - * Instructs the application to stop the main loop, cleanup and exit. - */ - public void stop () - { - _finished = true; - } - - // from interface RunQueue - public void postRunnable (Runnable r) - { - _evqueue.append(r); - } - - // from interface RunQueue - public boolean isDispatchThread () - { - return Thread.currentThread() == _dispatchThread; - } - - // from interface RunQueue - public boolean isRunning () - { - return !_finished; - } - - /** - * Determines the display configuration and creates the display. This must - * fill in {@link #_api} as a side-effect. - */ - protected DisplaySystem createDisplay () - throws JmeException - { - PropertiesIO props = new PropertiesIO(getConfigPath("jme.cfg")); - if (!props.load()) { - LWJGLPropertiesDialog dialog = - new LWJGLPropertiesDialog(props, (String)null); - while (dialog.isVisible()) { - try { - Thread.sleep(5); - } catch (InterruptedException e) { - log.warning("Error waiting for dialog system, " + - "using defaults."); - } - } - } - _api = props.getRenderer(); - DisplaySystem display = DisplaySystem.getDisplaySystem(_api); - display.createWindow(props.getWidth(), props.getHeight(), - props.getDepth(), props.getFreq(), - props.getFullscreen()); - return display; - } - - /** - * Initializes the underlying rendering system, creating a display of - * the proper resolution and depth. - */ - protected void initDisplay () - throws JmeException - { - // create the main display system - _display = createDisplay(); - - // create a camera - int width = _display.getWidth(), height = _display.getHeight(); - _camera = _display.getRenderer().createCamera(width, height); - - // start with a black background - _display.getRenderer().setBackgroundColor(ColorRGBA.black); - - // enable all of the "quick compares," which means that states will - // be refreshed only when necessary - Arrays.fill(RenderState.QUICK_COMPARE, true); - - // set up the camera - _camera.setFrustumPerspective(45.0f, width/(float)height, 1, 10000); - Vector3f loc = new Vector3f(0.0f, 0.0f, 25.0f); - Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f); - Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f); - Vector3f dir = new Vector3f(0.0f, 0f, -1.0f); - _camera.setFrame(loc, left, up, dir); - _camera.update(); - _display.getRenderer().setCamera(_camera); - - // tell the renderer to keep track of rendering information (total - // triangles drawn, etc.) - _display.getRenderer().enableStatistics(true); - } - - /** - * Sets up a main input controller to handle the camera and deal with - * global user input. - */ - protected void initInput () - { - _camhand = createCameraHandler(_camera); - _input = createInputHandler(_camhand); - } - - /** - * Creates the camera handler which provides various camera manipulation - * functionality. - */ - protected CameraHandler createCameraHandler (Camera camera) - { - return new CameraHandler(camera); - } - - /** - * Creates the input handler used to control our camera and manage non-UI - * keyboard input. - */ - protected InputHandler createInputHandler (CameraHandler hand) - { - return new InputHandler(); - } - - /** - * Creates our root node and sets up the basic rendering system. - */ - protected void initRoot () - { - _root = new Node("Root"); - - // set up a node for our geometry - _geom = new Node("Geometry"); - - // make everything opaque by default - _geom.setRenderQueueMode(Renderer.QUEUE_OPAQUE); - - // set up a zbuffer - ZBufferState zbuf = _display.getRenderer().createZBufferState(); - zbuf.setEnabled(true); - zbuf.setFunction(ZBufferState.CF_LEQUAL); - _geom.setRenderState(zbuf); - _root.attachChild(_geom); - } - - /** - * Sets up some default lighting. - */ - protected void initLighting () - { - PointLight light = new PointLight(); - light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f)); - light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f)); - light.setLocation(new Vector3f(100, 100, 100)); - light.setEnabled(true); - - _lights = _display.getRenderer().createLightState(); - _lights.setEnabled(true); - _lights.attach(light); - _geom.setRenderState(_lights); - } - - /** - * Initializes our user interface bits. - */ - protected void initInterface () - { - // set up a node for our interface - _iface = new Node("Interface"); - _root.attachChild(_iface); - - // create our root node - _rnode = createRootNode(); - _iface.attachChild(_rnode); - - // we don't hide the cursor - MouseInput.get().setCursorVisible(true); - } - - /** - * Allows a customized root node to be created. - */ - protected BRootNode createRootNode () - { - return new PolledRootNode(_timer, _input); - } - - /** - * Called when initialization fails to give the application a chance - * to report the failure to the user. - */ - protected void reportInitFailure (Throwable t) - { - log.warning(t); - } - - /** - * Processes a single frame. - */ - protected final long processFrame () - { - // update our simulation and render a frame - long frameStart = _timer.getTime(); - if (_updateEnabled) { - update(frameStart); - } - if (_renderEnabled) { - render(frameStart); - _display.getRenderer().displayBackBuffer(); - } - return frameStart; - } - - /** - * Called every frame to update whatever sort of real time business we - * have that needs updating. - */ - protected void update (long frameTick) - { - // recalculate the frame rate - _timer.update(); - - // update the camera handler - _camhand.update(_frameTime); - - // run all of the controllers attached to nodes - _frameTime = (_lastTick == 0L) ? 0f : (float)(frameTick - _lastTick) / - _timer.getResolution(); - _lastTick = frameTick; - _root.updateGeometricState(_frameTime, true); - - // update our stats display if we have one - if (_stats != null) { - _stats.update(_timer, _display.getRenderer()); - } - } - - /** - * Called every frame to issue the rendering instructions for this frame. - */ - protected void render (float frameTime) - { - // clear out our previous information - _display.getRenderer().clearStatistics(); - _display.getRenderer().clearBuffers(); - - // draw the root node and all of its children - _display.getRenderer().draw(_root); - - // this would render bounding boxes - // _display.getRenderer().drawBounds(_root); - - // draw our stats atop everything - if (_stats != null) { - _display.getRenderer().draw(_stats); - } - } - - /** - * Called when the application is terminating cleanly after having - * successfully completed initialization and begun the main loop. - */ - protected void cleanup () - { - _display.reset(); - KeyInput.destroyIfInitalized(); - MouseInput.destroyIfInitalized(); - } - - /** - * Closes the display and exits the JVM process. - */ - protected void exit () - { - if (_display != null) { - _display.close(); - } - System.exit(0); - } - - /** - * Prepends the necessary bits onto the supplied path to properly - * locate it in our configuration directory. - */ - protected String getConfigPath (String file) - { - String cfgdir = ".narya"; - String home = System.getProperty("user.home"); - if (!StringUtil.isBlank(home)) { - cfgdir = home + File.separator + cfgdir; - } - // create the configuration directory if it does not already exist - File dir = new File(cfgdir); - if (!dir.exists()) { - dir.mkdir(); - } - return cfgdir + File.separator + file; - } - - /** Provides access to various needed bits. */ - protected JmeContext _ctx = new JmeContext() { - public DisplaySystem getDisplay () { - return _display; - } - - public Renderer getRenderer () { - return _display.getRenderer(); - } - - public CameraHandler getCameraHandler () { - return _camhand; - } - - public Node getGeometry () { - return _geom; - } - - public Node getInterface () { - return _iface; - } - - public InputHandler getInputHandler () { - return _input; - } - - public BRootNode getRootNode () { - return _rnode; - } - }; - - protected Timer _timer; - protected Thread _dispatchThread; - protected Queue _evqueue = Queue.newQueue(); - protected long _lastTick; - protected float _frameTime; - - protected String _api; - protected DisplaySystem _display; - protected Camera _camera; - protected CameraHandler _camhand; - - protected InputHandler _input; - protected BRootNode _rnode; - - protected long _ticksPerFrame; - protected int _targetFPS; - protected boolean _updateEnabled = true, _renderEnabled = true; - protected boolean _finished; - protected int _failures; - - protected Node _root, _geom, _iface; - protected LightState _lights; - protected StatsDisplay _stats; - - /** If we fail 100 frames in a row, stick a fork in ourselves. */ - protected static final int MAX_SUCCESSIVE_FAILURES = 100; -} diff --git a/src/java/com/threerings/jme/JmeCanvasApp.java b/src/java/com/threerings/jme/JmeCanvasApp.java deleted file mode 100644 index fe1b9c8a..00000000 --- a/src/java/com/threerings/jme/JmeCanvasApp.java +++ /dev/null @@ -1,202 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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; - -import java.awt.AWTEvent; -import java.awt.Canvas; -import java.awt.Graphics; -import java.awt.EventQueue; -import java.awt.event.ComponentAdapter; -import java.awt.event.ComponentEvent; - -import org.lwjgl.LWJGLException; - -import com.jme.renderer.lwjgl.LWJGLRenderer; -import com.jme.scene.Node; -import com.jme.system.DisplaySystem; -import com.jmex.awt.JMECanvas; -import com.jmex.awt.JMECanvasImplementor; -import com.jmex.awt.lwjgl.LWJGLCanvas; - -import com.jmex.bui.CanvasRootNode; - -import static com.threerings.jme.Log.log; - -/** - * Extends the basic {@link JmeApp} with the necessary wiring to use the - * GL/AWT bridge to display our GL interface in an AWT component. - */ -public class JmeCanvasApp extends JmeApp -{ - public JmeCanvasApp (int width, int height) - { - _display = DisplaySystem.getDisplaySystem("LWJGL"); - - // create a throwaway canvas so that the display system knows it's - // created, then create our custom canvas - _display.createCanvas(width, height); - try { - _canvas = createCanvas(); - } catch (LWJGLException e) { - log.warning("Failed to create LWJGL canvas [error=" + e + "]."); - } - ((JMECanvas)_canvas).setImplementor(_winimp); - _canvas.setBounds(0, 0, width, height); - _canvas.addComponentListener(new ComponentAdapter() { - public void componentResized (ComponentEvent ce) { - _winimp.resizeCanvas(_canvas.getWidth(), _canvas.getHeight()); - } - }); - } - - /** - * Returns the AWT canvas that contains our GL display. - */ - public Canvas getCanvas () - { - return _canvas; - } - - public void run () - { - Thread t = new Thread() { - public void run () { - while (!_finished) { - // queue up another repaint - _canvas.repaint(); - try { - Thread.sleep(10); - } catch (Exception e) { - } - } - } - }; - t.setDaemon(true); - t.start(); - } - - // documentation inherited from interface RunQueue - public void postRunnable (Runnable r) - { - EventQueue.invokeLater(r); - } - - // documentation inherited from interface RunQueue - public boolean isDispatchThread () - { - return EventQueue.isDispatchThread(); - } - - /** - * Creates and returns the LWJGL canvas instance. - */ - protected Canvas createCanvas () - throws LWJGLException - { - // LWJGL's canvas releases the context after painting. we make it - // current again, because we want it valid when we process events. - // block mouse and keyboard events until the context is valid. - return new LWJGLCanvas() { - public void addNotify () { - super.addNotify(); - disableEvents(MOUSE_KEY_EVENT_MASK); - } - public void update (Graphics g) { - super.update(g); - try { - makeCurrent(); - } catch (LWJGLException e) { - log.warning("Failed to make context current [error=" + - e + "]."); - } - } - protected void initGL () { - super.initGL(); - enableEvents(MOUSE_KEY_EVENT_MASK); - } - }; - } - - // documentation inherited - protected DisplaySystem createDisplay () - { - // we've already created our display earlier so just return it - _api = "LWJGL"; - return _display; - } - - // documentation inherited - protected void initInterface () - { - _iface = new Node("Interface"); - _root.attachChild(_iface); - - _rnode = new CanvasRootNode(_canvas); - _iface.attachChild(_rnode); - } - - /** This is used if we embed our GL display in an AWT component. */ - protected JMECanvasImplementor _winimp = new JMECanvasImplementor() { - public void doSetup () { - super.doSetup(); - - LWJGLRenderer renderer = - new LWJGLRenderer(_canvas.getWidth(), _canvas.getHeight()); - renderer.setHeadless(true); - setRenderer(renderer); - _display.setRenderer(renderer); - _display.getCurrentContext().setupRecords(renderer); - DisplaySystem.updateStates(renderer); - - if (!init()) { - log.warning("JmeCanvasApp init failed."); - } - } - - public void doUpdate () { - } - - public void doRender () { - // here we do our normal frame processing - try { - processFrame(); - // we don't process events as the AWT queue handles them - _failures = 0; - } catch (Throwable t) { - log.warning(t); - // stick a fork in things if we fail too many - // times in a row - if (++_failures > MAX_SUCCESSIVE_FAILURES) { - JmeCanvasApp.this.stop(); - } - } - } - }; - - protected Canvas _canvas; - - protected static final long MOUSE_KEY_EVENT_MASK = - AWTEvent.MOUSE_EVENT_MASK | - AWTEvent.MOUSE_MOTION_EVENT_MASK | - AWTEvent.MOUSE_WHEEL_EVENT_MASK | - AWTEvent.KEY_EVENT_MASK; -} diff --git a/src/java/com/threerings/jme/JmeContext.java b/src/java/com/threerings/jme/JmeContext.java deleted file mode 100644 index f5640710..00000000 --- a/src/java/com/threerings/jme/JmeContext.java +++ /dev/null @@ -1,59 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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; - -import com.jme.input.InputHandler; -import com.jme.renderer.Renderer; -import com.jme.scene.Node; -import com.jme.system.DisplaySystem; - -import com.jmex.bui.BRootNode; - -import com.threerings.jme.camera.CameraHandler; - -/** - * Provides access to the various bits needed by things that operate in - * JME land. - */ -public interface JmeContext -{ - /** Returns the display to which we are rendering. */ - public DisplaySystem getDisplay (); - - /** Returns the renderer being used to draw everything. */ - public Renderer getRenderer (); - - /** Returns the handler for the camera being used to view the scene. */ - public CameraHandler getCameraHandler (); - - /** Returns the main geometry of our scene graph. */ - public Node getGeometry (); - - /** Returns the main interface node of our scene graph. */ - public Node getInterface (); - - /** Returns our main input handler. */ - public InputHandler getInputHandler (); - - /** Returns our UI root node. */ - public BRootNode getRootNode (); -} diff --git a/src/java/com/threerings/jme/Log.java b/src/java/com/threerings/jme/Log.java deleted file mode 100644 index 79ddc4f1..00000000 --- a/src/java/com/threerings/jme/Log.java +++ /dev/null @@ -1,33 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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; - -import com.samskivert.util.Logger; - -/** - * Contains a reference to the log object used by this package. - */ -public class Log -{ - /** We dispatch our log messages through this logger. */ - public static Logger log = Logger.getLogger("com.threerings.nenya.jme"); -} diff --git a/src/java/com/threerings/jme/StatsDisplay.java b/src/java/com/threerings/jme/StatsDisplay.java deleted file mode 100644 index 402e54a5..00000000 --- a/src/java/com/threerings/jme/StatsDisplay.java +++ /dev/null @@ -1,83 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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; - -import com.jme.image.Texture; -import com.jme.renderer.Renderer; -import com.jme.scene.Node; -import com.jme.scene.Text; -import com.jme.scene.state.AlphaState; -import com.jme.scene.state.TextureState; -import com.jme.util.TextureManager; -import com.jme.util.Timer; - -/** - * Tracks and displays render statistics. - */ -public class StatsDisplay extends Node -{ - public StatsDisplay (Renderer renderer) - { - super("StatsNode"); - - // create an alpha state that will allow us to blend the text on - // top of whatever else is below - AlphaState astate = renderer.createAlphaState(); - astate.setBlendEnabled(true); - astate.setSrcFunction(AlphaState.SB_SRC_ALPHA); - astate.setDstFunction(AlphaState.DB_ONE); - astate.setTestEnabled(true); - astate.setTestFunction(AlphaState.TF_GREATER); - astate.setEnabled(true); - - // create a font texture - TextureState font = renderer.createTextureState(); - font.setTexture( - TextureManager.loadTexture( - getClass().getClassLoader().getResource(DEFAULT_JME_FONT), - Texture.MM_LINEAR, Texture.FM_LINEAR)); - font.setEnabled(true); - - _text = new Text("StatsLabel", ""); - _text.setCullMode(CULL_NEVER); - _text.setTextureCombineMode(TextureState.REPLACE); - - attachChild(_text); - setRenderState(font); - setRenderState(astate); - } - - public void update (Timer timer, Renderer renderer) - { - _stats.setLength(0); - _stats.append("FPS: ").append((int)timer.getFrameRate()); - _stats.append(" - ").append(renderer.getStatistics(_temp)); - _text.print(_stats.toString()); - } - - protected Text _text; - protected StringBuilder _stats = new StringBuilder(); - protected StringBuffer _temp = new StringBuffer(); - - protected static final String DEFAULT_JME_FONT = - "rsrc/media/jme/defaultfont.tga"; -} diff --git a/src/java/com/threerings/jme/camera/CameraHandler.java b/src/java/com/threerings/jme/camera/CameraHandler.java deleted file mode 100644 index 47715826..00000000 --- a/src/java/com/threerings/jme/camera/CameraHandler.java +++ /dev/null @@ -1,412 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.camera; - -import com.jme.math.FastMath; -import com.jme.math.Matrix3f; -import com.jme.math.Plane; -import com.jme.math.Vector3f; -import com.jme.renderer.Camera; - -import com.samskivert.util.ObserverList; -import com.threerings.jme.JmeApp; - -/** - * Provides various useful mechanisms for manipulating the camera. - */ -public class CameraHandler -{ - /** - * Creates a new camera handler. The camera begins life at the origin, - * facing in the negative z direction (pointing at the ground). - */ - public CameraHandler (Camera camera) - { - _camera = camera; - resetAxes(); - } - - /** - * Resets the camera orientation to its initial state. - */ - public void resetAxes () - { - _camera.getDirection().set(0, 0, -1); - _camera.getLeft().set(-1, 0, 0); - _camera.getUp().set(0, 1, 0); - _camera.update(); - - _rxdir.set(1, 0, 0); - _rydir.set(0, 1, 0); - } - - /** - * Configures limits on the camera tilt. - */ - public void setTiltLimits (float minAngle, float maxAngle) - { - _minTilt = minAngle; - _maxTilt = maxAngle; - } - - /** - * Configures limits on the distance the camera can be panned. - * - * @param boundViaFrustum if true instead of bounding the camera's - * position, we will compute the intersections of the view frustum with the - * ground plan and bound that rectangle into the specified bounds. - * Note: the camera must generally be pointing down at the ground - * (up to perhaps 45 degrees or so) for this to work. At higher angles the - * back of the view frustum will intersect the ground plane at or near - * infinity. - */ - public void setPanLimits (float minX, float minY, float maxX, float maxY, - boolean boundViaFrustum) - { - _minX = minX; - _minY = minY; - _maxX = maxX; - _maxY = maxY; - _boundViaFrustum = boundViaFrustum; - } - - /** - * Configures the minimum and maximum zoom values allowed for the - * camera. - */ - public void setZoomLimits (float minZoom, float maxZoom) - { - _minZoom = minZoom; - _maxZoom = maxZoom; - } - - /** - * Enables or disables the current set of limits. - */ - public void setLimitsEnabled (boolean enabled) - { - _limitsEnabled = enabled; - } - - /** - * Sets the camera zoom level to a value between zero (zoomed in maximally) - * and 1 (zoomed out maximally). Zoom limits must have already been set up - * via a call to {@link #setZoomLimits}. - */ - public void setZoomLevel (float level) - { -// Log.info("Zoom " + level + " " + _camera.getLocation()); - level = Math.max(0f, Math.min(level, 1f)); - _camera.getLocation().z = _minZ + (_maxZ - _minZ) * level; - _camera.update(); - } - - /** - * Returns the current camera zoom level. - */ - public float getZoomLevel () - { - return (_camera.getLocation().z - _minZ) / (_maxZ - _minZ); - } - - /** - * Adds a camera path observer. - */ - public void addCameraObserver (CameraPath.Observer camobs) - { - _campathobs.add(camobs); - } - - /** - * Removes a camera path observer. - */ - public void removeCameraObserver (CameraPath.Observer camobs) - { - _campathobs.remove(camobs); - } - - /** - * Starts the camera moving along a path which will be updated every tick - * until it is complete. - */ - public void moveCamera (CameraPath path) - { - if (_campath != null) { - _campath.abort(); - _campathobs.apply(new CompletedOp(_campath)); - } - _campath = path; - } - - /** - * Returns true if the camera is currently animating along a path, false if - * it is not. - */ - public boolean cameraIsMoving () - { - return (_campath != null); - } - - /** - * Skips immediately to the end of the current camera path. - */ - public void skipPath () - { - // fake an update far enough into the future to trick the camera path - // into thinking it's done - update(100); - } - - /** - * This is called by the {@link JmeApp} on every frame to allow the handler - * to update the camera as necessary. - */ - public void update (float frameTime) - { - if (_campath != null) { - if (_campath.tick(frameTime)) { - CameraPath opath = _campath; - _campath = null; - _campathobs.apply(new CompletedOp(opath)); - } - } - } - - /** - * Returns the camera being manipulated by this handler. - */ - public Camera getCamera () - { - return _camera; - } - - /** - * Adjusts the camera's location. The specified location will be bounded - * within the current pan and zoom limits. - */ - public void setLocation (Vector3f location) - { - _camera.setLocation(bound(location)); - _camera.update(); - } - - /** - * Pans the camera the specified distance in the x and y directions. These - * distances will be multiplied by the current "view" x and y axes and - * added to the camera's position. - */ - public void panCamera (float x, float y) - { - Vector3f loc = _camera.getLocation(); - loc.addLocal(_rxdir.mult(x, _temp)); - loc.addLocal(_rydir.mult(y, _temp)); - setLocation(loc); - } - - /** - * Zooms the camera in (distance < 0) and out (distance > 0) by the - * specified amount. The distance is multiplied by the camera's current - * direction and added to its current position, which is then bounded into - * the pan and zoom volume. - */ - public void zoomCamera (float distance) - { - Vector3f loc = _camera.getLocation(); - float dist = getGroundPoint().distance(loc), - ndist = Math.min(Math.max(dist + distance, _minZoom), _maxZoom); - if ((distance = ndist - dist) == 0f) { - return; - } - loc.subtractLocal(_camera.getDirection().mult(distance, _temp)); - setLocation(loc); - } - - /** - * Locates the point on the ground at which the camera is "looking" and - * rotates the camera from that point around the specified vector by the - * specified angle. Additionally zooms the camera in (deltaZoom < 0) or out - * (deltaZoom > 0) along its direction of view by the specified amount. - */ - public void rotateCamera ( - Vector3f spot, Vector3f axis, float deltaAngle, float deltaZoom) - { - // get a vector from the camera's current position to the point around - // which we're going to orbit - Vector3f direction = _camera.getLocation().subtract(spot); - - // if we're rotating around the left vector, impose tilt limits - if (axis == _camera.getLeft()) { - float angle = FastMath.asin(_ground.normal.dot(direction) / - direction.length()); - float nangle = Math.min(Math.max(angle + deltaAngle, _minTilt), - _maxTilt); - if ((deltaAngle = nangle - angle) == 0f) { - return; - } - } - - // create a rotation matrix - _rotm.fromAngleAxis(deltaAngle, axis); - - // rotate the direction vector and the camera itself - _rotm.mult(direction, direction); - _rotm.mult(_camera.getUp(), _camera.getUp()); - _rotm.mult(_camera.getLeft(), _camera.getLeft()); - _rotm.mult(_camera.getDirection(), _camera.getDirection()); - - // if we're rotating around the ground normal, we need to update our - // notion of side-to-side and forward for panning - if (axis == _ground.normal) { - _rotm.mult(_rxdir, _rxdir); - _rotm.mult(_rydir, _rydir); - } - - // finally move the camera to its new location, zooming in or out in - // the process - float scale = 1 + (deltaZoom / direction.length()); - direction.scaleAdd(scale, spot); - setLocation(direction); - } - - /** - * Swings the camera perpendicular to the ground normal, around the point - * on the ground at which it is looking. - */ - public void orbitCamera (float deltaAngle) - { - rotateCamera(getGroundPoint(), _ground.normal, deltaAngle, 0); - } - - /** - * Swings the camera perpendicular to its left vector around the point on - * the ground at which it is looking. - */ - public void tiltCamera (float deltaAngle) - { - rotateCamera(getGroundPoint(), _camera.getLeft(), deltaAngle, 0); - } - - /** - * Returns the point on the ground (z = 0) at which the camera is looking. - */ - public Vector3f getGroundPoint () - { - float dist = -1f * _ground.normal.dot(_camera.getLocation()) / - _ground.normal.dot(_camera.getDirection()); - return _camera.getLocation().add(_camera.getDirection().mult(dist)); - } - - /** - * Returns the ground normal. Z is the default ground plane and the normal - * points in the positive z direction. Do not modify this value. - */ - public Vector3f getGroundNormal () - { - return _ground.normal; - } - - protected Vector3f bound (Vector3f loc) - { - if (!_limitsEnabled) { - return loc; - } - if (_boundViaFrustum) { - bound(_camera.getFrustumLeft(), _camera.getFrustumTop(), loc); - bound(_camera.getFrustumLeft(), _camera.getFrustumBottom(), loc); - bound(_camera.getFrustumRight(), _camera.getFrustumTop(), loc); - bound(_camera.getFrustumRight(), _camera.getFrustumBottom(), loc); - } else { - loc.x = Math.max(Math.min(loc.x, _maxX), _minX); - loc.y = Math.max(Math.min(loc.y, _maxY), _minY); - } - loc.z = Math.max(Math.min(loc.z, _maxZ), _minZ); - return loc; - } - - protected void bound (float left, float up, Vector3f loc) - { - // start with the location of the camera moved out into the near - // frustum plane - _temp.set(loc); - _temp.scaleAdd(_camera.getFrustumNear(), _camera.getDirection(), loc); - - // then slide it over to a corner of the near frustum rectangle - _temp.scaleAdd(left, _camera.getLeft(), _temp); - _temp.scaleAdd(up, _camera.getUp(), _temp); - - // turn this into a vector with origin at the camera's location - _temp.subtractLocal(loc); - _temp.normalizeLocal(); - - // determine the intersection of said vector with the ground plane - float dist = -1f * _ground.normal.dot(loc) / _ground.normal.dot(_temp); - _temp.scaleAdd(dist, _temp, loc); - - // we then assume that if the corner of the "viewable ground rectangle" - // is outside our bounds that we can simply adjust the camera location - // by the amount it is out of bounds - if (_temp.x > _maxX) { - loc.x -= (_temp.x - _maxX); - } else if (_temp.x < _minX) { - loc.x += (_minX - _temp.x); - } - if (_temp.y > _maxY) { - loc.y -= (_temp.y - _maxY); - } else if (_temp.y < _minY) { - loc.y += (_minY - _temp.y); - } - } - - /** Used to dispatch {@link CameraPath.Observer#pathCompleted}. */ - protected static class CompletedOp implements ObserverList.ObserverOp - { - public CompletedOp (CameraPath path) { - _path = path; - } - public boolean apply (CameraPath.Observer observer) { - return observer.pathCompleted(_path); - } - protected CameraPath _path; - } - - protected Camera _camera; - protected CameraPath _campath; - protected ObserverList _campathobs = ObserverList.newSafeInOrder(); - - protected Matrix3f _rotm = new Matrix3f(); - protected Vector3f _temp = new Vector3f(); - - protected boolean _boundViaFrustum, _limitsEnabled = true; - protected float _minX = -Float.MAX_VALUE, _maxX = Float.MAX_VALUE; - protected float _minY = -Float.MAX_VALUE, _maxY = Float.MAX_VALUE; - protected float _minZ = -Float.MAX_VALUE, _maxZ = Float.MAX_VALUE; - protected float _minZoom = 0f, _maxZoom = Float.MAX_VALUE; - protected float _minTilt = -Float.MAX_VALUE, _maxTilt = Float.MAX_VALUE; - - protected Vector3f _rxdir = new Vector3f(1, 0, 0); - protected Vector3f _rydir = new Vector3f(0, 1, 0); - - protected static final Vector3f _xdir = new Vector3f(1, 0, 0); - protected static final Vector3f _ydir = new Vector3f(0, 1, 0); - - protected static final Plane _ground = new Plane(new Vector3f(0, 0, 1), 0); -} diff --git a/src/java/com/threerings/jme/camera/CameraPath.java b/src/java/com/threerings/jme/camera/CameraPath.java deleted file mode 100644 index fadbcd76..00000000 --- a/src/java/com/threerings/jme/camera/CameraPath.java +++ /dev/null @@ -1,67 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.camera; - -/** - * Used to move the camera along a particular path. - */ -public abstract class CameraPath -{ - /** Used to inform observers when a camera path is completed or aborted. */ - public interface Observer - { - /** - * Called when this path is finished (potentially early because another - * path was set before this path completed). - * - * @param path the path that was completed. - * - * @return true if the observer should remain in the list, false if it - * should be removed following this notification. - */ - public boolean pathCompleted (CameraPath path); - } - - /** - * This is called on every frame to allow the path to adjust the position - * of the camera. - * - * @return true if the path is completed and can be disposed, false if it - * is not yet completed. - */ - public abstract boolean tick (float secondsSince); - - /** - * Called if this path is aborted prior to completion due to being replaced - * by a new camera path. - */ - public void abort () - { - } - - protected CameraPath (CameraHandler camhand) - { - _camhand = camhand; - } - - protected CameraHandler _camhand; -} diff --git a/src/java/com/threerings/jme/camera/GodViewHandler.java b/src/java/com/threerings/jme/camera/GodViewHandler.java deleted file mode 100644 index 9a7a4dce..00000000 --- a/src/java/com/threerings/jme/camera/GodViewHandler.java +++ /dev/null @@ -1,202 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.camera; - -import com.jme.math.FastMath; - -import com.jme.input.InputHandler; -import com.jme.input.KeyBindingManager; -import com.jme.input.KeyInput; -import com.jme.input.action.*; -import com.jme.input.action.InputActionEvent; - -/** - * Sets up camera controls for moving around from a top-down perspective, - * suitable for strategy games and their ilk. The "ground" is assumed to be the - * XY plane. - */ -public class GodViewHandler extends InputHandler -{ - /** - * Creates the handler. - * - * @param camhand The camera to move with this handler. - */ - public GodViewHandler (CameraHandler camhand) - { - _camhand = camhand; - setKeyBindings(); - addActions(); - } - - protected void setKeyBindings () - { - KeyBindingManager keyboard = KeyBindingManager.getKeyBindingManager(); - - // the key bindings for the pan actions - keyboard.set("forward", KeyInput.KEY_W); - keyboard.set("arrow_forward", KeyInput.KEY_UP); - keyboard.set("backward", KeyInput.KEY_S); - keyboard.set("arrow_backward", KeyInput.KEY_DOWN); - keyboard.set("left", KeyInput.KEY_A); - keyboard.set("arrow_left", KeyInput.KEY_LEFT); - keyboard.set("right", KeyInput.KEY_D); - keyboard.set("arrow_right", KeyInput.KEY_RIGHT); - - // the key bindings for the zoom actions - keyboard.set("zoomIn", KeyInput.KEY_UP); - keyboard.set("zoomOut", KeyInput.KEY_DOWN); - - // the key bindings for the orbit actions - keyboard.set("turnRight", KeyInput.KEY_RIGHT); - keyboard.set("turnLeft", KeyInput.KEY_LEFT); - - // the key bindings for the tilt actions - keyboard.set("tiltForward", KeyInput.KEY_HOME); - keyboard.set("tiltBack", KeyInput.KEY_END); - - keyboard.set("screenshot", KeyInput.KEY_F12); - } - - protected void addActions () - { - addAction(new KeyScreenShotAction(), "screenshot", false); - addPanActions(); - addZoomActions(); - addOrbitActions(); - addTiltActions(); - } - - /** - * Adds actions for panning the camera around the scene. - */ - protected void addPanActions () - { - InputAction forward = new InputAction() { - public void performAction (InputActionEvent evt) { - _camhand.panCamera(0, speed * evt.getTime()); - } - }; - forward.setSpeed(0.5f); - addAction(forward, "forward", true); - addAction(forward, "arrow_forward", true); - - InputAction backward = new InputAction() { - public void performAction (InputActionEvent evt) { - _camhand.panCamera(0, -speed * evt.getTime()); - } - }; - backward.setSpeed(0.5f); - addAction(backward, "backward", true); - addAction(backward, "arrow_backward", true); - - InputAction left = new InputAction() { - public void performAction (InputActionEvent evt) { - _camhand.panCamera(-speed * evt.getTime(), 0); - } - }; - left.setSpeed(0.5f); - addAction(left, "left", true); - addAction(left, "arrow_left", true); - - InputAction right = new InputAction() { - public void performAction (InputActionEvent evt) { - _camhand.panCamera(speed * evt.getTime(), 0); - } - }; - right.setSpeed(0.5f); - addAction(right, "right", true); - addAction(right, "arrow_right", true); - } - - /** - * Adds actions for zooming the camaera in and out. - */ - protected void addZoomActions () - { - InputAction zoomIn = new InputAction() { - public void performAction (InputActionEvent evt) { - _camhand.zoomCamera(-speed * evt.getTime()); - } - }; - zoomIn.setSpeed(0.5f); - addAction(zoomIn, "zoomIn", true); - - InputAction zoomOut = new InputAction() { - public void performAction (InputActionEvent evt) { - _camhand.zoomCamera(speed * evt.getTime()); - } - }; - zoomOut.setSpeed(0.5f); - addAction(zoomOut, "zoomOut", true); - } - - /** - * Adds actions for orbiting the camera around the viewpoint. - */ - protected void addOrbitActions () - { - addAction(new OrbitAction(-FastMath.PI / 2), "turnRight", true); - addAction(new OrbitAction(FastMath.PI / 2), "turnLeft", true); - } - - /** - * Adds actions for tilting the camera (rotating around the yaw axis). - */ - protected void addTiltActions () - { - addAction(new TiltAction(-FastMath.PI / 2), "tiltForward", true); - addAction(new TiltAction(FastMath.PI / 2), "tiltBack", true); - } - - protected class OrbitAction extends InputAction - { - public OrbitAction (float radPerSec) - { - _radPerSec = radPerSec; - } - - public void performAction (InputActionEvent evt) - { - _camhand.orbitCamera(_radPerSec * evt.getTime()); - } - - protected float _radPerSec; - } - - protected class TiltAction extends InputAction - { - public TiltAction (float radPerSec) - { - _radPerSec = radPerSec; - } - - public void performAction (InputActionEvent evt) - { - _camhand.tiltCamera(_radPerSec * evt.getTime()); - } - - protected float _radPerSec; - } - - protected CameraHandler _camhand; -} diff --git a/src/java/com/threerings/jme/camera/PanPath.java b/src/java/com/threerings/jme/camera/PanPath.java deleted file mode 100644 index cda0b4af..00000000 --- a/src/java/com/threerings/jme/camera/PanPath.java +++ /dev/null @@ -1,87 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.camera; - -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.renderer.Camera; - -/** - * Pans the camera to the specified location in the specified amount of time. - */ -public class PanPath extends CameraPath -{ - /** - * Creates a panning path for the specified camera that will retain the - * camera's current orientation. - * - * @param target the target position for the camera. - * @param duration the number of seconds in which to pan the camera. - */ - public PanPath (CameraHandler camhand, Vector3f target, float duration) - { - this(camhand, target, null, duration); - } - - /** - * Creates a panning path for the specified camera. - * - * @param target the target position for the camera. - * @param trot the target rotation for the camera (or null to - * keep its current orientation) - * @param duration the number of seconds in which to pan the camera. - */ - public PanPath (CameraHandler camhand, Vector3f target, Quaternion trot, - float duration) - { - super(camhand); - - Camera cam = camhand.getCamera(); - _start = new Vector3f(cam.getLocation()); - _velocity = target.subtract(_start); - _velocity.divideLocal(duration); - if (trot != null) { - _irot = new Quaternion(); - _irot.fromAxes(cam.getLeft(), cam.getUp(), cam.getDirection()); - _trot = trot; - } - - _duration = duration; - } - - // documentation inherited - public boolean tick (float secondsSince) - { - _elapsed = Math.min(_elapsed + secondsSince, _duration); - _camloc.scaleAdd(_elapsed, _velocity, _start); - _camhand.setLocation(_camloc); - if (_irot != null) { - _camhand.getCamera().setAxes(_axes.slerp(_irot, _trot, - _elapsed / _duration)); - } - return (_elapsed >= _duration); - } - - protected Vector3f _start, _velocity, _camloc = new Vector3f(); - protected Quaternion _irot, _trot, _axes = new Quaternion(); - protected float _elapsed, _duration; -} diff --git a/src/java/com/threerings/jme/camera/SplinePath.java b/src/java/com/threerings/jme/camera/SplinePath.java deleted file mode 100644 index 880552f4..00000000 --- a/src/java/com/threerings/jme/camera/SplinePath.java +++ /dev/null @@ -1,111 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.camera; - -import com.jme.math.Vector3f; -import com.jme.renderer.Camera; - -/** - * Moves the camera along a cubic Hermite spline path defined by the start and - * end locations and directions. Spline formulas obtained from - * Wikipedia. - */ -public class SplinePath extends CameraPath -{ - /** - * Creates a cubic spline path for the camera to follow. - * - * @param tloc the target location - * @param tdir the target direction - * @param axis the heading axis (typically {@link Vector3f#UNIT_Z}) - * @param duration the duration of the path - * @param tension the tension parameter, which can range from zero to one: - * higher tension values create a more direct path with a sharper turn, - * lower values create a rounder path with a smoother turn - */ - public SplinePath (CameraHandler camhand, Vector3f tloc, - Vector3f tdir, Vector3f axis, float duration, float tension) - { - super(camhand); - - // get the spline function coefficients - Camera cam = camhand.getCamera(); - _p0 = new Vector3f(cam.getLocation()); - _p1 = new Vector3f(tloc); - float tscale = (1f - tension) * _p0.distance(_p1); - _m0 = cam.getDirection().mult(tscale); - _m1 = tdir.mult(tscale); - - _axis = axis; - _duration = duration; - } - - // documentation inherited - public boolean tick (float secondsSince) - { - _elapsed = Math.min(_elapsed + secondsSince, _duration); - float t = _elapsed / _duration, t2 = t*t, t3 = t2*t, - h00 = 2*t3 - 3*t2 + 1, - h00p = 6*t2 - 6*t, - h10 = t3 - 2*t2 + t, - h10p = 3*t2 - 4*t + 1, - h01 = -2*t3 + 3*t2, - h01p = -6*t2 + 6*t, - h11 = t3 - t2, - h11p = 3*t2 - 2*t; - - // take the derivative to find the direction - _p0.mult(h00p, _dir); - _dir.scaleAdd(h10p, _m0, _dir); - _dir.scaleAdd(h01p, _p1, _dir); - _dir.scaleAdd(h11p, _m1, _dir); - _dir.normalizeLocal(); - - // evaluate the spline function to find the location - _p0.mult(h00, _loc); - _loc.scaleAdd(h10, _m0, _loc); - _loc.scaleAdd(h01, _p1, _loc); - _loc.scaleAdd(h11, _m1, _loc); - - // compute the left and up vectors using the direction and - // axis vectors - Camera cam = _camhand.getCamera(); - _axis.cross(_dir, _left); - _left.normalizeLocal(); - _dir.cross(_left, _up); - - // update the camera's location and orientation - cam.setFrame(_loc, _left, _up, _dir); - - return _elapsed >= _duration; - } - - /** The parameters of the spline. */ - Vector3f _p0, _m0, _p1, _m1, _axis; - - /** Working vectors. */ - Vector3f _loc = new Vector3f(), _left = new Vector3f(), - _up = new Vector3f(), _dir = new Vector3f(); - - /** The elapsed time and total duration. */ - float _elapsed, _duration; -} diff --git a/src/java/com/threerings/jme/camera/SwingPath.java b/src/java/com/threerings/jme/camera/SwingPath.java deleted file mode 100644 index 61ccbcb4..00000000 --- a/src/java/com/threerings/jme/camera/SwingPath.java +++ /dev/null @@ -1,167 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.camera; - -import com.jme.math.FastMath; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; - -import static com.threerings.jme.Log.log; - -/** - * Swings the camera around a point of interest (which should be somewhere - * along the camera's view vector). Also optionally pans the camera and/or - * zooms it in or out (moves it along its view vector) in the process. - * - *

- */ -public class SwingPath extends CameraPath -{ - /** - * Creates a rotating, zooming path for the specified camera. - * - * @param spot the point of interest around which to swing the camera. - * @param axis the axis around which to rotate the camera. - * @param angle the angle through which to rotate the camera. - * @param angvel the (absolute value of the) velocity at which to rotate - * the camera (in radians per second). - * @param zoom the distance to zoom along the camera's view axis (negative - * = in, positive = out). - */ - public SwingPath (CameraHandler camhand, Vector3f spot, Vector3f axis, - float angle, float angvel, float zoom) - { - this(camhand, spot, axis, angle, angvel, null, 0f, null, zoom); - } - - /** - * Creates a rotating, panning, zooming path for the specified camera. - * - * @param spot the point of interest around which to swing the camera. - * @param paxis the primary axis around which to rotate the camera. - * @param pangle the angle through which to rotate the camera about the - * primary axis. - * @param angvel the (absolute value of the) velocity at which to rotate - * the camera (in radians per second) about the primary angle. - * @param saxis the secondary axis around which to rotate the camera, or - * null for none - * @param sangle the angle through which to rotate the camera about the - * secondary axis - * @param pan the amount to pan the camera, or null for none - * @param zoom the distance to zoom along the camera's view axis (negative - * = in, positive = out). - */ - public SwingPath (CameraHandler camhand, Vector3f spot, Vector3f paxis, - float pangle, float angvel, Vector3f saxis, float sangle, - Vector3f pan, float zoom) - { - super(camhand); - - if (pangle == 0) { - log.warning("Requested to swing camera through zero degrees " + - "[spot=" + spot + ", paxis=" + paxis + - ", angvel=" + angvel + ", zoom=" + zoom + "]."); - pangle = 0.0001f; - } - if (angvel <= 0) { - log.warning("Requested to swing camera with invalid velocity " + - "[spot=" + spot + ", paxis=" + paxis + ", pangle=" + - pangle + ", angvel=" + angvel + ", zoom=" + zoom + - "]."); - angvel = FastMath.PI; - } - - _spot = new Vector3f(spot); - _paxis = paxis; - _pangle = pangle; - _pangvel = (pangle > 0) ? angvel : -1 * angvel; - _saxis = (saxis == null) ? null : new Vector3f(saxis); - _sangle = sangle; - _sangvel = _sangle * _pangvel / _pangle; - _pan = pan; - if (_pan != null) { - _panvel = _pan.mult(_pangvel / _pangle); - _panned = new Vector3f(); - } - _zoom = zoom; - _zoomvel = _zoom * _pangvel / _pangle; - -// Log.info("Swinging camera [angle=" + _angle + ", angvel=" + _angvel + -// ", zoom=" + _zoom + ", zoomvel=" + _zoomvel + "]."); - } - - // documentation inherited - public boolean tick (float secondsSince) - { - float deltaPAngle = (secondsSince * _pangvel); - float deltaSAngle = (secondsSince * _sangvel); - float deltaZoom = (secondsSince * _zoomvel); - _protated += deltaPAngle; - _srotated += deltaSAngle; - _zoomed += deltaZoom; - if (_pan != null) { - _panvel.mult(secondsSince, _deltaPan); - _panned.addLocal(_deltaPan); - } - - // clamp our rotation at the target angle and determine whether or not - // we're done - boolean done = false; - if (_pangle > 0 && _protated > _pangle || - _pangle < 0 && _protated < _pangle) { - deltaPAngle -= (_protated - _pangle); - deltaSAngle -= (_srotated - _sangle); - deltaZoom -= (_zoomed - _zoom); - if (_pan != null) { - _deltaPan.subtractLocal(_panned).addLocal(_pan); - } - _protated = _pangle; - _srotated = _sangle; - _panned = _pan; - _zoomed = _zoom; - done = true; - } - - // have the camera handler do the necessary rotating, panning, zooming - if (_pan != null) { - _camhand.setLocation( - _camhand.getCamera().getLocation().addLocal(_deltaPan)); - _spot.addLocal(_deltaPan); - } - _camhand.rotateCamera(_spot, _paxis, deltaPAngle, deltaZoom); - if (_saxis != null) { - _rot.fromAngleAxis(deltaPAngle, _paxis).multLocal(_saxis); - _camhand.rotateCamera(_spot, _saxis, deltaSAngle, 0f); - } - - return done; - } - - protected Vector3f _spot, _paxis, _saxis; - protected float _pangle, _pangvel, _protated; - protected float _sangle, _sangvel, _srotated; - protected Vector3f _pan, _panvel, _panned; - protected float _zoom, _zoomvel, _zoomed; - - protected Quaternion _rot = new Quaternion(); - protected Vector3f _deltaPan = new Vector3f(); -} diff --git a/src/java/com/threerings/jme/camera/rotate_zoom.dia b/src/java/com/threerings/jme/camera/rotate_zoom.dia deleted file mode 100644 index 603bd5cc..00000000 Binary files a/src/java/com/threerings/jme/camera/rotate_zoom.dia and /dev/null differ diff --git a/src/java/com/threerings/jme/camera/rotate_zoom.png b/src/java/com/threerings/jme/camera/rotate_zoom.png deleted file mode 100644 index d04c2484..00000000 Binary files a/src/java/com/threerings/jme/camera/rotate_zoom.png and /dev/null differ diff --git a/src/java/com/threerings/jme/chat/ChatView.java b/src/java/com/threerings/jme/chat/ChatView.java deleted file mode 100644 index 5ba8af53..00000000 --- a/src/java/com/threerings/jme/chat/ChatView.java +++ /dev/null @@ -1,203 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.chat; - -import com.jme.renderer.ColorRGBA; - -import com.jmex.bui.BButton; -import com.jmex.bui.BContainer; -import com.jmex.bui.BTextArea; -import com.jmex.bui.BTextField; -import com.jmex.bui.event.ActionEvent; -import com.jmex.bui.event.ActionListener; -import com.jmex.bui.layout.BorderLayout; -import com.jmex.bui.layout.GroupLayout; - -import com.threerings.crowd.chat.client.ChatDirector; -import com.threerings.crowd.chat.client.ChatDisplay; -import com.threerings.crowd.chat.client.SpeakService; -import com.threerings.crowd.chat.data.ChatCodes; -import com.threerings.crowd.chat.data.ChatMessage; -import com.threerings.crowd.chat.data.SystemMessage; -import com.threerings.crowd.chat.data.UserMessage; -import com.threerings.crowd.data.PlaceObject; - -import com.threerings.jme.JmeContext; - -import static com.threerings.jme.Log.log; - -/** - * Displays chat messages and allows for their input. - */ -public class ChatView extends BContainer - implements ChatDisplay -{ - public ChatView (JmeContext ctx, ChatDirector chatdtr) - { - _chatdtr = chatdtr; - setLayoutManager(new BorderLayout(2, 2)); - add(_text = new BTextArea(), BorderLayout.CENTER); - _incont = new BContainer(GroupLayout.makeHStretch()); - add(_incont, BorderLayout.SOUTH); - _incont.add(_input = new BTextField()); - _input.addListener(_inlist); - } - - public void willEnterPlace (PlaceObject plobj) - { - setSpeakService(plobj.speakService, null); - } - - public void didLeavePlace (PlaceObject plobj) - { - clearSpeakService(); - } - - public void setSpeakService (SpeakService spsvc, String localType) - { - if (spsvc != null) { - _spsvc = spsvc; - _localType = localType; - _chatdtr.addChatDisplay(this); - } - } - - public void clearSpeakService () - { - if (_spsvc != null) { - _chatdtr.removeChatDisplay(this); - _spsvc = null; - _localType = null; - } - } - - public void setChatButton (BButton button) - { - _inBtn = button; - _incont.add(_inBtn, GroupLayout.FIXED); - _inBtn.addListener(_inlist); - } - - /** - * Instructs our chat input field to request focus. - */ - public void requestFocus () - { - _input.requestFocus(); - } - - // documentation inherited from interface ChatDisplay - public void clear () - { - if (_input.hasFocus() || _inBtn.hasFocus()) { - _text.clearText(); - } - } - - // documentation inherited from interface ChatDisplay - public boolean displayMessage (ChatMessage msg, boolean alreadyDisplayed) - { - // we may be restricted in the chat types we handle - if (!handlesType(msg.localtype)) { - return false; - } - - if (msg instanceof UserMessage) { - UserMessage umsg = (UserMessage) msg; - if (ChatCodes.USER_CHAT_TYPE.equals(umsg.localtype)) { - append("[" + umsg.speaker + " whispers] ", ColorRGBA.green); - append(umsg.message + "\n"); - } else { - append("<" + umsg.speaker + "> ", ColorRGBA.blue); - append(umsg.message + "\n"); - } - return true; - - } else if (msg instanceof SystemMessage) { - append(msg.message + "\n", ColorRGBA.red); - return true; - - } else { - log.warning("Received unknown message type: " + msg + "."); - return false; - } - } - - // documentation inherited - public void setEnabled (boolean enabled) - { - _input.setEnabled(enabled); - } - - protected void displayError (String message) - { - append(message + "\n", ColorRGBA.red); - } - - protected void append (String text, ColorRGBA color) - { - _text.appendText(text, color); - } - - protected void append (String text) - { - _text.appendText(text); - } - - protected boolean handlesType (String localType) - { - return _localType == null || _localType.equals(localType); - } - - protected boolean handleInput (String text) - { - if (text.length() == 0) { - // no empty banter - return false; - } - String msg = _chatdtr.requestChat(_spsvc, text, true); - if (msg.equals(ChatCodes.SUCCESS)) { - return true; - } else { - _chatdtr.displayFeedback(null, msg); - return false; - } - } - - /** Used to trigger sending chat (on return key or button press). */ - protected ActionListener _inlist = new ActionListener() { - public void actionPerformed (ActionEvent event) { - if (handleInput(_input.getText())) { - _input.setText(""); - } - } - }; - - protected ChatDirector _chatdtr; - protected SpeakService _spsvc; - protected String _localType; - - protected BTextArea _text; - protected BContainer _incont; - protected BTextField _input; - protected BButton _inBtn; -} diff --git a/src/java/com/threerings/jme/effect/FadeInOutEffect.java b/src/java/com/threerings/jme/effect/FadeInOutEffect.java deleted file mode 100644 index 79cd62be..00000000 --- a/src/java/com/threerings/jme/effect/FadeInOutEffect.java +++ /dev/null @@ -1,147 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.effect; - -import com.jme.math.Vector3f; -import com.jme.renderer.ColorRGBA; -import com.jme.renderer.Renderer; -import com.jme.scene.Node; -import com.jme.scene.shape.Quad; -import com.jme.scene.state.AlphaState; -import com.jme.system.DisplaySystem; - -import com.threerings.jme.util.LinearTimeFunction; -import com.threerings.jme.util.TimeFunction; - -/** - * Fades a supplied quad (or one that covers the screen) in from a solid color - * or out to a solid color. - */ -public class FadeInOutEffect extends Node -{ - public FadeInOutEffect (ColorRGBA color, float startAlpha, float endAlpha, - float duration, boolean overUI) - { - this(color, new LinearTimeFunction(startAlpha, endAlpha, duration), - overUI); - } - - public FadeInOutEffect (ColorRGBA color, TimeFunction alphaFunc, - boolean overUI) - { - this(null, color, alphaFunc, overUI); - setQuad(createCurtain()); - } - - public FadeInOutEffect (Quad quad, ColorRGBA color, TimeFunction alphaFunc, - boolean overUI) - { - super("FadeInOut"); - - _color = new ColorRGBA( - color.r, color.g, color.b, alphaFunc.getValue(0)); - _alphaFunc = alphaFunc; - - DisplaySystem ds = DisplaySystem.getDisplaySystem(); - _astate = ds.getRenderer().createAlphaState(); - _astate.setBlendEnabled(true); - _astate.setSrcFunction(AlphaState.SB_SRC_ALPHA); - _astate.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); - _astate.setEnabled(true); - - if (quad != null) { - setQuad(quad); - } - - setRenderQueueMode(Renderer.QUEUE_ORTHO); - setZOrder(overUI ? -1 : 1); - } - - /** - * Configures the quad that will be faded in or out. - */ - public void setQuad (Quad quad) - { - attachChild(quad); - quad.setDefaultColor(_color); - quad.setRenderState(_astate); - quad.updateRenderState(); - } - - /** - * Allows the fade to be paused. - */ - public void setPaused (boolean paused) - { - _paused = paused; - } - - /** - * Indicates whether or not the fade is paused. - */ - public boolean isPaused () - { - return _paused; - } - - // documentation inherited - public void updateGeometricState (float time, boolean initiator) - { - super.updateGeometricState(time, initiator); - if (_paused) { - return; - } - - float alpha = _alphaFunc.getValue(time); - _color.a = Math.min(1f, Math.max(0f, alpha)); - if (_alphaFunc.isComplete()) { - fadeComplete(); - } - } - - /** - * Called (only once) when we have reached the end of our fade. - * Automatically detaches this effect from the hierarchy. - */ - protected void fadeComplete () - { - getParent().detachChild(this); - } - - /** - * Creates a quad that covers the entire screen for full-screen fades. - */ - protected Quad createCurtain () - { - // create a quad the size of the screen - DisplaySystem ds = DisplaySystem.getDisplaySystem(); - float width = ds.getWidth(), height = ds.getHeight(); - Quad curtain = new Quad("curtain" + hashCode(), width, height); - curtain.setLocalTranslation(new Vector3f(width/2, height/2, 0f)); - return curtain; - } - - protected ColorRGBA _color; - protected AlphaState _astate; - protected TimeFunction _alphaFunc; - protected boolean _paused; -} diff --git a/src/java/com/threerings/jme/effect/WindowSlider.java b/src/java/com/threerings/jme/effect/WindowSlider.java deleted file mode 100644 index 7b397703..00000000 --- a/src/java/com/threerings/jme/effect/WindowSlider.java +++ /dev/null @@ -1,157 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.effect; - -import com.jme.scene.Node; -import com.jme.system.DisplaySystem; - -import com.jmex.bui.BWindow; - -import com.threerings.jme.util.LinearTimeFunction; -import com.threerings.jme.util.TimeFunction; - -/** - * Slides a window onto the center of the screen from offscreen or offscreen - * from the center of the screen. - */ -public class WindowSlider extends Node -{ - // slides from the specified location into the center of the screen - public static final int FROM_TOP = 0; - public static final int FROM_RIGHT = 1; - - // slides from the center of the screen off screen in the specified direction - public static final int TO_TOP = 2; - public static final int TO_RIGHT = 3; - - // slides down from the specified location stopping when whole window is visible (window - // remains "stuck" to the edge from which it slid in) - public static final int FROM_TOP_STICKY = 4; - - /** - * Creates a window slider with the specified mode and window that will - * slide the window either onto or off of the screen in the specified - * number of seconds. - * - * @param dx an offset applied to the starting or destination position - * along the x axis (starting for sliding off, destination for sliding on). - * @param dy an offset applied along the y axis. - */ - public WindowSlider (BWindow window, int mode, float duration, - int dx, int dy) - { - super("slider"); - - DisplaySystem ds = DisplaySystem.getDisplaySystem(); - int swidth = ds.getWidth(), sheight = ds.getHeight(); - int wwidth = window.getWidth(), wheight = window.getHeight(); - - int start = 0, end = 0; - switch (mode) { - case FROM_TOP: - start = sheight+wheight; - end = (sheight-wheight)/2 + dy; - window.setLocation((swidth-wwidth)/2 + dx, start); - break; - - case FROM_RIGHT: - start = swidth+wwidth; - end = (swidth-wwidth)/2 + dx; - window.setLocation(start, (sheight-wheight)/2 + dy); - break; - - case TO_TOP: - start = (sheight-wheight)/2 + dy; - end = sheight+wheight; - window.setLocation((swidth-wwidth)/2 + dx, start); - break; - - case TO_RIGHT: - start = (swidth-wwidth)/2 + dx; - end = swidth+wwidth; - window.setLocation(start, (sheight-wheight)/2 + dy); - break; - - case FROM_TOP_STICKY: - start = sheight+wheight; - end = sheight-wheight + dy; - window.setLocation((swidth-wwidth)/2 + dx, start); - } - - _mode = mode; - _window = window; - _tfunc = new LinearTimeFunction(start, end, duration); - } - - /** - * Allows some number of ticks to be skipped to give the window that is - * being slid a chance to be layed out before we start keeping track of - * time. The layout may be expensive and cause the frame rate to drop for a - * frame or two, thus booching our smooth sliding onto the screen. - */ - public void setSkipTicks (int skipTicks) - { - _skipTicks = skipTicks; - } - - // documentation inherited - public void updateGeometricState (float time, boolean initiator) - { - super.updateGeometricState(time, initiator); - - // skip ticks as long as we need to - if (_skipTicks-- > 0) { - return; - } - - int winx, winy; - if (_mode % 2 == 1) { - winx = (int)_tfunc.getValue(time); - winy = _window.getY(); - } else { - winx = _window.getX(); - winy = (int)_tfunc.getValue(time); - } - _window.setLocation(winx, winy); - - if (_tfunc.isComplete()) { - slideComplete(); - } - } - - /** - * Called (only once) when we have reached the end of our slide. - * Automatically detaches this effect from the hierarchy. - */ - protected void slideComplete () - { - getParent().detachChild(this); - } - - protected int _mode; - protected BWindow _window; - protected TimeFunction _tfunc; - - // skip two frames by default as that generally handles the normal window - // layout process - protected int _skipTicks = 2; -} diff --git a/src/java/com/threerings/jme/model/BillboardController.java b/src/java/com/threerings/jme/model/BillboardController.java deleted file mode 100644 index 60d14738..00000000 --- a/src/java/com/threerings/jme/model/BillboardController.java +++ /dev/null @@ -1,177 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Properties; - -import com.jme.math.FastMath; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.renderer.Camera; -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.system.DisplaySystem; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -/** - * Orients its target towards the camera plane. - */ -public class BillboardController extends ModelController -{ - /** Determines how the billboard is rotated. */ - public enum Alignment { - DIR_X_POS_Z(false, true), - DIR_X_DIR_Z(false, false), - POS_X_POS_Z(true, true), - DIR_Z(false), - POS_Z(true); - - /** Determines whether rotation is limited to the Z axis. */ - public boolean isAxial () { - return _axial; - } - - /** Determines whether to tilt in the direction of the vector from the eyepoint to the - * target's origin (the eye vector) as opposed to the camera direction. */ - public boolean isEyeRelativeX () { - return _eyeRelativeX; - } - - /** Determines whether to swivel in the direction of the eye vector as opposed to the - * camera direction. */ - public boolean isEyeRelativeZ () { - return _eyeRelativeZ; - } - - Alignment (boolean eyeRelativeX, boolean eyeRelativeZ) { - _eyeRelativeX = eyeRelativeX; - _eyeRelativeZ = eyeRelativeZ; - } - - Alignment (boolean eyeRelativeZ) { - _axial = true; - _eyeRelativeZ = eyeRelativeZ; - } - - protected boolean _axial, _eyeRelativeX, _eyeRelativeZ; - }; - - @Override - public void configure (Properties props, Spatial target) - { - super.configure(props, target); - _alignment = Enum.valueOf(Alignment.class, - props.getProperty("alignment", "dir_x_pos_z").toUpperCase()); - } - - // documentation inherited - public void update (float time) - { - Camera cam = DisplaySystem.getDisplaySystem().getRenderer().getCamera(); - if (!isActive() || cam == null) { - return; - } - if (_alignment.isEyeRelativeZ()) { - _target.getWorldTranslation().subtract(cam.getLocation(), _yvec); - } else { - _yvec.set(cam.getDirection()); - } - _zvec.set(_alignment.isAxial() ? Vector3f.UNIT_Z : cam.getUp()); - if (_alignment.isEyeRelativeX()) { - // use the forward vector as-is - _yvec.normalizeLocal().cross(_zvec, _xvec); - if (_xvec.length() < FastMath.FLT_EPSILON) { - return; - } - _xvec.normalizeLocal().cross(_yvec, _zvec); - - } else { - // project the forward vector onto the up plane - _yvec.scaleAdd(-_zvec.dot(_yvec), _zvec, _yvec); - if (_yvec.length() < FastMath.FLT_EPSILON) { - return; - } - _yvec.normalizeLocal().cross(_zvec, _xvec); - } - // compute the world rotation with the axes and rotate into - // parent's coordinate system - Quaternion lrot = _target.getLocalRotation(); - lrot.fromAxes(_xvec, _yvec, _zvec); - Spatial parent = _target.getParent(); - if (parent == null) { - _rot.loadIdentity(); - } else { - _rot.set(parent.getWorldRotation()).inverseLocal(); - } - _rot.mult(lrot, lrot); - } - - @Override - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - BillboardController bstore; - if (store == null) { - bstore = new BillboardController(); - } else { - bstore = (BillboardController)store; - } - super.putClone(bstore, properties); - bstore._alignment = _alignment; - return bstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - _alignment = Enum.valueOf(Alignment.class, - capsule.readString("alignment", "DIR_X_POS_Z")); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_alignment.name(), "alignment", "DIR_X_POS_Z"); - } - - /** The alignment mode. */ - protected Alignment _alignment; - - /** A temporary quaternion. */ - protected Quaternion _rot = new Quaternion(); - - /** Temporary axis vectors. */ - protected Vector3f _xvec = new Vector3f(), _yvec = new Vector3f(), _zvec = new Vector3f(); - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/EmissionController.java b/src/java/com/threerings/jme/model/EmissionController.java deleted file mode 100644 index d353fbd1..00000000 --- a/src/java/com/threerings/jme/model/EmissionController.java +++ /dev/null @@ -1,97 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Properties; - -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -/** - * A model controller whose target represents an emitter. - */ -public abstract class EmissionController extends ModelController -{ - @Override - public void configure (Properties props, Spatial target) - { - super.configure(props, target); - _hideTarget = Boolean.parseBoolean( - props.getProperty("hide_target", "true")); - } - - @Override - public void init (Model model) - { - super.init(model); - if (_hideTarget) { - _target.setCullMode(Spatial.CULL_ALWAYS); - if (_target instanceof ModelNode) { - // make sure the node isn't turned back on by an - // animation - ((ModelNode)_target).setForceCull(true); - } - } - } - - @Override - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - if (store == null) { - return null; - } - EmissionController estore = (EmissionController)store; - super.putClone(estore, properties); - estore._hideTarget = _hideTarget; - return estore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - _hideTarget = capsule.readBoolean("hideTarget", true); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_hideTarget, "hideTarget", true); - } - - /** Whether or not the target should be hidden from view. */ - protected boolean _hideTarget; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/Model.java b/src/java/com/threerings/jme/model/Model.java deleted file mode 100644 index 82995fa5..00000000 --- a/src/java/com/threerings/jme/model/Model.java +++ /dev/null @@ -1,1194 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import java.nio.FloatBuffer; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import com.jme.bounding.BoundingVolume; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.renderer.Camera; -import com.jme.renderer.Renderer; -import com.jme.scene.Controller; -import com.jme.scene.Node; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; -import com.jme.util.export.Savable; -import com.jme.util.export.binary.BinaryExporter; -import com.jme.util.export.binary.BinaryImporter; - -import com.samskivert.util.ArrayUtil; -import com.samskivert.util.ObserverList; -import com.samskivert.util.PropertiesUtil; -import com.samskivert.util.RandomUtil; -import com.samskivert.util.StringUtil; - -import com.threerings.jme.util.SpatialVisitor; - -import static com.threerings.jme.Log.log; - -/** - * The base node for models. - */ -public class Model extends ModelNode -{ - /** The supported types of animation in decreasing order of complexity. */ - public enum AnimationMode { - SKIN, MORPH, FLIPBOOK - }; - - /** Lets listeners know when animations are completed (which only happens - * for non-repeating animations) or cancelled. */ - public interface AnimationObserver - { - /** - * Called when an animation has started. - * - * @return true to remain on the observer list, false to remove self - */ - public boolean animationStarted (Model model, String anim); - - /** - * Called when a non-repeating animation has finished. - * - * @return true to remain on the observer list, false to remove self - */ - public boolean animationCompleted (Model model, String anim); - - /** - * Called when an animation has been cancelled. - * - * @return true to remain on the observer list, false to remove self - */ - public boolean animationCancelled (Model model, String anim); - } - - /** An animation for the model. */ - public static class Animation - implements Savable - { - /** The rate of the animation in frames per second. */ - public int frameRate; - - /** The animation repeat type ({@link Controller#RT_CLAMP}, - * {@link Controller#RT_CYCLE}, or {@link Controller#RT_WRAP}). */ - public int repeatType; - - /** Any nodes visible that never move within the model. */ - public Spatial[] staticTargets; - - /** The transformation targets of the animation. */ - public Spatial[] transformTargets; - - /** The animation transforms (one transform per target per frame). */ - public transient Transform[][] transforms; - - /** Uniquely identifies this animation within the model. */ - public transient int animId; - - /** For each frame, whether the frame has been stored in meshes. */ - public transient boolean[] stored; - - /** - * Returns this animation's duration in seconds. - */ - public float getDuration () - { - return (float)transforms.length / frameRate; - } - - /** - * Rebinds this animation for a prototype instance. - * - * @param pnodes a mapping from prototype nodes to instance nodes - */ - public Animation rebind (Map pnodes) - { - Animation anim = new Animation(); - anim.frameRate = frameRate; - anim.repeatType = repeatType; - anim.staticTargets = rebind(staticTargets, pnodes); - anim.transformTargets = rebind(transformTargets, pnodes); - anim.transforms = transforms; - anim.animId = animId; - anim.stored = stored; - return anim; - } - - /** - * Applies the transforms for a frame of this animation. - */ - public void applyFrame (int fidx) - { - Transform[] xforms = transforms[fidx]; - for (int ii = 0; ii < transformTargets.length; ii++) { - xforms[ii].apply(transformTargets[ii]); - } - } - - /** - * Blends the transforms between two frames of this animation. - */ - public void blendFrames (int fidx, int nidx, float alpha) - { - Transform[] xforms = transforms[fidx], nxforms = transforms[nidx]; - for (int ii = 0; ii < transformTargets.length; ii++) { - xforms[ii].blend(nxforms[ii], alpha, transformTargets[ii]); - } - } - - // documentation inherited - public Class getClassTag () - { - return getClass(); - } - - // documentation inherited - public void read (JMEImporter im) - throws IOException - { - InputCapsule capsule = im.getCapsule(this); - frameRate = capsule.readInt("frameRate", 0); - repeatType = capsule.readInt("repeatType", Controller.RT_CLAMP); - staticTargets = ArrayUtil.copy(capsule.readSavableArray( - "staticTargets", null), new Spatial[0]); - transformTargets = ArrayUtil.copy(capsule.readSavableArray( - "transformTargets", null), new Spatial[0]); - FloatBuffer pxforms = capsule.readFloatBuffer("transforms", null); - transforms = new Transform[pxforms.capacity() / - Transform.PACKED_SIZE / transformTargets.length][]; - for (int ii = 0; ii < transforms.length; ii++) { - Transform[] frame = transforms[ii] = - new Transform[transformTargets.length]; - for (int jj = 0; jj < frame.length; jj++) { - frame[jj] = new Transform(pxforms); - } - } - } - - // documentation inherited - public void write (JMEExporter ex) - throws IOException - { - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(frameRate, "frameRate", 0); - capsule.write(repeatType, "repeatType", Controller.RT_CLAMP); - capsule.write(staticTargets, "staticTargets", null); - capsule.write(transformTargets, "transformTargets", null); - FloatBuffer pxforms = FloatBuffer.allocate( - transforms.length * transformTargets.length * Transform.PACKED_SIZE); - for (Transform[] frame : transforms) { - for (Transform xform : frame) { - xform.writeToBuffer(pxforms); - } - } - pxforms.rewind(); - capsule.write(pxforms, "transforms", null); - } - - protected Spatial[] rebind (Spatial[] targets, Map pnodes) - { - Spatial[] ntargets = new Spatial[targets.length]; - for (int ii = 0; ii < targets.length; ii++) { - ntargets[ii] = (Spatial)pnodes.get(targets[ii]); - } - return ntargets; - } - - private static final long serialVersionUID = 1; - } - - /** A frame element that manipulates the target's transform. */ - public static final class Transform - { - /** The number of floats required to store a packed transform. */ - public static final int PACKED_SIZE = 3 + 4 + 3; - - public Transform ( - Vector3f translation, Quaternion rotation, Vector3f scale) - { - _translation = translation; - _rotation = rotation; - _scale = scale; - } - - public Transform (FloatBuffer buf) - { - _translation = new Vector3f(buf.get(), buf.get(), buf.get()); - _rotation = new Quaternion(buf.get(), buf.get(), buf.get(), - buf.get()); - _scale = new Vector3f(buf.get(), buf.get(), buf.get()); - } - - public void apply (Spatial target) - { - target.getLocalTranslation().set(_translation); - target.getLocalRotation().set(_rotation); - target.getLocalScale().set(_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); - } - - /** - * Writes this transform to the current position in the supplied - * buffer. - */ - public void writeToBuffer (FloatBuffer buf) - { - buf.put(_translation.x); - buf.put(_translation.y); - buf.put(_translation.z); - - buf.put(_rotation.x); - buf.put(_rotation.y); - buf.put(_rotation.z); - buf.put(_rotation.w); - - buf.put(_scale.x); - buf.put(_scale.y); - buf.put(_scale.z); - } - - /** The transform at this frame. */ - protected Vector3f _translation, _scale; - protected Quaternion _rotation; - } - - /** Customized clone creator for models. */ - public static class CloneCreator - { - /** A shared seed used to select textures consistently. */ - public int random; - - /** Maps original objects to their copies. */ - public Map originalToCopy = Maps.newHashMap(); - - public CloneCreator (Model toCopy) - { - _toCopy = toCopy; - addProperty("vertices"); - addProperty("colors"); - addProperty("normals"); - addProperty("texcoords"); - addProperty("vboinfo"); - addProperty("indices"); - addProperty("obbtree"); - addProperty("displaylistid"); - addProperty("bound"); - } - - /** - * Sets the named property. - */ - public void addProperty (String name) - { - _properties.add(name); - } - - /** - * Clears the named property. - */ - public void removeProperty (String name) - { - _properties.remove(name); - } - - /** - * Checks whether the named property has been set. - */ - public boolean isSet (String name) - { - return _properties.contains(name); - } - - /** - * Creates a new copy of the target model. - */ - public Model createCopy () - { - random = RandomUtil.getInt(Integer.MAX_VALUE); - Model copy = (Model)_toCopy.putClone(null, this); - originalToCopy.clear(); // make sure no references remain - return copy; - } - - /** The model to copy. */ - protected Model _toCopy; - - /** The set of added properties. */ - protected HashSet _properties = Sets.newHashSet(); - } - - /** - * Attempts to read a model from the specified file. - */ - public static Model readFromFile (File file) - throws IOException - { - // read the serialized model and its children - FileInputStream fis = new FileInputStream(file); - Model model = (Model)BinaryImporter.getInstance().load(fis); - fis.close(); - - // initialize the model as a prototype - model.initPrototype(); - - return model; - } - - /** - * No-arg constructor for deserialization. - */ - public Model () - { - } - - /** - * Standard constructor. - */ - public Model (String name, Properties props) - { - super(name); - _props = props; - } - - /** - * Returns a reference to the properties of the model. - */ - public Properties getProperties () - { - return _props; - } - - /** - * Initializes this model as prototype. Only necessary when the prototype - * was not loaded through {@link #readFromFile}. - */ - public void initPrototype () - { - // initialize shared transient animation state - if (_anims != null) { - int nextId = 1; - for (Animation anim : _anims.values()) { - anim.animId = nextId++; - anim.stored = new boolean[anim.transforms.length]; - } - } - setReferenceTransforms(); - cullInvisibleNodes(); - initInstance(); - } - - /** - * Returns the names of the model's variant configurations. - */ - public String[] getVariantNames () - { - return StringUtil.parseStringArray(_props.getProperty("variants", "")); - } - - /** - * Adds an animation to the model's library. This should only be called by - * the model compiler. - */ - public void addAnimation (String name, Animation anim) - { - if (_anims == null) { - _anims = Maps.newHashMap(); - } - _anims.put(name, anim); - - // store the original transforms - Transform[] oxforms = new Transform[anim.transformTargets.length]; - for (int ii = 0; ii < anim.transformTargets.length; ii++) { - Spatial target = anim.transformTargets[ii]; - oxforms[ii] = new Transform( - new Vector3f(target.getLocalTranslation()), - new Quaternion(target.getLocalRotation()), - new Vector3f(target.getLocalScale())); - } - - // run through every frame of the animation, expanding the bounding - // volumes of any deformable meshes - for (int ii = 0; ii < anim.transforms.length; ii++) { - for (int jj = 0; jj < anim.transforms[ii].length; jj++) { - anim.transforms[ii][jj].apply(anim.transformTargets[jj]); - } - updateWorldData(0f); - expandModelBounds(); - } - - // restore the original transforms - for (int ii = 0; ii < anim.transformTargets.length; ii++) { - oxforms[ii].apply(anim.transformTargets[ii]); - } - updateWorldData(0f); - } - - /** - * Sets the animation mode to use for this model. This should be set - * on the prototype before any animations are started or any instances - * are created. - */ - public void setAnimationMode (AnimationMode mode) - { - _animMode = mode; - } - - /** - * Returns the animation mode configured for this model. - */ - public AnimationMode getAnimationMode () - { - return _animMode; - } - - /** - * Returns the names of the model's animations. - */ - public String[] getAnimationNames () - { - if (_prototype != null) { - return _prototype.getAnimationNames(); - } - return (_anims == null) ? new String[0] : - _anims.keySet().toArray(new String[_anims.size()]); - } - - /** - * Checks whether the unit has an animation with the given name. - */ - public boolean hasAnimation (String name) - { - if (_prototype != null) { - return _prototype.hasAnimation(name); - } - return (_anims == null) ? false : _anims.containsKey(name); - } - - /** - * Starts the named animation. - * - * @return the duration of the started animation (for looping animations, - * the duration of one cycle), or -1 if the animation was not found - */ - public float startAnimation (String name) - { - return startAnimation (name, 0, +1); - } - - /** - * Starts the named animation. - * - * @param fidx the frame to start with - * @param fdir the direction to go (+1 forward, -1 backward) - * - * @return the duration of the started animation (for looping animations, - * the duration of one cycle), or -1 if the animation was not found - */ - public float startAnimation (String name, int fidx, int fdir) - { - Animation anim = getAnimation(name); - if (anim == null) { - return -1f; - } - if (_anim != null) { - _animObservers.apply(new AnimCancelledOp(_animName)); - } - - // first cull all model nodes, then re-activate the ones in the target lists - cullModelNodes(); - for (Spatial target : anim.staticTargets) { - ((ModelNode)target).updateCullMode(); - } - for (Spatial target : anim.transformTargets) { - ((ModelNode)target).updateCullMode(); - } - - _paused = false; - _anim = anim; - _animName = name; - _fidx = fidx; - _nidx = fidx; - _fdir = fdir; - _elapsed = 0f; - advanceFrameCounter(); - _animObservers.apply(new AnimStartedOp(_animName)); - return anim.getDuration() / _animSpeed; - } - - /** - * Fast-forwards the current animation by the given number of seconds. - */ - public void fastForwardAnimation (float time) - { - updateAnimation(time); - } - - /** - * Gets a reference to the animation with the given name. - */ - public Animation getAnimation (String name) - { - if (_anims == null) { - return null; - } - Animation anim = _anims.get(name); - if (anim != null) { - return anim; - } - if (_prototype != null) { - Animation panim = _prototype._anims.get(name); - if (panim != null) { - _anims.put(name, anim = panim.rebind(_pnodes)); - return anim; - } - } - log.warning("Requested unknown animation [name=" + name + "]."); - return null; - } - - /** - * Returns a reference to the currently running animation, or - * null if no animation is running. - */ - public Animation getAnimation () - { - return _anim; - } - - /** - * Stops the currently running animation. - */ - public void stopAnimation () - { - if (_anim == null) { - return; - } - if (_outside) { - // make sure the meshes are in the right places when we come back into view - updateMeshes(); - } - _paused = false; - _anim = null; - _animObservers.apply(new AnimCancelledOp(_animName)); - } - - /** - * Sets the pause state of the animation. - */ - public void pauseAnimation (boolean pause) - { - _paused = pause; - } - - /** - * Returns the pause state of the animation. - */ - public boolean isAnimationPaused () - { - return _paused; - } - - /** - * Causes the animation to start running in reverse. - */ - public void reverseAnimation () - { - _fdir *= -1; - } - - /** - * Sets the animation speed, which acts as a multiplier for the frame rate - * of each animation. - */ - public void setAnimationSpeed (float speed) - { - _animSpeed = speed; - } - - /** - * Returns the currently configured animation speed. - */ - public float getAnimationSpeed () - { - return _animSpeed; - } - - /** - * Adds an animation observer. - */ - public void addAnimationObserver (AnimationObserver obs) - { - _animObservers.add(obs); - } - - /** - * Removes an animation observer. - */ - public void removeAnimationObserver (AnimationObserver obs) - { - _animObservers.remove(obs); - } - - /** - * Returns a reference to the node that contains this model's emissions - * (in world space, so the emissions do not move with the model). This - * node is created and added when this method is first called. - */ - public Node getEmissionNode () - { - if (_emissionNode == null) { - attachChild(_emissionNode = new Node("emissions") { - public void updateWorldVectors () { - worldTranslation.set(localTranslation); - worldRotation.set(localRotation); - worldScale.set(localScale); - } - }); - } - return _emissionNode; - } - - /** - * Writes this model out to a file. - */ - public void writeToFile (File file) - throws IOException - { - // start out by writing this node and its children - FileOutputStream fos = new FileOutputStream(file); - BinaryExporter.getInstance().save(this, fos); - fos.close(); - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - String[] propNames = capsule.readStringArray("propNames", null), - propValues = capsule.readStringArray("propValues", null); - _props = new Properties(); - for (int ii = 0; ii < propNames.length; ii++) { - _props.setProperty(propNames[ii], propValues[ii]); - } - String[] animNames = capsule.readStringArray("animNames", null); - if (animNames != null) { - Savable[] animValues = capsule.readSavableArray( - "animValues", null); - _anims = Maps.newHashMap(); - for (int ii = 0; ii < animNames.length; ii++) { - _anims.put(animNames[ii], (Animation)animValues[ii]); - } - } else { - _anims = null; - } - List controllers = capsule.readSavableArrayList("controllers", null); - if (controllers != null) { - for (Object ctrl : controllers) { - addController((Controller)ctrl); - } - } - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - // don't serialize the emission node; it contains transient geometry - // created by controllers - if (_emissionNode != null) { - detachChild(_emissionNode); - } - super.write(ex); - if (_emissionNode != null) { - attachChild(_emissionNode); - } - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_props.keySet().toArray(new String[_props.size()]), - "propNames", null); - capsule.write(_props.values().toArray(new String[_props.size()]), - "propValues", null); - if (_anims != null) { - capsule.write(_anims.keySet().toArray( - new String[_anims.size()]), "animNames", null); - capsule.write(_anims.values().toArray( - new Animation[_anims.size()]), "animValues", null); - } - capsule.writeSavableArrayList(getControllers(), "controllers", null); - } - - @Override - public void resolveTextures (TextureProvider tprov) - { - super.resolveTextures(tprov); - for (Object ctrl : getControllers()) { - if (ctrl instanceof ModelController) { - ((ModelController)ctrl).resolveTextures(tprov); - } - } - } - - /** - * Creates a new prototype using the given variant configuration. - * Use {@link #createInstance} on the returned prototype to create - * additional instances of the variant. - */ - public Model createPrototype (String variant) - { - if (_prototype != null) { - return _prototype.createPrototype(variant); - } - // create an instance and rebind all animations - final Model prototype = createInstance(); - if (_anims != null) { - for (Map.Entry entry : _anims.entrySet()) { - prototype._anims.put(entry.getKey(), - entry.getValue().rebind(prototype._pnodes)); - } - } - prototype._prototype = null; - prototype._pnodes = null; - - // reconfigure meshes with new variant type - if (variant != null) { - prototype._props = PropertiesUtil.getFilteredProperties( - _props, variant); - new SpatialVisitor(ModelMesh.class) { - public void visit (ModelMesh mesh) { - mesh.reconfigure(PropertiesUtil.getFilteredProperties( - prototype._props, mesh.getParent().getName())); - } - }.traverse(prototype); - } - return prototype; - } - - /** - * Creates and returns a new instance of this model. - */ - public Model createInstance () - { - if (_prototype != null) { - return _prototype.createInstance(); - } - if (_ccreator == null) { - _ccreator = new CloneCreator(this); - } - Model instance = _ccreator.createCopy(); - instance.initInstance(); - return instance; - } - - /** - * Locks the transforms and bounds of this model in the expectation that it - * will never be moved from its current position. - */ - public void lockInstance () - { - // collect the instance's animation and controller targets and lock - // recursively - HashSet targets = Sets.newHashSet(); - for (String aname : getAnimationNames()) { - Collections.addAll(targets, getAnimation(aname).transformTargets); - } - for (Object ctrl : getControllers()) { - if (ctrl instanceof ModelController) { - targets.add(((ModelController)ctrl).getTarget()); - } - } - lockInstance(targets); - } - - @Override - public Spatial putClone (Spatial store, CloneCreator properties) - { - Model mstore = (Model)properties.originalToCopy.get(this); - if (mstore != null) { - return mstore; - } else if (store == null) { - mstore = new Model(getName(), _props); - } else { - mstore = (Model)store; - } - // don't clone the emission node, as it contains transient geometry - if (_emissionNode != null) { - detachChild(_emissionNode); - } - super.putClone(mstore, properties); - if (_emissionNode != null) { - attachChild(_emissionNode); - } - mstore._prototype = this; - if (_anims != null) { - mstore._anims = Maps.newHashMap(); - } - mstore._pnodes = Maps.newHashMap(properties.originalToCopy); - mstore._animMode = _animMode; - return mstore; - } - - @Override - public void updateGeometricState (float time, boolean initiator) - { - // if we were not visible the last time we were rendered, don't do a - // full update; just update the world bound and wait until we come - // into view - boolean wasOutside = _outside; - _outside = isOutsideFrustum() && worldBound != null; - - // slow evvvverything down by the animation speed - time *= _animSpeed; - if (_anim != null) { - updateAnimation(time); - } - - // update controllers and children with accumulated time - _accum += time; - if (_outside) { - if ((lockedMode & LOCKED_TRANSFORMS) != 0) { - return; // world bound will not changed - } - if (!wasOutside) { - storeWorldBound(); - } - updateWorldVectors(); - worldBound = _storedBound.transform(getWorldRotation(), - getWorldTranslation(), getWorldScale(), worldBound); - - } else { - super.updateGeometricState(_shouldAccumulate ? _accum : time, - initiator); - _accum = 0f; - } - } - - @Override - public void onDraw (Renderer r) - { - // if we switch from invisible to visible, we have to do a last-minute - // full update (which only works if our meshes are enqueued) - super.onDraw(r); - if (_outside && !isOutsideFrustum()) { - updateWorldData(0f); - } - } - - /** - * Transforms the current world bound into model space and stores it for - * when the model is offscreen. - */ - protected void storeWorldBound () - { - // update the bounds with an identity transform (which will be - // overwritten after this method is called) - getWorldRotation().loadIdentity(); - getWorldTranslation().set(Vector3f.ZERO); - getWorldScale().set(Vector3f.UNIT_XYZ); - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - getChild(ii).updateGeometricState(0f, false); - } - updateWorldBound(); - - _storedBound = worldBound.clone(_storedBound); - } - - /** - * Determines whether this node was determined to be entirely outside the - * view frustum. - */ - protected boolean isOutsideFrustum () - { - for (Node node = this; node != null; node = node.getParent()) { - if (node.getLastFrustumIntersection() == Camera.OUTSIDE_FRUSTUM) { - return true; - } - } - return false; - } - - /** - * Initializes the per-instance state of this model. - */ - protected void initInstance () - { - // initialize the controllers - for (Object ctrl : getControllers()) { - if (ctrl instanceof ModelController) { - ModelController mctrl = (ModelController)ctrl; - mctrl.init(this); - _shouldAccumulate |= mctrl.shouldAccumulate(); - } - } - } - - /** - * Updates the model's state according to the current animation. - */ - protected void updateAnimation (float time) - { - // no need to update between frames for flipbook animation - if (_animMode == AnimationMode.FLIPBOOK && _elapsed > 0f && - _elapsed < 1f) { - _elapsed += (time * _anim.frameRate); - return; - } - - // advance the frame counter if necessary - while (_elapsed > 1f) { - if (!_paused) { - advanceFrameCounter(); - _elapsed -= 1f; - } else { - _elapsed = 1f; - } - } - - // update the target transforms and animation frame if not outside the - // view frustum - if (!_outside) { - updateMeshes(); - } - - // if the next index is the same as this one, we are finished - if (_fidx == _nidx && !_paused) { - _anim = null; - _animObservers.apply(new AnimCompletedOp(_animName)); - return; - } - _elapsed += (time * _anim.frameRate); - } - - /** - * Advances the frame counter by one frame. - */ - protected void advanceFrameCounter () - { - _fidx = _nidx; - int nframes = _anim.transforms.length; - if (_anim.repeatType == Controller.RT_CLAMP) { - _nidx = Math.max(0, Math.min(_nidx + _fdir, nframes - 1)); - - } else if (_anim.repeatType == Controller.RT_WRAP) { - // % is not a modulo operator, so is not guaranteed to be positive - _nidx = (_nidx + _fdir) % nframes; - if (_nidx < 0) { - _nidx += nframes; - } - - } else { // _anim.repeatType == Controller.RT_CYCLE - if ((_nidx + _fdir) < 0 || (_nidx + _fdir) >= nframes) { - _fdir *= -1; // reverse direction - } - _nidx += _fdir; - } - } - - /** - * Updates the states of the model's meshes according to the animation state. - */ - protected void updateMeshes () - { - if (_animMode == AnimationMode.FLIPBOOK) { - int frameId = (_anim.animId << 16) | _fidx; - _anim.applyFrame(_fidx); - if (!_anim.stored[_fidx]) { - storeMeshFrame(frameId, false); - updateWorldData(0f); - _anim.stored[_fidx] = true; - } - setMeshFrame(frameId); - - } else if (_animMode == AnimationMode.MORPH) { - int frameId1 = (_anim.animId << 16) | _fidx, - frameId2 = (_anim.animId << 16) | _nidx; - if (!_anim.stored[_fidx]) { - storeMeshFrame(frameId1, true); - _anim.applyFrame(_fidx); - updateWorldData(0f); - _anim.stored[_fidx] = true; - } - if (!_anim.stored[_nidx]) { - storeMeshFrame(frameId2, true); - _anim.applyFrame(_nidx); - updateWorldData(0f); - _anim.stored[_nidx] = true; - } - _anim.blendFrames(_fidx, _nidx, _elapsed); - blendMeshFrames(frameId1, frameId2, _elapsed); - - } else { // _animMode == AnimationMode.SKIN - _anim.blendFrames(_fidx, _nidx, _elapsed); - } - } - - /** A reference to the prototype, or null if this is a prototype. */ - protected Model _prototype; - - /** For prototype models, a customized clone creator used to generate instances. */ - protected CloneCreator _ccreator; - - /** The animation mode to use for this model. */ - protected AnimationMode _animMode; - - /** For instances, maps prototype nodes to their corresponding instance nodes. */ - protected Map _pnodes; - - /** The model properties. */ - protected Properties _props; - - /** The model animations. */ - protected HashMap _anims; - - /** The currently running animation, or null for none. */ - protected Animation _anim; - - /** The name of the currently running animation, if any. */ - protected String _animName; - - /** The current animation speed multiplier. */ - protected float _animSpeed = 1f; - - /** The index of the current and next frames. */ - protected int _fidx, _nidx; - - /** The direction for wrapping animations (+1 forward, -1 backward). */ - protected int _fdir; - - /** The frame portion elapsed since the start of the current frame. */ - protected float _elapsed; - - /** The pause status of this model. */ - protected boolean _paused; - - /** The amount of update time accumulated while outside of view frustum. */ - protected float _accum; - - /** Whether or not we should accumulate update time while out of view. */ - protected boolean _shouldAccumulate; - - /** The child node that contains the model's emissions in world space. */ - protected Node _emissionNode; - - /** The model space bounding volume stored for use when the model is - * offscreen. */ - protected BoundingVolume _storedBound; - - /** Whether or not we were outside the frustum at the last update. */ - protected boolean _outside; - - /** Animation completion listeners. */ - protected ObserverList _animObservers = - new ObserverList(ObserverList.FAST_UNSAFE_NOTIFY); - - /** Used to notify observers of animation initiation. */ - protected class AnimStartedOp - implements ObserverList.ObserverOp - { - public AnimStartedOp (String name) - { - _name = name; - } - - // documentation inherited from interface ObserverOp - public boolean apply (AnimationObserver obs) - { - return obs.animationStarted(Model.this, _name); - } - - /** The name of the animation started. */ - protected String _name; - } - - /** Used to notify observers of animation completion. */ - protected class AnimCompletedOp - implements ObserverList.ObserverOp - { - public AnimCompletedOp (String name) - { - _name = name; - } - - // documentation inherited from interface ObserverOp - public boolean apply (AnimationObserver obs) - { - return obs.animationCompleted(Model.this, _name); - } - - /** The name of the animation completed. */ - protected String _name; - } - - /** Used to notify observers of animation cancellation. */ - protected class AnimCancelledOp - implements ObserverList.ObserverOp - { - public AnimCancelledOp (String name) - { - _name = name; - } - - // documentation inherited from interface ObserverOp - public boolean apply (AnimationObserver obs) - { - return obs.animationCancelled(Model.this, _name); - } - - /** The name of the animation cancelled. */ - protected String _name; - } - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/ModelController.java b/src/java/com/threerings/jme/model/ModelController.java deleted file mode 100644 index 91e32a25..00000000 --- a/src/java/com/threerings/jme/model/ModelController.java +++ /dev/null @@ -1,188 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Collections; -import java.util.HashSet; -import java.util.Properties; - -import com.google.common.collect.Sets; - -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -import com.samskivert.util.StringUtil; - -/** - * The superclass of procedural animation controllers for models. - */ -public abstract class ModelController extends Controller -{ - /** - * Configures this controller based on the supplied (sub-)properties and - * controller target. - */ - public void configure (Properties props, Spatial target) - { - _target = target; - String[] anims = StringUtil.parseStringArray( - props.getProperty("animations", "")); - if (anims.length == 0) { - return; - } - _animations = Sets.newHashSet(); - Collections.addAll(_animations, anims); - } - - /** - * Returns a reference to the controller's target. - */ - public Spatial getTarget () - { - return _target; - } - - /** - * Resolves any textures required by the controller. - */ - public void resolveTextures (TextureProvider tprov) - { - } - - /** - * Initializes this controller. - */ - public void init (Model model) - { - model.addAnimationObserver(_animobs); - if (_animations != null) { - setActive(false); - } - } - - /** - * Determines whether the controller updates should include time - * accumulated while the model was out of sight. Accumulating will - * be turned off only if all controllers are non-accumulating. - */ - public boolean shouldAccumulate () - { - return true; - } - - /** - * Creates or populates and returns a clone of this object using the given - * clone properties. - * - * @param store an instance of this class to populate, or null - * to create a new instance - */ - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - if (store == null) { - return null; - } - ModelController mstore = (ModelController)store; - mstore._target = ((ModelSpatial)_target).putClone(null, properties); - mstore._animations = _animations; - return mstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - InputCapsule capsule = im.getCapsule(this); - _target = (Spatial)capsule.readSavable("target", null); - String[] anims = capsule.readStringArray("animations", null); - if (anims != null) { - _animations = Sets.newHashSet(); - Collections.addAll(_animations, anims); - } else { - _animations = null; - } - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_target, "target", null); - capsule.write((_animations == null) ? - null : _animations.toArray(new String[_animations.size()]), - "animations", null); - } - - /** - * Called when an animation is started on the model. - */ - protected void animationStarted (String anim) - { - if (_animations != null && _animations.contains(anim)) { - setActive(true); - } - } - - /** - * Called when an animation is stopped on the model. - */ - protected void animationStopped (String anim) - { - if (_animations != null) { - setActive(false); - } - } - - /** The target to control. */ - protected Spatial _target; - - /** The animations for which this controller should be active, or - * null for all of them. */ - protected HashSet _animations; - - /** Listens to the model's animation state. */ - protected Model.AnimationObserver _animobs = - new Model.AnimationObserver() { - public boolean animationStarted (Model model, String anim) { - ModelController.this.animationStarted(anim); - return true; - } - public boolean animationCompleted (Model model, String anim) { - animationStopped(anim); - return true; - } - public boolean animationCancelled (Model model, String anim) { - animationStopped(anim); - return true; - } - }; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/ModelMesh.java b/src/java/com/threerings/jme/model/ModelMesh.java deleted file mode 100644 index f5a05c13..00000000 --- a/src/java/com/threerings/jme/model/ModelMesh.java +++ /dev/null @@ -1,904 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; - -import java.util.ArrayList; -import java.util.Properties; - -import com.google.common.collect.Lists; - -import com.jme.bounding.BoundingBox; -import com.jme.bounding.BoundingSphere; -import com.jme.bounding.BoundingVolume; -import com.jme.image.Image; -import com.jme.image.Texture; -import com.jme.math.FastMath; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.renderer.ColorRGBA; -import com.jme.renderer.Renderer; -import com.jme.scene.Spatial; -import com.jme.scene.TriMesh; -import com.jme.scene.VBOInfo; -import com.jme.scene.batch.TriangleBatch; -import com.jme.scene.state.AlphaState; -import com.jme.scene.state.CullState; -import com.jme.scene.state.FogState; -import com.jme.scene.state.LightState; -import com.jme.scene.state.RenderState; -import com.jme.scene.state.TextureState; -import com.jme.scene.state.ZBufferState; -import com.jme.system.DisplaySystem; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; -import com.jme.util.geom.BufferUtils; - -import com.samskivert.util.PropertiesUtil; -import com.samskivert.util.StringUtil; - -import com.threerings.jme.util.ShaderCache; - -/** - * A {@link TriMesh} with a serialization mechanism tailored to stored models. - */ -public class ModelMesh extends TriMesh - implements ModelSpatial -{ - /** - * No-arg constructor for deserialization. - */ - public ModelMesh () - { - super("mesh"); - } - - /** - * Creates a mesh with no vertex data. - */ - public ModelMesh (String name) - { - super(name); - } - - @Override - public int hashCode () - { - // hash on the name rather than the identity for consistent ordering - return getName().hashCode(); - } - - /** - * Reconfigures this model with a new set of (sub-)properties. Textures - * must be (re-)resolved after calling this method. - */ - public void reconfigure (Properties props) - { - configure(_solid, _textureKey, _transparent, props); - setRenderStates(); - } - - /** - * 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 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 - */ - public void configure ( - boolean solid, String texture, boolean transparent, Properties props) - { - _textureKey = texture; - _textures = (texture == null) ? null : StringUtil.parseStringArray( - props.getProperty(texture, texture)); - Properties tprops = PropertiesUtil.getFilteredProperties( - props, texture); - _sphereMapped = Boolean.parseBoolean(tprops.getProperty("sphere_map")); - _filterMode = "nearest".equals(tprops.getProperty("filter")) ? - Texture.FM_NEAREST : Texture.FM_LINEAR; - _mipMapMode = getMipMapMode(tprops.getProperty("mipmap")); - _compress = Boolean.parseBoolean(tprops.getProperty("compress", "true")); - String emissive = tprops.getProperty("emissive"); - if (Boolean.parseBoolean(emissive)) { - _emissive = true; - } else { - _emissiveMap = emissive; - } - _additive = Boolean.parseBoolean(tprops.getProperty("additive")); - _solid = solid; - _transparent = transparent; - String threshold = tprops.getProperty("alpha_threshold"); - _alphaThreshold = (threshold == null) ? - DEFAULT_ALPHA_THRESHOLD : Float.parseFloat(threshold); - _translucent = _transparent && - Boolean.parseBoolean(tprops.getProperty("translucent")); - } - - /** - * Adjusts the vertices and the transform of the mesh so that the mesh's - * position lies at the center of its bounding volume. - */ - public void centerVertices () - { - Vector3f offset = getBatch(0).getModelBound().getCenter().negate(); - if (!offset.equals(Vector3f.ZERO)) { - getLocalTranslation().subtractLocal(offset); - getBatch(0).getModelBound().getCenter().set(Vector3f.ZERO); - getBatch(0).translatePoints(offset); - } - storeOriginalBuffers(); - } - - /** - * Adds an overlay layer to this mesh. After the mesh is rendered with - * its configured states, these states will be applied and the mesh will - * be rendered again. - */ - public void addOverlay (RenderState[] overlay) - { - if (_overlays == null) { - _overlays = Lists.newArrayListWithCapacity(1); - } - _overlays.add(overlay); - } - - /** - * Removes a layer from this mesh. - */ - public void removeOverlay (RenderState[] overlay) - { - if (_overlays != null) { - _overlays.remove(overlay); - if (_overlays.isEmpty()) { - _overlays = null; - } - } - } - - @Override - public void reconstruct ( - FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors, - FloatBuffer textures, IntBuffer indices) - { - super.reconstruct(vertices, normals, colors, textures, indices); - for (int ii = 1, nn = getTextureCount(); ii < nn; ii++) { - setTextureBuffer(0, getTextureBuffer(0, 0), ii); - } - - // store any buffers that will be manipulated on a per-instance basis - storeOriginalBuffers(); - - // initialize the model if we're displaying - setRenderStates(); - } - - // documentation inherited from interface ModelSpatial - public Spatial putClone (Spatial store, Model.CloneCreator properties) - { - ModelMesh mstore = (ModelMesh)properties.originalToCopy.get(this); - if (mstore != null) { - return mstore; - } else if (store == null) { - mstore = new ModelMesh(getName()); - } else { - mstore = (ModelMesh)store; - } - properties.originalToCopy.put(this, mstore); - mstore.normalsMode = normalsMode; - mstore.cullMode = cullMode; - for (int ii = 0; ii < RenderState.RS_MAX_STATE; ii++) { - RenderState rstate = getRenderState(ii); - if (rstate != null) { - mstore.setRenderState(rstate); - } - } - mstore.renderQueueMode = renderQueueMode; - mstore.lockedMode = lockedMode; - mstore.lightCombineMode = lightCombineMode; - mstore.textureCombineMode = textureCombineMode; - mstore.name = name; - mstore.isCollidable = isCollidable; - mstore.localRotation.set(localRotation); - mstore.localTranslation.set(localTranslation); - mstore.localScale.set(localScale); - for (Object controller : getControllers()) { - if (controller instanceof ModelController) { - mstore.addController( - ((ModelController)controller).putClone(null, properties)); - } - } - TriangleBatch batch = getBatch(0), mbatch = mstore.getBatch(0); - mbatch.setVertexBuffer(properties.isSet("vertices") ? - batch.getVertexBuffer() : - BufferUtils.clone(batch.getVertexBuffer())); - mbatch.setColorBuffer(properties.isSet("colors") ? - batch.getColorBuffer() : - BufferUtils.clone(batch.getColorBuffer())); - mbatch.setNormalBuffer(properties.isSet("normals") ? - batch.getNormalBuffer() : - BufferUtils.clone(batch.getNormalBuffer())); - FloatBuffer texcoords; - for (int ii = 0; (texcoords = batch.getTextureBuffer(ii)) != null; - ii++) { - mbatch.setTextureBuffer(properties.isSet("texcoords") ? - texcoords : BufferUtils.clone(texcoords), ii); - } - mbatch.setIndexBuffer((properties.isSet("indices") && !_translucent) ? - batch.getIndexBuffer() : - BufferUtils.clone(batch.getIndexBuffer())); - if (properties.isSet("vboinfo")) { - mbatch.setVBOInfo(batch.getVBOInfo()); - } - if (properties.isSet("obbtree")) { - mbatch.setCollisionTree(batch.getCollisionTree()); - } - if (properties.isSet("displaylistid")) { - mbatch.setDisplayListID(batch.getDisplayListID()); - } - if (batch.getModelBound() != null) { - mbatch.setModelBound(properties.isSet("bound") ? - batch.getModelBound() : batch.getModelBound().clone(null)); - } - mstore._textureKey = _textureKey; - if (_textures != null && _textures.length > 1) { - int tidx = 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; - } - mstore._sphereMapped = _sphereMapped; - mstore._filterMode = _filterMode; - mstore._mipMapMode = _mipMapMode; - mstore._compress = _compress; - mstore._emissiveMap = _emissiveMap; - mstore._emissive = _emissive; - mstore._additive = _additive; - mstore._solid = _solid; - mstore._transparent = _transparent; - mstore._alphaThreshold = _alphaThreshold; - mstore._translucent = _translucent; - mstore._oibuf = _oibuf; - mstore._vbuf = _vbuf; - return mstore; - } - - @Override - public void updateWorldVectors () - { - if (!_transformLocked) { - super.updateWorldVectors(); - } - } - - @Override - public void read (JMEImporter im) - throws IOException - { - InputCapsule capsule = im.getCapsule(this); - setName(capsule.readString("name", null)); - setLocalTranslation((Vector3f)capsule.readSavable( - "localTranslation", null)); - setLocalRotation((Quaternion)capsule.readSavable( - "localRotation", null)); - setLocalScale((Vector3f)capsule.readSavable( - "localScale", null)); - TriangleBatch batch = getBatch(0); - batch.setModelBound((BoundingVolume)capsule.readSavable( - "modelBound", null)); - _textureKey = capsule.readString("textureKey", null); - _textures = capsule.readStringArray("textures", null); - _sphereMapped = capsule.readBoolean("sphereMapped", false); - _filterMode = capsule.readInt("filterMode", Texture.FM_LINEAR); - _mipMapMode = capsule.readInt("mipMapMode", Texture.MM_LINEAR_LINEAR); - _compress = capsule.readBoolean("compress", true); - _emissiveMap = capsule.readString("emissiveMap", null); - _emissive = capsule.readBoolean("emissive", false); - _additive = capsule.readBoolean("additive", false); - _solid = capsule.readBoolean("solid", true); - _transparent = capsule.readBoolean("transparent", false); - _alphaThreshold = capsule.readFloat("alphaThreshold", - DEFAULT_ALPHA_THRESHOLD); - _translucent = capsule.readBoolean("translucent", false); - - reconstruct(capsule.readFloatBuffer("vertexBuffer", null), - capsule.readFloatBuffer("normalBuffer", null), null, - capsule.readFloatBuffer("textureBuffer", null), - capsule.readIntBuffer("indexBuffer", null)); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(getName(), "name", null); - capsule.write(getLocalTranslation(), "localTranslation", null); - capsule.write(getLocalRotation(), "localRotation", null); - capsule.write(getLocalScale(), "localScale", null); - capsule.write(getBatch(0).getModelBound(), "modelBound", null); - capsule.write(getVertexBuffer(0), "vertexBuffer", null); - capsule.write(getNormalBuffer(0), "normalBuffer", null); - capsule.write(getTextureBuffer(0, 0), "textureBuffer", null); - capsule.write(getIndexBuffer(0), "indexBuffer", null); - capsule.write(_textureKey, "textureKey", null); - capsule.write(_textures, "textures", null); - capsule.write(_sphereMapped, "sphereMapped", false); - capsule.write(_filterMode, "filterMode", Texture.FM_LINEAR); - capsule.write(_mipMapMode, "mipMapMode", Texture.MM_LINEAR_LINEAR); - capsule.write(_compress, "compress", true); - capsule.write(_emissiveMap, "emissiveMap", null); - capsule.write(_emissive, "emissive", false); - capsule.write(_additive, "additive", false); - capsule.write(_solid, "solid", true); - capsule.write(_transparent, "transparent", false); - capsule.write(_alphaThreshold, "alphaThreshold", - DEFAULT_ALPHA_THRESHOLD); - capsule.write(_translucent, "translucent", false); - } - - // documentation inherited from interface ModelSpatial - public void expandModelBounds () - { - // no-op - } - - // documentation inherited from interface ModelSpatial - public void setReferenceTransforms () - { - // no-op - } - - // documentation inherited from interface ModelSpatial - public void lockStaticMeshes ( - Renderer renderer, boolean useVBOs, boolean useDisplayLists) - { - if (useVBOs && renderer.supportsVBO()) { - VBOInfo vboinfo = new VBOInfo(true); - vboinfo.setVBOIndexEnabled(!_translucent); - setVBOInfo(vboinfo); - - } else if (useDisplayLists && !_translucent) { - lockMeshes(renderer); - } - } - - // documentation inherited from interface ModelSpatial - public void resolveTextures (TextureProvider tprov) - { - if (_textures == null) { - return; - } - Texture emissiveTex = null; - if (_emissiveMap != null && TextureState.getNumberOfFixedUnits() >= 2) { - TextureState tstate = tprov.getTexture(_emissiveMap); - emissiveTex = tstate.getTexture(); - emissiveTex.setApply(Texture.AM_BLEND); - emissiveTex.getBlendColor().set(ColorRGBA.white); - } - _tstates = new TextureState[_textures.length]; - for (int ii = 0; ii < _textures.length; ii++) { - _tstates[ii] = tprov.getTexture(_textures[ii]); - Texture tex = _tstates[ii].getTexture(); - if (_sphereMapped) { - tex.setEnvironmentalMapMode(Texture.EM_SPHERE); - } - tex.setFilter(_filterMode); - tex.setMipmapState(_mipMapMode); - if (_compress && _tstates[ii].isS3TCAvailable()) { - Image image = tex.getImage(); - int type = image.getType(); - if (type == Image.RGB888) { - image.setType(Image.RGB888_DXT1); - } else if (type == Image.RGBA8888) { - image.setType(Image.RGBA8888_DXT5); - } - } - if (emissiveTex != null) { - _tstates[ii] = DisplaySystem.getDisplaySystem(). - getRenderer().createTextureState(); - _tstates[ii].setTexture(emissiveTex, 0); - _tstates[ii].setTexture(tex, 1); - } - } - if (_tstates[0] != null) { - setRenderState(_tstates[0]); - } else { - clearRenderState(RenderState.RS_TEXTURE); - } - } - - // documentation inherited from interface ModelSpatial - public void configureShaders (ShaderCache scache) - { - // no-op - } - - // documentation inherited from interface ModelSpatial - public void storeMeshFrame (int frameId, boolean blend) - { - // no-op - } - - // documentation inherited from interface ModelSpatial - public void setMeshFrame (int frameId) - { - // no-op - } - - // documentation inherited from interface ModelSpatial - public void blendMeshFrames (int frameId1, int frameId2, float alpha) - { - // no-op - } - - @Override - protected void setupBatchList () - { - batchList = Lists.newArrayListWithCapacity(1); - TriangleBatch batch = createModelBatch(); - batch.setParentGeom(this); - batchList.add(batch); - } - - /** - * Creates a batch for this mesh. - */ - protected ModelBatch createModelBatch () - { - return new ModelBatch(); - } - - /** - * Returns the number of textures this mesh uses (they must all share the - * same texture coordinates). - */ - protected int getTextureCount () - { - return (_emissiveMap == null || TextureState.getNumberOfFixedUnits() < 2) ? 1 : 2; - } - - /** - * For buffers that must be manipulated in some fashion, this method stores - * the originals. - */ - protected void storeOriginalBuffers () - { - if (!_translucent) { - return; - } - IntBuffer ibuf = getIndexBuffer(0); - ibuf.rewind(); - IntBuffer.wrap(_oibuf = new int[ibuf.capacity()]).put(ibuf); - - FloatBuffer vbuf = getVertexBuffer(0); - vbuf.rewind(); - FloatBuffer.wrap(_vbuf = new float[vbuf.capacity()]).put(vbuf); - } - - /** - * Sets the model's render states (excluding the texture state, which is - * set by {@link #resolveTextures}) according to its configuration. - */ - protected void setRenderStates () - { - if (DisplaySystem.getDisplaySystem() == null) { - return; - } - if (_backCull == null) { - initSharedStates(); - } - if (_emissive) { - setRenderState(_emissiveLight); - } - if (_solid) { - setRenderState(_backCull); - } - if (_additive) { - setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); - setRenderState(_addAlpha); - setRenderState(_overlayZBuffer); - setRenderState(_noFog); - } else if (_transparent) { - setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); - if (_translucent) { - setRenderState(_blendAlpha); - setRenderState(_overlayZBuffer); - } else if (_alphaThreshold == DEFAULT_ALPHA_THRESHOLD) { - setRenderState(_defaultTestAlpha); - } else { - setRenderState(createTestAlpha(_alphaThreshold)); - } - } - } - - /** - * Locks the transform and bounds of this mesh on the assumption that its - * position will not change. - */ - protected void lockInstance () - { - lockBounds(); - _transformLocked = true; - } - - /** - * Returns the mip-map mode corresponding to the given string - * (defaulting to {@link Texture#MM_LINEAR_LINEAR}). - */ - protected static int getMipMapMode (String mmode) - { - if ("none".equals(mmode)) { - return Texture.MM_NONE; - } else if ("nearest".equals(mmode)) { - return Texture.MM_NEAREST; - } else if ("linear".equals(mmode)) { - return Texture.MM_LINEAR; - } else if ("nearest_nearest".equals(mmode)) { - return Texture.MM_NEAREST_NEAREST; - } else if ("nearest_linear".equals(mmode)) { - return Texture.MM_NEAREST_LINEAR; - } else if ("linear_nearest".equals(mmode)) { - return Texture.MM_LINEAR_NEAREST; - } else { - return Texture.MM_LINEAR_LINEAR; - } - } - - /** - * 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); - _addAlpha = renderer.createAlphaState(); - _addAlpha.setBlendEnabled(true); - _addAlpha.setDstFunction(AlphaState.DB_ONE); - _defaultTestAlpha = createTestAlpha(DEFAULT_ALPHA_THRESHOLD); - _overlayZBuffer = renderer.createZBufferState(); - _overlayZBuffer.setFunction(ZBufferState.CF_LEQUAL); - _overlayZBuffer.setWritable(false); - _emissiveLight = renderer.createLightState(); - _emissiveLight.setGlobalAmbient(ColorRGBA.white); - _noFog = renderer.createFogState(); - _noFog.setEnabled(false); - } - - /** - * Creates an alpha state what will throw away fragments with alpha - * values less than or equal to the given threshold. - */ - protected static AlphaState createTestAlpha (float threshold) - { - AlphaState astate = DisplaySystem.getDisplaySystem(). - getRenderer().createAlphaState(); - astate.setBlendEnabled(true); - astate.setTestEnabled(true); - astate.setTestFunction(AlphaState.TF_GREATER); - astate.setReference(threshold); - return astate; - } - - /** - * Sorts the encoded triangle index/distance pairs in {@link #_tcodes} - * using a two-pass (16 bit) radix sort (as described by - * Pierre - * Terdiman. {@link #_bcounts} is assumed to be initialized to the - * counts for the first radix. - */ - protected static void sortTriangleCodes (int tcount) - { - // initialize the offsets for the first radix (LSB) and clear - // the counts - initByteOffsets(); - - // sort by the first radix and get the counts for the second - // (swapping directions in the hope of using the cache more - // effectively) - if (_stcodes == null || _stcodes.length < tcount) { - _stcodes = new int[tcount]; - } - int tcode; - for (int ii = tcount - 1; ii >= 0; ii--) { - tcode = _tcodes[ii]; - _stcodes[_boffsets[tcode & 0xFF]++] = tcode; - _bcounts[(tcode >> 8) & 0xFF]++; - } - - // initialize offsets for the second radix, clear counts, and - // sort by the second radix - initByteOffsets(); - for (int ii = 0; ii < tcount; ii++) { - tcode = _stcodes[ii]; - _tcodes[_boffsets[(tcode >> 8) & 0xFF]++] = tcode; - } - } - - /** - * Sets the initial byte offsets used to place bytes within the sorted - * array using the byte counts, clearing the counts in the process. - */ - protected static void initByteOffsets () - { - _boffsets[0] = 0; - for (int ii = 1; ii < 256; ii++) { - _boffsets[ii] = _boffsets[ii - 1] + _bcounts[ii - 1]; - _bcounts[ii - 1] = 0; - } - _bcounts[255] = 0; - } - - /** Sorts triangles for transparent meshes and renders overlays as well as - * the base layer. */ - protected class ModelBatch extends TriangleBatch - { - @Override - public void draw (Renderer r) - { - boolean drawing = (isEnabled() && r.isProcessingQueue()); - if (drawing) { - if (_translucent) { - sortTriangles(r); - } - preDraw(); - } - super.draw(r); - if (_overlays != null && drawing) { - for (int ii = 0, nn = _overlays.size(); ii < nn; ii++) { - preDrawOverlay(ii); - r.draw(this); - postDrawOverlay(ii); - } - } - } - - /** - * Gives derived classes a chance to update states immediately before drawing. - */ - protected void preDraw () - { - } - - /** - * Updates the batch's states with those of the identified overlay. - */ - protected void preDrawOverlay (int oidx) - { - RenderState[] overlay = _overlays.get(oidx); - for (RenderState rstate : overlay) { - int idx = rstate.getType(); - _ostates[idx] = states[idx]; - states[idx] = rstate; - } - } - - /** - * Restores the batch's original states after drawing an overlay. - */ - protected void postDrawOverlay (int oidx) - { - RenderState[] overlay = _overlays.get(oidx); - for (RenderState rstate : overlay) { - int idx = rstate.getType(); - states[idx] = _ostates[idx]; - } - } - - /** - * Sorts the batch's triangles by their distance to the camera. - */ - protected void sortTriangles (Renderer r) - { - // using the camera's direction in model space and the position - // and size of the model bound, find a set of plane parameters - // that determine the distance to a camera-aligned plane - // that touches the near edge of the bounding volume, as well - // as a scaling factor that brings the distance into a 16-bit - // integer range - getParentGeom().getWorldRotation().inverse().mult( - r.getCamera().getDirection(), _cdir); - BoundingVolume mbound = getModelBound(); - Vector3f mc = mbound.getCenter(); - float radius; - if (mbound instanceof BoundingSphere) { - radius = ((BoundingSphere)mbound).getRadius(); - } else { // mbound instanceof BoundingBox - BoundingBox bbox = (BoundingBox)mbound; - radius = FastMath.sqrt(3f) * Math.max(bbox.xExtent, - Math.max(bbox.yExtent, bbox.zExtent)); - } - float a = _cdir.x, b = _cdir.y, c = _cdir.z, - d = radius - a*mc.x - b*mc.y - c*mc.z, - dscale = 65535f / (radius * 2); - - // premultiply the scale and averaging factor - a *= dscale / 3f; - b *= dscale / 3f; - c *= dscale / 3f; - d *= dscale; - - // encode the model's triangles into integers such that the - // high 16 bits represent the original triangle index and the - // low 16 bits represent the distance to the plane. also - // increment the byte counts used for radix sorting - int tcount = getTriangleCount(), idist; - if (_tcodes == null || _tcodes.length < tcount) { - _tcodes = new int[tcount]; - } - int i1, i2, i3; - for (int ii = 0, idx = 0; ii < tcount; ii++) { - i1 = _oibuf[idx++] * 3; - i2 = _oibuf[idx++] * 3; - i3 = _oibuf[idx++] * 3; - idist = (int)( - a * (_vbuf[i1++] + _vbuf[i2++] + _vbuf[i3++]) + - b * (_vbuf[i1++] + _vbuf[i2++] + _vbuf[i3++]) + - c * (_vbuf[i1++] + _vbuf[i2++] + _vbuf[i3++]) + d); - _tcodes[ii] = (ii << 16) | idist; - _bcounts[idist & 0xFF]++; - } - - // sort the encoded triangles by increasing distance - sortTriangleCodes(tcount); - - // reorder the triangles as dictated by the sorted codes, furthest - // triangles first - int icount = tcount * 3, idx; - if (_sibuf == null || _sibuf.length < icount) { - _sibuf = new int[icount]; - } - for (int ii = tcount - 1, sidx = 0; ii >= 0; ii--) { - idx = ((_tcodes[ii] >> 16) & 0xFFFF) * 3; - _sibuf[sidx++] = _oibuf[idx++]; - _sibuf[sidx++] = _oibuf[idx++]; - _sibuf[sidx++] = _oibuf[idx]; - } - - // copy the indices to the buffer - IntBuffer ibuf = getIndexBuffer(); - ibuf.rewind(); - ibuf.put(_sibuf, 0, icount); - } - - /** - * Gives derived classes a chance to update the states immediately before drawing. - * - * @param oidx the index of the overlay being rendered, or -1 for the base layer. - */ - protected void processStates (int oidx) - { - } - - /** Temporarily stores the original states. */ - protected RenderState[] _ostates = - new RenderState[RenderState.RS_MAX_STATE]; - } - - /** The name of the texture specified in the model file, which acts as a - * property key and a default value. */ - protected String _textureKey; - - /** The name of this model's textures, or null for none. */ - protected String[] _textures; - - /** Whether or not to use sphere mapping on this model's textures. */ - protected boolean _sphereMapped; - - /** The filter mode to use on magnification. */ - protected int _filterMode; - - /** The mipmap mode to use on minification. */ - protected int _mipMapMode; - - /** Whether or not to use compressed textures, if available. */ - protected boolean _compress; - - /** The emissive map, if specified. */ - protected String _emissiveMap; - - /** Whether or not this mesh is completely emissive. */ - protected boolean _emissive; - - /** Whether or not this mesh should be rendered with additive blending. */ - protected boolean _additive; - - /** 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 alpha threshold below which fragments are discarded. */ - protected float _alphaThreshold; - - /** Whether or not the triangles of this mesh should be depth-sorted before - * rendering. */ - protected boolean _translucent; - - /** If non-null, additional layers to render over the base layer. */ - protected ArrayList _overlays; - - /** For prototype meshes, the resolved texture states. */ - protected TextureState[] _tstates; - - /** Whether or not the transform has been locked. This operates in a - * slightly different way than JME's locking, in that it allows applying - * transformations to display lists. */ - protected boolean _transformLocked; - - /** For depth-sorted and skinned meshes, the array of vertices. */ - protected float[] _vbuf; - - /** For depth-sorted meshes, the original array of indices. */ - protected int[] _oibuf; - - /** 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 additive blending. */ - protected static AlphaState _addAlpha; - - /** The shared state for alpha testing with the default threshold. */ - protected static AlphaState _defaultTestAlpha; - - /** The shared state for checking, but not writing to, the z buffer. */ - protected static ZBufferState _overlayZBuffer; - - /** A light state that simulates emissivity. */ - protected static LightState _emissiveLight; - - /** A fog state that disables fog. */ - protected static FogState _noFog; - - /** Work vector to store the camera direction. */ - protected static Vector3f _cdir = new Vector3f(); - - /** Work arrays used to sort triangles. */ - protected static int[] _tcodes, _stcodes; - - /** Holds counts of each byte and array offsets for radix sorting. */ - protected static int[] _bcounts = new int[256], _boffsets = new int[256]; - - /** Work array used to hold indices of sorted triangles. */ - protected static int[] _sibuf; - - /** The default alpha threshold. */ - protected static final float DEFAULT_ALPHA_THRESHOLD = 0.5f; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/ModelNode.java b/src/java/com/threerings/jme/model/ModelNode.java deleted file mode 100644 index b31bf3e6..00000000 --- a/src/java/com/threerings/jme/model/ModelNode.java +++ /dev/null @@ -1,414 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.HashSet; -import java.util.List; - -import com.jme.math.Matrix4f; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.renderer.Renderer; -import com.jme.scene.Node; -import com.jme.scene.Spatial; -import com.jme.scene.state.RenderState; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -import com.threerings.jme.util.JmeUtil; -import com.threerings.jme.util.ShaderCache; - -/** - * A {@link Node} with a serialization mechanism tailored to stored models. - */ -public class ModelNode extends Node - implements ModelSpatial -{ - /** - * No-arg constructor for deserialization. - */ - public ModelNode () - { - super("node"); - } - - /** - * Standard constructor. - */ - public ModelNode (String name) - { - super(name); - } - - @Override - public int hashCode () - { - // hash on the name rather than the identity for consistent ordering - return getName().hashCode(); - } - - /** - * Recursively searches the scene graph rooted at this node for a - * node with the provided name. - */ - public Spatial getDescendant (String name) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child.getName().equals(name)) { - return child; - } else if (child instanceof ModelNode) { - child = ((ModelNode)child).getDescendant(name); - if (child != null) { - return child; - } - } - } - return null; - } - - /** - * Returns a reference to the model space transform of the node. - */ - public Matrix4f getModelTransform () - { - return _modelTransform; - } - - @Override - public void updateWorldData (float time) - { - // we use locked bounds as an indication that we can skip the update - // altogether - if ((lockedMode & LOCKED_BOUNDS) == 0) { - super.updateWorldData(time); - } - } - - @Override - public void updateWorldBound () - { - // don't bother updating if we know there are no visible descendants - if (_hasVisibleDescendants) { - super.updateWorldBound(); - } - } - - @Override - public void updateWorldVectors () - { - super.updateWorldVectors(); - if (parent instanceof ModelNode) { - JmeUtil.setTransform(getLocalTranslation(), getLocalRotation(), - getLocalScale(), _localTransform); - ((ModelNode)parent).getModelTransform().mult(_localTransform, - _modelTransform); - - } else { - _modelTransform.loadIdentity(); - } - } - - // documentation inherited from interface ModelSpatial - public Spatial putClone (Spatial store, Model.CloneCreator properties) - { - ModelNode mstore = (ModelNode)properties.originalToCopy.get(this); - if (mstore != null) { - return mstore; - } else if (store == null) { - mstore = new ModelNode(getName()); - } else { - mstore = (ModelNode)store; - } - properties.originalToCopy.put(this, mstore); - mstore.normalsMode = normalsMode; - mstore.cullMode = cullMode; - for (int ii = 0; ii < RenderState.RS_MAX_STATE; ii++) { - RenderState rstate = getRenderState(ii); - if (rstate != null) { - mstore.setRenderState(rstate); - } - } - mstore.renderQueueMode = renderQueueMode; - mstore.lockedMode = lockedMode; - mstore.lightCombineMode = lightCombineMode; - mstore.textureCombineMode = textureCombineMode; - mstore.name = name; - mstore.isCollidable = isCollidable; - mstore.localRotation.set(localRotation); - mstore.localTranslation.set(localTranslation); - mstore.localScale.set(localScale); - for (Object controller : getControllers()) { - if (controller instanceof ModelController) { - mstore.addController( - ((ModelController)controller).putClone(null, properties)); - } - } - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - mstore.attachChild( - ((ModelSpatial)child).putClone(null, properties)); - } - } - mstore._hasVisibleDescendants = _hasVisibleDescendants; - return mstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - InputCapsule capsule = im.getCapsule(this); - setName(capsule.readString("name", null)); - setLocalTranslation((Vector3f)capsule.readSavable( - "localTranslation", null)); - setLocalRotation((Quaternion)capsule.readSavable( - "localRotation", null)); - setLocalScale((Vector3f)capsule.readSavable( - "localScale", null)); - List children = capsule.readSavableArrayList("children", null); - if (children != null) { - for (Object child : children) { - attachChild((Spatial)child); - } - } - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(getName(), "name", null); - capsule.write(getLocalTranslation(), "localTranslation", null); - capsule.write(getLocalRotation(), "localRotation", null); - capsule.write(getLocalScale(), "localScale", null); - capsule.writeSavableArrayList(getChildren(), "children", null); - } - - // documentation inherited from interface ModelSpatial - public void expandModelBounds () - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).expandModelBounds(); - } - } - } - - // documentation inherited from interface ModelSpatial - public void setReferenceTransforms () - { - updateWorldVectors(); - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).setReferenceTransforms(); - } - } - } - - // documentation inherited from interface ModelSpatial - public void lockStaticMeshes ( - Renderer renderer, boolean useVBOs, boolean useDisplayLists) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).lockStaticMeshes(renderer, useVBOs, - useDisplayLists); - } - } - } - - // documentation inherited from interface ModelSpatial - public void resolveTextures (TextureProvider tprov) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).resolveTextures(tprov); - } - } - } - - // documentation inherited from interface ModelSpatial - public void configureShaders (ShaderCache scache) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).configureShaders(scache); - } - } - } - - // documentation inherited from interface ModelSpatial - public void storeMeshFrame (int frameId, boolean blend) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).storeMeshFrame(frameId, blend); - } - } - } - - // documentation inherited from interface ModelSpatial - public void setMeshFrame (int frameId) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).setMeshFrame(frameId); - } - } - } - - // documentation inherited from interface ModelSpatial - public void blendMeshFrames (int frameId1, int frameId2, float alpha) - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelSpatial) { - ((ModelSpatial)child).blendMeshFrames( - frameId1, frameId2, alpha); - } - } - } - - /** - * Sets whether this node should be culled even if it has mesh - * descendants. - */ - public void setForceCull (boolean force) - { - _forceCull = force; - } - - /** - * Checks whether this node should be culled even if it has mesh - * descendants. - */ - public boolean getForceCull () - { - return _forceCull; - } - - /** - * Sets the cull state of any nodes that do not contain geometric - * descendants to {@link CULL_ALWAYS} so that they don't waste - * rendering time. - * - * @return true if this node should be drawn, false if it contains - * no mesh descendants - */ - protected boolean cullInvisibleNodes () - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (!(child instanceof ModelNode) || - ((ModelNode)child).cullInvisibleNodes()) { - _hasVisibleDescendants = true; - } - } - updateCullMode(); - return _hasVisibleDescendants; - } - - /** - * Locks the transforms and bounds of this instance with the assumption - * that the position will never change. - * - * @param targets the targets of the model's controllers, which determine - * the subset of nodes that can be locked - * @return true if this node is a target or contains any targets, otherwise - * false - */ - protected boolean lockInstance (HashSet targets) - { - updateWorldVectors(); - lockedMode |= LOCKED_TRANSFORMS; - - boolean containsTargets = false; - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (targets.contains(child) || (child instanceof ModelNode && - ((ModelNode)child).lockInstance(targets))) { - containsTargets = true; - - } else if (child instanceof ModelMesh) { - ((ModelMesh)child).lockInstance(); - } - } - if (containsTargets) { - return true; - } else { - updateWorldBound(); - lockedMode |= LOCKED_BOUNDS; - return false; - } - } - - /** - * Recursively culls all model nodes under this one in preparation for - * activating the ones listed in an animation. - */ - protected void cullModelNodes () - { - for (int ii = 0, nn = getQuantity(); ii < nn; ii++) { - Spatial child = getChild(ii); - if (child instanceof ModelNode) { - child.setCullMode(CULL_ALWAYS); - ((ModelNode)child).cullModelNodes(); - } - } - } - - /** - * Makes this node visible if and only if it has visible descendants and - * has not been specifically culled. - */ - protected void updateCullMode () - { - setCullMode((_hasVisibleDescendants && !_forceCull) ? - CULL_INHERIT : CULL_ALWAYS); - } - - /** The node's transform in local and model space. */ - protected Matrix4f _localTransform = new Matrix4f(), - _modelTransform = new Matrix4f(); - - /** Whether or not this node has mesh descendants. */ - protected boolean _hasVisibleDescendants; - - /** If true, cull the node even if it has mesh descendants. */ - protected boolean _forceCull; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/ModelSpatial.java b/src/java/com/threerings/jme/model/ModelSpatial.java deleted file mode 100644 index 35f38592..00000000 --- a/src/java/com/threerings/jme/model/ModelSpatial.java +++ /dev/null @@ -1,97 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.renderer.Renderer; -import com.jme.scene.Spatial; - -import com.threerings.jme.util.ShaderCache; - -/** - * Contains method common to both {@link ModelNode}s and {@link ModelMesh}es. - */ -public interface ModelSpatial -{ - /** - * Recursively expands the model bounds of any deformable meshes so that - * they include the current vertex positions. - */ - public void expandModelBounds (); - - /** - * Recursively sets the reference transforms for any bones in the model. - */ - public void setReferenceTransforms (); - - /** - * Recursively compiles any static meshes to vertex buffer objects (VBOs) - * or display lists. - * - * @param useVBOs if true, use VBOs if the graphics card supports them - * @param useDisplayLists if true and not using VBOs, compile static - * objects to display lists - */ - public void lockStaticMeshes ( - Renderer renderer, boolean useVBOs, boolean useDisplayLists); - - /** - * Recursively resolves texture references using the given provider. - */ - public void resolveTextures (TextureProvider tprov); - - /** - * Recursively creates or reconfigures any shaders used by the model using the supplied cache. - */ - public void configureShaders (ShaderCache scache); - - /** - * Recursively requests that the current state of all skinned meshes be - * stored as an animation frame on the next update. - * - * @param frameId the frame id, which uniquely identifies one frame of - * one animation - * @param blend whether or not the stored frames will be retrieved by - * calls to {@link #blendMeshFrames} as opposed to {@link #setMeshFrame} - */ - public void storeMeshFrame (int frameId, boolean blend); - - /** - * Recursively switches all skinned meshes to a stored animation frame for - * the next update. - */ - public void setMeshFrame (int frameId); - - /** - * Recursively blends all skinned meshes between two stored animation - * frames for the next update. - */ - public void blendMeshFrames (int frameId1, int frameId2, float alpha); - - /** - * Creates or populates and returns a clone of this object using the given - * clone properties. - * - * @param store an instance of this class to populate, or null - * to create a new instance - */ - public Spatial putClone (Spatial store, Model.CloneCreator properties); -} diff --git a/src/java/com/threerings/jme/model/Rotator.java b/src/java/com/threerings/jme/model/Rotator.java deleted file mode 100644 index 7bff0ced..00000000 --- a/src/java/com/threerings/jme/model/Rotator.java +++ /dev/null @@ -1,109 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Properties; - -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -import com.threerings.jme.util.JmeUtil; - -/** - * A procedural animation that rotates a node around at a constant angular - * velocity. - */ -public class Rotator extends ModelController -{ - @Override - public void configure (Properties props, Spatial target) - { - super.configure(props, target); - _axis = JmeUtil.parseAxis(props.getProperty("axis", "x")); - _velocity = Float.parseFloat(props.getProperty("velocity", "3.14")); - } - - // documentation inherited - public void update (float time) - { - if (!isActive()) { - return; - } - _rot.fromAngleNormalAxis(time * _velocity, _axis); - _target.getLocalRotation().multLocal(_rot); - } - - @Override - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - Rotator rstore; - if (store == null) { - rstore = new Rotator(); - } else { - rstore = (Rotator)store; - } - super.putClone(rstore, properties); - rstore._axis = _axis; - rstore._velocity = _velocity; - return rstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - _axis = (Vector3f)capsule.readSavable("axis", null); - _velocity = capsule.readFloat("velocity", 0f); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_axis, "axis", null); - capsule.write(_velocity, "velocity", 0f); - } - - /** The axis about which to rotate. */ - protected Vector3f _axis; - - /** The velocity at which to rotate in radians per second. */ - protected float _velocity; - - /** A temporary quaternion. */ - protected Quaternion _rot = new Quaternion(); - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/SkinMesh.java b/src/java/com/threerings/jme/model/SkinMesh.java deleted file mode 100644 index d6554880..00000000 --- a/src/java/com/threerings/jme/model/SkinMesh.java +++ /dev/null @@ -1,760 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.nio.ByteBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import org.lwjgl.opengl.GLContext; - -import com.jme.bounding.BoundingVolume; -import com.jme.math.Matrix4f; -import com.jme.renderer.Renderer; -import com.jme.scene.Spatial; -import com.jme.scene.TriMesh; -import com.jme.scene.VBOInfo; -import com.jme.scene.batch.SharedBatch; -import com.jme.scene.batch.TriangleBatch; -import com.jme.scene.state.GLSLShaderObjectsState; -import com.jme.scene.state.RenderState; -import com.jme.system.DisplaySystem; -import com.jme.util.ShaderAttribute; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; -import com.jme.util.export.Savable; -import com.jme.util.geom.BufferUtils; - -import com.samskivert.util.ArrayUtil; -import com.samskivert.util.HashIntMap; -import com.samskivert.util.ListUtil; - -import com.threerings.jme.util.JmeUtil; -import com.threerings.jme.util.ShaderCache; -import com.threerings.jme.util.ShaderConfig; - -/** - * A triangle mesh that deforms according to a bone hierarchy. - */ -public class SkinMesh extends ModelMesh -{ - /** The maximum number of bone matrices that we can use for hardware skinning. */ - public static final int MAX_SHADER_BONE_COUNT = 31; - - /** The maximum number of bones influencing a single vertex for hardware skinning. */ - public static final int MAX_SHADER_BONES_PER_VERTEX = 4; - - /** Represents the vertex weights of a group of vertices influenced by the - * same set of bones. */ - public static class WeightGroup - implements Savable - { - /** The number of vertices in this weight group. */ - public int vertexCount; - - /** The bones influencing this group. */ - public Bone[] bones; - - /** The array of interleaved weights (of length vertexCount * - * boneIndices.length): weights for first vertex, weights for - * second, etc. */ - public float[] weights; - - /** - * Rebinds this weight group for a prototype instance. - * - * @param bmap the mapping from prototype to instance bones - */ - public WeightGroup rebind (Map bmap) - { - WeightGroup wgroup = new WeightGroup(); - wgroup.vertexCount = vertexCount; - wgroup.bones = new Bone[bones.length]; - for (int ii = 0; ii < bones.length; ii++) { - wgroup.bones[ii] = bmap.get(bones[ii]); - } - wgroup.weights = weights; - return wgroup; - } - - // documentation inherited - public Class getClassTag () - { - return getClass(); - } - - // documentation inherited - public void read (JMEImporter im) - throws IOException - { - InputCapsule capsule = im.getCapsule(this); - vertexCount = capsule.readInt("vertexCount", 0); - bones = ArrayUtil.copy(capsule.readSavableArray("bones", null), - new Bone[0]); - weights = capsule.readFloatArray("weights", null); - } - - // documentation inherited - public void write (JMEExporter ex) - throws IOException - { - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(vertexCount, "vertexCount", 0); - capsule.write(bones, "bones", null); - capsule.write(weights, "weights", null); - } - - private static final long serialVersionUID = 1; - } - - /** Represents a bone that influences the mesh. */ - public static class Bone - implements Savable - { - /** The node that defines the bone's position. */ - public ModelNode node; - - /** The inverse of the bone's model space reference transform. */ - public transient Matrix4f invRefTransform; - - /** The bone's current transform in model space. */ - public transient Matrix4f transform; - - public Bone (ModelNode node) - { - this(); - this.node = node; - } - - public Bone () - { - transform = new Matrix4f(); - } - - /** - * Rebinds this bone for a prototype instance. - * - * @param pnodes a mapping from prototype nodes to instance nodes - */ - public Bone rebind (Map pnodes) - { - Bone bone = new Bone((ModelNode)pnodes.get(node)); - bone.invRefTransform = invRefTransform; - bone.transform = new Matrix4f(); - return bone; - } - - // documentation inherited - public Class getClassTag () - { - return getClass(); - } - - // documentation inherited - public void read (JMEImporter im) - throws IOException - { - InputCapsule capsule = im.getCapsule(this); - node = (ModelNode)capsule.readSavable("node", null); - } - - // documentation inherited - public void write (JMEExporter ex) - throws IOException - { - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(node, "node", null); - } - - private static final long serialVersionUID = 1; - } - - /** - * No-arg constructor for deserialization. - */ - public SkinMesh () - { - } - - /** - * Creates an empty mesh. - */ - public SkinMesh (String name) - { - super(name); - } - - /** - * Sets the array of weight groups that determine how bones affect - * each vertex. - */ - public void setWeightGroups (WeightGroup[] weightGroups) - { - _weightGroups = weightGroups; - - // compile a list of all referenced bones - HashSet bones = Sets.newHashSet(); - for (WeightGroup group : weightGroups) { - Collections.addAll(bones, group.bones); - } - _bones = bones.toArray(new Bone[bones.size()]); - } - - @Override - public void addOverlay (RenderState[] overlay) - { - // add a cloned state config (with same uniforms) for the overlay - super.addOverlay(overlay); - if (_sconfig == null) { - return; - } - if (_osconfigs == null) { - _osconfigs = Lists.newArrayListWithCapacity(1); - } - SkinShaderConfig osconfig = (SkinShaderConfig)_sconfig.clone(); - osconfig.getState().uniforms = _sconfig.getState().uniforms; - _osconfigs.add(osconfig); - } - - @Override - public void removeOverlay (RenderState[] overlay) - { - // remove the corresponding state config - int idx = (_overlays == null) ? -1 : _overlays.indexOf(overlay); - super.removeOverlay(overlay); - if (_osconfigs != null && idx >= 0) { - _osconfigs.remove(idx); - if (_osconfigs.isEmpty()) { - _osconfigs = null; - } - } - } - - @Override - public void reconstruct ( - FloatBuffer vertices, FloatBuffer normals, FloatBuffer colors, - FloatBuffer textures, IntBuffer indices) - { - super.reconstruct(vertices, normals, colors, textures, indices); - - // initialize the quantized frame table - _frames = new HashIntMap(); - } - - @Override - public Spatial putClone (Spatial store, Model.CloneCreator properties) - { - SkinMesh mstore = (SkinMesh)properties.originalToCopy.get(this); - if (mstore != null) { - return mstore; - } else if (store == null) { - mstore = new SkinMesh(getName()); - } else { - mstore = (SkinMesh)store; - } - GLSLShaderObjectsState sstate = (GLSLShaderObjectsState)getRenderState( - RenderState.RS_GLSL_SHADER_OBJECTS); - if (sstate == null) { - // vertices and normals must be cloned if not using a shader - properties.removeProperty("vertices"); - properties.removeProperty("normals"); - } - properties.removeProperty("displaylistid"); - super.putClone(mstore, properties); - if (sstate == null) { - properties.addProperty("vertices"); - properties.addProperty("normals"); - } - properties.addProperty("displaylistid"); - mstore._frames = _frames; - mstore._useDisplayLists = _useDisplayLists; - mstore._invRefTransform = _invRefTransform; - mstore._bones = new Bone[_bones.length]; - HashMap bmap = Maps.newHashMap(); - for (int ii = 0; ii < _bones.length; ii++) { - bmap.put(_bones[ii], mstore._bones[ii] = - _bones[ii].rebind(properties.originalToCopy)); - } - mstore._weightGroups = new WeightGroup[_weightGroups.length]; - for (int ii = 0; ii < _weightGroups.length; ii++) { - mstore._weightGroups[ii] = _weightGroups[ii].rebind(bmap); - } - mstore._ovbuf = _ovbuf; - mstore._onbuf = _onbuf; - mstore._vbuf = (sstate == null) ? new float[_vbuf.length] : _vbuf; - mstore._nbuf = (sstate == null) ? new float[_nbuf.length] : _nbuf; - if (_sconfig != null) { - mstore._sconfig = (SkinShaderConfig)_sconfig.clone(); - mstore.setRenderState(mstore._sconfig.getState()); - } - return mstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - setWeightGroups(ArrayUtil.copy(capsule.readSavableArray( - "weightGroups", null), new WeightGroup[0])); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_weightGroups, "weightGroups", null); - } - - @Override - public void expandModelBounds () - { - BoundingVolume obound = getBatch(0).getModelBound().clone(null); - updateModelBound(); - getBatch(0).getModelBound().mergeLocal(obound); - } - - @Override - public void setReferenceTransforms () - { - _invRefTransform = new Matrix4f(); - if (parent instanceof ModelNode) { - Matrix4f transform = new Matrix4f(); - JmeUtil.setTransform(getLocalTranslation(), getLocalRotation(), - getLocalScale(), transform); - ((ModelNode)parent).getModelTransform().mult(transform, - _invRefTransform); - _invRefTransform.invertLocal(); - } - for (Bone bone : _bones) { - bone.invRefTransform = - _invRefTransform.mult(bone.node.getModelTransform()).invert(); - } - } - - @Override - public void lockStaticMeshes ( - Renderer renderer, boolean useVBOs, boolean useDisplayLists) - { - // we can use VBOs for color, texture, and indices if not using shaders - if (useVBOs && renderer.supportsVBO()) { - // use VBOs for shader attributes - GLSLShaderObjectsState sstate = (GLSLShaderObjectsState)getRenderState( - RenderState.RS_GLSL_SHADER_OBJECTS); - if (sstate != null) { - for (ShaderAttribute attrib : sstate.attribs.values()) { - attrib.useVBO = true; - } - } - - VBOInfo vboinfo = new VBOInfo(true); - if (sstate == null) { - vboinfo.setVBOVertexEnabled(false); - vboinfo.setVBONormalEnabled(false); - } - vboinfo.setVBOIndexEnabled(!_translucent); - setVBOInfo(vboinfo); - } - _useDisplayLists = useDisplayLists && !_translucent; - } - - @Override - public void configureShaders (ShaderCache scache) - { - if (_disableShaders || !GLContext.getCapabilities().GL_ARB_vertex_shader || - _bones.length > MAX_SHADER_BONE_COUNT) { - return; - } - int bonesPerVertex = 0; - for (WeightGroup group : _weightGroups) { - bonesPerVertex = Math.max(group.bones.length, bonesPerVertex); - } - if (bonesPerVertex > MAX_SHADER_BONES_PER_VERTEX) { - return; - } - _sconfig = new SkinShaderConfig(scache, _emissiveMap != null); - if (_sconfig.update(getBatch(0).states)) { - setShaderAttributes(); - setRenderState(_sconfig.getState()); - } else { - _sconfig = null; - _disableShaders = true; - } - } - - @Override - public void storeMeshFrame (int frameId, boolean blend) - { - _storeFrameId = frameId; - _storeBlend = blend; - } - - @Override - public void setMeshFrame (int frameId) - { - TriangleBatch batch = getBatch(0), - tbatch = (TriangleBatch)_frames.get(frameId); - if (batch instanceof SharedBatch) { - ((SharedBatch)batch).setTarget(tbatch); - } else { - clearBatches(); - addBatch(new SharedBatch(tbatch)); - getBatch(0).updateRenderState(); - } - } - - @Override - public void blendMeshFrames (int frameId1, int frameId2, float alpha) - { - BlendFrame frame1 = (BlendFrame)_frames.get(frameId1), - frame2 = (BlendFrame)_frames.get(frameId2); - frame1.blend(frame2, alpha, _vbuf, _nbuf); - FloatBuffer vbuf = getVertexBuffer(0), nbuf = getNormalBuffer(0); - vbuf.rewind(); - vbuf.put(_vbuf); - nbuf.rewind(); - nbuf.put(_nbuf); - } - - @Override - public void updateWorldData (float time) - { - super.updateWorldData(time); - if (_weightGroups == null || _storeFrameId == -1 || - (_storeFrameId == 0 && getCullMode() == CULL_ALWAYS)) { - return; - } - // update the bone transforms - for (Bone bone : _bones) { - _invRefTransform.mult(bone.node.getModelTransform(), - bone.transform); - bone.transform.multLocal(bone.invRefTransform); - } - - // if we're using shaders, initialize the uniform variables with the bone transforms - GLSLShaderObjectsState sstate = (GLSLShaderObjectsState)getRenderState( - RenderState.RS_GLSL_SHADER_OBJECTS); - if (sstate != null) { - for (int ii = 0; ii < _bones.length; ii++) { - sstate.setUniform("boneTransforms[" + ii + "]", _bones[ii].transform, true); - } - return; - } - - // deform the mesh according to the positions of the bones (this code - // is ugly as sin because it's optimized at a low level) - Bone[] bones; - int vertexCount, jj, kk, ww; - float[] weights; - Matrix4f m; - float weight, ovx, ovy, ovz, onx, ony, onz, vx, vy, vz, nx, ny, nz; - for (int ii = 0, bidx = 0; ii < _weightGroups.length; ii++) { - vertexCount = _weightGroups[ii].vertexCount; - bones = _weightGroups[ii].bones; - weights = _weightGroups[ii].weights; - for (jj = 0, ww = 0; jj < vertexCount; jj++) { - ovx = _ovbuf[bidx]; - ovy = _ovbuf[bidx + 1]; - ovz = _ovbuf[bidx + 2]; - onx = _onbuf[bidx]; - ony = _onbuf[bidx + 1]; - onz = _onbuf[bidx + 2]; - vx = vy = vz = 0f; - nx = ny = nz = 0f; - for (kk = 0; kk < bones.length; kk++) { - m = bones[kk].transform; - weight = weights[ww++]; - - vx += (ovx*m.m00 + ovy*m.m01 + ovz*m.m02 + m.m03) * weight; - vy += (ovx*m.m10 + ovy*m.m11 + ovz*m.m12 + m.m13) * weight; - vz += (ovx*m.m20 + ovy*m.m21 + ovz*m.m22 + m.m23) * weight; - - nx += (onx*m.m00 + ony*m.m01 + onz*m.m02) * weight; - ny += (onx*m.m10 + ony*m.m11 + onz*m.m12) * weight; - nz += (onx*m.m20 + ony*m.m21 + onz*m.m22) * weight; - } - _vbuf[bidx] = vx; - _vbuf[bidx + 1] = vy; - _vbuf[bidx + 2] = vz; - _nbuf[bidx++] = nx; - _nbuf[bidx++] = ny; - _nbuf[bidx++] = nz; - } - } - - // if skinning in real time, copy the data from arrays to buffers; - // otherwise, store the mesh as an animation frame - if (_storeFrameId == 0) { - FloatBuffer vbuf = getVertexBuffer(0), nbuf = getNormalBuffer(0); - vbuf.rewind(); - vbuf.put(_vbuf); - nbuf.rewind(); - nbuf.put(_nbuf); - } else { - storeFrame(); - _storeFrameId = -1; - } - } - - /** - * Stores the current frame data for later use. - */ - protected void storeFrame () - { - if (_storeBlend) { - _frames.put(_storeFrameId, new BlendFrame(_vbuf.clone(), _nbuf.clone())); - } else { - TriangleBatch batch = getBatch(0), tbatch = new TriangleBatch(); - tbatch.setParentGeom(DUMMY_MESH); - tbatch.setColorBuffer(batch.getColorBuffer()); - int nunits = batch.getNumberOfUnits(); - for (int ii = 0; ii < nunits; ii++) { - tbatch.setTextureBuffer(batch.getTextureBuffer(ii), ii); - } - tbatch.setIndexBuffer(batch.getIndexBuffer()); - tbatch.setVertexBuffer(BufferUtils.createFloatBuffer(_vbuf)); - tbatch.setNormalBuffer(BufferUtils.createFloatBuffer(_nbuf)); - VBOInfo ovboinfo = batch.getVBOInfo(); - if (ovboinfo != null) { - VBOInfo vboinfo = new VBOInfo(true); - vboinfo.setVBOIndexEnabled(!_translucent); - vboinfo.setVBOColorID(ovboinfo.getVBOColorID()); - for (int ii = 0; ii < nunits; ii++) { - vboinfo.setVBOTextureID(ii, ovboinfo.getVBOTextureID(ii)); - } - vboinfo.setVBOIndexID(ovboinfo.getVBOIndexID()); - tbatch.setVBOInfo(vboinfo); - } else if (_useDisplayLists) { - tbatch.lockMeshes( - DisplaySystem.getDisplaySystem().getRenderer()); - } - _frames.put(_storeFrameId, tbatch); - } - } - - @Override - protected ModelBatch createModelBatch () - { - // update the shader configs immediately before drawing - return new ModelBatch() { - protected void preDraw () { - if (_sconfig != null) { - _sconfig.update(states); - } - } - protected void preDrawOverlay (int oidx) { - super.preDrawOverlay(oidx); - if (_osconfigs != null) { - _ostates[RenderState.RS_GLSL_SHADER_OBJECTS] = - states[RenderState.RS_GLSL_SHADER_OBJECTS]; - SkinShaderConfig osconfig = _osconfigs.get(oidx); - states[RenderState.RS_GLSL_SHADER_OBJECTS] = osconfig.getState(); - _osconfigs.get(oidx).update(states); - } - } - protected void postDrawOverlay (int oidx) { - super.postDrawOverlay(oidx); - if (_osconfigs != null) { - states[RenderState.RS_GLSL_SHADER_OBJECTS] = - _ostates[RenderState.RS_GLSL_SHADER_OBJECTS]; - } - } - }; - } - - @Override - protected void storeOriginalBuffers () - { - super.storeOriginalBuffers(); - - FloatBuffer vbuf = getVertexBuffer(0), nbuf = getNormalBuffer(0); - vbuf.rewind(); - nbuf.rewind(); - FloatBuffer.wrap(_ovbuf = new float[vbuf.capacity()]).put(vbuf); - FloatBuffer.wrap(_onbuf = new float[nbuf.capacity()]).put(nbuf); - _vbuf = new float[_ovbuf.length]; - _nbuf = new float[_onbuf.length]; - } - - /** - * Initializes the skin shader attributes (bone indices and weights) in the supplied state. - */ - protected void setShaderAttributes () - { - int size = getBatch(0).getVertexCount() * 4; - ByteBuffer bibuf = BufferUtils.createByteBuffer(size); - FloatBuffer bwbuf = BufferUtils.createFloatBuffer(size); - - for (WeightGroup group : _weightGroups) { - byte[] indices = new byte[4]; - for (int ii = 0; ii < 4; ii++) { - indices[ii] = (byte)((ii < group.bones.length) ? - ListUtil.indexOf(_bones, group.bones[ii]) : 0); - } - for (int ii = 0, widx = 0; ii < group.vertexCount; ii++) { - bibuf.put(indices); - for (int jj = 0; jj < 4; jj++) { - bwbuf.put((jj < group.bones.length) ? group.weights[widx++] : 0f); - } - } - } - bibuf.rewind(); - bwbuf.rewind(); - - GLSLShaderObjectsState sstate = _sconfig.getState(); - sstate.setAttributePointer("boneIndices", 4, false, false, 0, bibuf); - sstate.setAttributePointer("boneWeights", 4, false, 0, bwbuf); - } - - /** Tracks the configuration of a skin shader. */ - protected static class SkinShaderConfig extends ShaderConfig - { - public SkinShaderConfig (ShaderCache scache, boolean emissiveMapped) - { - super(scache); - _emissiveMapped = emissiveMapped; - - // set bindings from texture units to samplers - if (emissiveMapped) { - _state.setUniform("diffuseMap", 1); - _state.setUniform("emissiveMap", 0); - } else { - _state.setUniform("diffuseMap", 0); - } - } - - @Override - protected String getVertexShader () - { - return "media/jme/skin.vert"; - } - - @Override - protected String getFragmentShader () - { - return "media/jme/skin.frag"; - } - - @Override - protected void getDefinitions (ArrayList defs) - { - super.getDefinitions(defs); - if (_emissiveMapped) { - defs.add("EMISSIVE_MAPPED"); - } - } - - @Override - protected void getDerivedDefinitions (ArrayList ddefs) - { - super.getDerivedDefinitions(ddefs); - ddefs.add("MAX_BONE_COUNT " + MAX_SHADER_BONE_COUNT); - } - - protected boolean _emissiveMapped; - } - - /** A stored frame used for linear blending. */ - protected static class BlendFrame - { - /** The skinned vertex and normal values. */ - public float[] vbuf, nbuf; - - public BlendFrame (float[] vbuf, float[] nbuf) - { - this.vbuf = vbuf; - this.nbuf = nbuf; - } - - public void blend ( - BlendFrame next, float alpha, float[] rvbuf, float[] rnbuf) - { - float[] nvbuf = next.vbuf, nnbuf = next.nbuf; - float ialpha = 1f - alpha; - for (int ii = 0, nn = vbuf.length; ii < nn; ii++) { - rvbuf[ii] = vbuf[ii] * ialpha + nvbuf[ii] * alpha; - rnbuf[ii] = nbuf[ii] * ialpha + nnbuf[ii] * alpha; - } - } - } - - /** Pre-skinned {@link TriangleBatch}es or {@link BlendFrame}s shared - * between all instances corresponding to frame ids from - * {@link #storeAnimationFrame}. */ - protected HashIntMap _frames; - - /** Whether or to use display lists if VBOs are unavailable for quantized - * meshes. */ - protected boolean _useDisplayLists; - - /** The inverse of the model space reference transform. */ - protected Matrix4f _invRefTransform; - - /** The groups of vertices influenced by different sets of bones. */ - protected WeightGroup[] _weightGroups; - - /** The bones referenced by the weight groups. */ - protected Bone[] _bones; - - /** The original (undeformed) vertex and normal buffers and the deformed - * versions. */ - protected float[] _onbuf, _ovbuf, _nbuf; - - /** The primary skin shader configuration. */ - protected SkinShaderConfig _sconfig; - - /** Skin shader configurations for each overlay. */ - protected ArrayList _osconfigs; - - /** The frame id to store on the next update. If 0, don't store any frame - * and skin the mesh as normal. If -1, a frame has been stored and thus - * skinning should only take place when further frames are requested. */ - protected int _storeFrameId; - - /** Whether or not the stored frame id will be used for blending. */ - protected boolean _storeBlend; - - /** Set if we determine that our shaders don't compile to prevent us from trying again. */ - protected static boolean _disableShaders; - - /** A dummy mesh that simply hold transformation values. */ - protected static final TriMesh DUMMY_MESH = new TriMesh(); - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/TextureAnimator.java b/src/java/com/threerings/jme/model/TextureAnimator.java deleted file mode 100644 index fe2c0ad2..00000000 --- a/src/java/com/threerings/jme/model/TextureAnimator.java +++ /dev/null @@ -1,157 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Properties; - -import com.jme.image.Texture; -import com.jme.math.Vector3f; -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -import com.threerings.jme.util.JmeUtil; -import com.threerings.jme.util.JmeUtil.FrameState; - -/** - * Animates a model's textures by flipping between different parts. - */ -public class TextureAnimator extends TextureController -{ - @Override - public void configure (Properties props, Spatial target) - { - super.configure(props, target); - _frameWidth = Float.valueOf(props.getProperty("frame_width", "0.5")); - _frameHeight = Float.valueOf(props.getProperty("frame_height", "0.5")); - _frameCount = Integer.valueOf(props.getProperty("frame_count", "4")); - _frameRate = Float.valueOf(props.getProperty("frame_rate", "1")); - _repeatType = JmeUtil.parseRepeatType(props.getProperty("repeat_type"), - Controller.RT_WRAP); - } - - // documentation inherited - public void update (float time) - { - super.update(time); - if (!isActive()) { - return; - } - _fstate.update(time, _frameRate, _frameCount, _repeatType); - _translation.set( - (_fstate.idx % _hframes) * _frameWidth, - -(_fstate.idx / _hframes) * _frameHeight, - 0f); - } - - @Override - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - TextureAnimator tstore; - if (store == null) { - tstore = new TextureAnimator(); - } else { - tstore = (TextureAnimator)store; - } - super.putClone(tstore, properties); - tstore._frameWidth = _frameWidth; - tstore._frameHeight = _frameHeight; - tstore._frameCount = _frameCount; - tstore._frameRate = _frameRate; - tstore._repeatType = _repeatType; - return tstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - _frameWidth = capsule.readFloat("frameWidth", 0.5f); - _frameHeight = capsule.readFloat("frameHeight", 0.5f); - _frameCount = capsule.readInt("frameCount", 4); - _frameRate = capsule.readFloat("frameRate", 1f); - _repeatType = capsule.readInt("repeatType", Controller.RT_WRAP); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_frameWidth, "frameWidth", 0.5f); - capsule.write(_frameHeight, "frameHeight", 0.5f); - capsule.write(_frameCount, "frameCount", 4); - capsule.write(_frameRate, "frameRate", 1f); - capsule.write(_repeatType, "repeatType", Controller.RT_WRAP); - } - - @Override - protected void initTextures () - { - super.initTextures(); - - // compute derived values - _hframes = (int)Math.floor(1f / _frameWidth); - _vframes = (int)Math.floor(1f / _frameHeight); - - // use the same translation vector for all textures - _translation = new Vector3f(); - for (Texture texture : _textures) { - texture.setTranslation(_translation); - } - } - - /** The width of the frames in texture units. */ - protected float _frameWidth; - - /** The height of the frames in texture units. */ - protected float _frameHeight; - - /** The number of frames in the texture. */ - protected int _frameCount; - - /** The rate at which to display the frames (frames per second). */ - protected float _frameRate; - - /** The repeat type (one of the constants in {@link Controller}). */ - protected int _repeatType; - - /** The number of frames on the horizontal and vertical axes. */ - protected transient int _hframes, _vframes; - - /** The animation position. */ - protected transient FrameState _fstate = new FrameState(); - - /** The shared texture translation. */ - protected transient Vector3f _translation; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/TextureController.java b/src/java/com/threerings/jme/model/TextureController.java deleted file mode 100644 index 99d0714f..00000000 --- a/src/java/com/threerings/jme/model/TextureController.java +++ /dev/null @@ -1,95 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.util.HashMap; - -import com.google.common.collect.Maps; - -import com.jme.image.Texture; -import com.jme.scene.state.RenderState; -import com.jme.scene.state.TextureState; -import com.jme.system.DisplaySystem; - -import com.threerings.jme.util.SpatialVisitor; - -/** - * Base class for controllers that affect a model's textures. - */ -public abstract class TextureController extends ModelController -{ - @Override - public void resolveTextures (TextureProvider tprov) - { - // reinitialize the cloned textures if we re-resolve - super.resolveTextures(tprov); - _textures = null; - } - - // documentation inherited - public void update (float time) - { - // initialize the textures before the first update - if (_textures == null) { - initTextures(); - } - } - - /** - * Performs any per-instance initialization required for textures. - */ - protected void initTextures () - { - // find and clone all textures under the target - final HashMap clones = Maps.newHashMap(); - new SpatialVisitor(ModelMesh.class) { - protected void visit (ModelMesh mesh) { - TextureState otstate = (TextureState)mesh.getRenderState(RenderState.RS_TEXTURE); - if (otstate == null) { - return; - } - TextureState ntstate = - DisplaySystem.getDisplaySystem().getRenderer().createTextureState(); - for (int ii = 0, nn = otstate.getNumberOfSetTextures(); ii < nn; ii++) { - Texture tex = otstate.getTexture(ii), ctex = clones.get(tex); - if (ctex == null) { - if (tex.getTextureId() == 0) { - otstate.apply(); // load before cloning - } - clones.put(tex, ctex = tex.createSimpleClone()); - } - ntstate.setTexture(ctex, ii); - } - mesh.setRenderState(ntstate); - } - }.traverse(_target); - _target.updateRenderState(); - - // remember them for updates - _textures = clones.values().toArray(new Texture[0]); - } - - /** The cloned textures to manipulate. */ - protected transient Texture[] _textures; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/TextureProvider.java b/src/java/com/threerings/jme/model/TextureProvider.java deleted file mode 100644 index db51dfe7..00000000 --- a/src/java/com/threerings/jme/model/TextureProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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. - * - * @param name the name of the texture, which will be interpreted as an - * absolute resource path if it starts with a forward slash; otherwise, - * as a relative resource path - */ - public TextureState getTexture (String name); -} diff --git a/src/java/com/threerings/jme/model/TextureTranslator.java b/src/java/com/threerings/jme/model/TextureTranslator.java deleted file mode 100644 index 1735aa38..00000000 --- a/src/java/com/threerings/jme/model/TextureTranslator.java +++ /dev/null @@ -1,122 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Properties; - -import com.jme.image.Texture; -import com.jme.math.Vector2f; -import com.jme.math.Vector3f; -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -import com.samskivert.util.StringUtil; - -import static com.threerings.jme.Log.log; - -/** - * A procedural animation that translates the model's textures at a constant velocity. - */ -public class TextureTranslator extends TextureController -{ - @Override - public void configure (Properties props, Spatial target) - { - super.configure(props, target); - String velstr = props.getProperty("velocity", "1, 0"); - float[] vel = StringUtil.parseFloatArray(velstr); - if (vel != null && vel.length == 2) { - _velocity = new Vector2f(vel[0], vel[1]); - } else { - log.warning("Invalid velocity [velocity=" + velstr + "]."); - } - } - - // documentation inherited - public void update (float time) - { - super.update(time); - if (!isActive()) { - return; - } - _translation.addLocal(_velocity.x * time, _velocity.y * time, 0f); - } - - @Override - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - TextureTranslator tstore; - if (store == null) { - tstore = new TextureTranslator(); - } else { - tstore = (TextureTranslator)store; - } - super.putClone(tstore, properties); - tstore._velocity = _velocity; - return tstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - _velocity = (Vector2f)capsule.readSavable("velocity", null); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_velocity, "velocity", null); - } - - @Override - protected void initTextures () - { - super.initTextures(); - - // use the same translation vector for all textures - _translation = new Vector3f(); - for (Texture texture : _textures) { - texture.setTranslation(_translation); - } - } - - /** The velocity at which to translate the texture. */ - protected Vector2f _velocity; - - /** The shared translation vector. */ - protected transient Vector3f _translation; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/model/Translator.java b/src/java/com/threerings/jme/model/Translator.java deleted file mode 100644 index a35441c2..00000000 --- a/src/java/com/threerings/jme/model/Translator.java +++ /dev/null @@ -1,130 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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 java.io.IOException; - -import java.util.Properties; - -import com.jme.math.Vector3f; -import com.jme.scene.Controller; -import com.jme.scene.Spatial; -import com.jme.util.export.JMEExporter; -import com.jme.util.export.JMEImporter; -import com.jme.util.export.InputCapsule; -import com.jme.util.export.OutputCapsule; - -import com.threerings.jme.util.JmeUtil; - -/** - * A procedural animation that moves a node along a straight line at a constant velocity (then - * either repeats or moves it in the other direction). - */ -public class Translator extends ModelController -{ - @Override - public void configure (Properties props, Spatial target) - { - super.configure(props, target); - _from = JmeUtil.parseVector3f(props.getProperty("from", "0, 0, 0")); - _to = JmeUtil.parseVector3f(props.getProperty("to", "10, 0, 0")); - _duration = Float.parseFloat(props.getProperty("duration", "1")); - _repeatType = JmeUtil.parseRepeatType(props.getProperty("repeat_type"), - Controller.RT_WRAP); - } - - // documentation inherited - public void update (float time) - { - if (!isActive()) { - return; - } - _elapsed += (time / _duration); - float alpha; - if (_repeatType == Controller.RT_CLAMP) { - alpha = Math.min(_elapsed, 1f); - } else if (_repeatType == Controller.RT_WRAP) { - alpha = (_elapsed - (int)_elapsed); - } else { // _repeatType == Controller.RT_CYCLE - int ipart = (int)_elapsed; - float fpart = (_elapsed - ipart); - alpha = (ipart % 2 == 0) ? fpart : (1f - fpart); - } - _target.getLocalTranslation().interpolate(_from, _to, alpha); - } - - @Override - public Controller putClone ( - Controller store, Model.CloneCreator properties) - { - Translator tstore; - if (store == null) { - tstore = new Translator(); - } else { - tstore = (Translator)store; - } - super.putClone(tstore, properties); - tstore._from = _from; - tstore._to = _to; - tstore._duration = _duration; - tstore._repeatType = _repeatType; - return tstore; - } - - @Override - public void read (JMEImporter im) - throws IOException - { - super.read(im); - InputCapsule capsule = im.getCapsule(this); - _from = (Vector3f)capsule.readSavable("from", null); - _to = (Vector3f)capsule.readSavable("to", null); - _duration = capsule.readFloat("duration", 1f); - _repeatType = capsule.readInt("repeatType", Controller.RT_WRAP); - } - - @Override - public void write (JMEExporter ex) - throws IOException - { - super.write(ex); - OutputCapsule capsule = ex.getCapsule(this); - capsule.write(_from, "from", null); - capsule.write(_to, "to", null); - capsule.write(_duration, "duration", 1f); - capsule.write(_repeatType, "repeatType", Controller.RT_WRAP); - } - - /** The beginning and end of the path. */ - protected Vector3f _from, _to; - - /** The duration of the path. */ - protected float _duration; - - /** What to do after reaching the destination. */ - protected int _repeatType; - - /** The accumulated amount of time elapsed. */ - protected transient float _elapsed; - - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/package.html b/src/java/com/threerings/jme/package.html deleted file mode 100644 index e6df5fa9..00000000 --- a/src/java/com/threerings/jme/package.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - Defines extensions to jMonkeyEngine - an OpenGL-based 3D rendering engine. An application framework is - provided that integrates jME with the Presents distributed object - system and other useful bits and bobs are also included. - - - diff --git a/src/java/com/threerings/jme/sprite/BallisticPath.java b/src/java/com/threerings/jme/sprite/BallisticPath.java deleted file mode 100644 index fb5e0699..00000000 --- a/src/java/com/threerings/jme/sprite/BallisticPath.java +++ /dev/null @@ -1,92 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.math.FastMath; -import com.jme.math.Vector3f; - -/** - * Moves a sprite ballistically. - */ -public class BallisticPath extends Path -{ - /** Gravity: it's the law. */ - public static final float G = -9.8f; - - /** - * Moves the supplied sprite from the starting coordinate (which will - * be modified) using the starting velocity, under the specified - * acceleration. - */ - public BallisticPath (Sprite sprite, Vector3f start, Vector3f velocity, - Vector3f accel, float duration) - { - super(sprite); - _curpos = start; - _velocity = velocity; - _accel = accel; - _duration = duration; - } - - // documentation inherited - public void update (float time) - { - // adjust the position - _velocity.mult(time, _temp); - _curpos.addLocal(_temp); - _sprite.setLocalTranslation(_curpos); - - // check to see if we're done - _accum += time; - if (_accum >= _duration) { - _sprite.pathCompleted(); - } else { - // adjust our velocity due to acceleration - _accel.mult(time, _temp); - _velocity.addLocal(_temp); - } - } - - /** - * Computes and returns the angle of elevation needed to launch a - * ballistic projectile at the specified velocity and have it travel - * the specified range (when it will once again reach the launch - * elevation). - */ - public static float computeElevation (float range, float vel, float accel) - { - return FastMath.asin(accel * range / (vel * vel)) / 2; - } - - /** - * Computes and returns the flight time of a projectile launched at an - * angle previously computed with {@link #computeElevation}.. - */ - public static float computeFlightTime (float range, float vel, float angle) - { - return range / (vel * FastMath.cos(angle)); - } - - protected Vector3f _curpos, _velocity, _accel; - protected float _duration, _accum; - protected Vector3f _temp = new Vector3f(0, 0, 0); -} diff --git a/src/java/com/threerings/jme/sprite/CubicSplinePath.java b/src/java/com/threerings/jme/sprite/CubicSplinePath.java deleted file mode 100644 index cb7b092f..00000000 --- a/src/java/com/threerings/jme/sprite/CubicSplinePath.java +++ /dev/null @@ -1,188 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.math.Vector3f; - -/** - * Moves a sprite along an interpolated spline based on a series of control - * points. - */ -public class CubicSplinePath extends Path -{ - /** - * Creates a path for the supplied sprite traversing the supplied - * series of points with the specified duration between points. The - * path assumes that all the control points exist on either the same - * x or y axis. The non-fixed x/y axis must be in order (either ascending - * or descending), and the z values will be interpolated. - * - * @param points a list of points to interpolate between. Currently - * all the points along one dimension must be equal. - * @param durations defines the elapsed time between each successive - * traversal. This will as a result be shorter by one element than the - * points array. - */ - public CubicSplinePath ( - Sprite sprite, Vector3f[] points, float[] durations) - { - super(sprite); - _isX = (points[0].x != points[1].x); - _x = new float[points.length]; - _y = new float[points.length]; - _z = (_isX ? points[0].y : points[0].x); - for (int ii = 0; ii < points.length; ii++) { - _x[ii] = (_isX ? points[ii].x : points[ii].y); - _y[ii] = points[ii].z; - } - _end = points[points.length - 1]; - _durations = durations; - calculateDerivatives(); - } - - // documentation inherited - public void update (float time) - { - // note the accumulated time - _accum += time; - - // if we have surpassed the time for this segment, subtract the - // segment time and move on to the next segment - while (_current < _durations.length && _accum > _durations[_current]) { - _accum -= _durations[_current]; - _current++; - } - - // if we have completed out path, move the sprite to the final - // position and wrap everything up - if (_current >= _durations.length) { - _sprite.setLocalTranslation(_end); - _sprite.pathCompleted(); - return; - } - - // move the sprite to the appropriate position between points - _sprite.getLocalTranslation().set(interpolate(0f)); - } - - /** - * Calculates the second derivative values for all the control points - * along the path. - */ - protected void calculateDerivatives () - { - float[] u = new float[_x.length]; - _y2 = new float[_x.length]; - for (int ii = 1; ii < _x.length - 1; ii++) { - float sig = (_x[ii] - _x[ii-1])/(_x[ii+1] - _x[ii-1]); - float p = sig * _y2[ii-1] + 2; - _y2[ii] = (sig - 1f) / p; - u[ii] = (6f * ((_y[ii+1] - _y[ii]) / (_x[ii+1] - _x[ii]) - - (_y[ii] - _y[ii-1]) / (_x[ii] - _x[ii-1])) / - (_x[ii+1] - _x[ii-1]) - sig * u[ii-1]) / p; - } - for (int ii = _x.length - 2; ii >= 0; ii--) { - _y2[ii] = _y2[ii] * _y2[ii + 1] + u[ii]; - } - } - - /** - * Interpolates the z value based on the current time point on the path. - * - * @param delta is the difference from the current time point to - * interpolate the point. - */ - protected Vector3f interpolate (float delta) - { - int idx = _current; - // no change, just use the current value - if (delta == 0f) { - delta = _accum; - - // find the control point after the current one for interpolating - } else if (delta + _accum > _durations[idx]) { - delta -= _durations[idx] - _accum; - while (idx < _durations.length - 1) { - idx++; - if (delta < _durations[idx]) { - break; - } - delta -= _durations[idx]; - } - if (delta > _durations[idx] || idx == _durations.length - 1) { - return _end; - } - - // find the control point before the current one for interpolating - } else if (_accum + delta < 0) { - delta += _accum; - while (idx > 0) { - idx--; - delta += _durations[idx]; - if (delta > 0) { - break; - } - } - if (delta < 0) { - delta = 0; - } - - // we're using the same control point, simply adjust the time point - } else { - delta += _accum; - } - - float h = _x[idx + 1] - _x[idx]; - // no different between these points, just return the current value - if (h == 0) { - if (_sprite != null) { - return new Vector3f(_sprite.getLocalTranslation()); - } - return new Vector3f(); - } - - float x = _x[idx] + h * (delta / _durations[idx]); - float a = (_x[idx + 1] - x) / h; - float b = (x - _x[idx]) / h; - float a3 = a * a * a, b3 = b * b * b; - float y = a * _y[idx] + b * _y[idx + 1] + - ((a3 - a) * _y2[idx] + (b3 - b) * _y2[idx + 1]) * - (h * h) / 6; - float z = y; - if (_isX) { - y = _z; - } else { - y = x; - x = _z; - } - return new Vector3f(x, y, z); - } - - /** The final path point */ - protected Vector3f _end; - /** The array of control points, derivatives and durations. */ - protected float[] _x, _y, _y2, _durations; - - protected float _accum, _z; - protected int _current; - protected boolean _isX; -} diff --git a/src/java/com/threerings/jme/sprite/LinePath.java b/src/java/com/threerings/jme/sprite/LinePath.java deleted file mode 100644 index 640482be..00000000 --- a/src/java/com/threerings/jme/sprite/LinePath.java +++ /dev/null @@ -1,60 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.math.Vector3f; - -/** - * Moves a sprite along a straight line. - */ -public class LinePath extends Path -{ - /** - * Moves the supplied sprite from the starting coordinate to the - * specified destination coordinate in the specified time. - */ - public LinePath (Sprite sprite, Vector3f start, Vector3f finish, - float duration) - { - super(sprite); - _start = start; - _finish = finish; - _duration = duration; - } - - // documentation inherited - public void update (float time) - { - _accum += time; - if (_accum >= _duration) { - _sprite.setLocalTranslation(_finish); - _sprite.pathCompleted(); - } else { - _temp.interpolate(_start, _finish, _accum / _duration); - _sprite.setLocalTranslation(_temp); - } - } - - protected Vector3f _start, _finish; - protected float _duration, _accum; - protected Vector3f _temp = new Vector3f(0, 0, 0); -} diff --git a/src/java/com/threerings/jme/sprite/LineSegmentPath.java b/src/java/com/threerings/jme/sprite/LineSegmentPath.java deleted file mode 100644 index 95f34f9f..00000000 --- a/src/java/com/threerings/jme/sprite/LineSegmentPath.java +++ /dev/null @@ -1,103 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; - -/** - * Moves a sprite along a series of straight lines. - */ -public class LineSegmentPath extends Path -{ - /** - * Creates a path for the supplied sprite traversing the supplied - * series of points with the specified duration between points. - * - * @param points a list of points between which the sprite will be - * moved linearly (the sprite will be moved immediately to the first - * point). - * @param durations defines the elapsed time between each successive - * traversal. This will as a result be shorter by one element than the - * points array. - */ - public LineSegmentPath (Sprite sprite, Vector3f up, Vector3f orient, - Vector3f[] points, float[] durations) - { - super(sprite); - _up = up; - _orient = orient; - _points = points; - _durations = durations; - updateRotation(); - } - - // documentation inherited - public void update (float time) - { - // note the accumulated time - _accum += time; - - // if we have surpassed the time for this segment, subtract the - // segment time and move on to the next segment - while (_current < _durations.length && _accum > _durations[_current]) { - _accum -= _durations[_current]; - advance(); - } - - // if we have completed our path, move the sprite to the final - // position and wrap everything up - if (_current >= _durations.length) { - _sprite.setLocalTranslation(_points[_points.length-1]); - _sprite.pathCompleted(); - return; - } - - // move the sprite to the appropriate position between points - _temp.interpolate(_points[_current], _points[_current+1], - _accum / _durations[_current]); - _sprite.setLocalTranslation(_temp); - } - - protected void advance () - { - _current++; - if (_current < _points.length-1) { - updateRotation(); - } - } - - protected void updateRotation () - { - _points[_current+1].subtract(_points[_current], _temp); - PathUtil.computeRotation(_up, _orient, _temp, _rotate); - _sprite.getLocalRotation().set(_rotate); - } - - protected Vector3f _up, _orient; - protected Vector3f[] _points; - protected float[] _durations; - protected float _accum; - protected int _current; - protected Vector3f _temp = new Vector3f(0, 0, 0); - protected Quaternion _rotate = new Quaternion(); -} diff --git a/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java b/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java deleted file mode 100644 index 2aac2f74..00000000 --- a/src/java/com/threerings/jme/sprite/OrientingBallisticPath.java +++ /dev/null @@ -1,70 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; - -/** - * A ballistic path that orients the sprite toward the velocity vector as - * it traverses the path. - */ -public class OrientingBallisticPath extends BallisticPath -{ - /** - * Creates a {@link BallisticPath} that will rotate the sprite so that - * the supplied orient is aligned with the velocity - * vector at all points along the path. If the provided orientation is - * not initially in line with the starting velocity, the sprite will - * be rotated immediately and then adjusted as it follows the path. - */ - public OrientingBallisticPath ( - Sprite sprite, Vector3f orient, Vector3f start, Vector3f velocity, - Vector3f accel, float duration) - { - super(sprite, start, velocity, accel, duration); - - // TODO: handle orient that is not (1, 0, 0) - _orient = orient; - - // compute the up vector (opposite of acceleration) - _up = accel.negate(); - _up.normalizeLocal(); - - _sprite.setLocalRotation( - PathUtil.computeAxisRotation(_up, velocity, _rotate)); - } - - // documentation inherited - public void update (float time) - { - // do the normal update - super.update(time); - - _sprite.setLocalRotation( - PathUtil.computeAxisRotation(_up, _velocity, _rotate)); - } - - protected Vector3f _orient; - protected Vector3f _up; - protected Quaternion _rotate = new Quaternion(); -} diff --git a/src/java/com/threerings/jme/sprite/Path.java b/src/java/com/threerings/jme/sprite/Path.java deleted file mode 100644 index 15b3a1dd..00000000 --- a/src/java/com/threerings/jme/sprite/Path.java +++ /dev/null @@ -1,51 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.scene.Controller; - -/** - * Defines a framework for moving sprites around and notifying interested - * parties when the sprite has completed its path or if the path has been - * cancelled. - */ -public abstract class Path extends Controller -{ - /** - * Creates and initializes this path with the sprite it will be - * manipulating. - */ - protected Path (Sprite sprite) - { - _sprite = sprite; - } - - /** - * Called when this path is removed from its sprite (either due to - * completion or cancellation). - */ - public void wasRemoved () - { - } - - protected Sprite _sprite; -} diff --git a/src/java/com/threerings/jme/sprite/PathObserver.java b/src/java/com/threerings/jme/sprite/PathObserver.java deleted file mode 100644 index 2ed59e3a..00000000 --- a/src/java/com/threerings/jme/sprite/PathObserver.java +++ /dev/null @@ -1,44 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -/** - * Implement this interface to find out when a sprite completes or cancels - * its path. - */ -public interface PathObserver extends SpriteObserver -{ - /** - * Called when a sprite's path is cancelled either because a new path - * was started or the path was explicitly cancelled with {@link - * Sprite#cancelMove}. - */ - public void pathCancelled (Sprite sprite, Path path); - - /** - * Called when a sprite completes its traversal of a path. - * - * @param sprite the sprite that completed its path. - * @param path the path that was completed. - */ - public void pathCompleted (Sprite sprite, Path path); -} diff --git a/src/java/com/threerings/jme/sprite/PathUtil.java b/src/java/com/threerings/jme/sprite/PathUtil.java deleted file mode 100644 index 95d4c5f0..00000000 --- a/src/java/com/threerings/jme/sprite/PathUtil.java +++ /dev/null @@ -1,95 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.math.FastMath; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; - -/** - * Path related utility functions. - */ -public class PathUtil -{ - /** - * Computes a rotation to align the X axis with the specified - * orientation and stores it in the provided target. The provided up - * vector is crossed with the new orientation to find the left vector - * and the left vector is recrossed with the orientation to find the - * correct up vector. - * - * @return the supplied target quaternion. - */ - public static Quaternion computeAxisRotation ( - Vector3f up, Vector3f orient, Quaternion target) - { - _axes[0].set(orient); - _axes[0].normalizeLocal(); - up.cross(_axes[0], _axes[1]); - _axes[1].normalizeLocal(); - _axes[0].cross(_axes[1], _axes[2]); - target.fromAxes(_axes); - return target; - } - - /** - * Computes a rotation from the one vector to another. - * - * @param axis will be used as the axis of rotation if the two vectors - * are parallel. - */ - public static Quaternion computeRotation ( - Vector3f axis, Vector3f from, Vector3f to, Quaternion target) - { - float angle = computeAngle(from, to); - if (angle == FastMath.PI) { // opposite - target.fromAngleAxis(angle, axis); - } else if (angle == 0) { // coincident - target.x = target.y = target.z = 0; - target.w = 1; - } else { - from.cross(to, _axis); - target.fromAngleAxis(angle, _axis); - } - return target; - } - - /** - * Computes the angle between two arbitrary vectors. - */ - public static float computeAngle (Vector3f one, Vector3f two) - { - return FastMath.acos(one.dot(two) / (one.length() * two.length())); - } - - /** - * Computes the angle between two normalized vectors. - */ - public static float computeAngleNormal (Vector3f one, Vector3f two) - { - return FastMath.acos(one.dot(two)); - } - - protected static Vector3f[] _axes = { - new Vector3f(), new Vector3f(), new Vector3f() }; - protected static Vector3f _axis = new Vector3f(); -} diff --git a/src/java/com/threerings/jme/sprite/Sprite.java b/src/java/com/threerings/jme/sprite/Sprite.java deleted file mode 100644 index d99c5dac..00000000 --- a/src/java/com/threerings/jme/sprite/Sprite.java +++ /dev/null @@ -1,244 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -import com.jme.scene.Node; -import com.jme.scene.Spatial; - -import com.samskivert.util.ObserverList; - -import static com.threerings.jme.Log.log; - -/** - * Represents a visual entity that one controls as a single unit. Sprites - * can be made to follow paths which is one of their primary reasons for - * existence. - */ -public class Sprite extends Node -{ - /** - * Walks down the hierarchy provided setting the animation speed on - * any controllers found along the way. - */ - public static void setAnimationSpeed (Spatial spatial, float speed) - { - for (int ii = 0; ii < spatial.getControllers().size(); ii++) { - spatial.getController(ii).setSpeed(speed); - } - if (spatial instanceof Node) { - Node node = (Node)spatial; - for (int ii = 0; ii < node.getQuantity(); ii++) { - setAnimationSpeed(node.getChild(ii), speed); - } - } - } - - /** - * Walks down the hierarchy provided turning on or off any controllers - * found along the way. - */ - public static void setAnimationActive (Spatial spatial, boolean active) - { - for (int ii = 0; ii < spatial.getControllers().size(); ii++) { - spatial.getController(ii).setActive(active); - } - if (spatial instanceof Node) { - Node node = (Node)spatial; - for (int ii = 0; ii < node.getQuantity(); ii++) { - setAnimationActive(node.getChild(ii), active); - } - } - } - - /** - * Walks down the hierarchy provided setting the animation repeat type on - * any controllers found along the way. - */ - public static void setAnimationRepeatType (Spatial spatial, int repeatType) - { - for (int ii = 0; ii < spatial.getControllers().size(); ii++) { - spatial.getController(ii).setRepeatType(repeatType); - } - if (spatial instanceof Node) { - Node node = (Node)spatial; - for (int ii = 0; ii < node.getQuantity(); ii++) { - setAnimationRepeatType(node.getChild(ii), repeatType); - } - } - } - - public Sprite () - { - super(""); - setName("sprite:" + hashCode()); - } - - /** - * Adds an observer to this sprite. Observers are notified when path - * related events take place. - */ - public void addObserver (SpriteObserver obs) - { - if (_observers == null) { - _observers = new ObserverList( - ObserverList.SAFE_IN_ORDER_NOTIFY); - } - _observers.add(obs); - } - - /** - * Removes the specified observer from this sprite. - */ - public void removeObserver (SpriteObserver obs) - { - if (_observers != null) { - _observers.remove(obs); - } - } - - /** - * Returns true if this sprite is moving along a path, false if not. - */ - public boolean isMoving () - { - return _path != null; - } - - /** - * Instructs this sprite to move along the specified path. Any - * currently executing path will be cancelled. - */ - public void move (Path path) - { - // if there's a previous path, let it know that it's going away - cancelMove(); - - // save off this path - _path = path; - addController(_path); - } - - /** - * Cancels any currently executing path. Any registered observers will - * be notified of the cancellation. - */ - public void cancelMove () - { - if (_path != null) { - Path oldpath = _path; - _path = null; - removeController(oldpath); - oldpath.wasRemoved(); - if (_observers != null) { - _observers.apply(new CancelledOp(this, oldpath)); - } - } - } - - /** - * Called by the active path when it has completed. Note: - * don't call this method unless you are implementing a {@link Path}. - */ - public void pathCompleted () - { - if (_path == null) { - log.warning("pathCompleted() called on pathless sprite " + - "(re-completed?) [sprite=" + this + "].", new Exception()); - return; - } - - Path oldpath = _path; - _path = null; - removeController(oldpath); - oldpath.wasRemoved(); - if (_observers != null) { - _observers.apply(new CompletedOp(this, oldpath)); - } - } - - /** - * Configures the speed of all controllers in our model hierarchy. - */ - public void setAnimationSpeed (float speed) - { - setAnimationSpeed(this, speed); - } - - /** - * Configures the active state of all controllers in our model hierarchy. - */ - public void setAnimationActive (boolean active) - { - setAnimationActive(this, active); - } - - /** - * Configures the repeat type of all controllers in our model hierarchy. - */ - public void setAnimationRepeatType (int repeatType) - { - setAnimationRepeatType(this, repeatType); - } - - /** Used to dispatch {@link PathObserver#pathCancelled}. */ - protected static class CancelledOp - implements ObserverList.ObserverOp - { - public CancelledOp (Sprite sprite, Path path) { - _sprite = sprite; - _path = path; - } - - public boolean apply (SpriteObserver observer) { - if (observer instanceof PathObserver) { - ((PathObserver)observer).pathCancelled(_sprite, _path); - } - return true; - } - - protected Sprite _sprite; - protected Path _path; - } - - /** Used to dispatch {@link PathObserver#pathCompleted}. */ - protected static class CompletedOp - implements ObserverList.ObserverOp - { - public CompletedOp (Sprite sprite, Path path) { - _sprite = sprite; - _path = path; - } - - public boolean apply (SpriteObserver observer) { - if (observer instanceof PathObserver) { - ((PathObserver)observer).pathCompleted(_sprite, _path); - } - return true; - } - - protected Sprite _sprite; - protected Path _path; - } - - protected ObserverList _observers; - protected Path _path; -} diff --git a/src/java/com/threerings/jme/sprite/SpriteObserver.java b/src/java/com/threerings/jme/sprite/SpriteObserver.java deleted file mode 100644 index 05813e07..00000000 --- a/src/java/com/threerings/jme/sprite/SpriteObserver.java +++ /dev/null @@ -1,29 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.sprite; - -/** - * The super-interface for all sprite observers. - */ -public interface SpriteObserver -{ -} diff --git a/src/java/com/threerings/jme/tile/FringeConfiguration.java b/src/java/com/threerings/jme/tile/FringeConfiguration.java deleted file mode 100644 index b9a78eda..00000000 --- a/src/java/com/threerings/jme/tile/FringeConfiguration.java +++ /dev/null @@ -1,163 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tile; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - -import com.samskivert.util.StringUtil; - -import static com.threerings.jme.Log.log; - -/** - * Used to manage data about which tiles fringe on which others and how - * they fringe. - */ -public class FringeConfiguration implements Serializable -{ - /** Contains information on a type of tile and all of the fringe - * records associated with it. */ - public static class TileRecord implements Serializable - { - /** The type of tile to which this applies. */ - public String type; - - /** The fringe priority of this type. */ - public int priority; - - /** A list of the fringe records that can be used for fringing. */ - public List fringes = Lists.newArrayList(); - - /** Used when parsing from an XML definition. */ - public void addFringe (FringeRecord record) - { - if (record.isValid()) { - fringes.add(record); - } else { - log.warning("Not adding invalid fringe record [tile=" + this + - ", fringe=" + record + "]."); - } - } - - /** Did everything parse well? */ - public boolean isValid () - { - return ((type != null) && (priority > 0)); - } - - /** Generates a string representation of this instance. */ - public String toString () - { - return "[type=" + type + ", priority=" + priority + - ", fringes=" + StringUtil.toString(fringes) + "]"; - } - - /** Increase this value when object's serialized state is impacted - * by a class change (modification of fields, inheritance). */ - private static final long serialVersionUID = 1; - } - - /** Used to parse the type fringe definitions. */ - public static class FringeRecord implements Serializable - { - /** The name of the fringe tileset image. */ - public String name; - - /** Is this a mask? */ - public boolean mask; - - /** Did everything parse well? */ - public boolean isValid () - { - return (name != null); - } - - /** Generates a string representation of this instance. */ - public String toString () - { - return "[name=" + name + ", mask=" + mask + "]"; - } - - /** Increase this value when object's serialized state is impacted - * by a class change (modification of fields, inheritance). */ - private static final long serialVersionUID = 1; - } - - /** - * Adds a parsed fringe record to this instance. This is used when - * parsing the fringe records from xml. - */ - public void addTileRecord (TileRecord record) - { - if (record.isValid()) { - _trecs.put(record.type, record); - } else { - log.warning("Refusing to add invalid tile record " + - "[tile=" + record + "]."); - } - } - - /** - * If the first type fringes upon the second, return the fringe - * priority of the first type, otherwise return -1. - */ - public int fringesOn (String fringer, String fringed) - { - TileRecord f1 = _trecs.get(fringer); - - // we better have a fringe record for the fringer - if (null != f1) { - // it had better have some types defined - if (f1.fringes.size() > 0) { - TileRecord f2 = _trecs.get(fringed); - // and we only fringe if fringed doesn't have a fringe - // record or has a lower priority - if ((null == f2) || (f1.priority > f2.priority)) { - return f1.priority; - } - } - } - - return -1; - } - - /** - * Get a random FringeRecord from amongst the ones listed for the - * specified type. - */ - public FringeRecord getFringe (String type, int hashValue) - { - TileRecord t = _trecs.get(type); - return t.fringes.get(hashValue % t.fringes.size()); - } - - /** The mapping from tile type to tile record. */ - protected Map _trecs = Maps.newHashMap(); - - /** Increase this value when object's serialized state is impacted by - * a class change (modification of fields, inheritance). */ - private static final long serialVersionUID = 1; -} diff --git a/src/java/com/threerings/jme/tile/TileFringer.java b/src/java/com/threerings/jme/tile/TileFringer.java deleted file mode 100644 index be198eaf..00000000 --- a/src/java/com/threerings/jme/tile/TileFringer.java +++ /dev/null @@ -1,406 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tile; - -import java.awt.Graphics2D; -import java.awt.Transparency; -import java.awt.image.BufferedImage; -import java.util.List; -import java.util.Map; - -import com.google.common.collect.Lists; - -import com.samskivert.util.QuickSort; - -import com.threerings.media.image.ImageUtil; -import com.threerings.media.tile.TileUtil; - -import static com.threerings.jme.Log.log; - -/** - * Computes fringe tile images according to the rules in an associated - * fringe configuration. - */ -public class TileFringer -{ - public static interface TileSource - { - /** Returns the type of tile at the specified coordinates or -1 if - * there is no tile at this coordinate. */ - public String getTileType (int x, int y); - - /** Returns the tile type to use when a coordinate has no tile. */ - public String getDefaultType (); - } - - public static interface ImageSource extends ImageUtil.ImageCreator - { - /** Creates a blank image into which various fringe images will be - * composited. */ - public BufferedImage createImage ( - int width, int height, int transparency); - - /** Returns the source image for a tile of the specified type. - * This can be randomly selected and change from call to call. */ - public BufferedImage getTileSource (String type); - - /** Returns the named fringe source image (one long strip). */ - public BufferedImage getFringeSource (String name); - } - - /** - * Creates a fringer that will fringe according to the rules in the - * supplied configuration. - */ - public TileFringer (FringeConfiguration config, ImageSource isrc) - { - _config = config; - _isrc = isrc; - } - - /** - * Computes, creates and returns the base tile with the appropriate - * fringe imagery applied to it for the specified location. - * - * @param masks used to cache intermediate images of tiles cut out - * using a fringe mask. - */ - public BufferedImage getFringeTile ( - TileSource tiles, int col, int row, Map masks) - { - // get the type of the tile we are considering - String baseType = tiles.getTileType(col, row); - if (baseType == null) { - baseType = tiles.getDefaultType(); - } - - // start with an empty fringer list - FringerRec fringers = null; - - // walk through our influence tiles - for (int y = row - 1, maxy = row + 2; y < maxy; y++) { - for (int x = col - 1, maxx = col + 2; x < maxx; x++) { - // we sensibly do not consider ourselves - if ((x == col) && (y == row)) { - continue; - } - - // determine the type of our fringing neighbor - String fringerType = tiles.getTileType(x, y); - if (fringerType == null) { - fringerType = tiles.getDefaultType(); - } - - // determine if it fringes on our tile - int pri = _config.fringesOn(fringerType, baseType); - if (pri == -1) { - continue; - } - - FringerRec fringer = (fringers == null) ? - null : fringers.find(fringerType); - if (fringer == null) { - fringer = fringers = - new FringerRec(fringerType, pri, fringers); - } - - // now turn on the appropriate fringebits - int dy = y - row, dx = x - col; - fringer.bits |= FLAGMATRIX[dy*3+dx+4]; - } - } - - // if nothing fringed, we're done - if (fringers == null) { - return null; - } - - // otherwise compose a fringe tile from the specified fringes - return composeFringeTile( - baseType, fringers.toArray(), masks, TileUtil.getTileHash(col, row)); - } - - /** - * Compose a fringe tile out of the various fringe images needed. - */ - protected BufferedImage composeFringeTile ( - String baseType, FringerRec[] fringers, Map masks, int hashValue) - { - // sort the array so that higher priority fringers get drawn first - QuickSort.sort(fringers); - - BufferedImage source = _isrc.getTileSource(baseType); - if (source == null) { - log.warning("Missing source tile [type=" + baseType + "]."); - return null; - } - - BufferedImage ftimg = _isrc.createImage( - source.getWidth(), source.getHeight(), Transparency.OPAQUE); - Graphics2D gfx = (Graphics2D)ftimg.getGraphics(); - try { - // start with the base tile image - gfx.drawImage(source, 0, 0, null); - - // and stamp the fringers on top of it - for (int ii = 0; ii < fringers.length; ii++) { - int[] indexes = getFringeIndexes(fringers[ii].bits); - for (int jj = 0; jj < indexes.length; jj++) { - stampTileImage(gfx, fringers[ii].fringerType, - indexes[jj], masks, hashValue); - } - } - - } finally { - gfx.dispose(); - } - return ftimg; - } - - /** - * Looks up or creates the appropriate fringe mask and draws it into - * the supplied graphics context. - */ - protected void stampTileImage ( - Graphics2D gfx, String fringerType, int index, - Map masks, int hashValue) - { - FringeConfiguration.FringeRecord frec = - _config.getFringe(fringerType, hashValue); - BufferedImage fsimg = (frec == null) ? null : - _isrc.getFringeSource(frec.name); - if (fsimg == null) { - log.warning("Missing fringe source image [type=" + fringerType + - ", hash=" + hashValue + ", frec=" + frec + "]."); - return; - } - - if (frec.mask) { - // it's a mask; look for it in the cache - String maskkey = fringerType + ":" + frec.name + ":" + index; - BufferedImage mimg = masks.get(maskkey); - if (mimg == null) { - BufferedImage fsrc = getSubimage(fsimg, index); - BufferedImage bsrc = _isrc.getTileSource(fringerType); - mimg = ImageUtil.composeMaskedImage(_isrc, fsrc, bsrc); - masks.put(maskkey, mimg); - } - gfx.drawImage(mimg, 0, 0, null); - - } else { - // this is a non-mask image so just use the data from the - // fringe source image directly - gfx.drawImage(getSubimage(fsimg, index), 0, 0, null); - } - } - - /** - * Returns the indexth tile image from the supplied - * source image. The source image is assumed to be a single strip of - * tile images, each with equal width and height. - */ - protected BufferedImage getSubimage (BufferedImage source, int index) - { - int size = source.getHeight(), x = size * index; - return source.getSubimage(x, 0, size, size); - } - - /** - * Get the fringe index specified by the fringebits. If no index - * is available, try breaking down the bits into contiguous regions of - * bits and look for indexes for those. - */ - protected int[] getFringeIndexes (int bits) - { - int index = BITS_TO_INDEX[bits]; - if (index != -1) { - int[] ret = new int[1]; - ret[0] = index; - return ret; - } - - // otherwise, split the bits into contiguous components - - // look for a zero and start our first split - int start = 0; - while ((((1 << start) & bits) != 0) && (start < NUM_FRINGEBITS)) { - start++; - } - - if (start == NUM_FRINGEBITS) { - // we never found an empty fringebit, and since index (above) - // was already -1, we have no fringe tile for these bits.. sad. - return new int[0]; - } - - List indexes = Lists.newArrayList(); - int weebits = 0; - for (int ii=(start + 1) % NUM_FRINGEBITS; ii != start; - ii = (ii + 1) % NUM_FRINGEBITS) { - - if (((1 << ii) & bits) != 0) { - weebits |= (1 << ii); - } else if (weebits != 0) { - index = BITS_TO_INDEX[weebits]; - if (index != -1) { - indexes.add(Integer.valueOf(index)); - } - weebits = 0; - } - } - if (weebits != 0) { - index = BITS_TO_INDEX[weebits]; - if (index != -1) { - indexes.add(Integer.valueOf(index)); - } - } - - int[] ret = new int[indexes.size()]; - for (int ii=0; ii < ret.length; ii++) { - ret[ii] = indexes.get(ii).intValue(); - } - return ret; - } - - /** A record for holding information about a particular fringe as - * we're computing what it will look like. */ - protected static class FringerRec implements Comparable - { - public String fringerType; - public int priority; - public int bits; - public FringerRec next; - - public FringerRec (String type, int pri, FringerRec next) { - fringerType = type; - priority = pri; - this.next = next; - } - - public FringerRec find (String type) - { - if (fringerType.equals(type)) { - return this; - } else if (next != null) { - return next.find(type); - } else { - return null; - } - } - - public FringerRec[] toArray () - { - return toArray(0); - } - - public int compareTo (FringerRec o) { - return priority - o.priority; - } - - public String toString () { - return "[type=" + fringerType + ", pri=" + priority + - ", bits=" + Integer.toString(bits, 16) + "]"; - } - - protected FringerRec[] toArray (int index) - { - FringerRec[] array; - if (next == null) { - array = new FringerRec[index+1]; - } else { - array = next.toArray(index+1); - } - array[index] = this; - return array; - } - } - - protected static final int NORTH = 1 << 0; - protected static final int NORTHEAST = 1 << 1; - protected static final int EAST = 1 << 2; - protected static final int SOUTHEAST = 1 << 3; - protected static final int SOUTH = 1 << 4; - protected static final int SOUTHWEST = 1 << 5; - protected static final int WEST = 1 << 6; - protected static final int NORTHWEST = 1 << 7; - - protected static final int NUM_FRINGEBITS = 8; - - /** A matrix mapping adjacent tiles to which fringe bits they affect. - * (x and y are offset by +1, since we can't have -1 as an array index). - * These are "upside down" thanks to OpenGL. */ - protected static final int[] FLAGMATRIX = { - SOUTHWEST, (SOUTHEAST | SOUTH | SOUTHWEST), SOUTHEAST, - (NORTHWEST | WEST | SOUTHWEST), 0, (NORTHEAST | EAST | SOUTHEAST), - NORTHWEST, (NORTHWEST | NORTH | NORTHEAST), NORTHEAST, - }; - - /** The fringe tiles we use. These are the 17 possible tiles made up - * of continuous fringebits sections. */ - protected static final int[] FRINGETILES = { - SOUTHEAST, - SOUTHWEST | SOUTH | SOUTHEAST, - SOUTHWEST, - NORTHEAST | EAST | SOUTHEAST, - NORTHWEST | WEST | SOUTHWEST, - NORTHEAST, - NORTHWEST | NORTH | NORTHEAST, - NORTHWEST, - - SOUTHWEST | WEST | NORTHWEST | NORTH | NORTHEAST, - NORTHWEST | NORTH | NORTHEAST | EAST | SOUTHEAST, - NORTHWEST | WEST | SOUTHWEST | SOUTH | SOUTHEAST, - SOUTHWEST | SOUTH | SOUTHEAST | EAST | NORTHEAST, - - NORTHEAST | NORTH | NORTHWEST | WEST | SOUTHWEST | SOUTH | SOUTHEAST, - SOUTHEAST | EAST | NORTHEAST | NORTH | NORTHWEST | WEST | SOUTHWEST, - SOUTHWEST | SOUTH | SOUTHEAST | EAST | NORTHEAST | NORTH | NORTHWEST, - NORTHWEST | WEST | SOUTHWEST | SOUTH | SOUTHEAST | EAST | NORTHEAST, - - // all the directions! - NORTH | NORTHEAST | EAST | SOUTHEAST | SOUTH | SOUTHWEST | - WEST | NORTHWEST - }; - - /** A reverse map of the {@link #FRINGETILES} array, for quickly - * looking up which tile we want. */ - protected static final int[] BITS_TO_INDEX; - - // Construct the BITS_TO_INDEX array. - static { - int num = (1 << NUM_FRINGEBITS); - BITS_TO_INDEX = new int[num]; - - // first clear everything to -1 (meaning there is no tile defined) - for (int ii=0; ii < num; ii++) { - BITS_TO_INDEX[ii] = -1; - } - - // then fill in with the defined tiles. - for (int ii=0; ii < FRINGETILES.length; ii++) { - BITS_TO_INDEX[FRINGETILES[ii]] = ii; - } - } - - protected ImageSource _isrc; - protected FringeConfiguration _config; -} diff --git a/src/java/com/threerings/jme/tile/tools/CompileFringeConfigurationTask.java b/src/java/com/threerings/jme/tile/tools/CompileFringeConfigurationTask.java deleted file mode 100644 index 6c5a8b2e..00000000 --- a/src/java/com/threerings/jme/tile/tools/CompileFringeConfigurationTask.java +++ /dev/null @@ -1,75 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tile.tools; - -import java.io.File; -import java.io.Serializable; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; - -import com.threerings.util.CompiledConfig; - -import com.threerings.jme.tile.tools.xml.FringeConfigurationParser; - -/** - * Compiles a fringe configuration from XML format into binary format. - */ -public class CompileFringeConfigurationTask extends Task -{ - public void setConfig (File config) - { - _config = config; - } - - public void setTarget (File target) - { - _target = target; - } - - public void execute () throws BuildException - { - // make sure the config file exists - if (!_config.exists()) { - throw new BuildException( - "Fringe configuration file not found [path=" + _config + "]."); - } - - FringeConfigurationParser parser = new FringeConfigurationParser(); - Serializable config; - try { - config = parser.parseConfig(_config); - } catch (Exception e) { - throw new BuildException("Failure parsing fringe config", e); - } - - try { - // and write it on out - CompiledConfig.saveConfig(_target, config); - } catch (Exception e) { - throw new BuildException("Failure writing serialized config", e); - } - } - - protected File _config; - protected File _target; -} diff --git a/src/java/com/threerings/jme/tile/tools/xml/FringeConfigurationParser.java b/src/java/com/threerings/jme/tile/tools/xml/FringeConfigurationParser.java deleted file mode 100644 index 0179105b..00000000 --- a/src/java/com/threerings/jme/tile/tools/xml/FringeConfigurationParser.java +++ /dev/null @@ -1,82 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tile.tools.xml; - -import java.io.Serializable; - -import org.apache.commons.digester.Digester; - -import com.samskivert.xml.SetPropertyFieldsRule; - -import com.threerings.tools.xml.CompiledConfigParser; - -import com.threerings.jme.tile.FringeConfiguration.TileRecord; -import com.threerings.jme.tile.FringeConfiguration.FringeRecord; -import com.threerings.jme.tile.FringeConfiguration; - -/** - * Parses fringe config definitions, which look like so (with angle - * brackets instead of square): - *
- * [fringe]
- *   [tile type="water" priority="100"]
- *      [fringe name="water_fringe_1"/]
- *      [fringe name="water_fringe_2"/]
- *      [fringe name="water_fringe_3"/]
- *   [/tile]
- *   [tile type="dirt" priority="10"]
- *      [fringe name="dirt_fringe_1" mask="true"/]
- *   [/tile]
- *   [tile type="cobble" priority="100"]
- *      [fringe name="cobble_fringe_1" mask="false"/]
- *   [/tile]
- * [/fringe]
- * 
- */ -public class FringeConfigurationParser extends CompiledConfigParser -{ - // documentation inherited - protected Serializable createConfigObject () - { - return new FringeConfiguration(); - } - - // documentation inherited - protected void addRules (Digester digest) - { - // configure top-level constraints - String prefix = "fringe"; - digest.addRule(prefix, new SetPropertyFieldsRule()); - - // create and configure fringe config instances - prefix += "/tile"; - digest.addObjectCreate(prefix, TileRecord.class.getName()); - digest.addRule(prefix, new SetPropertyFieldsRule()); - digest.addSetNext(prefix, "addTileRecord"); - - // create the fringe type records in each tile record - prefix += "/fringe"; - digest.addObjectCreate(prefix, FringeRecord.class.getName()); - digest.addRule(prefix, new SetPropertyFieldsRule()); - digest.addSetNext(prefix, "addFringe"); - } -} diff --git a/src/java/com/threerings/jme/tools/AnimationDef.java b/src/java/com/threerings/jme/tools/AnimationDef.java deleted file mode 100644 index 978c102e..00000000 --- a/src/java/com/threerings/jme/tools/AnimationDef.java +++ /dev/null @@ -1,212 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Properties; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - -import com.jme.math.Matrix4f; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.scene.Controller; -import com.jme.scene.Node; -import com.jme.scene.Spatial; - -import com.samskivert.util.Tuple; - -import com.threerings.jme.model.Model; -import com.threerings.jme.util.JmeUtil; - -import com.threerings.jme.tools.ModelDef.TransformNode; - -/** - * A basic representation for keyframe animations. - */ -public class AnimationDef -{ - /** The rate of the animation in frames per second. */ - public int frameRate; - - /** A single frame of the animation. */ - public static class FrameDef - { - /** Transform for affected nodes. */ - public ArrayList transforms = Lists.newArrayList(); - - public void addTransform (TransformDef transform) - { - transforms.add(transform); - } - - /** Adds all transform targets in this frame to the supplied sets. */ - public void addTransformTargets ( - HashMap nodes, HashMap tnodes, - HashSet staticTargets, HashSet transformTargets) - { - for (int ii = 0, nn = transforms.size(); ii < nn; ii++) { - String name = transforms.get(ii).name; - Spatial target = nodes.get(name); - if (target == null) { - continue; - } - TransformNode tnode = tnodes.get(name); - if (tnode.baseLocalTransform != null) { - staticTargets.add(target); - } else { - transformTargets.add(target); - } - } - } - - /** Returns the array of transforms for this frame. */ - public Model.Transform[] getTransforms (Spatial[] targets) - { - Model.Transform[] mtransforms = - new Model.Transform[targets.length]; - for (int ii = 0; ii < targets.length; ii++) { - mtransforms[ii] = getTransform(targets[ii]); - } - return mtransforms; - } - - /** Returns the transform for the supplied target. */ - protected Model.Transform getTransform (Spatial target) - { - String name = target.getName(); - for (int ii = 0, nn = transforms.size(); ii < nn; ii++) { - TransformDef transform = transforms.get(ii); - if (name.equals(transform.name)) { - return transform.getTransform(); - } - } - return null; - } - } - - /** A transform for a single node. */ - public static class TransformDef - { - /** The name of the affected node. */ - public String name; - - /** The transformation parameters. */ - public float[] translation; - public float[] rotation; - public float[] scale; - - /** Returns the live transform object. */ - public Model.Transform getTransform () - { - return new Model.Transform( - new Vector3f(translation[0], translation[1], translation[2]), - new Quaternion(rotation[0], rotation[1], rotation[2], rotation[3]), - new Vector3f(scale[0], scale[1], scale[2])); - } - } - - /** The individual frames of the animation. */ - public ArrayList frames = Lists.newArrayList(); - - public void addFrame (FrameDef frame) - { - frames.add(frame); - } - - /** - * Runs through each frame of the animation, updating the transforms of the preprocessing - * node to keep track of which transforms diverge from their original states. - */ - public void filterTransforms (Node root, HashMap nodes) - { - // clear the nodes' transformed flags - for (TransformNode node : nodes.values()) { - node.transformed = false; - } - - // run through all animation frames - for (FrameDef frame : frames) { - for (TransformDef transform : frame.transforms) { - TransformNode node = nodes.get(transform.name); - if (node != null) { - node.setLocalTransform( - transform.translation, transform.rotation, transform.scale); - node.transformed = true; - } - } - root.updateGeometricState(0f, true); - for (TransformNode node : nodes.values()) { - node.cullDivergentTransforms(); - } - } - - // remove from merge candidates any pairs where one is visible and the other isn't - for (TransformNode node : nodes.values()) { - for (Iterator> it = node.relativeTransforms.iterator(); - it.hasNext(); ) { - if (it.next().left.transformed != node.transformed) { - it.remove(); - } - } - } - } - - /** - * Creates the "live" animation object that will be serialized with the - * object. - * - * @param props the animation properties - * @param nodes the nodes in the model, mapped by name - */ - public Model.Animation createAnimation ( - Properties props, HashMap nodes, HashMap tnodes) - { - // find all affected nodes - HashSet staticTargets = Sets.newHashSet(), - transformTargets = Sets.newHashSet(); - for (int ii = 0, nn = frames.size(); ii < nn; ii++) { - frames.get(ii).addTransformTargets(nodes, tnodes, staticTargets, transformTargets); - } - - // create and configure the animation - Model.Animation anim = new Model.Animation(); - anim.frameRate = frameRate; - anim.repeatType = JmeUtil.parseRepeatType(props.getProperty("repeat_type"), - Controller.RT_CLAMP); - - // collect all transforms - anim.staticTargets = staticTargets.toArray(new Spatial[staticTargets.size()]); - anim.transformTargets = transformTargets.toArray(new Spatial[transformTargets.size()]); - anim.transforms = new Model.Transform[frames.size()][transformTargets.size()]; - for (int ii = 0; ii < anim.transforms.length; ii++) { - anim.transforms[ii] = - frames.get(ii).getTransforms(anim.transformTargets); - } - - return anim; - } -} diff --git a/src/java/com/threerings/jme/tools/BuildSphereMap.java b/src/java/com/threerings/jme/tools/BuildSphereMap.java deleted file mode 100644 index ba2660ad..00000000 --- a/src/java/com/threerings/jme/tools/BuildSphereMap.java +++ /dev/null @@ -1,164 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.awt.image.BufferedImage; - -import java.io.File; -import java.io.IOException; - -import javax.imageio.ImageIO; - -import com.jme.math.FastMath; -import com.jme.math.Vector3f; - -/** - * A tool for converting cube maps (sky boxes) to sphere maps. - */ -public class BuildSphereMap -{ - public static void main (String[] args) - { - if (args.length < 7) { - System.err.println("Usage: BuildSphereMap front.ext back.ext " + - "left.ext right.ext up.ext dest.ext size"); - System.exit(-1); - } - - try { - execute(new File(args[0]), new File(args[1]), new File(args[2]), - new File(args[3]), new File(args[4]), new File(args[5]), - Integer.parseInt(args[6])); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * Builds the sphere map. - * - * @param front the file containing the front side of the cube map - * @param back the file containing the back side of the cube map - * @param left the file containing the left side of the cube map - * @param right the file containing the right side of the cube map - * @param up the file containing the up side of the cube map - * @param target the file to contain the sphere map - * @param size the size of the sphere map to generate - */ - public static void execute (File front, File back, File left, File right, - File up, File target, int size) - throws IOException - { - // load up the sides of the cube map - BufferedImage[] sides = new BufferedImage[5]; - sides[FRONT] = ImageIO.read(front); - sides[BACK] = ImageIO.read(back); - sides[LEFT] = ImageIO.read(left); - sides[RIGHT] = ImageIO.read(right); - sides[UP] = ImageIO.read(up); - - // compute the pixels - int[] rgb = new int[size * size]; - Vector3f vec = new Vector3f(); - for (int y = 0, idx = 0; y < size; y++) { - for (int x = 0; x < size; x++, idx++) { - float vx = x / (size*0.5f) - 1f, vy = y / (size*0.5f) - 1f, d2 = vx*vx + vy*vy; - if (d2 <= 1f) { - vec.set(vx, vy, FastMath.sqrt(1f - d2)); - rgb[idx] = getCubeMapPixel(vec, sides); - } - } - } - - // create and write the image - BufferedImage image = new BufferedImage(size, size, - BufferedImage.TYPE_INT_RGB); - image.setRGB(0, 0, size, size, rgb, 0, size); - String dest = target.toString(), - ext = dest.substring(dest.lastIndexOf('.')+1); - ImageIO.write(image, ext, target); - } - - /** - * Returns the pixel from the cube map to which the given vector points. - */ - protected static int getCubeMapPixel (Vector3f vec, BufferedImage[] sides) - { - int side = getCubeMapSide(vec); - - float s, t; - switch (side) { - case FRONT: - s = -vec.x / vec.y; - t = vec.z / vec.y; - break; - case BACK: - s = -vec.x / vec.y; - t = -vec.z / vec.y; - break; - case LEFT: - s = vec.y / vec.x; - t = -vec.z / vec.x; - break; - case RIGHT: - s = vec.y / vec.x; - t = vec.z / vec.x; - break; - default: - case UP: - s = vec.x / vec.z; - t = -vec.y / vec.z; - break; - } - int width = sides[side].getWidth(), height = sides[side].getHeight(); - return sides[side].getRGB((int)((width-1) * (s+1f)/2f), - (int)((height-1) * (1f-t)/2f)); - } - - /** - * Returns the side index identifying the face of the cube map to which - * the given vector points. - */ - protected static int getCubeMapSide (Vector3f vec) - { - if (vec.x > vec.z && vec.x > vec.y && vec.x > -vec.y) { - return RIGHT; - - } else if (vec.x < -vec.z && vec.x < -vec.y && vec.x < vec.y) { - return LEFT; - - } else if (vec.y > vec.z) { - return FRONT; - - } else if (vec.y < -vec.z) { - return BACK; - - } else { - return UP; - } - } - - /** The sides of the cube map. */ - protected static final int FRONT = 0, BACK = 1, LEFT = 2, RIGHT = 3, - UP = 4; -} diff --git a/src/java/com/threerings/jme/tools/BuildSphereMapTask.java b/src/java/com/threerings/jme/tools/BuildSphereMapTask.java deleted file mode 100644 index 70c3d651..00000000 --- a/src/java/com/threerings/jme/tools/BuildSphereMapTask.java +++ /dev/null @@ -1,86 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.io.File; -import java.io.IOException; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.Task; - -/** - * An ant task for converting cube maps (sky boxes) to sphere maps. - */ -public class BuildSphereMapTask extends Task -{ - public void setFront (File front) - { - _front = front; - } - - public void setBack (File back) - { - _back = back; - } - - public void setLeft (File left) - { - _left = left; - } - - public void setRight (File right) - { - _right = right; - } - - public void setUp (File up) - { - _up = up; - } - - public void setTarget (File target) - { - _target = target; - } - - public void setSize (int size) - { - _size = size; - } - - public void execute () throws BuildException - { - try { - BuildSphereMap.execute(_front, _back, _left, _right, _up, _target, - _size); - - } catch (IOException e) { - throw new BuildException("Failure building sphere map", e); - } - } - - /** The files representing the sides of the cube map and the target. */ - protected File _front, _back, _left, _right, _up, _target; - - /** The size of the target image. */ - protected int _size; -} diff --git a/src/java/com/threerings/jme/tools/CompileModel.java b/src/java/com/threerings/jme/tools/CompileModel.java deleted file mode 100644 index 623aa370..00000000 --- a/src/java/com/threerings/jme/tools/CompileModel.java +++ /dev/null @@ -1,167 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.io.File; -import java.io.FileInputStream; - -import java.util.HashMap; -import java.util.Properties; -import java.util.logging.Level; - -import com.google.common.collect.Maps; - -import com.jme.scene.Node; -import com.jme.scene.Spatial; -import com.jme.util.LoggingSystem; -import com.jmex.model.XMLparser.Converters.DummyDisplaySystem; - -import com.samskivert.util.PropertiesUtil; -import com.samskivert.util.StringUtil; - -import com.threerings.jme.model.Model; -import com.threerings.jme.tools.ModelDef.TransformNode; -import com.threerings.jme.tools.xml.AnimationParser; -import com.threerings.jme.tools.xml.ModelParser; - -/** - * An application for compiling 3D models defined in XML to fast-loading binary files. - */ -public class CompileModel -{ - /** - * Loads the model described by the given properties file and compiles it to a - * .dat file in the same directory. - * - * @return the loaded model, or null if the compiled version is up-to-date - */ - public static Model compile (File source) - throws Exception - { - return compile(source, source.getParentFile()); - } - - /** - * Loads the model described by the given properties file and compiles it into a - * .dat file in the specified directory. - * - * @return the loaded model, or null if the compiled version is up-to-date - */ - public static Model compile (File source, File targetDir) - throws Exception - { - String sname = source.getName(); - int didx = sname.lastIndexOf('.'); - String root = (didx == -1) ? sname : sname.substring(0, didx); - File target = new File(targetDir, root + ".dat"); - File content = new File(source.getParentFile(), root + ".mxml"); - - boolean needsUpdate = false; - if (source.lastModified() >= target.lastModified() || - content.lastModified() >= target.lastModified()) { - needsUpdate = true; - } - - // load the model properties - Properties props = new Properties(); - FileInputStream in = new FileInputStream(source); - props.load(in); - in.close(); - - // locate the animations, if any - String[] anims = StringUtil.parseStringArray(props.getProperty("animations", "")); - File[] afiles = new File[anims.length]; - File dir = source.getParentFile(); - for (int ii = 0; ii < anims.length; ii++) { - afiles[ii] = new File(dir, anims[ii] + ".mxml"); - if (afiles[ii].lastModified() >= target.lastModified()) { - needsUpdate = true; - } - } - if (!needsUpdate) { - return null; - } - - System.out.println("Compiling to " + target + "..."); - - // parse the model and animations - ModelDef mdef = _mparser.parseModel(content.toString()); - AnimationDef[] adefs = new AnimationDef[anims.length]; - for (int ii = 0; ii < adefs.length; ii++) { - System.out.println(" Adding " + afiles[ii] + "..."); - adefs[ii] = _aparser.parseAnimation(afiles[ii].toString()); - } - - // preprocess the model and animations to determine which nodes never move, which never - // move within an animation, and which never move with respect to others - HashMap tnodes = Maps.newHashMap(); - Node troot = mdef.createTransformTree(props, tnodes); - for (AnimationDef adef : adefs) { - adef.filterTransforms(troot, tnodes); - } - mdef.mergeSpatials(tnodes); - - // load the model content - HashMap nodes = Maps.newHashMap(); - Model model = mdef.createModel(props, nodes); - model.initPrototype(); - - // load the animations, if any - for (int ii = 0; ii < anims.length; ii++) { - model.addAnimation(anims[ii], adefs[ii].createAnimation( - PropertiesUtil.getSubProperties(props, anims[ii]), nodes, tnodes)); - } - - // write and return the model - File parent = target.getParentFile(); - if (!parent.isDirectory() && !parent.mkdirs()) { - System.err.println("Unable to create target directory '" + parent + "'."); - } else { - model.writeToFile(target); - } - return model; - } - - public static void main (String[] args) - { - if (args.length < 1) { - System.err.println("Usage: CompileModel source.properties"); - System.exit(-1); - } - - // create a dummy display system - new DummyDisplaySystem(); - LoggingSystem.getLogger().setLevel(Level.WARNING); - - try { - compile(new File(args[0])); - } catch (Exception e) { - System.err.println("Error compiling model: " + e); - } - } - - /** A parser for the model definitions. */ - protected static ModelParser _mparser = new ModelParser(); - - /** A parser for the animation definitions. */ - protected static AnimationParser _aparser = new AnimationParser(); -} diff --git a/src/java/com/threerings/jme/tools/CompileModelTask.java b/src/java/com/threerings/jme/tools/CompileModelTask.java deleted file mode 100644 index 34010989..00000000 --- a/src/java/com/threerings/jme/tools/CompileModelTask.java +++ /dev/null @@ -1,87 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.io.File; - -import java.util.ArrayList; -import java.util.logging.Level; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.DirectoryScanner; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.types.FileSet; - -import com.google.common.collect.Lists; - -import com.jme.util.LoggingSystem; -import com.jmex.model.XMLparser.Converters.DummyDisplaySystem; - -/** - * An ant task for compiling 3D models defined in XML to fast-loading binary files. - */ -public class CompileModelTask extends Task -{ - public void setDest (File dest) - { - _dest = dest; - } - - public void addFileset (FileSet set) - { - _filesets.add(set); - } - - public void init () throws BuildException - { - // create a dummy display system - new DummyDisplaySystem(); - LoggingSystem.getLogger().setLevel(Level.WARNING); - } - - public void execute () - throws BuildException - { - String baseDir = getProject().getBaseDir().getPath(); - for (FileSet fs : _filesets) { - DirectoryScanner ds = fs.getDirectoryScanner(getProject()); - File fromDir = fs.getDir(getProject()); - for (String file : ds.getIncludedFiles()) { - File source = new File(fromDir, file); - File destDir = (_dest == null) ? source.getParentFile() : - new File(source.getParent().replaceAll(baseDir, _dest.getPath())); - try { - CompileModel.compile(source, destDir); - } catch (Exception e) { - System.err.println("Error compiling " + source + ": " + e); - } - } - } - } - - /** The directory in which we will generate our model output (in a directory tree mirroring the - * source files. */ - protected File _dest; - - /** A list of filesets that contain XML models. */ - protected ArrayList _filesets = Lists.newArrayList(); -} diff --git a/src/java/com/threerings/jme/tools/ConvertModel.java b/src/java/com/threerings/jme/tools/ConvertModel.java deleted file mode 100644 index 17da81d2..00000000 --- a/src/java/com/threerings/jme/tools/ConvertModel.java +++ /dev/null @@ -1,100 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; - -import com.jmex.model.XMLparser.Converters.AseToJme; -import com.jmex.model.XMLparser.Converters.DummyDisplaySystem; -import com.jmex.model.XMLparser.Converters.FormatConverter; -import com.jmex.model.XMLparser.Converters.MaxToJme; -import com.jmex.model.XMLparser.Converters.Md2ToJme; -import com.jmex.model.XMLparser.Converters.Md3ToJme; -import com.jmex.model.XMLparser.Converters.ObjToJme; - -/** - * A tool for converting various 3D model formats into JME's internal - * format. - */ -public class ConvertModel -{ - public static void main (String[] args) - { - if (args.length < 2) { - System.err.println("Usage: ConvertModel source.ext dest.jme"); - System.exit(-1); - } - - // create a dummy display system which the converters need - new DummyDisplaySystem(); - - File source = new File(args[0]); - File target = new File(args[1]); - - String path = source.getPath().toLowerCase(); - String type = path.substring(path.lastIndexOf(".") + 1); - - // set up our converter - FormatConverter convert = null; - if (type.equals("obj")) { - convert = new ObjToJme(); - try { - convert.setProperty("mtllib", new URL("file:" + source)); - } catch (Exception e) { - System.err.println("Failed to create material URL: " + e); - System.exit(-1); - } - } else if (type.equals("3ds")) { - convert = new MaxToJme(); - } else if (type.equals("md2")) { - convert = new Md2ToJme(); - } else if (type.equals("md3")) { - convert = new Md3ToJme(); - } else if (type.equals("ase")) { - convert = new AseToJme(); - } else { - System.err.println("Unknown model type '" + type + "'."); - System.exit(-1); - } - - // and do the deed - try { - BufferedOutputStream bout = new BufferedOutputStream( - new FileOutputStream(target)); - BufferedInputStream bin = new BufferedInputStream( - new FileInputStream(source)); - convert.convert(bin, bout); - bout.close(); - } catch (IOException ioe) { - System.err.println("Error converting '" + source + - "' to '" + target + "'."); - ioe.printStackTrace(System.err); - System.exit(-1); - } - } -} diff --git a/src/java/com/threerings/jme/tools/ConvertModelTask.java b/src/java/com/threerings/jme/tools/ConvertModelTask.java deleted file mode 100644 index 921b9711..00000000 --- a/src/java/com/threerings/jme/tools/ConvertModelTask.java +++ /dev/null @@ -1,136 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.net.URL; -import java.util.ArrayList; -import java.util.logging.Level; - -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.DirectoryScanner; -import org.apache.tools.ant.Task; -import org.apache.tools.ant.types.FileSet; - -import com.google.common.collect.Lists; - -import com.jme.util.LoggingSystem; -import com.jmex.model.XMLparser.Converters.AseToJme; -import com.jmex.model.XMLparser.Converters.DummyDisplaySystem; -import com.jmex.model.XMLparser.Converters.FormatConverter; -import com.jmex.model.XMLparser.Converters.MaxToJme; -import com.jmex.model.XMLparser.Converters.Md2ToJme; -import com.jmex.model.XMLparser.Converters.Md3ToJme; -import com.jmex.model.XMLparser.Converters.ObjToJme; - -/** - * An ant task for converting various 3D model formats into JME's internal - * format. - */ -public class ConvertModelTask extends Task -{ - public void addFileset (FileSet set) - { - _filesets.add(set); - } - - public void init () throws BuildException - { - // create a dummy display system which the converters need - new DummyDisplaySystem(); - LoggingSystem.getLogger().setLevel(Level.WARNING); - } - - public void execute () throws BuildException - { - for (FileSet fs : _filesets) { - DirectoryScanner ds = fs.getDirectoryScanner(getProject()); - File fromDir = fs.getDir(getProject()); - String[] srcFiles = ds.getIncludedFiles(); - - for (int f = 0; f < srcFiles.length; f++) { - File cfile = new File(fromDir, srcFiles[f]); - String target = srcFiles[f]; - int didx = target.lastIndexOf("."); - target = (didx == -1) ? target : target.substring(0, didx); - target += ".jme"; - convertModel(cfile, new File(fromDir, target)); - } - } - } - - protected void convertModel (File source, File target) - { - if (source.lastModified() < target.lastModified()) { - return; - } - - System.out.println("Converting " + source + "..."); - String path = source.getPath().toLowerCase(); - String type = path.substring(path.lastIndexOf(".") + 1); - - // set up our converter - FormatConverter convert = null; - if (type.equals("obj")) { - convert = new ObjToJme(); - try { - convert.setProperty("mtllib", new URL("file:" + source)); - } catch (Exception e) { - System.err.println("Failed to create material URL: " + e); - return; - } - } else if (type.equals("3ds")) { - convert = new MaxToJme(); - } else if (type.equals("md2")) { - convert = new Md2ToJme(); - } else if (type.equals("md3")) { - convert = new Md3ToJme(); - } else if (type.equals("ase")) { - convert = new AseToJme(); - } else { - System.err.println("Unknown model type '" + type + "'."); - return; - } - - // and do the deed - try { - BufferedOutputStream bout = new BufferedOutputStream( - new FileOutputStream(target)); - BufferedInputStream bin = new BufferedInputStream( - new FileInputStream(source)); - convert.convert(bin, bout); - bout.close(); - } catch (IOException ioe) { - System.err.println("Error converting '" + source + - "' to '" + target + "'."); - ioe.printStackTrace(System.err); - } - } - - /** A list of filesets that contain tileset bundle definitions. */ - protected ArrayList _filesets = Lists.newArrayList(); -} diff --git a/src/java/com/threerings/jme/tools/ModelDef.java b/src/java/com/threerings/jme/tools/ModelDef.java deleted file mode 100644 index 42ca4465..00000000 --- a/src/java/com/threerings/jme/tools/ModelDef.java +++ /dev/null @@ -1,1031 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.nio.FloatBuffer; -import java.nio.IntBuffer; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import com.google.common.base.Objects; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import com.jme.bounding.BoundingBox; -import com.jme.bounding.BoundingSphere; -import com.jme.math.FastMath; -import com.jme.math.Matrix4f; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.scene.Node; -import com.jme.scene.Spatial; -import com.jme.util.geom.BufferUtils; - -import com.samskivert.util.PropertiesUtil; -import com.samskivert.util.StringUtil; -import com.samskivert.util.Tuple; - -import com.threerings.jme.model.Model; -import com.threerings.jme.model.ModelController; -import com.threerings.jme.model.ModelMesh; -import com.threerings.jme.model.ModelNode; -import com.threerings.jme.model.SkinMesh; -import com.threerings.jme.util.JmeUtil; - -import static com.threerings.jme.Log.log; - -/** - * An intermediate representation for models used to store data parsed from - * XML and convert it into JME nodes. - */ -public class ModelDef -{ - /** The base class of nodes in the model. */ - public abstract static class SpatialDef - { - /** The node's name. */ - public String name; - - /** The name of the node's parent. */ - public String parent; - - /** The node's transformation. */ - public float[] translation; - public float[] rotation; - public float[] scale; - - /** - * Stores the names of all bones referenced by this spatial in the supplied set. - */ - public void getBoneNames (HashSet bones) - { - // nothing by default - } - - /** Checks whether it's possible (disregarding issues of transformation) to merge - * the specified spatial into this one. */ - public abstract boolean canMerge (Properties props, SpatialDef other); - - /** Merges another spatial into this one. */ - public abstract void merge (SpatialDef other, Matrix4f xform); - - /** Returns a JME node for this definition. */ - public Spatial getSpatial (Properties props) - { - if (_spatial == null) { - _spatial = createSpatial( - PropertiesUtil.getFilteredProperties(props, name)); - setTransform(); - } - return _spatial; - } - - /** Sets the transform of the created node. */ - protected void setTransform () - { - _spatial.getLocalTranslation().set(translation[0], translation[1], - translation[2]); - _spatial.getLocalRotation().set(rotation[0], rotation[1], - rotation[2], rotation[3]); - _spatial.getLocalScale().set(scale[0], scale[1], scale[2]); - } - - /** Creates a JME node for this definition. */ - public abstract Spatial createSpatial (Properties props); - - /** Resolves any name references using the supplied map. */ - public void resolveReferences ( - HashMap nodes, HashSet referenced) - { - Spatial pnode = nodes.get(parent); - if (pnode instanceof ModelNode) { - ((ModelNode)pnode).attachChild(_spatial); - - } else if (parent != null) { - log.warning("Missing or invalid parent node [spatial=" + - name + ", parent=" + parent + "]."); - } - } - - /** The JME node created for this definition. */ - protected Spatial _spatial; - } - - /** A rigid triangle mesh. */ - public static class TriMeshDef extends SpatialDef - { - /** The geometry offset transform. */ - public float[] offsetTranslation; - public float[] offsetRotation; - public float[] offsetScale; - - /** Whether or not the mesh allows back face culling. */ - public boolean solid; - - /** The texture of the mesh, if any. */ - public String texture; - - /** Whether or not the mesh is (partially) transparent. */ - public boolean transparent; - - /** The vertices of the mesh. */ - public HashArrayList vertices = new HashArrayList(); - - /** The triangle indices. */ - public ArrayList indices = Lists.newArrayList(); - - /** Whether or not any of the vertices have texture coordinates. */ - public boolean tcoords; - - public void addVertex (Vertex vertex) - { - int idx = vertices.indexOf(vertex); - if (idx != -1) { - indices.add(idx); - } else { - indices.add(vertices.size()); - vertices.add(vertex); - } - tcoords = tcoords || vertex.tcoords != null; - } - - // documentation inherited - public boolean canMerge (Properties props, SpatialDef other) - { - if (getClass() != other.getClass()) { - return false; // require exact class match - } - TriMeshDef omesh = (TriMeshDef)other; - return solid == omesh.solid && transparent == omesh.transparent && - Objects.equal(texture, omesh.texture) && - PropertiesUtil.getSubProperties(props, name).equals( - PropertiesUtil.getSubProperties(props, omesh.name)); - } - - // documentation inherited - public void merge (SpatialDef other, Matrix4f xform) - { - TriMeshDef omesh = (TriMeshDef)other; - - // prepend the inverse of the offset transformation - xform = getOffsetTransform().invertLocal().multLocal(xform); - - // and append the other's offset - xform.multLocal(omesh.getOffsetTransform()); - - // extract the rotation to transform normals - Quaternion xrot = xform.toRotationQuat(); - - // transform the vertices and add them in - for (Vertex vertex : omesh.vertices) { - vertex.transform(xform, xrot); - } - for (int idx : omesh.indices) { - addVertex(omesh.vertices.get(idx)); - } - } - - // documentation inherited - public Spatial createSpatial (Properties props) - { - ModelNode node = new ModelNode(name); - if (indices.size() > 0) { - _mesh = createMesh(); - optimizeVertexOrder(); - configureMesh(props); - node.attachChild(_mesh); - } - return node; - } - - /** Gets the matrix representing the offset transform. */ - protected Matrix4f getOffsetTransform () - { - Vector3f otrans = new Vector3f(), oscale = new Vector3f(1f, 1f, 1f); - Quaternion orot = new Quaternion(); - if (offsetTranslation != null) { - otrans.set(offsetTranslation[0], offsetTranslation[1], offsetTranslation[2]); - } - if (offsetRotation != null) { - orot.set(offsetRotation[0], offsetRotation[1], offsetRotation[2], - offsetRotation[3]); - } - if (offsetScale != null) { - oscale.set(offsetScale[0], offsetScale[1], offsetScale[2]); - } - return JmeUtil.setTransform(otrans, orot, oscale, new Matrix4f()); - } - - /** Creates the mesh to attach to the node. */ - protected ModelMesh createMesh () - { - return new ModelMesh("mesh"); - } - - /** Reorders the vertices to optimize for vertex cache utilization. Uses the algorithm - * described in Tom Forsyth's article - * - * Linear-Speed Vertex Cache Optimization. - */ - protected void optimizeVertexOrder () - { - // start by compiling a list of triangles cross-linked with the vertices they use - // (we use a linked hash set to ensure consistent iteration order for serialization) - LinkedHashSet triangles = new LinkedHashSet(); - for (int ii = 0, nn = indices.size(); ii < nn; ii += 3) { - Vertex[] tverts = new Vertex[] { - vertices.get(indices.get(ii)), - vertices.get(indices.get(ii + 1)), - vertices.get(indices.get(ii + 2)) - }; - Triangle triangle = new Triangle(tverts); - for (Vertex tvert : tverts) { - if (tvert.triangles == null) { - tvert.triangles = Lists.newArrayList(); - } - tvert.triangles.add(triangle); - } - triangles.add(triangle); - } - - // init the scores - for (Vertex vertex : vertices) { - vertex.updateScore(Integer.MAX_VALUE); - } - - // clear the vertices and indices to prepare for readdition - vertices.clear(); - indices.clear(); - - // while there are triangles remaining, keep adding the one with the best score - // (as determined by its LRU cache position and number of remaining triangles) - HashArrayList vcache = new HashArrayList(); - while (!triangles.isEmpty()) { - // first look for triangles in the cache - Triangle bestTriangle = null; - float bestScore = -1f; - for (Vertex vertex : vcache) { - for (Triangle triangle : vertex.triangles) { - float score = triangle.getScore(); - if (score > bestScore) { - bestTriangle = triangle; - bestScore = score; - } - } - } - - // if that didn't work, scan the full list - if (bestTriangle == null) { - for (Triangle triangle : triangles) { - float score = triangle.getScore(); - if (score > bestScore) { - bestTriangle = triangle; - bestScore = score; - } - } - } - - // add and update the vertices from the best triangle - triangles.remove(bestTriangle); - for (Vertex vertex : bestTriangle.vertices) { - addVertex(vertex); - vertex.triangles.remove(bestTriangle); - vcache.remove(vertex); - vcache.add(0, vertex); - } - - // update the scores of the vertices in the cache - for (int ii = 0, nn = vcache.size(); ii < nn; ii++) { - vcache.get(ii).updateScore(ii); - } - - // trim the excess (if any) from the end of the cache - while (vcache.size() > 64) { - vcache.remove(vcache.size() - 1); - } - } - } - - /** Configures the mesh. */ - protected void configureMesh (Properties props) - { - // set the geometry offset - if (offsetTranslation != null) { - _mesh.getLocalTranslation().set(offsetTranslation[0], - offsetTranslation[1], offsetTranslation[2]); - } - if (offsetRotation != null) { - _mesh.getLocalRotation().set(offsetRotation[0], - offsetRotation[1], offsetRotation[2], offsetRotation[3]); - } - if (offsetScale != null) { - _mesh.getLocalScale().set(offsetScale[0], offsetScale[1], - offsetScale[2]); - } - - // make sure texture is just a filename - int sidx = (texture == null) ? -1 : - Math.max(texture.lastIndexOf('/'), texture.lastIndexOf('\\')); - if (sidx != -1) { - texture = texture.substring(sidx + 1); - } - - // configure using properties - _mesh.configure(solid, texture, transparent, props); - - // set the various buffers - int vsize = vertices.size(); - FloatBuffer vbuf = BufferUtils.createVector3Buffer(vsize), - nbuf = BufferUtils.createVector3Buffer(vsize), - tbuf = tcoords ? BufferUtils.createVector2Buffer(vsize) : null; - for (int ii = 0; ii < vsize; ii++) { - vertices.get(ii).setInBuffers(vbuf, nbuf, tbuf); - } - IntBuffer ibuf = BufferUtils.createIntBuffer(indices.size()); - for (int ii = 0, nn = indices.size(); ii < nn; ii++) { - ibuf.put(indices.get(ii)); - } - _mesh.reconstruct(vbuf, nbuf, null, tbuf, ibuf); - - _mesh.setModelBound("sphere".equals(props.getProperty("bound")) ? - new BoundingSphere() : new BoundingBox()); - _mesh.updateModelBound(); - - // set the mesh's origin to the center of its bounding box - _mesh.centerVertices(); - } - - /** The mesh that contains the actual geometry. */ - protected ModelMesh _mesh; - } - - /** A triangle mesh that deforms according to bone positions. */ - public static class SkinMeshDef extends TriMeshDef - { - @Override - public void getBoneNames (HashSet bones) - { - for (Vertex vertex : vertices) { - bones.addAll(((SkinVertex)vertex).boneWeights.keySet()); - } - } - - @Override - protected ModelMesh createMesh () - { - return new SkinMesh("mesh"); - } - - @Override - public void resolveReferences ( - HashMap nodes, HashSet referenced) - { - super.resolveReferences(nodes, referenced); - if (_mesh == null) { - return; - } - - // create and set the final weight groups - SkinMesh.WeightGroup[] wgroups = new SkinMesh.WeightGroup[_groups.size()]; - HashMap bones = Maps.newHashMap(); - int ii = 0; - int mweights = 0, tweights = 0; - for (Map.Entry, WeightGroupDef> entry : - _groups.entrySet()) { - SkinMesh.WeightGroup wgroup = new SkinMesh.WeightGroup(); - wgroup.vertexCount = entry.getValue().indices.size(); - wgroup.bones = new SkinMesh.Bone[entry.getKey().size()]; - int jj = 0; - for (String bname : entry.getKey()) { - SkinMesh.Bone bone = bones.get(bname); - if (bone == null) { - Spatial node = nodes.get(bname); - bones.put(bname, - bone = new SkinMesh.Bone((ModelNode)node)); - referenced.add(node); - } - wgroup.bones[jj++] = bone; - } - wgroup.weights = toArray(entry.getValue().weights); - tweights += wgroup.bones.length; - mweights = Math.max(wgroup.bones.length, mweights); - wgroups[ii++] = wgroup; - } - ((SkinMesh)_mesh).setWeightGroups(wgroups); - } - - @Override - protected void configureMesh (Properties props) - { - // divide the vertices up by weight groups - _groups = Maps.newHashMap(); - for (int ii = 0, nn = vertices.size(); ii < nn; ii++) { - SkinVertex svertex = (SkinVertex)vertices.get(ii); - Set bones = svertex.boneWeights.keySet(); - WeightGroupDef group = _groups.get(bones); - if (group == null) { - _groups.put(bones, group = new WeightGroupDef()); - } - group.indices.add(ii); - for (String bone : bones) { - group.weights.add(svertex.boneWeights.get(bone).weight); - } - } - - // reorder the vertices by group - ArrayList overts = vertices; - vertices = new HashArrayList(); - int[] imap = new int[overts.size()]; - for (Map.Entry, WeightGroupDef> entry : - _groups.entrySet()) { - for (int idx : entry.getValue().indices) { - imap[idx] = vertices.size(); - vertices.add(overts.get(idx)); - } - } - for (int ii = 0, nn = indices.size(); ii < nn; ii++) { - indices.set(ii, imap[indices.get(ii)]); - } - - super.configureMesh(props); - } - - /** The intermediate weight groups, mapped by bone names. */ - protected HashMap, WeightGroupDef> _groups; - } - - /** A generic node. */ - public static class NodeDef extends SpatialDef - { - // documentation inherited - public boolean canMerge (Properties props, SpatialDef other) - { - return false; - } - - // documentation inherited - public void merge (SpatialDef other, Matrix4f xform) - { - throw new UnsupportedOperationException(); - } - - // documentation inherited - public Spatial createSpatial (Properties props) - { - return new ModelNode(name); - } - } - - /** Represents a triangle for processing purposes. */ - public static class Triangle - { - public Vertex[] vertices; - - public Triangle (Vertex[] vertices) - { - this.vertices = vertices; - } - - public float getScore () - { - return vertices[0].score + vertices[1].score + vertices[2].score; - } - } - - /** A basic vertex. */ - public static class Vertex - { - public float[] location; - public float[] normal; - public float[] tcoords; - - public ArrayList triangles; - public float score; - - public void updateScore (int cacheIdx) - { - float pscore; - if (cacheIdx > 63) { - pscore = 0f; // outside the cache - } else if (cacheIdx < 3) { - pscore = 0.75f; // the three most recent vertices - } else { - pscore = FastMath.pow((63 - cacheIdx) / 60f, 1.5f); - } - score = pscore + 2f * FastMath.pow(triangles.size(), -0.5f); - } - - public void transform (Matrix4f xform, Quaternion xrot) - { - Vector3f xvec = new Vector3f(location[0], location[1], location[2]); - xform.mult(xvec, xvec); - location[0] = xvec.x; - location[1] = xvec.y; - location[2] = xvec.z; - - xvec.set(normal[0], normal[1], normal[2]); - xrot.mult(xvec, xvec); - normal[0] = xvec.x; - normal[1] = xvec.y; - normal[2] = xvec.z; - } - - public void setInBuffers ( - FloatBuffer vbuf, FloatBuffer nbuf, FloatBuffer tbuf) - { - vbuf.put(location); - nbuf.put(normal); - - if (tbuf != null) { - if (tcoords != null) { - tbuf.put(tcoords); - } else { - tbuf.put(0f); - tbuf.put(0f); - } - } - } - - public String toString () - { - return StringUtil.toString(location); - } - - @Override - public int hashCode () - { - return Arrays.hashCode(location) ^ Arrays.hashCode(normal) ^ Arrays.hashCode(tcoords); - } - - @Override - public boolean equals (Object obj) - { - Vertex overt = (Vertex)obj; - return Arrays.equals(location, overt.location) && - Arrays.equals(normal, overt.normal) && - Arrays.equals(tcoords, overt.tcoords); - } - } - - /** A vertex influenced by a number of bones. */ - public static class SkinVertex extends Vertex - { - /** The bones influencing the vertex, mapped by name. */ - public HashMap boneWeights = Maps.newHashMap(); - - public void addBoneWeight (BoneWeight weight) - { - if (weight.weight == 0f) { - return; - } - BoneWeight bweight = boneWeights.get(weight.bone); - if (bweight != null) { - bweight.weight += weight.weight; - } else { - boneWeights.put(weight.bone, weight); - } - } - - /** Finds the bone nodes influencing this vertex. */ - public HashSet getBones (HashMap nodes) - { - HashSet bones = Sets.newHashSet(); - for (String bone : boneWeights.keySet()) { - Spatial node = nodes.get(bone); - if (node instanceof ModelNode) { - bones.add((ModelNode)node); - } else { - log.warning("Missing or invalid bone for bone weight " + - "[bone=" + bone + "]."); - } - } - return bones; - } - - /** Returns the weight of the given bone. */ - public float getWeight (ModelNode bone) - { - BoneWeight bweight = boneWeights.get(bone.getName()); - return (bweight == null) ? 0f : bweight.weight; - } - } - - /** The influence of a bone on a vertex. */ - public static class BoneWeight - { - /** The name of the influencing bone. */ - public String bone; - - /** The amount of influence. */ - public float weight; - } - - /** A group of vertices influenced by the same bone. */ - public static class WeightGroupDef - { - /** The indices of the affected vertex. */ - public ArrayList indices = Lists.newArrayList(); - - /** The interleaved vertex weights. */ - public ArrayList weights = Lists.newArrayList(); - } - - /** Contains the transform of a node for preprocessing. */ - public static class TransformNode extends Node - { - /** The source definition. */ - public SpatialDef spatial; - - /** If true, this node is referenced by name (as a bone or parent) and cannot be merged - * into another. */ - public boolean referenced; - - /** If true, this node is a controller target; nodes beneath it can only be merged with - * other descendants. */ - public boolean controlled; - - /** The node's current local transform. */ - public Matrix4f localTransform = new Matrix4f(); - - /** The node's current world space transform. */ - public Matrix4f worldTransform = new Matrix4f(); - - /** The node's local transform in the original model, or null if the node's - * transform has diverged from the original. */ - public Matrix4f baseLocalTransform; - - /** The relative transforms between this and all other loosely compatible nodes not yet - * eliminated. As soon as the relative transform diverges in the course of preprocessing - * an animation, the node/transform pair is removed from the list. */ - public ArrayList> relativeTransforms; - - /** Marks this node as having been transformed in the course of an animation. */ - public boolean transformed; - - public TransformNode (SpatialDef spatial) - { - super(spatial.name); - this.spatial = spatial; - setLocalTransform(spatial.translation, spatial.rotation, spatial.scale); - } - - public void setLocalTransform (float[] translation, float[] rotation, float[] scale) - { - getLocalTranslation().set(translation[0], translation[1], translation[2]); - getLocalRotation().set(rotation[0], rotation[1], rotation[2], rotation[3]); - getLocalScale().set(scale[0], scale[1], scale[2]); - JmeUtil.setTransform( - getLocalTranslation(), getLocalRotation(), getLocalScale(), localTransform); - } - - @Override - public void updateWorldVectors () - { - super.updateWorldVectors(); - JmeUtil.setTransform( - getWorldTranslation(), getWorldRotation(), getWorldScale(), worldTransform); - } - - public boolean canMerge (Properties props, TransformNode onode) - { - // nodes must have same controlled ancestor - return !onode.referenced && spatial.canMerge(props, onode.spatial) && - getControlledAncestor() == onode.getControlledAncestor(); - } - - protected Node getControlledAncestor () - { - Node ref = this; - while (ref instanceof TransformNode && !((TransformNode)ref).controlled) { - ref = ref.getParent(); - } - return ref; - } - - public void cullDivergentTransforms () - { - if (baseLocalTransform != null && !epsilonEquals(localTransform, baseLocalTransform)) { - baseLocalTransform = null; - } - for (Iterator> it = relativeTransforms.iterator(); - it.hasNext(); ) { - Tuple tuple = it.next(); - if (!epsilonEquals(getRelativeTransform(tuple.left), tuple.right)) { - it.remove(); - } - } - } - - public Matrix4f getRelativeTransform (TransformNode other) - { - // return the matrix that takes vertices from the space of the other node - // into the space of this one - Matrix4f inv = new Matrix4f(); - worldTransform.invert(inv); - return inv.mult(other.worldTransform); - } - } - - /** The meshes and bones comprising the model. */ - public ArrayList spatials = Lists.newArrayList(); - - public void addSpatial (SpatialDef spatial) - { - // put nodes before meshes so that bones are updated before skin - spatials.add(spatial instanceof NodeDef ? 0 : spatials.size(), - spatial); - } - - /** - * Creates and returns a transform tree representing the model for preprocessing. - */ - public Node createTransformTree (Properties props, HashMap nodes) - { - // create the nodes and map them by name - for (SpatialDef spatial : spatials) { - nodes.put(spatial.name, new TransformNode(spatial)); - } - - // resolve the parents and collect the names of the bones - Node root = new Node("root"); - HashSet bones = Sets.newHashSet(); - for (TransformNode node : nodes.values()) { - if (node.spatial.parent == null) { - root.attachChild(node); - } else { - TransformNode pnode = nodes.get(node.spatial.parent); - if (pnode != null) { - pnode.attachChild(node); - pnode.referenced = true; - } - } - node.spatial.getBoneNames(bones); - } - - // mark the bones as referenced - for (String name : bones) { - TransformNode node = nodes.get(name); - if (node != null) { - node.referenced = true; - } - } - - // mark the controlled nodes - String[] controllers = StringUtil.parseStringArray(props.getProperty("controllers", "")); - for (String controller : controllers) { - Properties subProps = PropertiesUtil.getSubProperties(props, controller); - TransformNode node = nodes.get(subProps.getProperty("node", controller)); - if (node != null) { - node.referenced = node.controlled = true; - } - } - - // store the base transforms and relative transforms for merge candidates - root.updateGeometricState(0f, true); - for (TransformNode node : nodes.values()) { - node.baseLocalTransform = new Matrix4f(node.localTransform); - node.relativeTransforms = Lists.newArrayList(); - for (TransformNode onode : nodes.values()) { - if (node == onode || !node.canMerge(props, onode)) { - continue; - } - node.relativeTransforms.add(new Tuple( - onode, node.getRelativeTransform(onode))); - } - } - - return root; - } - - /** - * Merges compatible meshes that retain the same relative transform throughout all animations. - */ - public void mergeSpatials (HashMap nodes) - { - for (TransformNode node : nodes.values()) { - if (!spatials.contains(node.spatial)) { - continue; - } - for (Tuple tuple : node.relativeTransforms) { - if (spatials.contains(tuple.left.spatial)) { - node.spatial.merge(tuple.left.spatial, tuple.right); - spatials.remove(tuple.left.spatial); - } - } - } - } - - /** - * Creates the model node defined herein. - * - * @param props the properties of the model - * @param nodes a node map to populate - */ - public Model createModel (Properties props, HashMap nodes) - { - Model model = new Model(props.getProperty("name", "model"), props); - - // start by creating the spatials and mapping them to their names - for (int ii = 0, nn = spatials.size(); ii < nn; ii++) { - Spatial spatial = spatials.get(ii).getSpatial(props); - nodes.put(spatial.getName(), spatial); - } - - // then go through again, resolving any name references and attaching root children - HashSet referenced = Sets.newHashSet(); - for (int ii = 0, nn = spatials.size(); ii < nn; ii++) { - SpatialDef sdef = spatials.get(ii); - sdef.resolveReferences(nodes, referenced); - if (sdef.getSpatial(props).getParent() == null) { - model.attachChild(sdef.getSpatial(props)); - } - } - - // create any controllers listed - String[] controllers = StringUtil.parseStringArray( - props.getProperty("controllers", "")); - for (int ii = 0; ii < controllers.length; ii++) { - Properties subProps = - PropertiesUtil.getSubProperties(props, controllers[ii]); - String node = subProps.getProperty("node", controllers[ii]); - Spatial target = node.equals(model.getName()) ? - model : nodes.get(node); - if (target == null) { - log.warning("Missing controller node [name=" + node + "]."); - continue; - } - ModelController ctrl = createController(subProps, target); - if (ctrl != null) { - model.addController(ctrl); - referenced.add(target); - } - } - - // get rid of any nodes that serve no purpose - pruneUnusedNodes(model, nodes, referenced); - - // set the overall scale - model.setLocalScale(Float.parseFloat(props.getProperty("scale", "1"))); - - return model; - } - - /** Creates, configures, and returns a model controller. */ - protected ModelController createController ( - Properties props, Spatial target) - { - // attempt to create an instance of the controller - ModelController ctrl; - String cname = props.getProperty("class", ""); - try { - ctrl = (ModelController)Class.forName(cname).newInstance(); - } catch (Exception e) { - log.warning("Error instantiating controller [class=" + cname + - ", error=" + e + "]."); - return null; - } - ctrl.configure(props, target); - return ctrl; - } - - /** Recursively removes any unused nodes. */ - protected boolean pruneUnusedNodes ( - ModelNode node, HashMap nodes, - HashSet referenced) - { - boolean hasValidChildren = false; - for (int ii = node.getQuantity() - 1; ii >= 0; ii--) { - Spatial child = node.getChild(ii); - if (!(child instanceof ModelNode) || - pruneUnusedNodes((ModelNode)child, nodes, referenced)) { - hasValidChildren = true; - } else { - node.detachChildAt(ii); - nodes.remove(child.getName()); - } - } - return referenced.contains(node) || hasValidChildren; - } - - /** Determines whether a pair of matrices are "close enough" to equal. */ - public static boolean epsilonEquals (Matrix4f m1, Matrix4f m2) - { - for (int ii = 0; ii < 4; ii++) { - for (int jj = 0; jj < 4; jj++) { - if (FastMath.abs(m1.get(ii, jj) - m2.get(ii, jj)) > 0.0001f) { - return false; - } - } - } - return true; - } - - /** Converts a boxed Float list to an unboxed float array. */ - protected static float[] toArray (ArrayList list) - { - float[] array = new float[list.size()]; - for (int ii = 0, nn = list.size(); ii < nn; ii++) { - array[ii] = list.get(ii); - } - return array; - } - - /** Accelerates {@link ArrayList#indexOf}, {@link ArrayList#contains}, and - * {@link ArrayList#remove} using an internal hash map (assumes that all elements of the list - * are unique and non-null). */ - protected static class HashArrayList extends ArrayList - { - @Override - public boolean add (E element) - { - add(size(), element); - return true; - } - - @Override - public void add (int idx, E element) - { - super.add(idx, element); - remapFrom(idx); - } - - @Override - public E remove (int idx) - { - E element = super.remove(idx); - _indices.remove(element); - remapFrom(idx); - return element; - } - - @Override - public void clear () - { - super.clear(); - _indices.clear(); - } - - @Override - public int indexOf (Object obj) - { - Integer idx = _indices.get(obj); - return (idx == null ? -1 : idx); - } - - @Override - public boolean contains (Object obj) - { - return _indices.containsKey(obj); - } - - @Override - public boolean remove (Object obj) - { - Integer idx = _indices.remove(obj); - if (idx != null) { - super.remove(idx); - return true; - } else { - return false; - } - } - - protected void remapFrom (int idx) - { - for (int ii = idx, nn = size(); ii < nn; ii++) { - _indices.put(get(ii), ii); - } - } - - /** Maps elements to their indices in the list. */ - protected HashMap _indices = Maps.newHashMap(); - } -} diff --git a/src/java/com/threerings/jme/tools/ModelViewer.java b/src/java/com/threerings/jme/tools/ModelViewer.java deleted file mode 100644 index cb7ff5ba..00000000 --- a/src/java/com/threerings/jme/tools/ModelViewer.java +++ /dev/null @@ -1,1142 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools; - -import java.awt.BorderLayout; -import java.awt.Point; -import java.awt.event.ActionEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseMotionListener; -import java.awt.event.MouseWheelEvent; -import java.awt.event.MouseWheelListener; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; - -import java.net.MalformedURLException; -import java.net.URL; - -import java.text.DecimalFormat; - -import java.util.HashMap; -import java.util.logging.Level; - -import javax.swing.AbstractAction; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.ButtonGroup; -import javax.swing.ButtonModel; -import javax.swing.DefaultComboBoxModel; -import javax.swing.JButton; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JComboBox; -import javax.swing.JDialog; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JSlider; -import javax.swing.KeyStroke; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; -import javax.swing.filechooser.FileFilter; - -import com.google.common.base.Objects; -import com.google.common.collect.Maps; - -import com.jme.bounding.BoundingBox; -import com.jme.bounding.BoundingVolume; -import com.jme.image.Texture; -import com.jme.light.DirectionalLight; -import com.jme.math.FastMath; -import com.jme.math.Vector3f; -import com.jme.renderer.Camera; -import com.jme.renderer.ColorRGBA; -import com.jme.renderer.Renderer; -import com.jme.scene.Controller; -import com.jme.scene.Line; -import com.jme.scene.Node; -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.system.JmeException; -import com.jme.util.LoggingSystem; -import com.jme.util.TextureKey; -import com.jme.util.TextureManager; -import com.jme.util.export.binary.BinaryImporter; -import com.jme.util.geom.Debugger; -import com.jmex.effects.particles.ParticleGeometry; - -import com.samskivert.swing.GroupLayout; -import com.samskivert.swing.Spacer; -import com.samskivert.util.PrefsConfig; -import com.samskivert.util.StringUtil; - -import com.threerings.resource.ResourceManager; -import com.threerings.util.MessageBundle; -import com.threerings.util.MessageManager; - -import com.threerings.jme.JmeCanvasApp; -import com.threerings.jme.camera.CameraHandler; -import com.threerings.jme.model.Model; -import com.threerings.jme.model.TextureProvider; -import com.threerings.jme.util.ShaderCache; -import com.threerings.jme.util.SpatialVisitor; - -import static com.threerings.jme.Log.log; - -/** - * A simple viewer application that allows users to examine models and their animations by loading - * them from their uncompiled .properties / .mxml representations or - * their compiled .dat representations. - */ -public class ModelViewer extends JmeCanvasApp -{ - public static void main (String[] args) - { - // write standard output and error to a log file - if (System.getProperty("no_log_redir") == null) { - String dlog = "viewer.log"; - try { - PrintStream logOut = new PrintStream( - new FileOutputStream(dlog), true); - System.setOut(logOut); - System.setErr(logOut); - - } catch (IOException ioe) { - log.warning("Failed to open debug log [path=" + dlog + - ", error=" + ioe + "]."); - } - } - LoggingSystem.getLoggingSystem().setLevel(Level.WARNING); - new ModelViewer(args.length > 0 ? args[0] : null); - } - - /** - * Creates and initializes an instance of the model viewer application. - * - * @param path the path of the model to view, or null for - * none - */ - public ModelViewer (String path) - { - super(1024, 768); - _rsrcmgr = new ResourceManager("rsrc"); - _scache = new ShaderCache(_rsrcmgr); - _msg = new MessageManager("rsrc.i18n").getBundle("jme.viewer"); - _path = path; - - JPopupMenu.setDefaultLightWeightPopupEnabled(false); - - _frame = new JFrame(_msg.get("m.title")); - _frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - - JMenuBar menu = new JMenuBar(); - _frame.setJMenuBar(menu); - - JMenu file = new JMenu(_msg.get("m.file_menu")); - file.setMnemonic(KeyEvent.VK_F); - menu.add(file); - Action load = new AbstractAction(_msg.get("m.file_load")) { - public void actionPerformed (ActionEvent e) { - showLoadDialog(); - } - }; - load.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_L); - load.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_L, KeyEvent.CTRL_MASK)); - file.add(load); - - Action importAction = new AbstractAction(_msg.get("m.file_import")) { - public void actionPerformed (ActionEvent e) { - showImportDialog(); - } - }; - importAction.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_I); - importAction.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK)); - file.add(importAction); - - file.addSeparator(); - Action quit = new AbstractAction(_msg.get("m.file_quit")) { - public void actionPerformed (ActionEvent e) { - System.exit(0); - } - }; - quit.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_Q); - quit.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_MASK)); - file.add(quit); - - 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( - KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_MASK)); - view.add(_pivots); - - _bounds = new JCheckBoxMenuItem(_msg.get("m.view_bounds")); - _bounds.setMnemonic(KeyEvent.VK_B); - _bounds.setAccelerator( - KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK)); - view.add(_bounds); - - _normals = new JCheckBoxMenuItem(_msg.get("m.view_normals")); - _normals.setMnemonic(KeyEvent.VK_N); - _normals.setAccelerator( - KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_MASK)); - view.add(_normals); - view.addSeparator(); - - Action campos = new AbstractAction(_msg.get("m.view_campos")) { - public void actionPerformed (ActionEvent e) { - _campos.setVisible(!_campos.isVisible()); - } - }; - campos.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_A); - campos.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK)); - view.add(new JCheckBoxMenuItem(campos)); - view.addSeparator(); - - _vmenu = new JMenu(_msg.get("m.model_variant")); - view.add(_vmenu); - - JMenu amode = new JMenu(_msg.get("m.animation_mode")); - final JRadioButtonMenuItem flipbook = - new JRadioButtonMenuItem(_msg.get("m.mode_flipbook")), - morph = new JRadioButtonMenuItem(_msg.get("m.mode_morph")), - skin = new JRadioButtonMenuItem(_msg.get("m.mode_skin")); - ButtonGroup mgroup = new ButtonGroup() { - public void setSelected (ButtonModel model, boolean b) { - super.setSelected(model, b); - if (b) { - if (flipbook.isSelected()) { - _animMode = Model.AnimationMode.FLIPBOOK; - } else if (morph.isSelected()) { - _animMode = Model.AnimationMode.MORPH; - } else { - _animMode = Model.AnimationMode.SKIN; - } - if (_loaded != null) { - loadModel(_loaded); // reload - } - } - } - }; - - mgroup.add(flipbook); - mgroup.add(morph); - mgroup.add(skin); - mgroup.setSelected(skin.getModel(), true); - amode.add(skin); - amode.add(morph); - amode.add(flipbook); - view.add(amode); - view.addSeparator(); - - Action rlight = new AbstractAction(_msg.get("m.view_light")) { - public void actionPerformed (ActionEvent e) { - if (_rldialog == null) { - _rldialog = new RotateLightDialog(); - _rldialog.pack(); - } - _rldialog.setVisible(true); - } - }; - rlight.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R); - rlight.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_MASK)); - view.add(new JMenuItem(rlight)); - - Action rcamera = new AbstractAction(_msg.get("m.view_recenter")) { - public void actionPerformed (ActionEvent e) { - ((OrbitCameraHandler)_camhand).recenter(); - updateCameraPosition(); - } - }; - rcamera.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_C); - rcamera.putValue(Action.ACCELERATOR_KEY, - KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK)); - view.add(new JMenuItem(rcamera)); - - _frame.getContentPane().add(getCanvas(), BorderLayout.CENTER); - - JPanel bpanel = new JPanel(new BorderLayout()); - _frame.getContentPane().add(bpanel, BorderLayout.SOUTH); - - _animctrls = new JPanel(); - _animctrls.setBorder(BorderFactory.createEtchedBorder()); - bpanel.add(_animctrls, BorderLayout.NORTH); - _animctrls.add(new JLabel(_msg.get("m.anim_select"))); - _animctrls.add(_animbox = new JComboBox()); - _animctrls.add(new JButton( - new AbstractAction(_msg.get("m.anim_start")) { - public void actionPerformed (ActionEvent e) { - String anim = (String)_animbox.getSelectedItem(); - if (_model.hasAnimation(anim)) { - _model.startAnimation(anim); - } else { // it's a sequence - if (_model.getAnimation() != null) { - _sequence = null; - _model.stopAnimation(); - } - _sequence = StringUtil.parseStringArray( - _model.getProperties().getProperty( - anim + ".animations", "")); - if (_sequence.length == 0) { - _sequence = null; - } else { - _model.startAnimation(_sequence[_seqidx = 0]); - } - } - } - })); - _animctrls.add(_animstop = new JButton( - new AbstractAction(_msg.get("m.anim_stop")) { - public void actionPerformed (ActionEvent e) { - _model.stopAnimation(); - } - })); - _animstop.setEnabled(false); - _animctrls.add(new Spacer(50, 1)); - _animctrls.add(new JLabel(_msg.get("m.anim_speed"))); - _animctrls.add(_animspeed = new JSlider(-100, +100, 0)); - _animspeed.setMajorTickSpacing(10); - _animspeed.setSnapToTicks(true); - _animspeed.setPaintTicks(true); - _animspeed.addChangeListener(new ChangeListener() { - public void stateChanged (ChangeEvent e) { - updateAnimationSpeed(); - } - }); - _animctrls.setVisible(false); - - JPanel spanel = new JPanel(new BorderLayout()); - bpanel.add(spanel, BorderLayout.SOUTH); - - _status = new JLabel(" "); - _status.setHorizontalAlignment(JLabel.LEFT); - _status.setBorder(BorderFactory.createEtchedBorder()); - spanel.add(_status, BorderLayout.CENTER); - - _campos = new JLabel(" "); - _campos.setBorder(BorderFactory.createEtchedBorder()); - _campos.setVisible(false); - spanel.add(_campos, BorderLayout.EAST); - - _frame.pack(); - _frame.setVisible(true); - - run(); - } - - @Override - public boolean init () - { - if (!super.init()) { - return false; - } - if (_path != null) { - loadModel(new File(_path)); - } - return true; - } - - @Override - protected void initDisplay () - throws JmeException - { - super.initDisplay(); - _ctx.getRenderer().setBackgroundColor(ColorRGBA.gray); - _ctx.getRenderer().getQueue().setTwoPassTransparency(false); - } - - @Override - protected void initInput () - { - super.initInput(); - - _camhand.setTiltLimits(-FastMath.HALF_PI, FastMath.HALF_PI); - _camhand.setZoomLimits(1f, 500f); - _camhand.tiltCamera(-FastMath.PI * 7.0f / 16.0f); - updateCameraPosition(); - - MouseOrbiter orbiter = new MouseOrbiter(); - _canvas.addMouseListener(orbiter); - _canvas.addMouseMotionListener(orbiter); - _canvas.addMouseWheelListener(orbiter); - } - - /** - * Updates the camera position label. - */ - protected void updateCameraPosition () - { - Camera cam = _camhand.getCamera(); - Vector3f pos = cam.getLocation(), dir = cam.getDirection(); - float heading = -FastMath.atan2(dir.x, dir.y) * FastMath.RAD_TO_DEG, - pitch = FastMath.asin(dir.z) * FastMath.RAD_TO_DEG; - _campos.setText( - "XYZ: " + CAMPOS_FORMAT.format(pos.x) + ", " + - CAMPOS_FORMAT.format(pos.y) + ", " + - CAMPOS_FORMAT.format(pos.z) + - " HP: " + CAMPOS_FORMAT.format(heading) + ", " + - CAMPOS_FORMAT.format(pitch)); - } - - @Override - protected CameraHandler createCameraHandler (Camera camera) - { - return new OrbitCameraHandler(camera); - } - - @Override - protected void initRoot () - { - super.initRoot(); - - // 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()); - _ctx.getGeometry().setNormalsMode(Spatial.NM_GL_NORMALIZE_PROVIDED); - _wfstate.setEnabled(false); - - // create a grid on the XY plane to provide some reference - Vector3f[] points = new Vector3f[GRID_SIZE*2 + GRID_SIZE*2]; - float halfLength = (GRID_SIZE - 1) * GRID_SPACING / 2; - int idx = 0; - for (int xx = 0; xx < GRID_SIZE; xx++) { - points[idx++] = new Vector3f( - -halfLength + xx*GRID_SPACING, -halfLength, 0f); - points[idx++] = new Vector3f( - -halfLength + xx*GRID_SPACING, +halfLength, 0f); - } - for (int yy = 0; yy < GRID_SIZE; yy++) { - points[idx++] = new Vector3f( - -halfLength, -halfLength + yy*GRID_SPACING, 0f); - points[idx++] = new Vector3f( - +halfLength, -halfLength + yy*GRID_SPACING, 0f); - - } - Line grid = new Line("grid", points, null, null, null); - grid.getBatch(0).getDefaultColor().set(0.25f, 0.25f, 0.25f, 1f); - grid.setLightCombineMode(LightState.OFF); - grid.setModelBound(new BoundingBox()); - grid.updateModelBound(); - _ctx.getGeometry().attachChild(grid); - grid.updateRenderState(); - - // attach a dummy node to draw debugging views - _ctx.getGeometry().attachChild(new Node("debug") { - public void onDraw (Renderer r) { - if (_model == null) { - return; - } - if (_pivots.getState()) { - drawPivots(_model, r); - } - if (_bounds.getState()) { - Debugger.drawBounds(_model, r); - } - if (_normals.getState()) { - Debugger.drawNormals(_model, r, 5f, true); - } - } - }); - } - - /** - * Draws the pivot axes of the given node and its children. - */ - protected void drawPivots (Spatial spatial, Renderer r) - { - if (_axes == null) { - _axes = new Line("axes", - new Vector3f[] { Vector3f.ZERO, Vector3f.UNIT_X, Vector3f.ZERO, - Vector3f.UNIT_Y, Vector3f.ZERO, Vector3f.UNIT_Z }, null, - new ColorRGBA[] { ColorRGBA.red, ColorRGBA.red, - ColorRGBA.green, ColorRGBA.green, ColorRGBA.blue, - ColorRGBA.blue }, null); - _axes.setRenderQueueMode(Renderer.QUEUE_SKIP); - _axes.setRenderState(r.createZBufferState()); - LightState lstate = r.createLightState(); - lstate.setEnabled(false); - _axes.setRenderState(lstate); - _axes.updateRenderState(); - } - _axes.getRenderState(ZBufferState.RS_ZBUFFER).apply(); - _axes.getRenderState(LightState.RS_LIGHT).apply(); - _axes.getWorldTranslation().set(spatial.getWorldTranslation()); - _axes.getWorldRotation().set(spatial.getWorldRotation()); - _axes.draw(r); - - if (spatial instanceof Node) { - Node node = (Node)spatial; - for (int ii = 0, nn = node.getQuantity(); ii < nn; ii++) { - drawPivots(node.getChild(ii), r); - } - } - } - - @Override - protected void initLighting () - { - _dlight = new DirectionalLight(); - _dlight.setEnabled(true); - _dlight.getDirection().set(-1f, 0f, -1f).normalizeLocal(); - _dlight.getAmbient().set(0.25f, 0.25f, 0.25f, 1f); - - LightState lstate = _ctx.getRenderer().createLightState(); - lstate.attach(_dlight); - _ctx.getGeometry().setRenderState(lstate); - _ctx.getGeometry().setLightCombineMode(LightState.REPLACE); - } - - /** - * Shows the load model dialog. - */ - protected void showLoadDialog () - { - if (_chooser == null) { - _chooser = new JFileChooser(); - _chooser.setDialogTitle(_msg.get("m.load_title")); - _chooser.setFileFilter(new FileFilter() { - public boolean accept (File file) { - if (file.isDirectory()) { - return true; - } - String path = file.toString().toLowerCase(); - return path.endsWith(".properties") || - path.endsWith(".dat"); - } - public String getDescription () { - return _msg.get("m.load_filter"); - } - }); - File dir = new File(_config.getValue("dir", ".")); - if (dir.exists()) { - _chooser.setCurrentDirectory(dir); - } - } - if (_chooser.showOpenDialog(_frame) == JFileChooser.APPROVE_OPTION) { - loadModel(_chooser.getSelectedFile()); - } - _config.setValue("dir", _chooser.getCurrentDirectory().toString()); - } - - /** - * Attempts to load a model from the specified location. - */ - protected void loadModel (File file) - { - String fpath = file.toString(); - try { - if (fpath.endsWith(".properties")) { - compileModel(file); - } else if (fpath.endsWith(".dat")) { - loadCompiledModel(file); - } else { - throw new Exception(_msg.get("m.invalid_type")); - } - _status.setText(_msg.get("m.loaded_model", fpath)); - _loaded = file; - - } catch (Exception e) { - e.printStackTrace(); - _status.setText(_msg.get("m.load_error", fpath, e)); - } - } - - /** - * Attempts to compile and load a model. - */ - protected void compileModel (File file) - throws Exception - { - _status.setText(_msg.get("m.compiling_model", file)); - Model model = CompileModel.compile(file); - if (model != null) { - setModel(model, file); - return; - } - - // if compileModel returned null, the .dat file is up-to-date - String fpath = file.toString(); - int didx = fpath.lastIndexOf('.'); - fpath = (didx == -1) ? fpath : fpath.substring(0, didx); - loadCompiledModel(new File(fpath + ".dat")); - } - - /** - * Attempts to load a model that has already been compiled. - */ - protected void loadCompiledModel (File file) - throws IOException - { - _status.setText(_msg.get("m.loading_model", file)); - setModel(Model.readFromFile(file), file); - } - - /** - * Sets the model once it's been loaded. - * - * @param file the file from which the model was loaded - */ - protected void setModel (Model model, File file) - { - if (_model != null) { - _ctx.getGeometry().detachChild(_model); - } - _ctx.getGeometry().attachChild(_model = _omodel = model); - _model.setAnimationMode(_animMode); - _model.configureShaders(_scache); - _model.lockStaticMeshes(_ctx.getRenderer(), true, true); - - // load the model's textures - resolveModelTextures(file); - - // recenter the camera - _model.updateGeometricState(0f, true); - ((OrbitCameraHandler)_camhand).recenter(); - updateCameraPosition(); - - // configure the variant menu - _variant = null; - _vmenu.removeAll(); - ButtonGroup vgroup = new ButtonGroup() { - public void setSelected (ButtonModel model, boolean b) { - super.setSelected(model, b); - String variant = model.getActionCommand(); - if (b && !Objects.equal(variant, _variant)) { - setVariant(model.getActionCommand()); - } - } - }; - JRadioButtonMenuItem def = new JRadioButtonMenuItem( - _msg.get("m.variant_default")); - def.setActionCommand(null); - vgroup.add(def); - _vmenu.add(def); - for (String variant : _model.getVariantNames()) { - JRadioButtonMenuItem vitem = new JRadioButtonMenuItem(variant); - vitem.setActionCommand(variant); - vgroup.add(vitem); - _vmenu.add(vitem); - } - vgroup.setSelected(def.getModel(), true); - - // configure the animation panel - String[] anims = _model.getAnimationNames(); - if (anims.length == 0) { - _animctrls.setVisible(false); - return; - } - _model.addAnimationObserver(_animobs); - _animctrls.setVisible(true); - DefaultComboBoxModel abmodel = new DefaultComboBoxModel(anims); - _animbox.setModel(abmodel); - updateAnimationSpeed(); - - // if there are any sequences, add those as well - String[] seqs = StringUtil.parseStringArray( - _model.getProperties().getProperty("sequences", "")); - for (String seq : seqs) { - abmodel.addElement(seq); - } - } - - /** - * Switches to the named variant. - */ - protected void setVariant (String variant) - { - _model.stopAnimation(); - _ctx.getGeometry().detachChild(_model); - _ctx.getGeometry().attachChild( - _model = _omodel.createPrototype(variant)); - _model.addAnimationObserver(_animobs); - updateAnimationSpeed(); - resolveModelTextures(_loaded); - _variant = variant; - } - - /** - * Resolve the textures from the file's directory. - */ - protected void resolveModelTextures (File file) - { - final File dir = file.getParentFile(); - _model.resolveTextures(new TextureProvider() { - public TextureState getTexture (String name) { - TextureState tstate = _tstates.get(name); - if (tstate == null) { - File file; - if (name.startsWith("/")) { - file = _rsrcmgr.getResourceFile(name.substring(1)); - } else { - file = new File(dir, name); - } - Texture tex = TextureManager.loadTexture(file.toString(), - Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR); - if (tex == null) { - log.warning("Couldn't find texture [path=" + file + - "]."); - return null; - } - tex.setWrap(Texture.WM_WRAP_S_WRAP_T); - tstate = _ctx.getRenderer().createTextureState(); - tstate.setTexture(tex); - _tstates.put(name, tstate); - } - return tstate; - } - protected HashMap _tstates = Maps.newHashMap(); - }); - _model.updateRenderState(); - } - - /** - * Shows the import particle system dialog. - */ - protected void showImportDialog () - { - if (_ichooser == null) { - _ichooser = new JFileChooser(); - _ichooser.setDialogTitle(_msg.get("m.import_title")); - _ichooser.setFileFilter(new FileFilter() { - public boolean accept (File file) { - if (file.isDirectory()) { - return true; - } - String path = file.toString().toLowerCase(); - return path.endsWith(".jme"); - } - public String getDescription () { - return _msg.get("m.import_filter"); - } - }); - File dir = new File(_config.getValue("import_dir", ".")); - if (dir.exists()) { - _ichooser.setCurrentDirectory(dir); - } - } - if (_ichooser.showOpenDialog(_frame) == JFileChooser.APPROVE_OPTION) { - importFile(_ichooser.getSelectedFile()); - } - _config.setValue("import_dir", - _ichooser.getCurrentDirectory().toString()); - } - - /** - * Attempts to import the specified file as a JME binary scene. - */ - protected void importFile (File file) - { - final File parent = file.getParentFile(); - TextureKey.setLocationOverride(new TextureKey.LocationOverride() { - public URL getLocation (String name) - throws MalformedURLException { - return new URL(parent.toURI().toURL(), name); - } - }); - try { - new ImportDialog(file, - (Spatial)BinaryImporter.getInstance().load( - file)).setVisible(true); - - } catch (Exception e) { - e.printStackTrace(); - _status.setText(_msg.get("m.load_error", file, e)); - } - TextureKey.setLocationOverride(null); - } - - /** - * Updates the model's animation speed based on the position of the - * animation speed slider. - */ - protected void updateAnimationSpeed () - { - _model.setAnimationSpeed( - FastMath.pow(2f, _animspeed.getValue() / 25f)); - } - - /** The resource manager. */ - protected ResourceManager _rsrcmgr; - - /** The shader cache. */ - protected ShaderCache _scache; - - /** The translation bundle. */ - protected MessageBundle _msg; - - /** The path of the initial model to load. */ - protected String _path; - - /** The last model successfully loaded. */ - protected File _loaded; - - /** The viewer frame. */ - protected JFrame _frame; - - /** The variant menu. */ - protected JMenu _vmenu; - - /** Debug view switches. */ - protected JCheckBoxMenuItem _pivots, _bounds, _normals; - - /** The animation controls. */ - protected JPanel _animctrls; - - /** The animation selector. */ - protected JComboBox _animbox; - - /** The "stop animation" button. */ - protected JButton _animstop; - - /** The animation speed slider. */ - protected JSlider _animspeed; - - /** The status bar. */ - protected JLabel _status; - - /** The camera position display. */ - protected JLabel _campos; - - /** The model file chooser. */ - protected JFileChooser _chooser; - - /** The import file chooser. */ - protected JFileChooser _ichooser; - - /** The desired animation mode. */ - protected Model.AnimationMode _animMode; - - /** The desired variant. */ - protected String _variant; - - /** The light rotation dialog. */ - protected RotateLightDialog _rldialog; - - /** The scene light. */ - protected DirectionalLight _dlight; - - /** Used to toggle wireframe rendering. */ - protected WireframeState _wfstate; - - /** The currently loaded model. */ - protected Model _model; - - /** The original model (before switching to a variant). */ - protected Model _omodel; - - /** Reused to draw pivot axes. */ - protected Line _axes; - - /** The current animation sequence, if any. */ - protected String[] _sequence; - - /** The current index in the animation sequence. */ - protected int _seqidx; - - /** Enables and disables the stop button when animations start and stop. */ - protected Model.AnimationObserver _animobs = - new Model.AnimationObserver() { - public boolean animationStarted (Model model, String name) { - _animstop.setEnabled(true); - return true; - } - public boolean animationCompleted (Model model, String name) { - if (_sequence != null && ++_seqidx < _sequence.length) { - _model.startAnimation(_sequence[_seqidx]); - } else { - _animstop.setEnabled(false); - _sequence = null; - } - return true; - } - public boolean animationCancelled (Model model, String name) { - if (_sequence != null && ++_seqidx < _sequence.length && - _model.getAnimation(name).repeatType != Controller.RT_CLAMP) { - _model.startAnimation(_sequence[_seqidx]); - } else { - _animstop.setEnabled(false); - _sequence = null; - } - return true; - } - }; - - /** Allows users to manipulate an imported JME file. */ - protected class ImportDialog extends JDialog - implements ChangeListener - { - public ImportDialog (File file, Spatial spatial) - { - super(_frame, _msg.get("m.import", file), false); - _spatial = spatial; - - // rotate from y-up to z-up and set initial scale - _spatial.getLocalRotation().fromAngleNormalAxis(FastMath.HALF_PI, - Vector3f.UNIT_X); - _spatial.setLocalScale(0.025f); - - JPanel cpanel = GroupLayout.makeVBox(); - getContentPane().add(cpanel, BorderLayout.CENTER); - - JPanel spanel = new JPanel(); - spanel.add(new JLabel(_msg.get("m.scale"))); - spanel.add(_scale = new JSlider(0, 1000, 250)); - _scale.addChangeListener(this); - cpanel.add(spanel); - - JPanel bpanel = new JPanel(); - bpanel.add(new JButton(new AbstractAction( - _msg.get("m.respawn_particles")) { - public void actionPerformed (ActionEvent e) { - _respawner.traverse(_spatial); - } - })); - bpanel.add(new JButton(new AbstractAction(_msg.get("m.close")) { - public void actionPerformed (ActionEvent e) { - setVisible(false); - } - })); - getContentPane().add(bpanel, BorderLayout.SOUTH); - pack(); - } - - // documentation inherited from interface ChangeListener - public void stateChanged (ChangeEvent e) - { - _spatial.setLocalScale(_scale.getValue() * 0.0001f); - } - - @Override - public void setVisible (boolean visible) - { - super.setVisible(visible); - if (visible && _spatial.getParent() == null) { - _ctx.getGeometry().attachChild(_spatial); - _spatial.updateRenderState(); - } else if (!visible && _spatial.getParent() != null) { - _ctx.getGeometry().detachChild(_spatial); - } - } - - /** The imported scene. */ - protected Spatial _spatial; - - /** The scale slider. */ - protected JSlider _scale; - } - - /** Allows users to move the directional light around. */ - protected class RotateLightDialog extends JDialog - implements ChangeListener - { - public RotateLightDialog () - { - super(_frame, _msg.get("m.rotate_light"), false); - - JPanel cpanel = GroupLayout.makeVBox(); - getContentPane().add(cpanel, BorderLayout.CENTER); - - JPanel apanel = new JPanel(); - apanel.add(new JLabel(_msg.get("m.azimuth"))); - apanel.add(_azimuth = new JSlider(-180, +180, 0)); - _azimuth.addChangeListener(this); - cpanel.add(apanel); - - JPanel epanel = new JPanel(); - epanel.add(new JLabel(_msg.get("m.elevation"))); - epanel.add(_elevation = new JSlider(-90, +90, 45)); - _elevation.addChangeListener(this); - cpanel.add(epanel); - - JPanel bpanel = new JPanel(); - bpanel.add(new JButton(new AbstractAction(_msg.get("m.close")) { - public void actionPerformed (ActionEvent e) { - setVisible(false); - } - })); - getContentPane().add(bpanel, BorderLayout.SOUTH); - } - - // documentation inherited from interface ChangeListener - public void stateChanged (ChangeEvent e) - { - float az = _azimuth.getValue() * FastMath.DEG_TO_RAD, - el = _elevation.getValue() * FastMath.DEG_TO_RAD; - _dlight.getDirection().set( - -FastMath.cos(az) * FastMath.cos(el), - -FastMath.sin(az) * FastMath.cos(el), - -FastMath.sin(el)); - } - - /** Azimuth and elevation sliders. */ - protected JSlider _azimuth, _elevation; - } - - /** Moves the camera using mouse input. */ - protected class MouseOrbiter extends MouseAdapter - implements MouseMotionListener, MouseWheelListener - { - @Override - public void mousePressed (MouseEvent e) - { - _mloc.setLocation(e.getX(), e.getY()); - } - - // documentation inherited from interface MouseMotionListener - public void mouseMoved (MouseEvent e) - { - } - - // documentation inherited from interface MouseMotionListener - public void mouseDragged (MouseEvent e) - { - int dx = e.getX() - _mloc.x, dy = e.getY() - _mloc.y; - _mloc.setLocation(e.getX(), e.getY()); - int mods = e.getModifiers(); - if ((mods & MouseEvent.BUTTON1_MASK) != 0) { - _camhand.tiltCamera(dy * FastMath.PI / 1000); - _camhand.orbitCamera(-dx * FastMath.PI / 1000); - } else if ((mods & MouseEvent.BUTTON2_MASK) != 0) { - _camhand.zoomCamera(dy/8f); - } else { - _camhand.panCamera(-dx/8f, dy/8f); - } - updateCameraPosition(); - } - - // documentation inherited from interface MouseWheelListener - public void mouseWheelMoved (MouseWheelEvent e) - { - _camhand.zoomCamera(e.getWheelRotation() * 10f); - updateCameraPosition(); - } - - /** The last recorded position of the mouse cursor. */ - protected Point _mloc = new Point(); - } - - /** A camera handler that pans in directions orthogonal to the camera - * direction. */ - protected class OrbitCameraHandler extends CameraHandler - { - public OrbitCameraHandler (Camera camera) - { - super(camera); - _gpoint = super.getGroundPoint(); - } - - @Override - public void panCamera (float x, float y) { - Vector3f offset = _camera.getLeft().mult(-x).addLocal( - _camera.getUp().mult(y)); - getGroundPoint().addLocal(offset); - _camera.getLocation().addLocal(offset); - _camera.onFrameChange(); - } - - @Override - public Vector3f getGroundPoint () - { - return _gpoint; - } - - /** - * Resets the ground point to the center of the grid or, if there is - * one, the center of the model. - */ - public void recenter () - { - Vector3f target = new Vector3f(); - if (_model != null) { - BoundingVolume bound = _model.getWorldBound(); - if (bound != null) { - bound.getCenter(target); - } - } - Vector3f offset = target.subtract(_gpoint); - _camera.getLocation().addLocal(offset); - _camera.onFrameChange(); - _gpoint.set(target); - } - - /** The point at which the camera is looking. */ - protected Vector3f _gpoint; - } - - /** The app configuration. */ - protected static PrefsConfig _config = new PrefsConfig("com/threerings/jme/tools/ModelViewer"); - - /** Forces all particle systems to respawn. */ - protected static SpatialVisitor _respawner = - new SpatialVisitor(ParticleGeometry.class) { - protected void visit (ParticleGeometry geom) { - geom.forceRespawn(); - } - }; - - /** The number of lines on the grid in each direction. */ - protected static final int GRID_SIZE = 32; - - /** The spacing between lines on the grid. */ - protected static final float GRID_SPACING = 2.5f; - - /** The number formal used for the camera position. */ - protected static final DecimalFormat CAMPOS_FORMAT = - new DecimalFormat("+000.000;-000.000"); -} diff --git a/src/java/com/threerings/jme/tools/xml/AnimationParser.java b/src/java/com/threerings/jme/tools/xml/AnimationParser.java deleted file mode 100644 index ec938709..00000000 --- a/src/java/com/threerings/jme/tools/xml/AnimationParser.java +++ /dev/null @@ -1,88 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools.xml; - -import java.io.FileInputStream; -import java.io.IOException; - -import org.xml.sax.SAXException; -import org.apache.commons.digester.Digester; - -import com.samskivert.xml.SetPropertyFieldsRule; - -import com.threerings.jme.tools.AnimationDef; - -/** - * Parses XML files containing animations. - */ -public class AnimationParser -{ - public AnimationParser () - { - // create and configure our digester - _digester = new Digester(); - - // add the rules - String anim = "animation"; - _digester.addObjectCreate(anim, AnimationDef.class.getName()); - _digester.addRule(anim, new SetPropertyFieldsRule()); - _digester.addSetNext(anim, "setAnimation", - AnimationDef.class.getName()); - - String frame = anim + "/frame"; - _digester.addObjectCreate(frame, - AnimationDef.FrameDef.class.getName()); - _digester.addSetNext(frame, "addFrame", - AnimationDef.FrameDef.class.getName()); - - String xform = frame + "/transform"; - _digester.addObjectCreate(xform, - AnimationDef.TransformDef.class.getName()); - _digester.addRule(xform, new SetPropertyFieldsRule()); - _digester.addSetNext(xform, "addTransform", - AnimationDef.TransformDef.class.getName()); - } - - /** - * Parses the XML file at the specified path into an animation - * definition. - */ - public AnimationDef parseAnimation (String path) - throws IOException, SAXException - { - _animation = null; - _digester.push(this); - _digester.parse(new FileInputStream(path)); - return _animation; - } - - /** - * Called by the parser once the animation is parsed. - */ - public void setAnimation (AnimationDef animation) - { - _animation = animation; - } - - protected Digester _digester; - protected AnimationDef _animation; -} diff --git a/src/java/com/threerings/jme/tools/xml/ModelParser.java b/src/java/com/threerings/jme/tools/xml/ModelParser.java deleted file mode 100644 index 35a6fae5..00000000 --- a/src/java/com/threerings/jme/tools/xml/ModelParser.java +++ /dev/null @@ -1,109 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.tools.xml; - -import java.io.FileInputStream; -import java.io.IOException; - -import org.xml.sax.SAXException; -import org.apache.commons.digester.Digester; - -import com.samskivert.xml.SetPropertyFieldsRule; - -import com.threerings.jme.tools.ModelDef; - -/** - * Parses XML files containing 3D models. - */ -public class ModelParser -{ - public ModelParser () - { - // create and configure our digester - _digester = new Digester(); - - // add the rules - String model = "model"; - _digester.addObjectCreate(model, ModelDef.class.getName()); - _digester.addSetNext(model, "setModel", ModelDef.class.getName()); - - String tmesh = model + "/triMesh"; - _digester.addObjectCreate(tmesh, ModelDef.TriMeshDef.class.getName()); - _digester.addRule(tmesh, new SetPropertyFieldsRule()); - _digester.addSetNext(tmesh, "addSpatial", - ModelDef.SpatialDef.class.getName()); - - String smesh = model + "/skinMesh"; - _digester.addObjectCreate(smesh, - ModelDef.SkinMeshDef.class.getName()); - _digester.addRule(smesh, new SetPropertyFieldsRule()); - _digester.addSetNext(smesh, "addSpatial", - ModelDef.SpatialDef.class.getName()); - - String node = model + "/node"; - _digester.addObjectCreate(node, ModelDef.NodeDef.class.getName()); - _digester.addRule(node, new SetPropertyFieldsRule()); - _digester.addSetNext(node, "addSpatial", - ModelDef.SpatialDef.class.getName()); - - String vertex = tmesh + "/vertex", svertex = smesh + "/vertex"; - _digester.addObjectCreate(vertex, ModelDef.Vertex.class.getName()); - _digester.addObjectCreate(svertex, - ModelDef.SkinVertex.class.getName()); - _digester.addRule(vertex, new SetPropertyFieldsRule()); - _digester.addRule(svertex, new SetPropertyFieldsRule()); - _digester.addSetNext(vertex, "addVertex", - ModelDef.Vertex.class.getName()); - _digester.addSetNext(svertex, "addVertex", - ModelDef.Vertex.class.getName()); - - String bweight = smesh + "/vertex/boneWeight"; - _digester.addObjectCreate(bweight, - ModelDef.BoneWeight.class.getName()); - _digester.addRule(bweight, new SetPropertyFieldsRule()); - _digester.addSetNext(bweight, "addBoneWeight", - ModelDef.BoneWeight.class.getName()); - } - - /** - * Parses the XML file at the specified path into a model definition. - */ - public ModelDef parseModel (String path) - throws IOException, SAXException - { - _model = null; - _digester.push(this); - _digester.parse(new FileInputStream(path)); - return _model; - } - - /** - * Called by the parser once the model is parsed. - */ - public void setModel (ModelDef model) - { - _model = model; - } - - protected Digester _digester; - protected ModelDef _model; -} diff --git a/src/java/com/threerings/jme/util/BatchVisitor.java b/src/java/com/threerings/jme/util/BatchVisitor.java deleted file mode 100644 index 183ade14..00000000 --- a/src/java/com/threerings/jme/util/BatchVisitor.java +++ /dev/null @@ -1,49 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -import com.jme.scene.Geometry; -import com.jme.scene.batch.GeomBatch; - -/** - * Visits all of the {@link GeomBatch}es in a scene. - */ -public abstract class BatchVisitor extends SpatialVisitor -{ - public BatchVisitor () - { - super(Geometry.class); - } - - // documentation inherited from SpatialVisitor - protected void visit (Geometry geom) - { - for (int ii = 0, nn = geom.getBatchCount(); ii < nn; ii++) { - visit(geom.getBatch(ii)); - } - } - - /** - * Called once for each {@link GeomBatch} in the scene graph. - */ - protected abstract void visit (GeomBatch batch); -} diff --git a/src/java/com/threerings/jme/util/ImageCache.java b/src/java/com/threerings/jme/util/ImageCache.java deleted file mode 100644 index 823aa5cb..00000000 --- a/src/java/com/threerings/jme/util/ImageCache.java +++ /dev/null @@ -1,410 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -import java.lang.ref.WeakReference; -import java.util.HashMap; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -import java.awt.Graphics2D; -import java.awt.color.ColorSpace; -import java.awt.geom.AffineTransform; -import java.awt.image.BandCombineOp; -import java.awt.image.BufferedImage; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.Raster; - -import com.google.common.collect.Maps; - -import com.jme.image.Image; -import com.jmex.bui.BImage; - -import com.threerings.media.image.Colorization; -import com.threerings.media.image.ImageUtil; - -import com.threerings.resource.ResourceManager; - -import static com.threerings.jme.Log.log; - -/** - * Manages a weak cache of image data to make life simpler for callers that don't want to worry - * about coordinating shared use of the same images. - */ -public class ImageCache -{ - /** - * Creates a JME-compatible image from the supplied buffered image. - */ - public static Image createImage (BufferedImage bufimg, boolean flip) - { - return createImage(bufimg, 1f, flip); - } - - /** - * Colorizes the supplied buffered image (which must be an 8-bit colormapped image), then - * converts the colorized image into a form that JME can display. - */ - public static Image createImage (BufferedImage bufimg, Colorization[] zations, boolean flip) - { - return createImage(bufimg, zations, 1f, flip); - } - - /** - * Colorizes the supplied buffered image (which must be an 8-bit colormapped image), then - * converts the colorized image into a form that JME can display. - */ - public static Image createImage (BufferedImage bufimg, Colorization[] zations, float scale, - boolean flip) - { - return createImage(ImageUtil.recolorImage(bufimg, zations), scale, flip); - } - - /** - * Creates a JME-compatible image from the supplied buffered image. - */ - public static Image createImage (BufferedImage bufimg, float scale, boolean flip) - { - // make sure images are square powers of two - int width = (int)(bufimg.getWidth() * scale); - int height = (int)(bufimg.getHeight() * scale); - int tsize = nextPOT(Math.max(width, height)); - - // convert the the image to the format that OpenGL prefers - BufferedImage dispimg = createCompatibleImage( - tsize, tsize, bufimg.getColorModel().hasAlpha()); - - // flip the image to convert into OpenGL's coordinate system - AffineTransform tx = null; - if (flip) { - tx = AffineTransform.getScaleInstance(scale, -scale); - tx.translate((tsize - width) / 2, (height - tsize) / 2 - bufimg.getHeight()); - } - - // "convert" the image by rendering the old into the new - Graphics2D gfx = (Graphics2D)dispimg.getGraphics(); - gfx.drawImage(bufimg, tx, null); - gfx.dispose(); - - // now extract the image data into a JME image - return convertImage(dispimg); - } - - /** - * Creates a buffered image in a format compatible with LWJGL with the specified dimensions. - * - * @param transparent if true, the image will be four bytes per pixel (RGBA), if false it will - * be three (and have no alpha channel). - */ - public static BufferedImage createCompatibleImage (int width, int height, boolean transparent) - { - if (transparent) { - return new BufferedImage(GL_ALPHA_MODEL, Raster.createInterleavedRaster( - DataBuffer.TYPE_BYTE, width, height, 4, null), - false, null); - } else { - return new BufferedImage(GL_OPAQUE_MODEL, Raster.createInterleavedRaster( - DataBuffer.TYPE_BYTE, width, height, 3, null), - false, null); - } - } - - /** - * Converts an image that was created with {@link #createCompatibleImage} into a JME {@link - * Image}. The data is assumed to have already been "flipped". - */ - public static Image convertImage (BufferedImage bufimg) - { - Image image = new Image(); - image.setType(bufimg.getColorModel().hasAlpha() ? Image.RGBA8888 : Image.RGB888); - image.setWidth(bufimg.getWidth()); - image.setHeight(bufimg.getHeight()); - image.setData(convertImage(bufimg, null)); - return image; - } - - /** - * Converts the supplied image (which must have been created with {@link - * #createCompatibleImage}) into a {@link ByteBuffer} that can be passed to {@link - * Image#setData}. - * - * @param target the results of a previous call to {@link #convertImage} that will be - * overwritten or null if a new buffer should be allocated. Of course a reused buffer must be - * used with the same image or one with the exact same configuration. - */ - public static ByteBuffer convertImage (BufferedImage image, ByteBuffer target) - { - DataBufferByte dbuf = (DataBufferByte)image.getRaster().getDataBuffer(); - byte[] data = dbuf.getData(); - if (target == null) { - target = ByteBuffer.allocateDirect(data.length); - target.order(ByteOrder.nativeOrder()); - } - target.clear(); - target.put(data); - target.flip(); - return target; - } - - /** - * Creates an image cache that will obtain its image data from the supplied resource manager. - */ - public ImageCache (ResourceManager rsrcmgr) - { - _rsrcmgr = rsrcmgr; - } - - /** - * See {@link #getImage(String,boolean)}. - */ - public Image getImage (String rsrcPath) - { - return getImage(rsrcPath, 1f, true); - } - - /** - * See {@link #getImage(String,float,boolean)}. - */ - public Image getImage (String rsrcPath, float scale) - { - return getImage(rsrcPath, scale, true); - } - - /** - * Loads up an image from the cache if possible or from the resource manager otherwise, in - * which case it is prepared for use by JME and OpenGL. Note: these images are cached - * separately from the {@link BImage} and {@link BufferedImage} caches. - * - * @param flip whether or not to convert the image from normal computer coordinates into OpenGL - * coordinates when loading. Note: this information is not cached, an image must - * always be requested as flipped or not flipped. - */ - public Image getImage (String rsrcPath, boolean flip) - { - return getImage(rsrcPath, 1f, flip); - } - - /** - * Loads up an image from the cache if possible or from the resource manager otherwise, in - * which case it is prepared for use by JME and OpenGL. Note: these images are cached - * separately from the {@link BImage} and {@link BufferedImage} caches. - * - * @param flip whether or not to convert the image from normal computer coordinates into OpenGL - * coordinates when loading. Note: this information is not cached, an image must - * always be requested as flipped or not flipped. - * @param scale a scale factor to apply to the image. As with the flip setting, the scale - * factor is not cached. - */ - public Image getImage (String rsrcPath, float scale, boolean flip) - { - // first check the cache - WeakReference iref = _imgcache.get(rsrcPath); - Image image; - if (iref != null && (image = iref.get()) != null) { - return image; - } - - // load the image data from the resource manager - BufferedImage bufimg; - try { - bufimg = _rsrcmgr.getImageResource(rsrcPath); - } catch (Throwable t) { - log.warning("Unable to load image resource " + - "[path=" + rsrcPath + "].", t); - // cope; return an error image of abitrary size - bufimg = ImageUtil.createErrorImage(64, 64); - } - - // create and cache a new JME image with the appropriate data - image = createImage(bufimg, scale, flip); - _imgcache.put(rsrcPath, new WeakReference(image)); - return image; - } - - /** - * Loads up an image from the cache if possible or from the resource manager otherwise, in - * which case it is prepared for use by BUI. Note: these images are cached separately - * from the {@link Image} and {@link BufferedImage} caches. - */ - public BImage getBImage (String rsrcPath) - { - return getBImage(rsrcPath, 1f, false); - } - - /** - * Loads up an image from the cache if possible or from the resource manager otherwise, in - * which case it is prepared for use by BUI. Note: these images are cached separately - * from the {@link Image} and {@link BufferedImage} caches. - * - * @param scale If none-unity the image will be scaled by the supplied factor before being - * converted into a {@link BImage}. - * @param returnNull If set to true, will return a null instead of generating an error image on - * failure - */ - public BImage getBImage (String rsrcPath, float scale, boolean returnNull) - { - // first check the cache - String key = rsrcPath + ":" + scale; - WeakReference iref = _buicache.get(key); - BImage image; - if (iref != null && (image = iref.get()) != null) { - return image; - } - - // load the image data from the resource manager - BufferedImage bufimg; - try { - bufimg = _rsrcmgr.getImageResource(rsrcPath); - } catch (Throwable t) { - if (returnNull) { - return null; - } - log.warning("Unable to load image resource [path=" + rsrcPath + "].", t); - // cope; return an error image of abitrary size - bufimg = ImageUtil.createErrorImage(64, 64); - } - - // create and cache a new BUI image with the appropriate (scaled if necessary) data - image = new BImage(scale == 1f ? bufimg : - bufimg.getScaledInstance(Math.round(bufimg.getWidth()*scale), - Math.round(bufimg.getHeight()*scale), - BufferedImage.SCALE_SMOOTH), true); - _buicache.put(key, new WeakReference(image)); - return image; - } - - /** - * Loads up a silhouette image (in which all non-transparent pixels are set to black) from the - * cache if possible or from the resource manager otherwise, in which case it is prepared for - * use by BUI. - */ - public BImage getSilhouetteBImage (String rsrcPath, boolean returnNull) - { - // first check the cache - String key = "silhouette:" + rsrcPath; - WeakReference iref = _buicache.get(key); - BImage image; - if (iref != null && (image = iref.get()) != null) { - return image; - } - - // load the image data from the resource manager - BufferedImage bufimg, silimg; - try { - bufimg = _rsrcmgr.getImageResource(rsrcPath); - - // now turn it into a silhouette - silimg = new BufferedImage(bufimg.getWidth(), bufimg.getHeight(), - BufferedImage.TYPE_4BYTE_ABGR); - new BandCombineOp(NON_ALPHA_TO_BROWN, null).filter( - bufimg.getRaster(), silimg.getRaster()); - - } catch (Throwable t) { - if (returnNull) { - return null; - } - log.warning("Unable to load image resource [path=" + rsrcPath + "].", t); - // cope; return an error image of abitrary size - silimg = ImageUtil.createErrorImage(64, 64); - } - - // create and cache a new BUI image with the appropriate data - image = new BImage(silimg, true); - _buicache.put(key, new WeakReference(image)); - return image; - } - - /** - * Colorizes the image with supplied path (which must be an 8-bit colormapped image), then - * converts the colorized image into a form that JME can display. - */ - public BImage createColorizedBImage (String path, Colorization[] zations, boolean flip) - { - return new BImage(ImageUtil.recolorImage(getBufferedImage(path), zations), flip); - } - - /** - * Loads up a buffered image from the cache if possible or from the resource manager - * otherwise. Note: these images are cached separately from the {@link Image} and - * {@link BImage} caches. - */ - public BufferedImage getBufferedImage (String rsrcPath) - { - // first check the cache - WeakReference iref = _bufcache.get(rsrcPath); - BufferedImage image; - if (iref != null && (image = iref.get()) != null) { - return image; - } - - // load the image data from the resource manager - try { - image = _rsrcmgr.getImageResource(rsrcPath); - } catch (Throwable t) { - log.warning("Unable to load image resource [path=" + rsrcPath + "].", t); - // cope; return an error image of abitrary size - image = ImageUtil.createErrorImage(64, 64); - } - - _bufcache.put(rsrcPath, new WeakReference(image)); - return image; - } - - /** Rounds the supplied value up to a power of two. */ - protected static int nextPOT (int value) - { - return (Integer.bitCount(value) > 1) ? (Integer.highestOneBit(value) << 1) : value; - } - - /** Provides access to our image data. */ - protected ResourceManager _rsrcmgr; - - /** A cache of {@link Image} instances. */ - protected HashMap> _imgcache = Maps.newHashMap(); - - /** A cache of {@link BImage} instances. */ - protected HashMap> _buicache = Maps.newHashMap(); - - /** A cache of {@link BufferedImage} instances. */ - protected HashMap> _bufcache = Maps.newHashMap(); - - /** Used to create buffered images in a format compatible with OpenGL. */ - protected static ComponentColorModel GL_ALPHA_MODEL = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 8 }, - true, false, ComponentColorModel.TRANSLUCENT, DataBuffer.TYPE_BYTE); - - /** Used to create buffered images in a format compatible with OpenGL. */ - protected static ComponentColorModel GL_OPAQUE_MODEL = new ComponentColorModel( - ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[] { 8, 8, 8, 0 }, - false, false, ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - - /** An operation that converts all channels except alpha to brown. */ - protected static final float[][] NON_ALPHA_TO_BROWN = { - { 0, 0, 0, 0x66/255f }, - { 0, 0, 0, 0x57/255f }, - { 0, 0, 0, 0x34/255f }, - { 0, 0, 0, 0.5f } - }; -} diff --git a/src/java/com/threerings/jme/util/JmeUtil.java b/src/java/com/threerings/jme/util/JmeUtil.java deleted file mode 100644 index cb2102a3..00000000 --- a/src/java/com/threerings/jme/util/JmeUtil.java +++ /dev/null @@ -1,186 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -import com.jme.math.Matrix4f; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.scene.Controller; - -import com.samskivert.util.StringUtil; - -import static com.threerings.jme.Log.log; - -/** - * Some static classes and methods of general utility to applications using JME. - */ -public class JmeUtil -{ - /** - * Represents the current position and direction in an animation composed of a fixed number of - * discrete frames using one of the repeat types defined in {@link Controller}. - */ - public static class FrameState - { - /** The index of the current frame. */ - public int idx; - - /** The current direction of animation. */ - public int dir = +1; - - /** The fractional progress towards the next frame. */ - public float accum; - - /** - * Resets the state back to the beginning. - */ - public void reset () - { - set(0, +1, 0f); - } - - /** - * Sets the entire frame state. - */ - public void set (int idx, int dir, float accum) - { - this.idx = idx; - this.dir = dir; - this.accum = accum; - } - - /** - * Updates the frame state after some amount of time has elapsed. - */ - public void update (float elapsed, float frameRate, int frameCount, int repeatType) - { - float frames = elapsed * frameRate; - for (accum += frames; accum >= 1f; accum -= 1f) { - advance(frameCount, repeatType); - } - } - - /** - * Advances the position by one frame. - */ - public void advance (int frameCount, int repeatType) - { - if ((idx += dir) >= frameCount) { - if (repeatType == Controller.RT_CLAMP) { - idx = frameCount - 1; - dir = 0; - } else if (repeatType == Controller.RT_WRAP) { - idx = 0; - } else { // repeatType == Controller.RT_CYCLE - idx = frameCount - 2; - dir = -1; - } - } else if (idx < 0) { - idx = 1; - dir = +1; - } - } - } - - /** - * Sets a matrix to the transform defined by the given translation, - * rotation, and scale values. - */ - public static Matrix4f setTransform ( - Vector3f translation, Quaternion rotation, Vector3f scale, Matrix4f result) - { - result.setRotationQuaternion(rotation); - result.setTranslation(translation); - - result.m00 *= scale.x; - result.m01 *= scale.y; - result.m02 *= scale.z; - - result.m10 *= scale.x; - result.m11 *= scale.y; - result.m12 *= scale.z; - - result.m20 *= scale.x; - result.m21 *= scale.y; - result.m22 *= scale.z; - - return result; - } - - /** - * Attempts to parse a string containing an axis: either "x", "y", or "z", or three - * comma-delimited values representing an axis vector. The value returned may be one of - * JME's "constant" vectors (for example, {@link Vector3f#UNIT_X}), so don't modify it. - */ - public static Vector3f parseAxis (String axis) - { - if ("x".equalsIgnoreCase(axis)) { - return Vector3f.UNIT_X; - } else if ("y".equalsIgnoreCase(axis)) { - return Vector3f.UNIT_Y; - } else if ("z".equalsIgnoreCase(axis)) { - return Vector3f.UNIT_Z; - } else { - Vector3f vector = parseVector3f(axis); - if (vector != null) { - vector.normalizeLocal(); - } - return vector; - } - } - - /** - * Attempts to parse a string containing three comma-delimited values and return a - * {@link Vector3f}. - */ - public static Vector3f parseVector3f (String vector) - { - if (vector != null) { - float[] vals = StringUtil.parseFloatArray(vector); - if (vals != null && vals.length == 3) { - return new Vector3f(vals[0], vals[1], vals[2]); - } else { - log.warning("Invalid vector [vector=" + vector + "]."); - } - } - return null; - } - - /** - * Attempts to parse a string describing one of the repeat types defined in {@link Controller}: - * "clamp", "cycle", or "wrap". Will return the specified default if the type is - * null or invalid. - */ - public static int parseRepeatType (String type, int defaultType) - { - if ("clamp".equals(type)) { - return Controller.RT_CLAMP; - } else if ("cycle".equals(type)) { - return Controller.RT_CYCLE; - } else if ("wrap".equals(type)) { - return Controller.RT_WRAP; - } else if (type != null) { - log.warning("Invalid repeat type [type=" + type + "]."); - } - return defaultType; - } -} diff --git a/src/java/com/threerings/jme/util/LinearTimeFunction.java b/src/java/com/threerings/jme/util/LinearTimeFunction.java deleted file mode 100644 index 41a42345..00000000 --- a/src/java/com/threerings/jme/util/LinearTimeFunction.java +++ /dev/null @@ -1,42 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -/** - * Varies a value linearly with time. - */ -public class LinearTimeFunction extends TimeFunction -{ - public LinearTimeFunction (float start, float end, float duration) - { - super(start, end, duration); - _range = (end - start); - } - - // documentation inherited - protected float computeValue () - { - return (_elapsed * _range / _duration) + _start; - } - - protected float _range; -} diff --git a/src/java/com/threerings/jme/util/ShaderCache.java b/src/java/com/threerings/jme/util/ShaderCache.java deleted file mode 100644 index 6f223e06..00000000 --- a/src/java/com/threerings/jme/util/ShaderCache.java +++ /dev/null @@ -1,263 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; - -import java.nio.ByteBuffer; -import java.nio.IntBuffer; -import java.nio.charset.Charset; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; - -import org.lwjgl.opengl.ARBShaderObjects; - -import com.google.common.base.Objects; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; - -import com.jme.scene.state.GLSLShaderObjectsState; -import com.jme.system.DisplaySystem; -import com.jme.util.ShaderAttribute; -import com.jme.util.ShaderUniform; -import com.jme.util.geom.BufferUtils; - -import com.samskivert.util.ArrayUtil; - -import com.threerings.resource.ResourceManager; - -import static com.threerings.jme.Log.*; - -/** - * Caches shaders under their names and preprocessor definitions, ensuring that identical shaders - * are only compiled once. - */ -public class ShaderCache -{ - /** - * Create a shader cache that will obtain shader source from the supplied resource manager. - */ - public ShaderCache (ResourceManager rsrcmgr) - { - _rsrcmgr = rsrcmgr; - } - - /** - * Creates a new shader state with the supplied vertex shader, fragment shader, - * and preprocessor definitions. If a program with the given parameters has already been - * compiled, the state will use the program id of the existing shader. - * - * @return the newly created state, or null if there was an error and the - * program could not be compiled. - */ - public GLSLShaderObjectsState createState (String vert, String frag, String... defs) - { - GLSLShaderObjectsState sstate = - DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState(); - return (configureState(sstate, vert, frag, defs) ? sstate : null); - } - - /** - * (Re)configures an existing shader state with the supplied parameters. - * - * @return true if the shader was successfully configured, false if the shader could not - * be compiled. - */ - public boolean configureState ( - GLSLShaderObjectsState sstate, String vert, String frag, String... defs) - { - return configureState(sstate, vert, frag, defs, null); - } - - /** - * (Re)configures an existing shader state with the supplied parameters. - * - * @param ddefs an optional array of derived preprocessor definitions that, unlike the - * principal definitions, need not be compared when differentiating between cached shaders. - * @return true if the shader was successfully configured, false if the shader could not - * be compiled. - */ - public boolean configureState ( - GLSLShaderObjectsState sstate, String vert, String frag, String[] defs, String[] ddefs) - { - ShaderKey key = new ShaderKey(vert, frag, defs); - Integer programId = _programIds.get(key); - if (programId == null) { - if (ddefs != null) { - defs = ArrayUtil.concatenate(defs, ddefs); - } - GLSLShaderObjectsState pstate = loadShaders(vert, frag, defs); - if (pstate == null) { - return false; - } - _programIds.put(key, programId = pstate.getProgramID()); - } - if (sstate.getProgramID() == programId) { - return true; - } - sstate.setProgramID(programId); - for (ShaderAttribute attrib : sstate.attribs.values()) { - attrib.attributeID = -1; - } - for (ShaderUniform uniform : sstate.uniforms.values()) { - uniform.uniformID = -1; - } - sstate.setNeedsRefresh(true); - return true; - } - - /** - * Checks whether the specified shader is already loaded. This is useful in order to avoid - * generating complex derived definitions when they won't be needed. - */ - public boolean isLoaded (String vert, String frag, String... defs) - { - return _programIds.containsKey(new ShaderKey(vert, frag, defs)); - } - - /** - * Loads the specified shaders (prepending the supplied preprocessor definitions) - * and returns a GLSL shader state. One of the supplied names may be null - * in order to use the fixed-function pipeline for that part. The method returns - * null if the shaders fail to compile (JME will log an error). - * - * @param defs a number of preprocessor definitions to be #defined in both shaders - * (e.g., "ENABLE_FOG", "NUM_LIGHTS 2"). - */ - protected GLSLShaderObjectsState loadShaders (String vert, String frag, String[] defs) - { - GLSLShaderObjectsState sstate = - DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState(); - sstate.load( - (vert == null) ? null : getSource(vert, defs), - (frag == null) ? null : getSource(frag, defs)); - - // check its link status - IntBuffer ibuf = BufferUtils.createIntBuffer(1); - ARBShaderObjects.glGetObjectParameterARB(sstate.getProgramID(), - ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB, ibuf); - if (ibuf.get(0) == 0) { - return null; // failed to link - } - - // check the info log - ARBShaderObjects.glGetObjectParameterARB(sstate.getProgramID(), - ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB, ibuf); - ByteBuffer bbuf = BufferUtils.createByteBuffer(ibuf.get(0)); - ARBShaderObjects.glGetInfoLogARB(sstate.getProgramID(), ibuf, bbuf); - String log = Charset.forName("US-ASCII").decode(bbuf).toString(); - - // if it runs in software mode, that counts as a failure - return (log.indexOf("software") == -1) ? sstate : null; - } - - /** - * Retrieves the source code to a shader as a single {@link String}, either by fetching it from - * the cache or loading it from the resource manager (and caching it). Returns - * null (after logging a warning) if the shader couldn't be found. - * - * @param defs an array of definitions to prepend to the result. - */ - protected String getSource (String shader, String[] defs) - { - // fetch the shader source - String source = _sources.get(shader); - if (source == null) { - StringBuilder buf = new StringBuilder(); - try { - BufferedReader reader = new BufferedReader( - new InputStreamReader(_rsrcmgr.getResource(shader))); - String line; - while ((line = reader.readLine()) != null) { - buf.append(line).append('\n'); - } - } catch (IOException e) { - log.warning("Failed to load shader [name=" + shader + ", error=" + e + "]."); - return null; - } - _sources.put(shader, (source = buf.toString())); - } - - // prepend the definitions (the version directive comes before anything else) - StringBuilder buf = new StringBuilder(); - buf.append("#version 110\n"); - for (String def : defs) { - buf.append("#define ").append(def).append('\n'); - } - buf.append(source); - return buf.toString(); - } - - /** Identifies a cached shader. */ - protected static class ShaderKey - { - /** The name of the vertex shader (or null for none). */ - public String vert; - - /** The name of the fragment shader (or null for none). */ - public String frag; - - /** The set of preprocessor definitions. */ - public HashSet defs = Sets.newHashSet(); - - public ShaderKey (String vert, String frag, String[] defs) - { - this.vert = vert; - this.frag = frag; - Collections.addAll(this.defs, defs); - } - - @Override - public int hashCode () - { - return (vert == null ? 0 : vert.hashCode()) + (frag == null ? 0 : frag.hashCode()) + - defs.hashCode(); - } - - @Override - public boolean equals (Object obj) - { - ShaderKey okey = (ShaderKey)obj; - return Objects.equal(vert, okey.vert) && Objects.equal(frag, okey.frag) && - defs.equals(okey.defs); - } - - @Override - public String toString () - { - return "[vert=" + vert + ", frag=" + frag + ", defs=" + defs + "]"; - } - } - - /** Provides access to shader source. */ - protected ResourceManager _rsrcmgr; - - /** Maps shader names to source strings. */ - protected HashMap _sources = Maps.newHashMap(); - - /** Maps shader keys to linked program ids. */ - protected HashMap _programIds = Maps.newHashMap(); -} diff --git a/src/java/com/threerings/jme/util/ShaderConfig.java b/src/java/com/threerings/jme/util/ShaderConfig.java deleted file mode 100644 index 362fa4f1..00000000 --- a/src/java/com/threerings/jme/util/ShaderConfig.java +++ /dev/null @@ -1,394 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -import java.util.ArrayList; - -import com.google.common.collect.Lists; - -import com.jme.image.Texture; -import com.jme.light.Light; -import com.jme.scene.state.FogState; -import com.jme.scene.state.GLSLShaderObjectsState; -import com.jme.scene.state.LightState; -import com.jme.scene.state.RenderState; -import com.jme.scene.state.TextureState; -import com.jme.system.DisplaySystem; -import com.jme.util.ShaderUniform; - -import com.samskivert.util.StringUtil; - -/** - * Tracks the configuration of a shader, which depends on (among other things) a set of - * {@link RenderState}s. When the state set changes, the shader must be reconfigured - * (recompiled or refetched from the {@link ShaderCache}). - */ -public abstract class ShaderConfig - implements Cloneable -{ - public ShaderConfig (ShaderCache scache) - { - _scache = scache; - _state = DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState(); - } - - /** - * Returns a reference to the render state controlled by this configuration. - */ - public GLSLShaderObjectsState getState () - { - return _state; - } - - /** - * Updates the configuration according to the provided state set. If the configuration has - * changed, the shader will be recompiled or refetched from the cache in order to reflect the - * new configuration. - * - * @return true if all went all, false if the shader could not be compiled. - */ - public boolean update (RenderState[] states) - { - // update the configurations to determine if we must reconfigure - if (!updateConfigs(states) && _state.getProgramID() > 0) { - return true; - } - - // reconfigure the shader state, generating the derived definitions only if the - // required configuration isn't in the cache - String vert = getVertexShader(), frag = getFragmentShader(); - ArrayList defs = Lists.newArrayList(); - getDefinitions(defs); - String[] darray = defs.toArray(new String[defs.size()]), ddarray = null; - if (!_scache.isLoaded(vert, frag, darray)) { - ArrayList ddefs = Lists.newArrayList(); - getDerivedDefinitions(ddefs); - ddarray = ddefs.toArray(new String[ddefs.size()]); - } - return _scache.configureState(_state, vert, frag, darray, ddarray); - } - - @Override - public ShaderConfig clone () - { - try { - ShaderConfig other = (ShaderConfig)super.clone(); - other._state = - DisplaySystem.getDisplaySystem().getRenderer().createGLSLShaderObjectsState(); - other._state.setProgramID(_state.getProgramID()); - other._state.attribs = _state.attribs; - for (ShaderUniform uniform : _state.uniforms.values()) { - other._state.uniforms.put(uniform.name, (ShaderUniform)uniform.clone()); - } - if (_lights != null) { - other._lights = _lights.clone(); - for (int ii = 0; ii < _lights.length; ii++) { - other._lights[ii] = _lights[ii].clone(); - } - } - if (_textures != null) { - other._textures = _textures.clone(); - for (int ii = 0; ii < _textures.length; ii++) { - other._textures[ii] = _textures[ii].clone(); - } - } - return other; - - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } - - /** - * Updates the component configurations according to the supplied state set, returning - * true if they have changed and the shader must be reconfigured. - */ - protected boolean updateConfigs (RenderState[] states) - { - // this is one place where we don't want short-circuit evaluation - boolean lchanged = updateLightConfigs((LightState)states[RenderState.RS_LIGHT]); - boolean tchanged = updateTextureConfigs((TextureState)states[RenderState.RS_TEXTURE]); - boolean fchanged = updateFogConfig((FogState)states[RenderState.RS_FOG]); - return lchanged || tchanged || fchanged; - } - - /** - * Updates the light configurations, returning true if they have changed. - */ - protected boolean updateLightConfigs (LightState lstate) - { - if (lstate == null || !lstate.isEnabled()) { - LightConfig[] olights = _lights; - _lights = null; - return (olights != null); - } - int lcount = Math.min(lstate.getQuantity(), MAX_LIGHTS); - if (_lights == null || _lights.length != lcount) { - _lights = new LightConfig[lcount]; - for (int ii = 0; ii < lcount; ii++) { - _lights[ii] = new LightConfig(); - _lights[ii].update(lstate.get(ii)); - } - return true; - } - boolean changed = false; - for (int ii = 0; ii < lcount; ii++) { - changed |= _lights[ii].update(lstate.get(ii)); - } - return changed; - } - - /** - * Updates the texture configurations, returning true if they have changed. - */ - protected boolean updateTextureConfigs (TextureState tstate) - { - if (tstate == null || !tstate.isEnabled()) { - TextureConfig[] otextures = _textures; - _textures = null; - return (otextures != null); - } - int tcount = tstate.getNumberOfSetTextures(); - if (_textures == null || _textures.length != tcount) { - _textures = new TextureConfig[tcount]; - for (int ii = 0; ii < tcount; ii++) { - _textures[ii] = new TextureConfig(); - _textures[ii].update(tstate.getTexture(ii)); - } - return true; - } - boolean changed = false; - for (int ii = 0; ii < tcount; ii++) { - changed |= _textures[ii].update(tstate.getTexture(ii)); - } - return changed; - } - - /** - * Updates the fog configuration, returning true if it has changed. - */ - protected boolean updateFogConfig (FogState fstate) - { - int ofunc = _fogDensityFunc; - _fogDensityFunc = (fstate == null || !fstate.isEnabled()) ? - -1 : fstate.getDensityFunction(); - return (ofunc != _fogDensityFunc); - } - - /** - * Returns the resource name of the vertex shader (or null for none). - */ - protected String getVertexShader () - { - return null; - } - - /** - * Returns the resource name of the fragment shader (or null for none). - */ - protected String getFragmentShader () - { - return null; - } - - /** - * Adds the preprocessor definitions that this configuration requires for its shader to the - * supplied list. - */ - protected void getDefinitions (ArrayList defs) - { - // the distinguishing definitions are just keys - if (_lights != null) { - defs.add("LIGHTS " + StringUtil.join(_lights, "/")); - } - if (_textures != null) { - defs.add("TEXTURES " + StringUtil.join(_textures, "/")); - } - if (_fogDensityFunc != -1) { - defs.add("FOG " + _fogDensityFunc); - } - } - - /** - * Adds the derived preprocessor definitions that this configuration requires to the supplied - * list. The derived definitions are not used to distinguish between cached shaders. - */ - protected void getDerivedDefinitions (ArrayList ddefs) - { - // add the def that sets the front color based on the light types - StringBuilder buf = new StringBuilder("SET_FRONT_COLOR "); - if (_lights != null) { - // start with the "scene color," which combines scene ambient, emissivity, etc. - buf.append("vec3 frontColor = gl_FrontLightModelProduct.sceneColor.rgb; "); - - // add snippets for each of the lights - for (int ii = 0; ii < _lights.length; ii++) { - String snippet = getLightSnippet(_lights[ii].type); - buf.append(snippet.replace("%", Integer.toString(ii))); - } - - // the alpha value comes from the diffuse color in the material - buf.append("gl_FrontColor = vec4(frontColor, gl_FrontMaterial.diffuse.a);"); - } else { - buf.append("gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);"); - } - ddefs.add(buf.toString()); - - // add the def that sets the texture coordinates based on the env map modes - buf = new StringBuilder("SET_TEX_COORDS"); - if (_textures != null) { - for (int ii = 0; ii < _textures.length; ii++) { - TextureConfig texture = _textures[ii]; - if (texture.envMapMode == -1) { - continue; - } - buf.append(" gl_TexCoord[" + ii + "] = "); - if (texture.envMapMode == Texture.EM_SPHERE) { - buf.append("vec4(eyeNormal.xy * 0.5 + vec2(0.5, 0.5), 0.0, 1.0);"); - } else { - buf.append("gl_MultiTexCoord" + ii + ";"); - } - } - } - ddefs.add(buf.toString()); - - // add the definition that sets the fog alpha based on the density function - buf = new StringBuilder("SET_FOG_ALPHA"); - if (_fogDensityFunc == FogState.DF_EXP) { - buf.append(" fogAlpha = exp(gl_Fog.density * eyeVertex.z);"); - } - ddefs.add(buf.toString()); - } - - /** - * Returns a code snippet that adds the influence of a light of the specified type (after - * replacing '%' with the light index). - */ - protected String getLightSnippet (int type) - { - if (type == Light.LT_POINT) { - return POINT_LIGHT_SNIPPET; - } else if (type == Light.LT_DIRECTIONAL) { - return DIRECTIONAL_LIGHT_SNIPPET; - } else { - return ""; - } - } - - /** The configuration of a single light in a {@link LightState}. */ - protected static class LightConfig - implements Cloneable - { - /** The type of light (see {@link Light#getType}). */ - public int type = -1; - - public boolean update (Light light) - { - int otype = type; - type = (light == null) ? -1 : light.getType(); - return (otype != type); - } - - @Override - public LightConfig clone () - { - try { - return (LightConfig) super.clone(); - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } - - @Override - public String toString () - { - return Integer.toString(type); - } - } - - /** The configuration of a single texture in a {@link TextureState}. */ - protected static class TextureConfig - implements Cloneable - { - /** The environment map mode (see {@link Texture#getEnvironmentalMapMode}). */ - public int envMapMode = -1; - - public boolean update (Texture texture) - { - int omode = envMapMode; - envMapMode = (texture == null) ? -1 : texture.getEnvironmentalMapMode(); - return (omode != envMapMode); - } - - @Override - public TextureConfig clone () - { - try { - return (TextureConfig) super.clone(); - } catch (CloneNotSupportedException e) { - throw new AssertionError(e); - } - } - - @Override - public String toString () - { - return Integer.toString(envMapMode); - } - } - - /** The cache used to reconfigure shaders. */ - protected ShaderCache _scache; - - /** The state object to reconfigure. */ - protected GLSLShaderObjectsState _state; - - /** The current light configurations (or null if lighting is disabled). */ - protected LightConfig[] _lights; - - /** The current texture configurations (or null if texturing is disabled). */ - protected TextureConfig[] _textures; - - /** The density function of the fog in the scene (or -1 for none). */ - protected int _fogDensityFunc = -1; - - /** To keep things sane, let's limit the total number of lights (OpenGL allows at least - * eight). */ - protected static final int MAX_LIGHTS = 4; - - /** A code snippet for adding the influence of a point light. */ - protected static final String POINT_LIGHT_SNIPPET = - "vec3 lvec% = gl_LightSource[%].position.xyz - eyeVertex; " + - "float ldist% = length(lvec%); " + - "frontColor += (gl_FrontLightProduct[%].ambient.rgb + " + - "gl_FrontLightProduct[%].diffuse.rgb * " + - "max(dot(eyeNormal, normalize(lvec%)), 0.0)) / " + - "(gl_LightSource[%].constantAttenuation + " + - "ldist% * gl_LightSource[%].linearAttenuation + " + - "ldist% * ldist% * gl_LightSource[%].quadraticAttenuation);"; - - /** A code snippet for adding the influence of a directional light. */ - protected static final String DIRECTIONAL_LIGHT_SNIPPET = - "frontColor += gl_FrontLightProduct[%].ambient.rgb + " + - "gl_FrontLightProduct[%].diffuse.rgb * " + - "max(dot(eyeNormal, gl_LightSource[%].position.xyz), 0.0);"; -} diff --git a/src/java/com/threerings/jme/util/SpatialVisitor.java b/src/java/com/threerings/jme/util/SpatialVisitor.java deleted file mode 100644 index 932060b9..00000000 --- a/src/java/com/threerings/jme/util/SpatialVisitor.java +++ /dev/null @@ -1,63 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -import com.jme.scene.Node; -import com.jme.scene.Spatial; - -/** - * Performs a depth-first scene graph traversal looking for {@link Spatial}s - * of a given class. - */ -public abstract class SpatialVisitor -{ - public SpatialVisitor (Class type) - { - _type = type; - } - - /** - * Traverses the given node in depth-first order, calling {@link #visit} - * for each {@link Spatial} of the configured class encountered. - */ - public void traverse (Spatial spatial) - { - if (_type.isInstance(spatial)) { - visit(_type.cast(spatial)); - } - if (spatial instanceof Node) { - Node node = (Node)spatial; - for (int ii = 0, nn = node.getQuantity(); ii < nn; ii++) { - traverse(node.getChild(ii)); - } - } - } - - /** - * Called once for each {@link Spatial} of the configured class in the - * scene graph. - */ - protected abstract void visit (T child); - - /** The type of spatial of interest. */ - protected Class _type; -} diff --git a/src/java/com/threerings/jme/util/TimeFunction.java b/src/java/com/threerings/jme/util/TimeFunction.java deleted file mode 100644 index 31eac71f..00000000 --- a/src/java/com/threerings/jme/util/TimeFunction.java +++ /dev/null @@ -1,99 +0,0 @@ -// -// $Id$ -// -// Nenya library - tools for developing networked games -// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved -// http://code.google.com/p/nenya/ -// -// 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.util; - -/** - * Used to vary a value over time where time is provided at discrete increments - * (on the frame tick) and the value is computed appropriately. This can be - * used for fades and other effects where different functions (linear, ease-in - * ease-out, etc.) should be easy to plug in. - */ -public abstract class TimeFunction -{ - /** - * Every time function varies a value from some starting value to some - * ending value over some duration. The way in which it varies - * (linearly, for example) is up to the derived class. - * - * @param start the starting value. - * @param end the ending value. - * @param duration the duration in seconds. - */ - public TimeFunction (float start, float end, float duration) - { - _start = start; - _end = end; - _duration = duration; - } - - /** - * Returns the current value given the supplied elapsed time. The value - * will be bounded to the originally supplied starting and ending values at - * times 0 (and below) and {@link #_duration} (and above) respectively. - * - * @param deltaTime the amount of time that has elapsed since the last call - * to this method. - */ - public float getValue (float deltaTime) - { - _elapsed += deltaTime; - - if (_elapsed <= 0) { - return _start; - } else if (_elapsed >= _duration) { - return _end; - } else { - return computeValue(); - } - } - - /** - * Returns true if this function has proceeded the full length of its - * duration. This should be called after a call to {@link #getValue} has - * been made to update our internal elapsed time. - */ - public boolean isComplete () - { - return _elapsed >= _duration; - } - - /** Generates a string representation of this instance. */ - public String toString () - { - return _start + " to " + _end + ", " + _elapsed + " of " + _duration; - } - - /** - * This must be implemented by our derived class to compute our value given - * the currently stored {@link #_elapsed} time. - */ - protected abstract float computeValue (); - - /** Our starting and ending values. */ - protected float _start, _end; - - /** The number of milliseconds over which we vary our value. */ - protected float _duration; - - /** The number of seconds that have elapsed since we started. */ - protected float _elapsed; -} diff --git a/tests/src/java/com/threerings/jme/JmeCanvasTestApp.java b/tests/src/java/com/threerings/jme/JmeCanvasTestApp.java deleted file mode 100644 index f7d54ca3..00000000 --- a/tests/src/java/com/threerings/jme/JmeCanvasTestApp.java +++ /dev/null @@ -1,62 +0,0 @@ -// -// $Id$ - -package com.threerings.jme; - -import java.awt.BorderLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import javax.swing.JButton; -import javax.swing.JFrame; - -import com.jme.bounding.BoundingBox; -import com.jme.math.Vector3f; -import com.jme.scene.shape.Box; - -/** - * Tests the JME/AWT integration bits. - */ -public class JmeCanvasTestApp extends JmeCanvasApp -{ - public static void main (String[] args) - { - final JmeCanvasTestApp app = new JmeCanvasTestApp(); - JFrame frame = new JFrame("JmeCanvasTest"); - frame.getContentPane().add(app.getCanvas(), BorderLayout.CENTER); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - frame.setSize(800, 600); - frame.setVisible(true); - - JButton button = new JButton("Create box"); - frame.getContentPane().add(button, BorderLayout.SOUTH); - button.addActionListener(new ActionListener() { - public void actionPerformed (ActionEvent event) { - app.addBox(); - } - }); - app.run(); - } - - public void addBox () - { - Vector3f max = new Vector3f(5, 5, 5); - Vector3f min = new Vector3f(-5, -5, -5); - - Box box = new Box("Box", min, max); - box.setModelBound(new BoundingBox()); - box.updateModelBound(); - box.setLocalTranslation(new Vector3f(0, 0, -10)); - _geom.attachChild(box); - _geom.updateRenderState(); - } - - protected JmeCanvasTestApp () - { - super(800, 600); - } - - protected void initRoot () - { - super.initRoot(); - } -} diff --git a/tests/src/java/com/threerings/jme/client/JabberApp.java b/tests/src/java/com/threerings/jme/client/JabberApp.java deleted file mode 100644 index 92e165d8..00000000 --- a/tests/src/java/com/threerings/jme/client/JabberApp.java +++ /dev/null @@ -1,161 +0,0 @@ -// -// $Id: JabberApp.java 3098 2004-08-27 02:12:55Z mdb $ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2010 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.client; - -import java.io.InputStream; -import java.io.InputStreamReader; - -import com.jme.bounding.BoundingBox; -import com.jme.math.FastMath; -import com.jme.math.Matrix3f; -import com.jme.math.Vector3f; -import com.jme.renderer.ColorRGBA; -import com.jme.scene.shape.Box; -import com.jme.util.LoggingSystem; -import com.jme.util.geom.BufferUtils; -import com.jmex.bui.BStyleSheet; - -import com.threerings.util.Name; - -import com.threerings.presents.client.Client; -import com.threerings.presents.net.UsernamePasswordCreds; - -import com.threerings.jme.JmeApp; - -import static com.threerings.jme.Log.log; - -/** - * The main point of entry for the Jabber client application. It creates - * and initializes the myriad components of the client and sets all the - * proper wheels in motion. - */ -public class JabberApp extends JmeApp -{ - /** Used to configure our user interface. */ - public static BStyleSheet stylesheet; - - // documentation inherited - public boolean init () - { - if (!super.init()) { - return false; - } - - // initialize our client instance - _client = new JabberClient(); - _client.init(this); - - // add some simple geometry for kicks - Vector3f max = new Vector3f(15, 15, 15); - Vector3f min = new Vector3f(5, 5, 5); - - Box t = new Box("Box", min, max); - t.setModelBound(new BoundingBox()); - t.updateModelBound(); - t.setLocalTranslation(new Vector3f(0, 0, -15)); - ColorRGBA[] colors = new ColorRGBA[24]; - for (int i = 0; i < 24; i++) { - colors[i] = ColorRGBA.randomColor(); - } - t.setColorBuffer(0, BufferUtils.createFloatBuffer(colors)); - _root.attachChild(t); - _root.updateRenderState(); - - // set up the camera - Vector3f loc = new Vector3f(0, -200, 200); - _camera.setLocation(loc); - Matrix3f rotm = new Matrix3f(); - rotm.fromAngleAxis(-FastMath.PI/5, _camera.getLeft()); - rotm.mult(_camera.getDirection(), _camera.getDirection()); - rotm.mult(_camera.getUp(), _camera.getUp()); - rotm.mult(_camera.getLeft(), _camera.getLeft()); - _camera.update(); - - // speed up key input - _input.setActionSpeed(100f); - - return true; - } - - public void run (String server, String username, String password) - { - Client client = _client.getContext().getClient(); - - // pass them on to the client - log.info("Using [server=" + server + "."); - client.setServer(server, Client.DEFAULT_SERVER_PORTS); - - // configure the client with some credentials and logon - if (username != null && password != null) { - // create and set our credentials - client.setCredentials( - new UsernamePasswordCreds(new Name(username), password)); - client.logon(); - } - - // now start up the main event loop - run(); - } - - // documentation inherited - public void stop () - { - // log off before we shutdown - Client client = _client.getContext().getClient(); - if (client.isLoggedOn()) { - client.logoff(false); - } - log.info("Stopping."); - super.stop(); - } - - public static void main (String[] args) - { - LoggingSystem.getLogger().setLevel(java.util.logging.Level.OFF); - - String server = "localhost"; - if (args.length > 0) { - server = args[0]; - } - - // load up the default BUI stylesheet - try { - InputStream stin = JabberApp.class.getClassLoader(). - getResourceAsStream("rsrc/style.bss"); - stylesheet = new BStyleSheet( - new InputStreamReader(stin), - new BStyleSheet.DefaultResourceProvider()); - } catch (Exception e) { - e.printStackTrace(System.err); - System.exit(-1); - } - - String username = (args.length > 1) ? args[1] : null; - String password = (args.length > 2) ? args[2] : null; - - JabberApp app = new JabberApp(); - app.init(); - app.run(server, username, password); - } - - protected JabberClient _client; -} diff --git a/tests/src/java/com/threerings/jme/client/JabberClient.java b/tests/src/java/com/threerings/jme/client/JabberClient.java deleted file mode 100644 index 67052121..00000000 --- a/tests/src/java/com/threerings/jme/client/JabberClient.java +++ /dev/null @@ -1,238 +0,0 @@ -// -// $Id: JabberClient.java 3283 2004-12-22 19:23:00Z ray $ -// -// Narya library - tools for developing networked games -// Copyright (C) 2002-2010 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.client; - -import com.jmex.bui.BRootNode; -import com.jme.input.InputHandler; -import com.jme.renderer.Renderer; -import com.jme.scene.Node; -import com.jme.system.DisplaySystem; - -import com.samskivert.util.Config; -import com.threerings.util.MessageManager; - -import com.threerings.presents.client.Client; -import com.threerings.presents.client.SessionObserver; -import com.threerings.presents.dobj.DObjectManager; - -import com.threerings.crowd.chat.client.ChatDirector; -import com.threerings.crowd.client.LocationDirector; -import com.threerings.crowd.client.OccupantDirector; -import com.threerings.crowd.client.PlaceView; -import com.threerings.crowd.util.CrowdContext; - -import com.threerings.jme.JmeContext; -import com.threerings.jme.camera.CameraHandler; - -/** - * The Jabber client takes care of instantiating all of the proper - * managers and loading up all of the necessary configuration and getting - * the client bootstrapped. It can be extended by games that require an - * extended context implementation. - */ -public class JabberClient - implements SessionObserver -{ - /** - * Initializes a new client and provides it with a frame in which to - * display everything. - */ - public void init (JabberApp app) - { - _app = app; - - // create our context - _ctx = createContextImpl(); - - // create the directors/managers/etc. provided by the context - createContextServices(app); - - // for test purposes, hardcode the server info - _client.setServer("localhost", Client.DEFAULT_SERVER_PORTS); - _client.addClientObserver(this); - } - - /** - * Returns a reference to the context in effect for this client. This - * reference is valid for the lifetime of the application. - */ - public CrowdContext getContext () - { - return _ctx; - } - - // documentation inherited from interface SessionObserver - public void clientWillLogon (Client client) - { - // nada - } - - // documentation inherited from interface SessionObserver - public void clientDidLogon (Client client) - { - // enter the one and only chat room; giant hack warning: we know - // that the place we're headed to is ID 2 because there's only one - // place on the whole server; a normal client would either issue - // an invocation service request at this point or look at - // something in the BootstrapData to figure out what to do - _ctx.getLocationDirector().moveTo(2); - } - - // documentation inherited from interface SessionObserver - public void clientObjectDidChange (Client client) - { - // nada - } - - // documentation inherited from interface SessionObserver - public void clientDidLogoff (Client client) - { - System.exit(0); - } - - /** - * Creates the {@link JabberContext} implementation that will be - * passed around to all of the client code. Derived classes may wish - * to override this and create some extended context implementation. - */ - protected CrowdContext createContextImpl () - { - return new JabberContextImpl(); - } - - /** - * Creates and initializes the various services that are provided by - * the context. Derived classes that provide an extended context - * should override this method and create their own extended - * services. They should be sure to call - * super.createContextServices. - */ - protected void createContextServices (JabberApp app) - { - // create the handles on our various services - _client = new Client(null, app); - - // create our managers and directors - _locdir = new LocationDirector(_ctx); - _occdir = new OccupantDirector(_ctx); - _msgmgr = new MessageManager(MESSAGE_MANAGER_PREFIX); - _chatdir = new ChatDirector(_ctx, null); - } - - /** - * The context implementation. This provides access to all of the - * objects and services that are needed by the operating client. - */ - protected class JabberContextImpl implements CrowdContext, JmeContext - { - /** - * Apparently the default constructor has default access, rather - * than protected access, even though this class is declared to be - * protected. Why, I don't know, but we need to be able to extend - * this class elsewhere, so we need this. - */ - protected JabberContextImpl () { - } - - public Client getClient () { - return _client; - } - - public DObjectManager getDObjectManager () { - return _client.getDObjectManager(); - } - - public Config getConfig () { - return _config; - } - - public LocationDirector getLocationDirector () { - return _locdir; - } - - public OccupantDirector getOccupantDirector () { - return _occdir; - } - - public ChatDirector getChatDirector () { - return _chatdir; - } - - public MessageManager getMessageManager () { - return _msgmgr; - } - - public void setPlaceView (PlaceView view) { - // TBD - } - - public void clearPlaceView (PlaceView view) { - // we'll just let the next place view replace our old one - } - - public Renderer getRenderer () { - return _app.getContext().getRenderer(); - } - - public DisplaySystem getDisplay () { - return _app.getContext().getDisplay(); - } - - public CameraHandler getCameraHandler () { - return _app.getContext().getCameraHandler(); - } - - public Node getGeometry () { - return _app.getContext().getGeometry(); - } - - public Node getInterface () { - return _app.getContext().getInterface(); - } - - public InputHandler getInputHandler () { - return _app.getContext().getInputHandler(); - } - -// public InputHandler getBufferedInputHandler () { -// return _app.getContext().getBufferedInputHandler(); -// } - - public BRootNode getRootNode () { - return _app.getContext().getRootNode(); - } - } - - protected CrowdContext _ctx; - protected JabberApp _app; - protected Config _config = new Config("jabber"); - - protected Client _client; - protected LocationDirector _locdir; - protected OccupantDirector _occdir; - protected ChatDirector _chatdir; - protected MessageManager _msgmgr; - - /** The prefix prepended to localization bundle names before looking - * them up in the classpath. */ - protected static final String MESSAGE_MANAGER_PREFIX = "rsrc.i18n"; -} diff --git a/tests/src/java/com/threerings/jme/client/JabberController.java b/tests/src/java/com/threerings/jme/client/JabberController.java deleted file mode 100644 index 329381b6..00000000 --- a/tests/src/java/com/threerings/jme/client/JabberController.java +++ /dev/null @@ -1,19 +0,0 @@ -// -// $Id$ - -package com.threerings.jme.client; - -import com.threerings.crowd.client.PlaceController; -import com.threerings.crowd.client.PlaceView; -import com.threerings.crowd.util.CrowdContext; - -/** - * Handles the basic bits for our simple chat room. - */ -public class JabberController extends PlaceController -{ - protected PlaceView createPlaceView (CrowdContext ctx) - { - return new JabberView(ctx); - } -} diff --git a/tests/src/java/com/threerings/jme/client/JabberView.java b/tests/src/java/com/threerings/jme/client/JabberView.java deleted file mode 100644 index 26fc814e..00000000 --- a/tests/src/java/com/threerings/jme/client/JabberView.java +++ /dev/null @@ -1,50 +0,0 @@ -// -// $Id$ - -package com.threerings.jme.client; - -import com.jmex.bui.BWindow; -import com.jmex.bui.layout.BorderLayout; - -import com.threerings.crowd.client.PlaceView; -import com.threerings.crowd.data.PlaceObject; -import com.threerings.crowd.util.CrowdContext; - -import com.threerings.jme.JmeContext; -import com.threerings.jme.chat.ChatView; - -/** - * Manages the "view" when we're in the chat room. - */ -public class JabberView extends BWindow - implements PlaceView -{ - public JabberView (CrowdContext ctx) - { - super(JabberApp.stylesheet, new BorderLayout()); - - _ctx = ctx; - _jctx = (JmeContext)ctx; - _chat = new ChatView(_jctx, _ctx.getChatDirector()); - add(_chat, BorderLayout.CENTER); - - _jctx.getRootNode().addWindow(this); - setBounds(0, 40, 640, 240); - } - - // documentation inherited from interface PlaceView - public void willEnterPlace (PlaceObject plobj) - { - _chat.willEnterPlace(plobj); - } - - // documentation inherited from interface PlaceView - public void didLeavePlace (PlaceObject plobj) - { - _chat.didLeavePlace(plobj); - } - - protected CrowdContext _ctx; - protected JmeContext _jctx; - protected ChatView _chat; -} diff --git a/tests/src/java/com/threerings/jme/data/JabberConfig.java b/tests/src/java/com/threerings/jme/data/JabberConfig.java deleted file mode 100644 index 1b5c11da..00000000 --- a/tests/src/java/com/threerings/jme/data/JabberConfig.java +++ /dev/null @@ -1,27 +0,0 @@ -// -// $Id$ - -package com.threerings.jme.data; - -import com.threerings.crowd.client.PlaceController; -import com.threerings.crowd.data.PlaceConfig; -import com.threerings.jme.client.JabberController; - -/** - * Defines the necessary bits for our chat room. - */ -public class JabberConfig extends PlaceConfig -{ - // documentation inherited - public PlaceController createController () - { - return new JabberController(); - } - - // documentation inherited - public String getManagerClassName () - { - // nothing special needed on the server side - return "com.threerings.crowd.server.PlaceManager"; - } -} diff --git a/tests/src/java/com/threerings/jme/server/JabberServer.java b/tests/src/java/com/threerings/jme/server/JabberServer.java deleted file mode 100644 index 5d73798c..00000000 --- a/tests/src/java/com/threerings/jme/server/JabberServer.java +++ /dev/null @@ -1,46 +0,0 @@ -// -// $Id$ - -package com.threerings.jme.server; - -import com.google.inject.Guice; -import com.google.inject.Injector; - -import com.threerings.crowd.server.CrowdServer; -import com.threerings.crowd.server.PlaceManager; - -import com.threerings.jme.data.JabberConfig; - -import static com.threerings.crowd.Log.log; - -/** - * A basic server that creates a single room and sticks everyone in it where they can chat with one - * another. - */ -public class JabberServer extends CrowdServer -{ - @Override // from CrowdServer - public void init (Injector injector) - throws Exception - { - super.init(injector); - - // create a single location - _place = _plreg.createPlace(new JabberConfig()); - log.info("Created chat room " + _place.where() + "."); - } - - public static void main (String[] args) - { - Injector injector = Guice.createInjector(new Module()); - JabberServer server = injector.getInstance(JabberServer.class); - try { - server.init(injector); - server.run(); - } catch (Exception e) { - log.warning("Unable to initialize server.", e); - } - } - - protected PlaceManager _place; -} diff --git a/tests/src/java/com/threerings/jme/sprite/PathTestApp.java b/tests/src/java/com/threerings/jme/sprite/PathTestApp.java deleted file mode 100644 index cda54240..00000000 --- a/tests/src/java/com/threerings/jme/sprite/PathTestApp.java +++ /dev/null @@ -1,149 +0,0 @@ -// -// $Id$ - -package com.threerings.jme.sprite; - -import java.util.Arrays; -import java.util.logging.Level; - -import com.jme.math.FastMath; -import com.jme.math.Matrix3f; -import com.jme.math.Quaternion; -import com.jme.math.Vector3f; -import com.jme.renderer.ColorRGBA; -import com.jme.scene.shape.Box; -import com.jme.scene.shape.Disk; -import com.jme.scene.shape.Quad; -import com.jme.scene.state.LightState; -import com.jme.util.LoggingSystem; - -import com.threerings.jme.JmeApp; -import com.threerings.jme.sprite.LineSegmentPath; - -/** - * Used for testing paths. - */ -public class PathTestApp extends JmeApp -{ - protected void initRoot () - { - super.initRoot(); - - float dist = 10; - - // set up the camera - Vector3f loc = new Vector3f(0, -dist, 10); - _camera.setLocation(loc); - Matrix3f rotm = new Matrix3f(); - rotm.fromAngleAxis(-FastMath.PI/4, _camera.getLeft()); - rotm.multLocal(_camera.getDirection()); - rotm.multLocal(_camera.getUp()); - rotm.multLocal(_camera.getLeft()); - _camera.update(); - - for (int yy = -1; yy < 1; yy++) { - for (int xx = -1; xx < 1; xx++) { - Quad quad = new Quad("ground", 10, 10); - quad.setLightCombineMode(LightState.OFF); - int index = (yy+1)*2 + (xx+1); - quad.setSolidColor(COLORS[index]); - quad.setLocalTranslation( - new Vector3f(xx * 10 + 5, yy * 10 + 5, -1)); - _geom.attachChild(quad); - } - } - - for (int yy = -1; yy <= 1; yy++) { - for (int xx = -1; xx <= 1; xx++) { - if (xx != 0 || yy != 0) { - setup(xx * dist, yy * dist); - } - } - } - } - - protected void setup (float x, float y) - { - Box target = new Box("target", new Vector3f(-.1f, -.1f, -.1f), - new Vector3f(.1f, .1f, .1f)); - target.setLocalTranslation(new Vector3f(x, y, 0)); - _geom.attachChild(target); - - Box box = new Box("box", new Vector3f(-1, -0.5f, -0.25f), - new Vector3f(1, 0.5f, 0.25f)); - Disk disk = new Disk("dot", 10, 10, 0.5f); - disk.setLightCombineMode(LightState.OFF); - disk.setLocalTranslation(new Vector3f(0.5f, 0f, 0.3f)); - Sprite shot = new Sprite(); - shot.attachChild(box); - shot.attachChild(disk); - _geom.attachChild(shot); - - testBallistic(shot, target); -// testLineSegment(shot); - } - - protected void testBallistic (Sprite shot, Box target) - { - // start with the "cannon" pointed along the x axis - Vector3f diff = target.getLocalTranslation().subtract( - shot.getLocalTranslation()); - Vector3f vel = diff.normalize(); - float range = diff.length(), angle = -FastMath.PI/4; - - Vector3f axis = UP.cross(vel); - axis.normalizeLocal(); - - // rotate it up (around the y axis) the necessary elevation - Quaternion rot = new Quaternion(); - rot.fromAngleAxis(angle, axis); - rot.multLocal(vel); - - // give the cannon its muzzle velocity - float muzvel = FastMath.sqrt(range * BallisticPath.G / - FastMath.sin(2*angle)); - vel.multLocal(muzvel); - - Vector3f start = new Vector3f(0, 0, 0); - float time = BallisticPath.computeFlightTime(range, muzvel, angle); - shot.move(new OrientingBallisticPath( - shot, new Vector3f(1, 0, 0), start, vel, GRAVITY, time)); - - System.out.println("Range: " + range); - System.out.println("Muzzle velocity: " + muzvel); - System.out.println("Rotation axis: " + axis); - System.out.println("Angle: " + angle + " (" + - (angle * 180 / FastMath.PI) + ")"); - System.out.println("Flight time: " + time); - System.out.println("Velocity: " + vel); - } - - protected void testLineSegment (Sprite shot) - { - Vector3f[] points = new Vector3f[] { - new Vector3f(0, 0, 0), new Vector3f(2, 0, 0), new Vector3f(3, 0, 0), - new Vector3f(3, 2, 0), new Vector3f(5, 2, 0), new Vector3f(5, -2, 0), - new Vector3f(-4, -2, 0) - }; - float[] durations = new float[points.length]; - Arrays.fill(durations, 1f); - Vector3f up = new Vector3f(0, 0, 1); - Vector3f orient = new Vector3f(1, 0, 0); - shot.move(new LineSegmentPath(shot, up, orient, points, durations)); - } - - public static void main (String[] args) - { - LoggingSystem.getLogger().setLevel(Level.OFF); - PathTestApp test = new PathTestApp(); - if (!test.init()) { - System.exit(-1); - } - test.run(); - } - - protected static final Vector3f GRAVITY = new Vector3f(0, 0, -9.8f); - protected static final Vector3f UP = new Vector3f(0, 0, 1); - protected static final ColorRGBA[] COLORS = { - ColorRGBA.red, ColorRGBA.green, ColorRGBA.blue, ColorRGBA.gray }; -}