[skycastle-commits] SF.net SVN: skycastle: [492] trunk/skycastle/modules/ui/src/main/java/org/ skycastle/sketch

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Mon, 28 Apr 2008 00:19:45 -0700

Revision: 492
          http://skycastle.svn.sourceforge.net/skycastle/?rev=492&view=rev
Author:   zzorn
Date:     2008-04-28 00:19:44 -0700 (Mon, 28 Apr 2008)

Log Message:
-----------
Fixed projection!  Yay.

Modified Paths:
--------------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java

Added Paths:
-----------
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java

Removed Paths:
-------------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/StrokeRenderer.java

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-27 23:20:35 UTC (rev 491)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
    2008-04-28 07:19:44 UTC (rev 492)
@@ -14,6 +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.util.ParameterChecker;
 import org.skycastle.util.listenable.collection.CollectionListener;
 import org.skycastle.util.listenable.collection.ListenableCollection;
@@ -47,6 +48,49 @@
     private final Node myRoot3DNode;
     private final PenManager myPenManager;
 
+    private final Object myProjectionLock = new Object();
+
+    private final List<ProjectionChangeListener> myProjectionChangeListeners = 
new ArrayList<ProjectionChangeListener>();
+
+    private final ProjectionChangeListener myProjectionChangeListenerDelegate 
= new ProjectionChangeListener()
+    {
+
+        public void onProjectionChanged( final float xOffs,
+                                         final float yOffs,
+                                         final float xScale,
+                                         final float yScale )
+        {
+            for ( final ProjectionChangeListener listener : 
myProjectionChangeListeners )
+            {
+                listener.onProjectionChanged( xOffs, yOffs, xScale, yScale );
+            }
+        }
+
+    };
+
+    private final ResizeHandler myResizeHandler = new ResizeHandler()
+    {
+
+        public void onScreenResized( final float newCanvasWidth,
+                                     final float newCanvasHeight,
+                                     final float canvasAspectRatio,
+                                     final Camera camera )
+        {
+            updateCameraSyncronized();
+
+            SwingUtilities.invokeLater( new Runnable()
+            {
+
+                public void run()
+                {
+                    notifyListenerAboutProjectionChange( 
myProjectionChangeListenerDelegate );
+                }
+
+            } );
+        }
+
+    };
+
     private Canvas3D myCanvas3D;
     private JToolBar myToolBar;
     private JMenuBar myMenuBar;
@@ -97,27 +141,13 @@
 
         myPenManager = new PenManager( myCanvas3D.get3DView() );
 
-        myCanvas3D.setResizeHandler( createResizeHandler() );
+        myCanvas3D.setResizeHandler( myResizeHandler );
 
         // Make all popup menus and tooltips heavyweight so that they can 
overlap the 3D view
         JPopupMenu.setDefaultLightWeightPopupEnabled( false );
         ToolTipManager.sharedInstance().setLightWeightPopupEnabled( false );
     }
 
-    private ResizeHandler createResizeHandler()
-    {
-        return new ResizeHandler()
-        {
-            public void onScreenResized( final float newCanvasWidth,
-                                         final float newCanvasHeight,
-                                         final float canvasAspectRatio,
-                                         final Camera camera )
-            {
-                // TODO
-            }
-        };
-    }
-
     //----------------------------------------------------------------------
     // Other Public Methods
 
@@ -190,10 +220,13 @@
         ParameterChecker.checkPositiveNonZeroNormalNumber( 
viewSizeHorizontally, "viewSizeHorizontally" );
         ParameterChecker.checkNormalNumber( rotationRadians, "rotationRadians" 
);
 
-        myCameraX = cameraX;
-        myCameraY = cameraY;
-        myViewSizeHorizontally = viewSizeHorizontally;
-        myRotationRadians = rotationRadians;
+        synchronized ( myProjectionLock )
+        {
+            myCameraX = cameraX;
+            myCameraY = cameraY;
+            myViewSizeHorizontally = viewSizeHorizontally;
+            myRotationRadians = rotationRadians;
+        }
 
         if ( myCanvas3D.getCamera() != null &&
              myCanvas3D.isInitialized() )
