[skycastle-commits] SF.net SVN: skycastle: [501] trunk/skycastle/modules

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Tue, 29 Apr 2008 14:42:09 -0700

Revision: 501
          http://skycastle.svn.sourceforge.net/skycastle/?rev=501&view=rev
Author:   zzorn
Date:     2008-04-29 14:42:09 -0700 (Tue, 29 Apr 2008)

Log Message:
-----------
Implemented a StrokePartRenderer, which renders a part of a stroke.  This 
allows re-using meshes from a pool for stroke renderig.

Also added an utility class for JME related utilities, and added an option to 
run commands later in the swing thread to the CommandStack.

Modified Paths:
--------------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/EmptyStroke.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/Stroke.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/StrokeImpl.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeAppearanceCalculator.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokePartRenderer.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
    
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java

Added Paths:
-----------
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackMode.java

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java 
                        (rev 0)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/opengl/JmeUtils.java 
2008-04-29 21:42:09 UTC (rev 501)
@@ -0,0 +1,87 @@
+package org.skycastle.opengl;
+
+import com.jme.renderer.ColorRGBA;
+import com.jme.renderer.Renderer;
+import com.jme.scene.Spatial;
+import com.jme.scene.state.AlphaState;
+import com.jme.scene.state.CullState;
+import com.jme.scene.state.MaterialState;
+
+/**
+ * Java Monkey Engine related utilities.
+ *
+ * @author Hans Haggstrom
+ */
+public final class JmeUtils
+{
+
+    //----------------------------------------------------------------------
+    // Static Methods
+
+    /**
+     * Sets the color of a {@link Spatial}.  Code borrowed from JME forums.
+     *
+     * @param renderer  the renderer that can be used to create render states.
+     * @param spatial   the {@link Spatial} whose color we should change.
+     * @param color     the color to use
+     * @param shininess amount of specular lighting (scale unknown?)
+     */
+    public static void setColor( final Renderer renderer,
+                                 final Spatial spatial,
+                                 final ColorRGBA color,
+                                 final float shininess )
+    {
+        final MaterialState materialState = renderer.createMaterialState();
+        materialState.setDiffuse( color );
+        materialState.setAmbient( color.mult( new ColorRGBA( 0.3f, 0.3f, 0.3f, 
1 ) ) );
+        materialState.setShininess( shininess );
+
+        final float mul = 1 + shininess > 18 ? ( shininess - 28 ) * 0.01f : 0;
+        materialState.setSpecular( color.mult( new ColorRGBA( mul, mul, mul, 1 
) ) );
+        spatial.setRenderState( materialState );
+
+        if ( color.a < 1 )
+        {
+            enableTranslucency( renderer, spatial );
+        }
+
+        CullState cullState = renderer.createCullState();
+        cullState.setCullMode( CullState.CS_BACK );
+        spatial.setRenderState( cullState );
+    }
+
+
+    /**
+     * Enables transparency for the specified {@link Spatial}.
+     *
+     * @param renderer the renderer that can be used to create render states.
+     * @param spatial  a spatial that should be allowed to contain transparent 
pars.
+     */
+    public static void enableTranslucency( final Renderer renderer, final 
Spatial spatial )
+    {
+        // strokeRenderer.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
+        final AlphaState alphaState = renderer.createAlphaState();
+        alphaState.setBlendEnabled( true );
+        alphaState.setSrcFunction( AlphaState.SB_SRC_ALPHA );
+        alphaState.setDstFunction( AlphaState.DB_ONE_MINUS_SRC_ALPHA );
+        alphaState.setTestEnabled( false );
+        alphaState.setEnabled( true );
+
+/*
+        alphaState.setTestEnabled(true);
+        alphaState.setTestFunction(AlphaState.TF_GREATER);
+*/
+
+        spatial.setRenderState( alphaState );
+        spatial.updateRenderState();
+        spatial.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private JmeUtils()
+    {
+    }
+
+}

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
 2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchController.java
 2008-04-29 21:42:09 UTC (rev 501)
@@ -24,7 +24,7 @@
     //======================================================================
     // Private Fields
 
-    private final CommandStack myCommandStack = new CommandStackImpl();
+    private final CommandStack myCommandStack = new CommandStackImpl( 
CommandStackMode.INVOKE_LATER_IN_SWING_THREAD );
 
 
     private final CommandAction myExitAction = new CommandAction( 
myCommandStack,

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
    2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
    2008-04-29 21:42:09 UTC (rev 501)
@@ -14,7 +14,7 @@
 import org.skycastle.sketch.model.group.Group;
 import org.skycastle.sketch.model.group.GroupElement;
 import org.skycastle.sketch.model.stroke.Stroke;
-import org.skycastle.sketch.rendering.StrokeRenderer;
+import org.skycastle.sketch.rendering.StrokePartRenderer;
 import org.skycastle.util.ParameterChecker;
 import org.skycastle.util.listenable.collection.CollectionListener;
 import org.skycastle.util.listenable.collection.ListenableCollection;
@@ -489,12 +489,14 @@
             {
                 final Stroke stroke = (Stroke) groupElement;
 
-/*
                 final StrokePartRenderer strokePartRenderer = new 
StrokePartRenderer( 1000 );
                 strokePartRenderer.setStroke( stroke, 0 );
                 myRoot3DNode.attachChild( strokePartRenderer );
+
+/*
+
+                myRoot3DNode.attachChild( new StrokeRenderer( stroke ) );
 */
-                myRoot3DNode.attachChild( new StrokeRenderer( stroke ) );
             }
             else if ( groupElement instanceof Group )
             {

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/EmptyStroke.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/EmptyStroke.java
 2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/EmptyStroke.java
 2008-04-29 21:42:09 UTC (rev 501)
@@ -71,4 +71,10 @@
     {
     }
 
+    public int getSize()
+    {
+        return 0;
+
+    }
+
 }

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/Stroke.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/Stroke.java
      2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/Stroke.java
      2008-04-29 21:42:09 UTC (rev 501)
@@ -29,7 +29,8 @@
     /**
      * Adds the specified StrokeListener.
      *
-     * @param addedStrokeListener a listener that will be notified about added 
points in the stroke.  Should not be null or already added.
+     * @param addedStrokeListener a listener that will be notified about added 
points in the stroke.  Should
+     *                            not be null or already added.
      */
     void addStrokeListener( StrokeListener addedStrokeListener );
 
@@ -40,4 +41,8 @@
      */
     void removeStrokeListener( StrokeListener removedStrokeListener );
 
+    /**
+     * @return number of points in this stroke.
+     */
+    int getSize();
 }

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/StrokeImpl.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/StrokeImpl.java
  2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/model/stroke/StrokeImpl.java
  2008-04-29 21:42:09 UTC (rev 501)
@@ -60,7 +60,9 @@
     public void addStrokeListener( StrokeListener addedStrokeListener )
     {
         ParameterChecker.checkNotNull( addedStrokeListener, 
"addedStrokeListener" );
-        ParameterChecker.checkNotAlreadyContained( addedStrokeListener, 
myStrokeListeners, "myStrokeListeners" );
+        ParameterChecker.checkNotAlreadyContained( addedStrokeListener,
+                                                   myStrokeListeners,
+                                                   "myStrokeListeners" );
 
         myStrokeListeners.add( addedStrokeListener );
     }
@@ -73,4 +75,10 @@
         myStrokeListeners.remove( removedStrokeListener );
     }
 
