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

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Tue, 29 Apr 2008 07:00:45 -0700

Revision: 499
          http://skycastle.svn.sourceforge.net/skycastle/?rev=499&view=rev
Author:   zzorn
Date:     2008-04-29 07:00:35 -0700 (Tue, 29 Apr 2008)

Log Message:
-----------
Started refactoring the render code.

Modified Paths:
--------------
    
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/utils/src/main/java/org/skycastle/util/ParameterChecker.java

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 10:36:15 UTC (rev 498)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokeAppearanceCalculator.java
     2008-04-29 14:00:35 UTC (rev 499)
@@ -37,7 +37,7 @@
     // Private Constants
 
     private static final float DEFAULT_Z_LEVEL = 0;
-    private static final float DEFAULT_WIDTH = 50;
+    private static final float DEFAULT_WIDTH = 70;
     private static final float DEFAULT_RED = 0;
     private static final float DEFAULT_GREEN = 0;
     private static final float DEFAULT_BLUE = 0;

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 10:36:15 UTC (rev 498)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/rendering/StrokePartRenderer.java
     2008-04-29 14:00:35 UTC (rev 499)
@@ -1,8 +1,301 @@
 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.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;
+
 /**
+ * Holds a part of a stroke.
+ * <p/>
+ * Can update either the whole stroke, or only added parts.
+ *
  * @author Hans Haggstrom
  */
 public class StrokePartRenderer
+        extends TriMesh
 {
+
+    //======================================================================
+    // Private Fields
+
+    private static int theStrokeMeshCounter = 0;
+
+    private final int myStartIndex;
+    private final int myPartLength;
+
+    private final Stroke myStroke;
+
+    private final Object myTextureStateLock = new Object();
+
+    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
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    private final StrokeAppearanceCalculator myAppearanceCalculator;
+
+    /**
+     * Creates a new {@link StrokeRenderer}.
+     *
+     * @param stroke     the stroke that should be rendered
+     * @param startIndex
+     */
+    public StrokeRenderer( final Stroke stroke, final int startIndex, final 
int partLength )
+    {
+        // JME seems to need an unique identifier for each node.  NOTE: Not 
thread safe.
+        //noinspection AssignmentToStaticFieldFromInstanceMethod
+        super( "StrokeMesh_" + theStrokeMeshCounter++ );
+
+        ParameterChecker.checkNotNull( stroke, "stroke" );
+        ParameterChecker.checkPositiveOrZeroInteger( startIndex, "startIndex" 
);
+        ParameterChecker.checkPositiveOrZeroInteger( partLength, "partLength" 
);
+
+        myStartIndex = startIndex;
+        myPartLength = partLength;
+        myStroke = stroke;
+
+        myAppearanceCalculator = new StrokeAppearanceCalculator( myStroke );
+
+
+        myStroke.addStrokeListener( new StrokeListener()
+        {
+
+            public void onPointAdded( final Stroke updatedStroke, final 
DataSample point )
+            {
+                recalculateStroke();
+            }
+
+        } );
+
+        if ( stroke.getPoints().size() >= 2 )
+        {
+            recalculateStroke();
+        }
+
+        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();
+    }
+
+
+    /**
+     * @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 );
+        myTextureCoordinates = BufferUtils.createVector2Buffer( 
numberOfVertices );
+        myNormals = BufferUtils.createVector3Buffer( numberOfVertices );
+        myIndices = BufferUtils.createIntBuffer( numberOfIndices );
+
+        // Stich together the vertices into triangles
+        initializeIndices();
+
+
+        updateBounds();
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void initializeVetices()
+    {
+        myAppearanceCalculator.resetToStart();
+
+        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();
+
+            myAppearanceCalculator.calculateNextPoint( positionLeft, 
positionMid, positionRight,
+                                                       colorLeft, colorMid, 
colorRight );
+
+            setPointData( index++, positionLeft, colorLeft );
+            setPointData( index++, positionMid, colorMid );
+            setPointData( index++, 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 );
+        }
+    }
+
+
 }

Modified: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
        2008-04-29 10:36:15 UTC (rev 498)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/ParameterChecker.java
        2008-04-29 14:00:35 UTC (rev 499)
@@ -134,6 +134,23 @@
      *
      * @throws IllegalArgumentException if the check fails.
      */
+    public static void checkPositiveOrZeroInteger( long parameter, String 
parameterName )
+    {
+        if ( parameter < 0 )
+        {
+            throwIllegalArgumentException( parameterName, parameter, "be a 
positive or zero number" );
+        }
+    }
+
+
+    /**
+     * Checks that the specified parameter is positive or zero.
+     *
+     * @param parameter     the parameter value to check
+     * @param parameterName the name of the parameter (used in error messages)
+     *
+     * @throws IllegalArgumentException if the check fails.
+     */
     public static void checkNonNegativeInteger( int parameter, String 
parameterName )
     {
         if ( parameter < 0 )


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: [499] trunk/skycastle/modules