@@ -217,22 +250,7 @@
         notifyListenerAboutProjectionChange( 
myProjectionChangeListenerDelegate );
     }
 
-    private void notifyListenerAboutProjectionChange( final 
ProjectionChangeListener listener )
-    {
-        final Component view = myCanvas3D.get3DView();
-        if ( view != null )
-        {
-            final float width = view.getWidth();
-            final float height = view.getHeight();
-            final float scale = myViewSizeHorizontally / width;
-            listener.onProjectionChanged( myCameraX - 0.5f * width * scale,
-                                          myCameraY - 0.5f * height * scale,
-                                          scale,
-                                          scale );
-        }
-    }
 
-
     /**
      * Rotates the camera.
      *
@@ -356,9 +374,62 @@
         } );
     }
 
+    /**
+     * @param listener a listener that is notified whenever the projection 
changes.
+     */
+    public void addProjectionChangeListener( final ProjectionChangeListener 
listener )
+    {
+        ParameterChecker.checkNotNull( listener, "listener" );
+        ParameterChecker.checkNotAlreadyContained( listener,
+                                                   myProjectionChangeListeners,
+                                                   
"myProjectionChangeListeners" );
+
+        myProjectionChangeListeners.add( listener );
+
+        notifyListenerAboutProjectionChange( listener );
+    }
+
+    /**
+     * Removes the specified ProjectionChangeListener.
+     *
+     * @param listener should not be null, and should be present.
+     */
+    public void removeProjectionChangeListener( final ProjectionChangeListener 
listener )
+    {
+        ParameterChecker.checkNotNull( listener, "listener" );
+        ParameterChecker.checkContained( listener,
+                                         myProjectionChangeListeners,
+                                         "myProjectionChangeListeners" );
+
+        myProjectionChangeListeners.remove( listener );
+    }
+
     //======================================================================
     // Private Methods
 
+    private void updateCameraSyncronized()
+    {
+        synchronized ( myProjectionLock )
+        {
+            updateCamera( myCanvas3D, myCameraX, myCameraY, 
myViewSizeHorizontally, myRotationRadians );
+        }
+    }
+
+    private void notifyListenerAboutProjectionChange( final 
ProjectionChangeListener listener )
+    {
+        final Component view = myCanvas3D.get3DView();
+        if ( view != null )
+        {
+            final float width = view.getWidth();
+            final float height = view.getHeight();
+            final float scale = myViewSizeHorizontally / width;
+            listener.onProjectionChanged( myCameraX - 0.5f * width * scale,
+                                          myCameraY - 0.5f * height * scale,
+                                          scale,
+                                          scale );
+        }
+    }
+
     private void updateCamera( final Canvas3D canvas3D,
                                final float cameraX,
                                final float cameraY,
@@ -445,51 +516,4 @@
         return menu;
     }
 
-    private final List<ProjectionChangeListener> myProjectionChangeListeners = 
new ArrayList<ProjectionChangeListener>();
-
-    private final ProjectionChangeListener myProjectionChangeListenerDelegate 
= new ProjectionChangeListener()
-    {
-        public void onProjectionChanged( final float xOffs,
-                                         final float yOffs,
-                                         final float xScale,
-                                         final float yScale )
-        {
-            for ( final ProjectionChangeListener listener : 
myProjectionChangeListeners )
-            {
-                listener.onProjectionChanged( xOffs, yOffs, xScale, yScale );
-            }
-        }
-    };
-
-    /**
-     * @param listener a listener that is notified whenever the projection 
changes.
-     */
-    public void addProjectionChangeListener( final ProjectionChangeListener 
listener )
-    {
-        ParameterChecker.checkNotNull( listener, "listener" );
-        ParameterChecker.checkNotAlreadyContained( listener,
-                                                   myProjectionChangeListeners,
-                                                   
"myProjectionChangeListeners" );
-
-        myProjectionChangeListeners.add( listener );
-
-        notifyListenerAboutProjectionChange( listener );
-    }
-
-    /**
-     * Removes the specified ProjectionChangeListener.
-     *
-     * @param listener should not be null, and should be present.
-     */
-    public void removeProjectionChangeListener( final ProjectionChangeListener 
listener )
-    {
-        ParameterChecker.checkNotNull( listener, "listener" );
-        ParameterChecker.checkContained( listener,
-                                         myProjectionChangeListeners,
-                                         "myProjectionChangeListeners" );
-
-        myProjectionChangeListeners.remove( listener );
-    }
-
-
 }