+    public int getSize()
+    {
+        return myPoints.size();
+
+    }
+
 }

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeAppearanceCalculator.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeAppearanceCalculator.java
     2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeAppearanceCalculator.java
     2008-04-29 21:42:09 UTC (rev 501)
@@ -37,11 +37,11 @@
     // Private Constants
 
     private static final float DEFAULT_Z_LEVEL = 0;
-    private static final float DEFAULT_WIDTH = 70;
+    private static final float DEFAULT_WIDTH = 15;
     private static final float DEFAULT_RED = 0;
     private static final float DEFAULT_GREEN = 0;
     private static final float DEFAULT_BLUE = 0;
-    private static final float DEFAULT_ALPHA = 0.33f;
+    private static final float DEFAULT_ALPHA = 0.3f;
 
     //======================================================================
     // Public Methods

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokePartRenderer.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokePartRenderer.java
     2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokePartRenderer.java
     2008-04-29 21:42:09 UTC (rev 501)
@@ -5,13 +5,12 @@
 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.state.AlphaState;
 import com.jme.system.DisplaySystem;
 import com.jme.util.GameTaskQueue;
 import com.jme.util.GameTaskQueueManager;
 import com.jme.util.geom.BufferUtils;
+import org.skycastle.opengl.JmeUtils;
 import org.skycastle.sketch.model.stroke.EmptyStroke;
 import org.skycastle.sketch.model.stroke.Stroke;
 import org.skycastle.sketch.model.stroke.StrokeListener;
@@ -29,7 +28,8 @@
  *
  * @author Hans Haggstrom
  */
-public class StrokePartRenderer
+@SuppressWarnings( { "serial" } )
+public final class StrokePartRenderer
         extends TriMesh
 {
 
@@ -114,24 +114,16 @@
 
         myStartIndex = startIndex;
         myStroke = stroke;
+        myAppearanceCalculator.setStroke( myStroke );
 
         myStroke.addStrokeListener( myStrokeListener );
 
         recalculateStrokeAppearance();
     }
 
-    /*
-    *//**
-     * @return the texture that this TerrainMesh is currently using, or null 
if it is using a placeholder
-     *         texture.
-     *//*
-    public Texture getTexture()
-    {
-        return myTexture;
-    }*/
-
     //======================================================================
     // Private Methods
+
     private void initializeGeometry( final int numberOfStrokePoints )
     {
         // Calculate sizes
@@ -150,11 +142,7 @@
         initializeIndices( myIndices, numberOfSegments );
 
         // Initialize the TriMesh
-        setVertexBuffer( 0, myVertexes );
-        setColorBuffer( 0, myColors );
-        setTextureBuffer( 0, myTextureCoordinates );
-        setNormalBuffer( 0, myNormals );
-        setIndexBuffer( 0, myIndices );
+        reconstruct();
 
         // Initialize bounding box
         setModelBound( new BoundingBox() );
@@ -162,12 +150,18 @@
     }
 
 
+    private void reconstruct()
+    {
+        reconstruct( myVertexes, myNormals, myColors, myTextureCoordinates, 
myIndices );
+    }
+
+
     private void onStrokePointAdded()
     {
-        recalculateStrokeAppearance();
 /*
-        throw new UnsupportedOperationException( "This method has not yet been 
implemented." ); // IMPLEMENT
+        calculateLastPointAppearance();
 */
+        recalculateStrokeAppearance();
     }
 
 
@@ -181,7 +175,7 @@
             {
                 final Renderer renderer = 
DisplaySystem.getDisplaySystem().getRenderer();
 
-                enableTranslucency( renderer, StrokePartRenderer.this );
+                JmeUtils.enableTranslucency( renderer, StrokePartRenderer.this 
);
 
                 return null;
             }
@@ -190,23 +184,40 @@
     }
 
 
-    private void enableTranslucency( final Renderer renderer, final Spatial 
spatial )
+    @SuppressWarnings( { "PointlessArithmeticExpression" } )
+    private void calculateLastPointAppearance()
     {
-        // strokeRenderer.setRenderQueueMode( Renderer.QUEUE_TRANSPARENT );
-        final AlphaState alphaState = renderer.createAlphaState();
-        alphaState.setBlendEnabled( true );
-        alphaState.setSrcFunction( AlphaState.SB_SRC_ALPHA );
-        alphaState.setDstFunction( AlphaState.DB_ONE_MINUS_SRC_ALPHA );
-        alphaState.setTestEnabled( false );
-        alphaState.setEnabled( true );
+        final Vector3f positionLeft = new Vector3f();
+        final Vector3f positionMid = new Vector3f();
+        final Vector3f positionRight = new Vector3f();
 
-        spatial.setRenderState( alphaState );
-        spatial.updateRenderState();
+        final ColorRGBA colorLeft = new ColorRGBA();
+        final ColorRGBA colorMid = new ColorRGBA();
+        final ColorRGBA colorRight = new ColorRGBA();
 
-        // TODO: Make the rendering two sided - how?
-/*
-                setCullMode( CULL_NEVER );
-*/
+        final int lastPointIndex = myStroke.getSize() - 1;
+
+        int bufferIndex = lastPointIndex - myStartIndex;
+
+        if ( bufferIndex < 0 ||
+             bufferIndex >= myPartLength )
+        {
+            throw new IllegalStateException(
+                    "The last point is not in this StrokePartRenderer, can't 
update its appearance." );
+        }
+
+        myAppearanceCalculator.resetToIndex( lastPointIndex );
+
+        myAppearanceCalculator.calculateNextPoint( positionLeft, positionMid, 
positionRight,
+                                                   colorLeft, colorMid, 
colorRight );
+
+        final int vertexIndex = bufferIndex * 3;
+        setPointData( vertexIndex + 0, positionLeft, colorLeft );
+        setPointData( vertexIndex + 1, positionMid, colorMid );
+        setPointData( vertexIndex + 2, positionRight, colorRight );
+
+        // Update bounds to include the new shape
+        updateModelBound();
     }
 
 
@@ -221,6 +232,9 @@
         final ColorRGBA colorMid = new ColorRGBA();
         final ColorRGBA colorRight = new ColorRGBA();
 
+        // Make the whole buffer writeable
+        clearBufferLimit();
+
         int pointIndex = myStartIndex;
 
         myAppearanceCalculator.resetToIndex( pointIndex );
@@ -240,27 +254,47 @@
             pointIndex++;
         }
 
-        // Fill in rest of the stroke part with invisible data
-        while ( pointIndex < getPartEndIndex() )
-        {
-            final int vertexIndex = pointIndex * 3;
+        // Do not render the rest of the stroke
+        setBufferLimit( pointIndex );
 
-            setPointData( vertexIndex + 0, ORIGO, TRANSPARENT_BLACK );
-            setPointData( vertexIndex + 1, ORIGO, TRANSPARENT_BLACK );
-            setPointData( vertexIndex + 2, ORIGO, TRANSPARENT_BLACK );
+        // Allow TriMesh to refresh its sizes from the limit values
+        reconstruct();
 
-            pointIndex++;
-        }
-
-        // Notify the 3D object that we changed it's appearance
-        // TODO
+        // Update new size bounds of this stroke
         updateModelBound();
-        updateGeometricState( 0, true );
-        updateRenderState();
+    }
 
-        updateModelBound();
+
+    private void clearBufferLimit()
+    {
+        myVertexes.clear();
+        myColors.clear();
+        myTextureCoordinates.clear();
+        myNormals.clear();
+        myIndices.clear();
     }
 