Deleted: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/StrokeRenderer.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/StrokeRenderer.java
   2008-04-27 23:20:35 UTC (rev 491)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/StrokeRenderer.java
   2008-04-28 07:19:44 UTC (rev 492)
@@ -1,508 +0,0 @@
-package org.skycastle.sketch;
-
-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.sketch.model.stroke.Stroke;
-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;
-
-/**
- * A 3D node that renders a {@link Stroke}.
- *
- * @author Hans Häggström
- */
-@SuppressWarnings( { "serial" } )
-public final class StrokeRenderer
-        extends TriMesh
-{
-
-    //======================================================================
-    // Private Fields
-
-    private static int theStrokeMeshCounter = 0;
-
-    private final Stroke myStroke;
-
-    private final float myZ;
-    private final FloatBuffer myVertexes;
-    private final FloatBuffer myColors;
-    private final FloatBuffer myTextureCoordinates;
-    private final FloatBuffer myNormals;
-    private final IntBuffer myIndices;
-    private final int myNumberOfVertices;
-    private final int myNumberOfIndices;
-
-    private final Object myTextureStateLock = new Object();
-    private final int myNumberOfPoints;
-    private final int myNumberOfSegments;
-    private final int myNumberOfTriangles;
-
-    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;
-
-    //======================================================================
-    // Public Methods
-
-    //----------------------------------------------------------------------
-    // Constructors
-
-    /**
-     * Creates a new {@link org.skycastle.sketch.StrokeRenderer}.
-     *
-     * @param stroke the stroke that should be rendered
-     */
-    public StrokeRenderer( final Stroke stroke )
-    {
-        this( stroke, 0 );
-    }
-
-
-    /**
-     * Creates a new {@link org.skycastle.sketch.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;
-        myZ = z;
-
-        // Calculate sizes
-        myNumberOfPoints = myStroke.getPoints().size();
-        myNumberOfSegments = myNumberOfPoints - 1;
-        myNumberOfTriangles = myNumberOfSegments * 
NUMBER_OF_TRIANGLES_PER_SEGMENT;
-        myNumberOfVertices = myNumberOfPoints * 3;
-        myNumberOfIndices = myNumberOfSegments * NUMBER_OF_INDICES_IN_SEGMENT;
-
-        // Create databuffers
-        myVertexes = BufferUtils.createVector3Buffer( myNumberOfVertices );
-        myColors = BufferUtils.createColorBuffer( myNumberOfVertices );
-        myTextureCoordinates = BufferUtils.createVector2Buffer( 
myNumberOfVertices );
-        myNormals = BufferUtils.createVector3Buffer( myNumberOfVertices );
-        myIndices = BufferUtils.createIntBuffer( myNumberOfIndices );
-
-        // Stich together the vertices into triangles
-        initializeIndices();
-
-
-        updateBounds();
-
-
-        GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE 
).enqueue( new Callable<Object>()
-        {
-
-            public Object call() throws Exception
-            {
-                final Renderer renderer = 
DisplaySystem.getDisplaySystem().getRenderer();
-
-                final StrokeRenderer strokeRenderer = 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();
-
-                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()
-    {
-        // Put vertices in correct places
-        initializeVetices();
-
-        // 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 )
-        {
-            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;
-                }
-
-            } );
-        }
-
-    */
-
-    /**
-     * @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
-
-/*
-    public void setPlaceholderTexture( final Texture texture, final 
BoundingRectangle textureArea )
-    {
-        synchronized ( myTextureStateLock )
-        {
-            myPlaceholderTextureInUse = true;
-
-            if ( myTextureState != null )
-            {
-                // Update texture indexes
-                setTextureCoordinates( textureArea );
-
-                // Update the geometry
-                updateGeometricState( 0, true );
-
-                // Use placeholder if no texture specified
-                Texture textureToUse = texture;
-                if ( textureToUse == null )
-                {
-                    textureToUse = PLACEHOLDER_TEXTURE;
-                }
-
-                // Set the texture
-                myTextureState.setTexture( textureToUse );
-
-                updateRenderState();
-            }
-        }
-    }
-*/
-
-/*
-    public boolean isPlaceholderTextureInUse()
-    {
-        return myPlaceholderTextureInUse;
-    }
-*/
-
-    //======================================================================
-    // Private Methods
-
-    private void initializeVetices()
-    {
-        final DataSample pointState = new DataSample();
-
-        int pointIndex = 0;
-        for ( final DataSample strokePoint : myStroke.getPoints() )
-        {
-            pointState.updateValuesWith( strokePoint );
-
-            initializePoint( pointState, pointIndex++ );
-        }
-    }
-
-
-    @SuppressWarnings( { "PointlessArithmeticExpression" } )
-    private void initializePoint( final DataSample strokePoint, final int 
pointIndex )
-    {
-        final int index = pointIndex * 3;
-
-        final float xPos = strokePoint.getVariable( "x", 0 );
-        final float yPos = strokePoint.getVariable( "y", 0 );
-        final float zPos = myZ;
-        final float width = strokePoint.getVariable( "width", 0.5f );
-
-        final float colorR = strokePoint.getVariable( "colorR", 0 );
-        final float colorG = strokePoint.getVariable( "colorG", 0 );
-        final float colorB = strokePoint.getVariable( "colorB", 0 );
-        final float colorA = strokePoint.getVariable( "colorA", 0.7f );
-
-        final Vector3f positionLeft = new Vector3f( xPos, yPos + width, zPos );
-        final ColorRGBA colorLeft = new ColorRGBA( colorR, colorG, colorB, 0 );
-
-        final Vector3f positionMid = new Vector3f( xPos, yPos, zPos );
-        final ColorRGBA colorMid = new ColorRGBA( colorR, colorG, colorB, 
colorA );
-
-        final Vector3f positionRight = new Vector3f( xPos, yPos - width, zPos 
);
-        final ColorRGBA colorRight = new ColorRGBA( colorR, colorG, colorB, 0 
);
-
-        setPointData( index + 0, positionLeft, colorLeft );
-        setPointData( index + 1, positionMid, colorMid );
-        setPointData( index + 2, positionRight, colorRight );
-    }
-
-
-    private void setPointData( final int index, final Vector3f position, final 
ColorRGBA color )
-    {
-        BufferUtils.setInBuffer( position, myVertexes, index );
-        BufferUtils.setInBuffer( new Vector3f(), myNormals, index );
-        BufferUtils.setInBuffer( color, myColors, index );
-        BufferUtils.setInBuffer( new Vector2f(), myTextureCoordinates, index );
-    }
-
-
-    @SuppressWarnings( { "PointlessArithmeticExpression" } )
-    private void initializeIndices()
-    {
-        // 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++ )
-        {
-            /*
-            Segment, with vertex order marked in:
-
-            0---3
-            | \ |
-            1---4   --> direction of stroke
-            | / |
-            2---5
-
-             */
-
-            final int segmentStartVertex = segment * 3;
-
-            myIndices.put( index++, segmentStartVertex + 3 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 0 );
-
-            myIndices.put( index++, segmentStartVertex + 0 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 1 );
-
-            myIndices.put( index++, segmentStartVertex + 1 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.put( index++, segmentStartVertex + 2 );
-
-            myIndices.put( index++, segmentStartVertex + 2 );
-            myIndices.put( index++, segmentStartVertex + 4 );
-            myIndices.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 );
-    }
-*/
-
-}

Copied: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
 (from rev 491, 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/StrokeRenderer.java)
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
                         (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeRenderer.java
 2008-04-28 07:19:44 UTC (rev 492)
@@ -0,0 +1,518 @@
+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.sketch.model.stroke.Stroke;
+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;
+
+/**
+ * A 3D node that renders a {@link Stroke}.
+ *
+ * @author Hans Häggström
+ */
+@SuppressWarnings( { "serial" } )
+public final class StrokeRenderer
+        extends TriMesh
+{
+
+    //======================================================================
+    // Private Fields
+
+    private static int theStrokeMeshCounter = 0;
+
+    private final Stroke myStroke;
+
+    private final float myZ;
+    private final FloatBuffer myVertexes;
+    private final FloatBuffer myColors;
+    private final FloatBuffer myTextureCoordinates;
+    private final FloatBuffer myNormals;
+    private final IntBuffer myIndices;
+    private final int myNumberOfVertices;
+    private final int myNumberOfIndices;
+
+    private final Object myTextureStateLock = new Object();
+    private final int myNumberOfPoints;
+    private final int myNumberOfSegments;
+    private final int myNumberOfTriangles;
+
+    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 static final float DEFAULT_WIDTH = 8f;
+    private static final float DEFAULT_RED = 0;
+    private static final float DEFAULT_GREEN = 0;
+    private static final float DEFAULT_BLUE = 0f;
+    private static final float DEFAULT_ALPHA = 0.7f;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new {@link StrokeRenderer}.
+     *
+     * @param stroke the stroke that should be rendered
+     */
+    public StrokeRenderer( final Stroke stroke )
+    {
+        this( stroke, 0 );
+    }
+
+
+    /**
+     * 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;
+        myZ = z;
+
+        // Calculate sizes
+        myNumberOfPoints = myStroke.getPoints().size();
+        myNumberOfSegments = myNumberOfPoints - 1;
+        myNumberOfTriangles = myNumberOfSegments * 
NUMBER_OF_TRIANGLES_PER_SEGMENT;
+        myNumberOfVertices = myNumberOfPoints * 3;
+        myNumberOfIndices = myNumberOfSegments * NUMBER_OF_INDICES_IN_SEGMENT;
+
+        // Create databuffers
+        myVertexes = BufferUtils.createVector3Buffer( myNumberOfVertices );
+        myColors = BufferUtils.createColorBuffer( myNumberOfVertices );
+        myTextureCoordinates = BufferUtils.createVector2Buffer( 
myNumberOfVertices );
+        myNormals = BufferUtils.createVector3Buffer( myNumberOfVertices );
+        myIndices = BufferUtils.createIntBuffer( myNumberOfIndices );
+
+        // Stich together the vertices into triangles
+        initializeIndices();
+
+
+        updateBounds();
+
+
+        GameTaskQueueManager.getManager().getQueue( GameTaskQueue.UPDATE 
).enqueue( new Callable<Object>()
+        {
+
+            public Object call()
+                    throws Exception
+            {
+                final Renderer renderer = 
DisplaySystem.getDisplaySystem().getRenderer();
+
+                final StrokeRenderer strokeRenderer = 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()
+    {
+        // Put vertices in correct places
+        initializeVetices();
+
+        // 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 )
+        {
+            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;
+                }
+
+            } );
+        }
+
+    */
+
+    /**
+     * @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
+
+/*
+    public void setPlaceholderTexture( final Texture texture, final 
BoundingRectangle textureArea )
+    {
+        synchronized ( myTextureStateLock )
+        {
+            myPlaceholderTextureInUse = true;
+
+            if ( myTextureState != null )
+            {
+                // Update texture indexes
+                setTextureCoordinates( textureArea );
+
+                // Update the geometry
+                updateGeometricState( 0, true );
+
+                // Use placeholder if no texture specified
+                Texture textureToUse = texture;
+                if ( textureToUse == null )
+                {
+                    textureToUse = PLACEHOLDER_TEXTURE;
+                }
+
+                // Set the texture
+                myTextureState.setTexture( textureToUse );
+
+                updateRenderState();
+            }
+        }
+    }
+*/
+
+/*
+    public boolean isPlaceholderTextureInUse()
+    {
+        return myPlaceholderTextureInUse;
+    }
+*/
+
+    //======================================================================
+    // Private Methods
+
+    private void initializeVetices()
+    {
+        final DataSample pointState = new DataSample();
+
+        int pointIndex = 0;
+        for ( final DataSample strokePoint : myStroke.getPoints() )
+        {
+            pointState.updateValuesWith( strokePoint );
+
+            initializePoint( pointState, pointIndex++ );
+        }
+    }
+
+
+    @SuppressWarnings( { "PointlessArithmeticExpression" } )
+    private void initializePoint( final DataSample strokePoint, final int 
pointIndex )
+    {
+        final int index = pointIndex * 3;
+
+        final float xPos = strokePoint.getVariable( "x", 0 );
+        final float yPos = strokePoint.getVariable( "y", 0 );
+        final float zPos = myZ;
+        final float width = strokePoint.getVariable( "width", DEFAULT_WIDTH );
+
+        final float colorR = strokePoint.getVariable( "colorR", DEFAULT_RED );
+        final float colorG = strokePoint.getVariable( "colorG", DEFAULT_GREEN 
);
+        final float colorB = strokePoint.getVariable( "colorB", DEFAULT_BLUE );
+        final float colorA = strokePoint.getVariable( "colorA", DEFAULT_ALPHA 
);
+
+        final Vector3f positionLeft = new Vector3f( xPos, yPos + width, zPos );
+        final ColorRGBA colorLeft = new ColorRGBA( colorR, colorG, colorB, 0 );
+
+        final Vector3f positionMid = new Vector3f( xPos, yPos, zPos );
+        final ColorRGBA colorMid = new ColorRGBA( colorR, colorG, colorB, 
colorA );
+
+        final Vector3f positionRight = new Vector3f( xPos, yPos - width, zPos 
);
+        final ColorRGBA colorRight = new ColorRGBA( colorR, colorG, colorB, 0 
);
+
+        setPointData( index + 0, positionLeft, colorLeft );
+        setPointData( index + 1, positionMid, colorMid );
+        setPointData( index + 2, positionRight, colorRight );
+    }
+
+
+    private void setPointData( final int index, final Vector3f position, final 
ColorRGBA color )
+    {
+        BufferUtils.setInBuffer( position, myVertexes, index );
+        BufferUtils.setInBuffer( new Vector3f(), myNormals, index );
+        BufferUtils.setInBuffer( color, myColors, index );
+        BufferUtils.setInBuffer( new Vector2f(), myTextureCoordinates, index );
+    }
+
+
+    @SuppressWarnings( { "PointlessArithmeticExpression" } )
+    private void initializeIndices()
+    {
+        // 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++ )
+        {
+            /*
+            Segment, with vertex order marked in:
+
+            0---3
+            | \ |
+            1---4   --> direction of stroke
+            | / |
+            2---5
+
+             */
+
+            final int segmentStartVertex = segment * 3;
+
+            myIndices.put( index++, segmentStartVertex + 3 );
+            myIndices.put( index++, segmentStartVertex + 4 );
+            myIndices.put( index++, segmentStartVertex + 0 );
+
+            myIndices.put( index++, segmentStartVertex + 0 );
+            myIndices.put( index++, segmentStartVertex + 4 );
+            myIndices.put( index++, segmentStartVertex + 1 );
+
+            myIndices.put( index++, segmentStartVertex + 1 );
+            myIndices.put( index++, segmentStartVertex + 4 );
+            myIndices.put( index++, segmentStartVertex + 2 );
+
+            myIndices.put( index++, segmentStartVertex + 2 );
+            myIndices.put( index++, segmentStartVertex + 4 );
+            myIndices.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 );
+    }
+*/
+
+}


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: [492] trunk/skycastle/modules/ui/src/main/java/org/ skycastle/sketch