+
+    private void setBufferLimit( final int pointIndex )
+    {
+        final int segmentIndex = pointIndex - 1;
+        final int vertexIndex = pointIndex * 3;
+        final int IndicesIndex = segmentIndex * NUMBER_OF_INDICES_IN_SEGMENT;
+
+        myVertexes.position( 3 * vertexIndex );
+        myColors.position( 4 * vertexIndex );
+        myTextureCoordinates.position( 2 * vertexIndex );
+        myNormals.position( 3 * vertexIndex );
+        myIndices.position( IndicesIndex );
+
+        myVertexes.flip();
+        myColors.flip();
+        myTextureCoordinates.flip();
+        myNormals.flip();
+        myIndices.flip();
+    }
+
+
     private int getPartEndIndex()
     {
         return myStartIndex + myPartLength;

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
 2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
 2008-04-29 21:42:09 UTC (rev 501)
@@ -1,28 +1,21 @@
 package org.skycastle.sketch.rendering;
 
 import com.jme.bounding.BoundingBox;
-import com.jme.image.Image;
-import com.jme.image.Texture;
 import com.jme.math.Vector2f;
 import com.jme.math.Vector3f;
 import com.jme.renderer.ColorRGBA;
 import com.jme.renderer.Renderer;
 import com.jme.scene.TriMesh;
-import com.jme.scene.state.AlphaState;
-import com.jme.scene.state.TextureState;
 import com.jme.system.DisplaySystem;
 import com.jme.util.GameTaskQueue;
 import com.jme.util.GameTaskQueueManager;
-import com.jme.util.TextureManager;
 import com.jme.util.geom.BufferUtils;
-import com.jmex.awt.swingui.ImageGraphics;
+import org.skycastle.opengl.JmeUtils;
 import org.skycastle.sketch.model.stroke.Stroke;
 import org.skycastle.sketch.model.stroke.StrokeListener;
 import org.skycastle.sketch.sample.DataSample;
-import org.skycastle.util.ImageUtils;
 import org.skycastle.util.ParameterChecker;
 
-import java.awt.image.BufferedImage;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 import java.util.concurrent.Callable;
@@ -43,39 +36,31 @@
     private static int theStrokeMeshCounter = 0;
 
     private final Stroke myStroke;
+    private final StrokeAppearanceCalculator myAppearanceCalculator;
+    private final StrokeListener myStrokeListener = new StrokeListener()
+    {
 
-    private final Object myTextureStateLock = new Object();
+        public void onPointAdded( final Stroke updatedStroke, final DataSample 
point )
+        {
+            initializeGeometry( myStroke.getPoints().size() );
 
+            // Put vertices in correct places
+            recalculateAppearance();
+        }
+
+    };
+
     private FloatBuffer myVertexes;
     private FloatBuffer myColors;
     private FloatBuffer myTextureCoordinates;
     private FloatBuffer myNormals;
     private IntBuffer myIndices;
-    private int myNumberOfSegments;
 
-    private TextureState myTextureState;
-    private Texture myTexture;
-    private ImageGraphics myTextureGraphics;
-
-    private TextureState myPlaceholderTextureState = null;
-
-    private boolean myPlaceholderTextureInUse = false;
-
     //======================================================================
     // Private Constants
 
-    private static final BufferedImage PLACEHOLDER_PICTURE = 
ImageUtils.createPlaceholderPicture( 128, 128 );
-    private static final float DEFAULT_ANISO_LEVEL = 1.0f;
-    private static final int DEFAULT_TEXTURE_IMAGE_FORMAT = 
com.jme.image.Image.GUESS_FORMAT_NO_S3TC;
-    private static final Texture PLACEHOLDER_TEXTURE = 
TextureManager.loadTexture( PLACEHOLDER_PICTURE,
-                                                                               
    Texture.MM_LINEAR_LINEAR,
-                                                                               
    Texture.FM_LINEAR,
-                                                                               
    1,
-                                                                               
    Image.GUESS_FORMAT_NO_S3TC,
-                                                                               
    false );
     private static final int NUMBER_OF_TRIANGLES_PER_SEGMENT = 4;
     private static final int NUMBER_OF_INDICES_IN_SEGMENT = 3 * 
NUMBER_OF_TRIANGLES_PER_SEGMENT;
-    private float myZ1;
 
     //======================================================================
     // Public Methods
@@ -90,48 +75,34 @@
      */
     public StrokeRenderer( final Stroke stroke )
     {
-        this( stroke, 0 );
-    }
-
-    private final StrokeAppearanceCalculator myAppearanceCalculator;
-
-    /**
-     * Creates a new {@link StrokeRenderer}.
-     *
-     * @param stroke the stroke that should be rendered
-     * @param z      the default height of the stroke.
-     */
-    public StrokeRenderer( final Stroke stroke, final float z )
-    {
         // JME seems to need an unique identifier for each node.  NOTE: Not 
thread safe.
         //noinspection AssignmentToStaticFieldFromInstanceMethod
         super( "StrokeMesh_" + theStrokeMeshCounter++ );
 
         // Check parameters
         ParameterChecker.checkNotNull( stroke, "stroke" );
-        ParameterChecker.checkNormalNumber( z, "z" );
 
         myStroke = stroke;
-        myZ1 = z;
 
         myAppearanceCalculator = new StrokeAppearanceCalculator( myStroke );
 
 
-        myStroke.addStrokeListener( new StrokeListener()
-        {
+        myStroke.addStrokeListener( myStrokeListener );
 
-            public void onPointAdded( final Stroke updatedStroke, final 
DataSample point )
-            {
-                recalculateStroke();
-            }
+        initializeGeometry( myStroke.getPoints().size() );
 
-        } );
+        // Put vertices in correct places
+        // recalculateAppearance();
 
-        if ( stroke.getPoints().size() >= 2 )
-        {
-            recalculateStroke();
-        }
 
+        initializeTranslucency();
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void initializeTranslucency()
+    {
         GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE 
).enqueue( new Callable<Object>()
         {
 
@@ -140,98 +111,29 @@
             {
                 final Renderer renderer = 
DisplaySystem.getDisplaySystem().getRenderer();
 
-                final StrokeRenderer strokeRenderer = StrokeRenderer.this;
+                JmeUtils.enableTranslucency( renderer, StrokeRenderer.this );
 
-                // strokeRenderer.setRenderQueueMode( 
Renderer.QUEUE_TRANSPARENT );
-                final AlphaState alphaState = renderer.createAlphaState();
-                alphaState.setBlendEnabled( true );
-                alphaState.setSrcFunction( AlphaState.SB_SRC_ALPHA );
-                alphaState.setDstFunction( AlphaState.DB_ONE_MINUS_SRC_ALPHA );
-                alphaState.setTestEnabled( false );
-                alphaState.setEnabled( true );
-
-                strokeRenderer.setRenderState( alphaState );
-                strokeRenderer.updateRenderState();
-
-                // TODO: Make the rendering two sided - how?
-/*
-                setCullMode( CULL_NEVER );
-*/
-
                 return null;
             }
 
         } );
     }
 
-    //----------------------------------------------------------------------
-    // Other Public Methods
 
-    /**
-     * Updates the positon and covered area of the terrain mesh.
-     * <p/>
-     * Called from the constructor, as well as when a TerrainMesh is re-used.
-     */
-    public void updateBounds()
+    private void initializeGeometry( final int numberOfStrokePoints )
     {
-        // Put vertices in correct places
-        initializeVetices();
+        // Calculate sizes
+        int numberOfSegments = numberOfStrokePoints - 1;
+        int numberOfVertices = numberOfStrokePoints * 3;
+        int numberOfIndices = numberOfSegments * NUMBER_OF_INDICES_IN_SEGMENT;
 
-        // Initialize the TriMesh
-        setVertexBuffer( 0, myVertexes );
-        setColorBuffer( 0, myColors );
-        setTextureBuffer( 0, myTextureCoordinates );
-        setNormalBuffer( 0, myNormals );
-        setIndexBuffer( 0, myIndices );
-
-        // Update bounding box
-        setModelBound( new BoundingBox() );
-        updateModelBound();
-    }
-
-    /* *
-    * Creates a texture from the specified image and applies it to this 
Terrainmesh.
-    *
-    * @param textureImage the image to create a texture from.  If null, a 
placeholder texture is created.
-    */
-    /*   public void setTextureImage( final BufferedImage textureImage )
+        if ( numberOfStrokePoints < 2 )
         {
-            GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE 
).enqueue( new Callable<Object>()
-            {
-
-                public Object call() throws Exception
-                {
-                    final Renderer renderer = 
DisplaySystem.getDisplaySystem().getRenderer();
-                    initTexture( textureImage, renderer );
-                    return null;
-                }
-
-            } );
+            numberOfSegments = 0;
+            numberOfVertices = 0;
+            numberOfIndices = 0;
         }
 
-    */
-
-    /**
-     * @return the texture that this TerrainMesh is currently using, or null 
if it is using a placeholder
-     *         texture.
-     */
-    public Texture getTexture()
-    {
-        return myTexture;
-    }
-
-    //======================================================================
-    // Private Methods
-
-    private void recalculateStroke()
-    {
-        // Calculate sizes
-        final int numberOfPoints = myStroke.getPoints().size();
-        myNumberOfSegments = numberOfPoints - 1;
-        final int numberOfTriangles = myNumberOfSegments * 
NUMBER_OF_TRIANGLES_PER_SEGMENT;
-        final int numberOfVertices = numberOfPoints * 3;
-        final int numberOfIndices = myNumberOfSegments * 
NUMBER_OF_INDICES_IN_SEGMENT;
-
         // Create databuffers
         myVertexes = BufferUtils.createVector3Buffer( numberOfVertices );
         myColors = BufferUtils.createColorBuffer( numberOfVertices );
@@ -240,75 +142,104 @@
         myIndices = BufferUtils.createIntBuffer( numberOfIndices );
 
         // Stich together the vertices into triangles
-        initializeIndices();
+        initializeIndices( myIndices, numberOfSegments );
 
+        // Initialize the TriMesh
+        reconstruct( myVertexes, myNormals, myColors, myTextureCoordinates, 
myIndices );
 
-        updateBounds();
+        // Update bounding box
+        setModelBound( new BoundingBox() );
+        updateModelBound();
     }
 
-/*
-    public void setPlaceholderTexture( final Texture texture, final 
BoundingRectangle textureArea )
+
+    private void recalculateAppearance()
     {
-        synchronized ( myTextureStateLock )
-        {
-            myPlaceholderTextureInUse = true;
+        final Vector3f positionLeft = new Vector3f();
+        final Vector3f positionMid = new Vector3f();
+        final Vector3f positionRight = new Vector3f();
 
-            if ( myTextureState != null )
-            {
-                // Update texture indexes
-                setTextureCoordinates( textureArea );
+        final ColorRGBA colorLeft = new ColorRGBA();
+        final ColorRGBA colorMid = new ColorRGBA();
+        final ColorRGBA colorRight = new ColorRGBA();
 
-                // Update the geometry
-                updateGeometricState( 0, true );
+        int pointIndex = 0;
 
-                // Use placeholder if no texture specified
-                Texture textureToUse = texture;
-                if ( textureToUse == null )
-                {
-                    textureToUse = PLACEHOLDER_TEXTURE;
-                }
+        myAppearanceCalculator.resetToIndex( pointIndex );
 
-                // Set the texture
-                myTextureState.setTexture( textureToUse );
+        while ( myAppearanceCalculator.hasNextPoint() )
+        {
+            myAppearanceCalculator.calculateNextPoint( positionLeft, 
positionMid, positionRight,
+                                                       colorLeft, colorMid, 
colorRight );
 
-                updateRenderState();
-            }
+            final int vertexIndex = pointIndex * 3;
+
+            setPointData( vertexIndex + 0, positionLeft, colorLeft );
+            setPointData( vertexIndex + 1, positionMid, colorMid );
+            setPointData( vertexIndex + 2, positionRight, colorRight );
+
+            pointIndex++;
         }
     }
-*/
 
-/*
-    public boolean isPlaceholderTextureInUse()
-    {
-        return myPlaceholderTextureInUse;
-    }
-*/
 
-    //======================================================================
-    // Private Methods
-
-    private void initializeVetices()
+    @SuppressWarnings( { "PointlessArithmeticExpression" } )
+    private void recalculateStrokeAppearance()
     {
-        myAppearanceCalculator.resetToStart();
+        final Vector3f positionLeft = new Vector3f();
+        final Vector3f positionMid = new Vector3f();
+        final Vector3f positionRight = new Vector3f();
 
-        int index = 0;
-        while ( myAppearanceCalculator.hasNextPoint() )
-        {
-            final Vector3f positionLeft = new Vector3f();
-            final Vector3f positionMid = new Vector3f();
-            final Vector3f positionRight = new Vector3f();
+        final ColorRGBA colorLeft = new ColorRGBA();
+        final ColorRGBA colorMid = new ColorRGBA();
+        final ColorRGBA colorRight = new ColorRGBA();
 
-            final ColorRGBA colorLeft = new ColorRGBA();
-            final ColorRGBA colorMid = new ColorRGBA();
-            final ColorRGBA colorRight = new ColorRGBA();
+        int pointIndex = 0;//myStartIndex;
 
+        myAppearanceCalculator.resetToIndex( pointIndex );
+
+        while ( myAppearanceCalculator.hasNextPoint() /*&&
+                pointIndex < getPartEndIndex()*/ )
+        {
             myAppearanceCalculator.calculateNextPoint( positionLeft, 
positionMid, positionRight,
                                                        colorLeft, colorMid, 
colorRight );
 
-            setPointData( index++, positionLeft, colorLeft );
-            setPointData( index++, positionMid, colorMid );
-            setPointData( index++, positionRight, colorRight );
+            final int vertexIndex = pointIndex * 3;
+
+            setPointData( vertexIndex + 0, positionLeft, colorLeft );
+            setPointData( vertexIndex + 1, positionMid, colorMid );
+            setPointData( vertexIndex + 2, positionRight, colorRight );
+
+            pointIndex++;
         }
+
+/*
+        // Fill in rest of the stroke part with invisible data
+        while ( pointIndex < getPartEndIndex() )
+        {
+            final int vertexIndex = pointIndex * 3;
+
+            setPointData( vertexIndex + 0, ORIGO, TRANSPARENT_BLACK );
+            setPointData( vertexIndex + 1, ORIGO, TRANSPARENT_BLACK );
+            setPointData( vertexIndex + 2, ORIGO, TRANSPARENT_BLACK );
+
+            pointIndex++;
+        }
+
+        // Notify the 3D object that we changed it's appearance
+        // TODO
+        reconstruct();
+*/
+
+        updateModelBound();
+/*
+        updateGeometricState( 0, true );
+        updateRenderState();
+
+        updateModelBound();
+
+        updateWorldBound();
+*/
     }
 
 
@@ -322,13 +253,13 @@
 
 
     @SuppressWarnings( { "PointlessArithmeticExpression" } )
-    private void initializeIndices()
+    private void initializeIndices( final IntBuffer indices, final int 
numberOfSegments )
     {
         // OPTIMIZE: Use triangle strips or fans to get more efficient results!
 
         // Create indices indicating the vertexes that make up triangle faces
         int index = 0;
-        for ( int segment = 0; segment < myNumberOfSegments; segment++ )
+        for ( int segment = 0; segment < numberOfSegments; segment++ )
         {
             /*
             Segment, with vertex order marked in:
@@ -343,170 +274,22 @@
 
             final int segmentStartVertex = segment * 3;
 
-            myIndices.put( index++, segmentStartVertex + 3 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 0 );
+            indices.put( index++, segmentStartVertex + 3 );
+            indices.put( index++, segmentStartVertex + 4 );
+            indices.put( index++, segmentStartVertex + 0 );
 
-            myIndices.put( index++, segmentStartVertex + 0 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 1 );
+            indices.put( index++, segmentStartVertex + 0 );
+            indices.put( index++, segmentStartVertex + 4 );
+            indices.put( index++, segmentStartVertex + 1 );
 
-            myIndices.put( index++, segmentStartVertex + 1 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 2 );
+            indices.put( index++, segmentStartVertex + 1 );
+            indices.put( index++, segmentStartVertex + 4 );
+            indices.put( index++, segmentStartVertex + 2 );
 
-            myIndices.put( index++, segmentStartVertex + 2 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 5 );
+            indices.put( index++, segmentStartVertex + 2 );
+            indices.put( index++, segmentStartVertex + 4 );
+            indices.put( index++, segmentStartVertex + 5 );
         }
     }
 
-/*
-    private void initTexture( BufferedImage textureImage, final Renderer 
renderer )
-    {
-        synchronized ( myTextureStateLock )
-        {
-            // The texture can be null e.g. if we ran out of memory
-            if ( textureImage == null )
-            {
-                textureImage = PLACEHOLDER_PICTURE;
-            }
-
-            // Remove any placeholder render state
-            if ( myPlaceholderTextureInUse )
-            {
-*/
-/*
-            clearRenderState( RenderState.RS_TEXTURE );
-*/
-/*
-*/
-/*
-            myPlaceholderTextureState.setEnabled( false );
-            myPlaceholderTextureState.setTexture( null );
-            myPlaceholderTextureState = null;
-*/
-/*
-                setTextureCoordinates( WHOLE_TEXTURE_AREA );
-*/
-/*
-*/
-/*
-            }
-
-            if ( myTextureGraphics == null )
-            {
-                // First time initializations:
-
-                // Create JME Image Renderer
-                myTextureGraphics = ImageGraphics.createInstance( 
textureImage.getWidth( null ),
-                                                                  
textureImage.getHeight( null ),
-                                                                  0 );
-                myTextureGraphics.drawImage( textureImage, 0, 0, null );
-                myTextureGraphics.update();
-
-                // Create texture
-                myTexture = TextureManager.loadTexture( null,
-                                                        createTextureKey( 
textureImage.hashCode() ),
-                                                        
myTextureGraphics.getImage() );
-
-                // Make sure this texture is not cached, as we will be 
updating it when the TerrainMesh is re-used
-                TextureManager.releaseTexture( myTexture );
-
-                // Clamp texture at edges (no wrapping)
-                myTexture.setWrap( Texture.WM_ECLAMP_S_ECLAMP_T );
-                myTexture.setMipmapState( Texture.MM_LINEAR_LINEAR );
-
-                createTextureRenderState( renderer, myTexture );
-
-                if ( myPlaceholderTextureInUse )
-                {
-                    myTextureState.setTexture( myTexture, 0 );
-                }
-            }
-            else
-            {
-                // Release the previously reserved textures, so that they 
don't take up space on the 3D card
-                // NOTE: Maybe this also forces JME to re-upload the changed 
texture?
-                if ( !myPlaceholderTextureInUse )
-                {
-                    myTextureState.deleteAll( true );
-                }
-                else
-                {
-                    myTextureState.setTexture( myTexture, 0 );
-                    myTextureState.deleteAll( true );
-                }
-
-                // Update the JME Image used by the texture
-                myTextureGraphics.drawImage( textureImage, 0, 0, null );
-                myTextureGraphics.update();
-                myTextureGraphics.update( myTexture );
-
-                // Make sure this texture is not cached, as we will be 
updating it when the TerrainMesh is re-used
-                TextureManager.releaseTexture( myTexture );
-
-                // Smoother look at low viewing angles
-                myTexture.setMipmapState( Texture.MM_LINEAR_LINEAR );
-            }
-
-            myPlaceholderTextureInUse = false;
-        }
-    }
-*/
-
-/*
-    private void createTextureRenderState( final Renderer renderer, final 
Texture texture )
-    {
-        myTextureState = renderer.createTextureState();
-        myTextureState.setEnabled( true );
-        myTextureState.setTexture( texture, 0 );
-        setRenderState( myTextureState );
-        updateRenderState();
-    }
-
-
-    private TextureKey createTextureKey( final int imageHashcode )
-    {
-        final TextureKey tkey = new TextureKey( null, Texture.MM_LINEAR, 
Texture.FM_LINEAR,
-                                                DEFAULT_ANISO_LEVEL, false, 
DEFAULT_TEXTURE_IMAGE_FORMAT );
-        tkey.setFileType( "" + imageHashcode );
-        return tkey;
-    }
-
-
-    private void setTextureCoordinates( BoundingRectangle boundingRectangle )
-    {
-        if ( boundingRectangle == null )
-        {
-            boundingRectangle = WHOLE_TEXTURE_AREA;
-        }
-
-        for ( int y = 0; y < mySizeY_vertices; y++ )
-        {
-            for ( int x = 0; x < mySizeX_vertices; x++ )
-            {
-                final int index = calculateMeshIndex( x, y );
-
-                final float textureXPos = (float) MathUtils.interpolateClamp( 
x,
-                                                                              
1,
-                                                                              
mySizeX_vertices - 2,
-                                                                              
boundingRectangle.getX1(),
-                                                                              
boundingRectangle.getX2() );
-                final float textureYPos = (float) MathUtils.interpolateClamp( 
y,
-                                                                              
1,
-                                                                              
mySizeY_vertices - 2,
-                                                                              
boundingRectangle.getY2(),
-                                                                              
boundingRectangle.getY1() );
-
-                final Vector2f textureCoordinate = new Vector2f( textureXPos, 
textureYPos );
-
-                BufferUtils.setInBuffer( textureCoordinate, 
myTextureCoordinates, index );
-            }
-        }
-
-        setTextureBuffer( 0, myTextureCoordinates );
-    }
-*/
-
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
        2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
        2008-04-29 21:42:09 UTC (rev 501)
@@ -1,5 +1,7 @@
 package org.skycastle.util.command;
 
+import org.skycastle.util.ParameterChecker;
+
 import javax.swing.*;
 import java.awt.event.ActionEvent;
 import java.util.ArrayDeque;
@@ -42,6 +44,8 @@
 
     };
 
+    private final CommandStackMode myCommandStackMode;
+
     //======================================================================
     // Public Methods
 
@@ -50,9 +54,16 @@
 
     /**
      * Creates a new {@link CommandStackImpl}.
+     *
+     * @param commandStackMode wether to directly execute invoked commands, or 
wether to run them later in the
+     *                         swing thread.
      */
-    public CommandStackImpl()
+    public CommandStackImpl( final CommandStackMode commandStackMode )
     {
+        ParameterChecker.checkNotNull( commandStackMode, "commandStackMode" );
+
+        myCommandStackMode = commandStackMode;
+
         updateActionStatuses();
     }
 
@@ -61,20 +72,25 @@
 
     public void invoke( final Command command )
     {
-        command.doCommand();
+        switch ( myCommandStackMode )
+        {
+            case DIRECT:
+                invokeDirect( command );
+                break;
+            case INVOKE_LATER_IN_SWING_THREAD:
+                SwingUtilities.invokeLater( new Runnable()
+                {
 
-        myRedoStack.clear();
+                    public void run()
+                    {
+                        invokeDirect( command );
+                    }
 
-        if ( command.isDisruptive() )
-        {
-            myUndoStack.clear();
+                } );
+                break;
+            default:
+                throw new IllegalStateException( "Unknown CommandStackMode: " 
+ myCommandStackMode );
         }
-        else if ( command.isUndoable() )
-        {
-            myUndoStack.push( command );
-        }
-
-        updateActionStatuses();
     }
 
 
@@ -158,6 +174,25 @@
     //======================================================================
     // Private Methods
 
+    private void invokeDirect( final Command command )
+    {
+        command.doCommand();
+
+        myRedoStack.clear();
+
+        if ( command.isDisruptive() )
+        {
+            myUndoStack.clear();
+        }
+        else if ( command.isUndoable() )
+        {
+            myUndoStack.push( command );
+        }
+
+        updateActionStatuses();
+    }
+
+
     private void updateActionStatuses()
     {
         myRedoAction.setEnabled( canRedo() );

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackMode.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackMode.java
                                (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackMode.java
        2008-04-29 21:42:09 UTC (rev 501)
@@ -0,0 +1,17 @@
+package org.skycastle.util.command;
+
+/**
+ * @author Hans Haggstrom
+ */
+public enum CommandStackMode
+{
+    /**
+     * Invoke the command directly in the same thread.
+     */
+    DIRECT,
+
+    /**
+     * The command is invoked later in the Swing thread.
+     */
+    INVOKE_LATER_IN_SWING_THREAD,
+}

Modified: 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java
        2008-04-29 15:51:11 UTC (rev 500)
+++ 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java
        2008-04-29 21:42:09 UTC (rev 501)
@@ -175,7 +175,7 @@
     {
         myCounter = new int[]{ 4 };
 
-        myCommandStack = new CommandStackImpl();
+        myCommandStack = new CommandStackImpl( CommandStackMode.DIRECT );
 
         myCountdownAction = new CommandAction( myCommandStack, "Countdown" )
         {


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle: [501] trunk/skycastle/modules