Draw a line

Got a question? Need help? Post here!

Draw a line

Postby kaivanwadiia » Thu Jun 21, 2012 3:43 am

Hi.. Is there anyway you can draw a line in Axgl??

In part of my game a player has to trace a line, i.e Hold the mouse and make a line which is not necessarily straight actually it will predominantly be crooked.

So is there anyway I can highlight this line to the user and actually even make it collidable if need be.

THanks
kaivanwadiia
Corporal
 
Posts: 17
Joined: Mon Jun 11, 2012 4:46 am

Re: Draw a line

Postby reverso13 » Wed Jul 25, 2012 2:04 pm

I'm also interested on this theme, let's see if someone knows the answer :roll:
reverso13
Corporal
 
Posts: 13
Joined: Wed Jul 25, 2012 2:03 pm

Re: Draw a line

Postby Matthew » Fri Aug 31, 2012 12:25 am

Not sure if it's cosher to post large chunks of code. But here's my AxGraph class I've been using for a game

It needs to be setup with AxGraph.Initilize(Ax.camera.baseProjection,Ax.camera.projection,null);

then you can just use it as follows:

AxGraph.screen.drawLine(x,y,x2,y2)
AxGraph.world.drawLine(x,y,x2,y2)

etc.

Let me know if you have any problems.

P.S. it's not the most efficient code in the world, but it works ok.

-Matthew.

Code: Select all
package org.axgl.render
{
   import flash.display.BitmapData;
   import flash.display3D.Context3D;
   import flash.display3D.Context3DCompareMode;
   import flash.display3D.Context3DProgramType;
   import flash.display3D.Context3DTriangleFace;
   import flash.display3D.Context3DVertexBufferFormat;
   import flash.display3D.IndexBuffer3D;
   import flash.display3D.VertexBuffer3D;
   import flash.display3D.textures.Texture;
   import flash.display3D.textures.TextureBase;
   import flash.geom.Matrix;
   import flash.geom.Matrix3D;
   import flash.geom.Rectangle;
   import flash.geom.Transform;
   import flash.geom.Vector3D;
   
   import org.axgl.*;
   import org.axgl.util.*;
   
   
   /**
    * Allows for drawing of basic objects in 3d space
    */
   public class AxGraph
   {      
      
      /** If enabled polygons will also draw there vertexes (including tangents).  Used for debugging. */
      public static const DEBUG_DRAW_POLYGON_VERTEXES:Boolean = false;
      
      /** Graph3d that draws to world space */      
      public static var world:AxGraph;
      /** Graph3d that drawse to screen space */
      public static var screen:AxGraph;
      /** Graph3d that draws to starmap */
      public static var starMap:AxGraph;
         
      /** Matrix used to transform co-ords to destination */
      public var transformationMatrix:Matrix3D;
      /** Shader used for drawing solid color objects */
      public var solidColorShader:AxShader;
      /** Shader used for drawing texture objects */
      public var textureShader:AxShader;
      /** Shader used for drawing texture objects with a color matrix*/
      public var textureShaderAdv:AxShader;
      /** Context used to render items */
      public var context:Context3D;
      
      
      // vertex data... note: these could be static if needed, unless I want to create a hi-res instance
      
      /** Defines a simple quad of co-ords (0,0), (1,1).  This can be scaled or rotated to draw any rectangular object */
      private var quadVertexBuffer:VertexBuffer3D;
      private var quadVertexData:Vector.<Number>;
      private var quadIndexBuffer:IndexBuffer3D;
      
      /** Defines vertexes for a circle */
      private var circleVertexBuffer:VertexBuffer3D;
      private var circleVertexData:Vector.<Number>;
      private var circleIndexBuffer:IndexBuffer3D;      
      
      /** Color used to draw objects */
      public var drawColor:Vector.<Number>
      
      /** Transforms the UV cords of a texture.  Used for rendering a section of a texture*/
      public var uvOffset:Vector.<Number>
      /** Transforms the UV cords of a texture.  Used for rendering a section of a texture*/       
      public var uvMultiplier:Vector.<Number>      
      
      public var blend:AxBlendMode = AxBlendMode.BLEND;
      
      /** Matrix used for drawing objects */
      protected var matrix:Matrix3D;
            
      /** if true screen coords will be used */
      private var useScreenCoords:Boolean = false;
                     
      public function AxGraph(transformationMatrix:Matrix3D)
      {         
         this.solidColorShader = AxCache.shader("GraphColorShader", VERTEX_SHADER, FRAGMENT_SHADER_SOLID_COLOR, 4);         
         this.textureShader = AxCache.shader("GraphTextureShader", VERTEX_SHADER, FRAGMENT_SHADER_TEXTURE, 4);
         this.textureShaderAdv = AxCache.shader("GraphTextureShaderAdv", VERTEX_SHADER, FRAGMENT_SHADER_TEXTURE_ADV, 4);
         this.drawColor = Vector.<Number>([0,1,1,1]);                        
         this.matrix = new Matrix3D();
         this.uvOffset = new Vector.<Number>(4,0);         
         this.uvMultiplier = new Vector.<Number>(4,1);         
         this.transformationMatrix = transformationMatrix;
         if (!context)
            context = Ax.context;
         this.context = context;
         
         createVertexData();         
      }      
      
      /**
       * Creates default screen and world graphics outputs using given matrixes
       */
      public static function Initilize(screenMatrix:Matrix3D,worldMatrix:Matrix3D,starMapMatrix:Matrix3D):void
      {
         AxGraph.screen = new AxGraph(screenMatrix);         
         AxGraph.world = new AxGraph(worldMatrix);
         AxGraph.starMap = new AxGraph(starMapMatrix);
      }
         
      
      /**
       * draws a rectangle from x,y to x2,y2
       */
      public function drawRect(x:Number,y:Number,x2:Number,y2:Number,color:AxColor,thickness:Number = 1):void
      {
         // if true uses the polygon function to draw the rectangle.  Has the advantage of the corners looking better (but I can
         // fix this with the draw lines aswell) but it's about twice as slow... which is a shame as I thought it might be faster
         const USE_POLYGON_METHOD:Boolean = false;
                  
         if (USE_POLYGON_METHOD)
         {         
            var data:Vector.<Number> = new Vector.<Number>(4*4);         
            data[0*4+0] = x;
            data[0*4+1] = y;
            data[1*4+0] = x2;
            data[1*4+1] = y;
            data[2*4+0] = x2;
            data[2*4+1] = y2;
            data[3*4+0] = x;
            data[3*4+1] = y2;         
            drawPolygon(0,0,1,color,data,-1,thickness,true);
         } else
         {
            drawLine(x+thickness/2,y,x2-thickness/2,y,color,thickness);
            drawLine(x2,y-thickness/2,x2,y2+thickness/2,color,thickness);
            drawLine(x2-thickness/2,y2,x+thickness/2,y2,color,thickness);
            drawLine(x,y2+thickness/2,x,y-thickness/2,color,thickness);   
         }         
      }         
      
      /**
       * draws a filled rectangle from x,y to x2,y2
       */
      public function fillRect(x:Number,y:Number,x2:Number,y2:Number,color:AxColor):void
      {
         //not the greatest solution, but this will work.  Just draw one really thick line.
         var width: Number = x2-x;
         var height: Number = y2-y;      
         drawLine(x,y+height/2,x+width,y+height/2,color,height);      
      }
      
      /**
       * Draws a polygon frame at given location
       *
       * todo: support non closed polygons
       *
       * @data: List of vertex locations in the format x1,y1,u1,v1,x2,y2,u2,v2 etc
       * @closed: If true a final line will be drawn between the last and first vertex
       */
      public function drawPolygon(x:Number,y:Number,scale:Number,color:AxColor,data:Vector.<Number>,vertexs:Number = -1,thickness:Number=1, closed:Boolean = true):void
      {
                  
         if (vertexs < 0)
            vertexs = data.length/4;
         
         // create vertex data
         var polygonVertexBuffer:VertexBuffer3D;
         var vertexData:Vector.<Number>;
         var polygonIndexBuffer:IndexBuffer3D;
         var indexData:Vector.<uint>;
         
         var tangent: AxVector = new AxVector;
         
         vertexData = new Vector.<Number>(vertexs*2*4,0);
         indexData = new Vector.<uint>(vertexs*6,0);
         
         for (var pointOn:int = 0;pointOn <= vertexs-1;pointOn++)                  
         {   
            var thisPoint:int = pointOn;
            var nextPoint:int = (pointOn + 1) % vertexs;
            
         
            if ((!closed) && (pointOn == vertexs-1))
            {
               // if we are an open polygon and this is the last vertex, reuse the last tangent rather than getting a tangent to the first
               // vertex... as that would warp the last line in the polygon
            } else
            {
               tangent.y = data[thisPoint*4+0]-data[nextPoint*4+0];
               tangent.x = data[nextPoint*4+1]-data[thisPoint*4+1];
            }
            
            tangent.normalise(thickness*0.5);
            
            // calculate vertex points with given thickness
            vertexData[0+0+pointOn*8] = x+scale*data[0+thisPoint*4]+tangent.x;
            vertexData[0+1+pointOn*8] = y+scale*data[1+thisPoint*4]+tangent.y;            
            vertexData[4+0+pointOn*8] = x+scale*data[0+thisPoint*4]-tangent.x;
            vertexData[4+1+pointOn*8] = y+scale*data[1+thisPoint*4]-tangent.y;
            
            if (DEBUG_DRAW_POLYGON_VERTEXES)
            {
               fillCircle(x+scale*data[0+thisPoint*4],y+scale*data[1+thisPoint*4],5,AxStaticColor.RED);
               fillCircle(vertexData[0+0+pointOn*8],vertexData[0+1+pointOn*8],2,AxStaticColor.YELLOW);
               fillCircle(vertexData[4+0+pointOn*8],vertexData[4+1+pointOn*8],2,AxStaticColor.YELLOW);
            }
            
            
            
            indexData[0+pointOn*6] = 0+thisPoint*2;
            indexData[1+pointOn*6] = 0+nextPoint*2;
            indexData[2+pointOn*6] = 1+thisPoint*2;
            indexData[3+pointOn*6] = 0+nextPoint*2;
            indexData[4+pointOn*6] = 1+nextPoint*2;
            indexData[5+pointOn*6] = 1+thisPoint*2;                     
         }
         
         
         polygonVertexBuffer = context.createVertexBuffer(vertexs*2,4);
         polygonVertexBuffer.uploadFromVector(vertexData, 0, vertexs*2);
         
         polygonIndexBuffer = context.createIndexBuffer(vertexs*6);
         polygonIndexBuffer.uploadFromVector(indexData, 0, vertexs * 6);
         
         matrix.identity();                  
         matrix.append(transformationMatrix);
         
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;                  
         
         context.setProgram(solidColorShader.program);
         context.setBlendFactors(blend.source, blend.destination);            
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, drawColor);
         context.setVertexBufferAt(0, polygonVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);         
         context.setVertexBufferAt(1, polygonVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
         context.drawTriangles(polygonIndexBuffer,0,closed ? vertexs * 2 : (vertexs-1) * 2);         
         context.setVertexBufferAt(0, null, 0, Context3DVertexBufferFormat.FLOAT_2);
         context.setVertexBufferAt(1, null, 2, Context3DVertexBufferFormat.FLOAT_2);                     
      }               
      
      /**
       * Draws an unfilled circle at x,y of given radius
       */
      public function drawCircle(x:Number,y:Number,radius:Number,color:AxColor,thickness:Number=1):void
      {   
         drawPolygon(x,y,radius,color,circleVertexData,36,thickness);
      }
            
      /**
       * Draws an circle segment at x,y of given radius and angles
       */
      public function drawSegment(x:Number,y:Number,radius:Number,startAngle:Number,endAngle:Number,color:AxColor):void
      {            
         drawArc(x,y,radius/2,startAngle,endAngle,color,radius);
      }
      
      
      /**
       * Draws an arc at x,y of given radius and angles
       */
      public function drawArc(x:Number,y:Number,radius:Number,startAngle:Number,endAngle:Number,color:AxColor,thickness:Number=1):void
      {   
         var vertexes:int = 8;
         var arcLength:Number = radius * Math.PI * 2 * (Math.abs(endAngle-startAngle)/360);         
         if (arcLength > 100) vertexes = 16;         
         if (arcLength > 200) vertexes = 24;
         if (arcLength > 400) vertexes = 32;
         if (arcLength > 800) vertexes = 64;         
                  
         var vertexData:Vector.<Number> = new Vector.<Number>
         vertexData.length = vertexes*4;
         vertexData.fixed = true;
         for (var vertexOn: int = 0;vertexOn < vertexes;vertexOn ++)
         {
            var factor:Number = vertexOn/(vertexes-1);            
            
            var radian:Number = (startAngle+(factor)*(endAngle-startAngle))*AxU.D2R;
            vertexData[vertexOn*4+0] = Math.sin(radian);
            vertexData[vertexOn*4+1] = -Math.cos(radian);
            vertexData[vertexOn*4+2] = 0;
            vertexData[vertexOn*4+3] = 0;            
         }
         
         drawPolygon(x,y,radius,color,vertexData,vertexes,thickness,false);
      }
      
      /**
       * draws a filled circle at x,y of given radius
       */
      public function fillCircle(x:Number,y:Number,radius:Number,color:AxColor):void
      {         
         
         matrix.identity();   
         matrix.appendScale(radius,radius,1);         
         matrix.appendTranslation(x,y,0);         
         matrix.append(transformationMatrix);
         
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;
                           
         context.setProgram(solidColorShader.program);
         context.setBlendFactors(blend.source, blend.destination);
                  
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);         
         context.setVertexBufferAt(0, circleVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); //load xy         
         context.setVertexBufferAt(1, circleVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); //loud uv
         context.drawTriangles(circleIndexBuffer);               
      }         
            
      /**
       * draws a line from x,y to x2,y2
       */
      public function drawLine(x:Number,y:Number,x2:Number,y2:Number,color:AxColor,thickness:Number = 1):void
      {                        
         if (thickness == 0) return;
                           
         var length:Number = Math.sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y))+1;         
         var angle:Number = AxU.getAngle(x,y,x2,y2)/Math.PI*180;
                  
         matrix.identity();   
         matrix.appendTranslation(-0.5,0,0);
         matrix.appendScale(thickness,-length,1);
         matrix.appendRotation(90+angle, Vector3D.Z_AXIS);         
         matrix.appendTranslation(x,y,0);         
         matrix.append(transformationMatrix);
                              
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;                  
                  
         context.setProgram(solidColorShader.program);
         context.setBlendFactors(blend.source, blend.destination);            
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, drawColor);
         context.setVertexBufferAt(0, quadVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);         
         context.setVertexBufferAt(1, quadVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
         context.drawTriangles(quadIndexBuffer);         
         context.setVertexBufferAt(0, null, 0, Context3DVertexBufferFormat.FLOAT_2);
         context.setVertexBufferAt(1, null, 2, Context3DVertexBufferFormat.FLOAT_2);
                           
      }
      
      /**
       * Creates vertex buffers, and indexes used for drawing
       */
      private function createVertexData():void
      {
         //LINE:
         quadVertexBuffer = context.createVertexBuffer(4, 4);
         quadVertexData = Vector.<Number>([            
            0,       0,      0,      0,          
            1,      0,      1,      0,
            0,      1,      0,      1,
            1,      1,      1,      1,]);                                     
         quadVertexBuffer.uploadFromVector(quadVertexData, 0, 4);         
         quadIndexBuffer = context.createIndexBuffer(6);
         quadIndexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 1, 2, 3]), 0, 6);
                  
         //CIRCLE:
         const segments:int = 36;
         
         var midPointVertex:int = segments;
         
         circleVertexBuffer = context.createVertexBuffer(segments+1,4);
         circleVertexData = new Vector.<Number>;         
         //circumfrance points
         for (var cnt:int = 0;cnt < segments;cnt++)
         {
            circleVertexData.push(Math.sin(cnt*360/segments*Math.PI/180));
            circleVertexData.push(-Math.cos(cnt*360/segments*Math.PI/180));
            circleVertexData.push(0);
            circleVertexData.push(0);
         }
         //center point
         circleVertexData.push(0);circleVertexData.push(0);circleVertexData.push(0);circleVertexData.push(0);
         
         circleVertexBuffer.uploadFromVector(circleVertexData,0,segments+1);      
         
         circleIndexBuffer = context.createIndexBuffer(segments*3);
         var tmp:Vector.<uint> = new Vector.<uint>;
         for (cnt = 0;cnt < segments;cnt++)
         {
            tmp.push(midPointVertex);
            tmp.push(cnt);
            if (cnt == (segments-1))
               tmp.push(0);
            else
               tmp.push(cnt+1);
         }         
         circleIndexBuffer.uploadFromVector(tmp,0,segments*3);               
      }
      
      /** creates a blank texture used to draw objects.
       * Note: not really sure why this is needed, but I can't get drawing to work without
       */
      protected function createTexture():void
      {
         var bitmap:BitmapData;
         bitmap = new BitmapData(1, 1, true, 0x000000);                  
      }
      
      /**
       * The vertex shader for this sprite.
       */
      private static const VERTEX_SHADER:Array = [      
         "m44 op, va0, vc0",
         "mul vt1, va1, vc5",      
         "add v1, vt1, vc4",      //pass uv to fragment shader
         //"mov v1, va1",
      ];
      
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_SOLID_COLOR:Array = [
         "mov oc, fc0"         
      ];      
      
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_TEXTURE:Array = [
         "tex ft0, v1, fs0 <2d,linear,mipnone>",
         "mul ft0, ft0, fc0",         
         //"add ft0, ft0, fc1",                  
         "mov oc, ft0"         
      ];
      
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_TEXTURE_ADV:Array = [
         "tex ft0, v1, fs0 <2d,linear,mipnone>",      
         "m44, ft0, ft0, fc2",                   
         "mul ft0, ft0, fc0",                                 
         "mov oc, ft0"                                             
      ];
            
   }   
   
}
Matthew
Private
 
Posts: 3
Joined: Thu Aug 16, 2012 8:10 pm

Re: Draw a line

Postby Jeddychan » Thu Sep 20, 2012 8:17 pm

Matthew wrote:Not sure if it's cosher to post large chunks of code. But here's my AxGraph class I've been using for a game

It needs to be setup with AxGraph.Initilize(Ax.camera.baseProjection,Ax.camera.projection,null);

then you can just use it as follows:

AxGraph.screen.drawLine(x,y,x2,y2)
AxGraph.world.drawLine(x,y,x2,y2)

etc.

Let me know if you have any problems.

P.S. it's not the most efficient code in the world, but it works ok.

-Matthew.



Hello,
I was wondering if you had a working example of this class. I've been trying to figure out how to get it to work, and having a working piece of code implementing the drawLine function would help me to figure out what I'm doing wrong.
Jeddychan
Private
 
Posts: 1
Joined: Thu Sep 20, 2012 8:14 pm

Re: Draw a line

Postby tharo » Fri Jun 21, 2013 11:11 am

I just took myself some time to make this code running.
It was .. a bit confusing how the Autor was using some classes... but however: I made it working!

Code: Select all
package info.orpg.patches
{
   import flash.display.BitmapData;
   import flash.display3D.Context3D;
   import flash.display3D.Context3DCompareMode;
   import flash.display3D.Context3DProgramType;
   import flash.display3D.Context3DTriangleFace;
   import flash.display3D.Context3DVertexBufferFormat;
   import flash.display3D.IndexBuffer3D;
   import flash.display3D.VertexBuffer3D;
   import flash.display3D.textures.Texture;
   import flash.display3D.textures.TextureBase;
   import flash.geom.Matrix;
   import flash.geom.Matrix3D;
   import flash.geom.Rectangle;
   import flash.geom.Transform;
   import flash.geom.Vector3D;
   
   import org.axgl.*;
   import org.axgl.util.*;
   import org.axgl.render.*;
   import flash.geom.Vector3D;
   
   /**
    * Allows for drawing of basic objects in 3d space
    */
   public class AxGraph
   {     
     
      /** If enabled polygons will also draw there vertexes (including tangents).  Used for debugging. */
      public static const DEBUG_DRAW_POLYGON_VERTEXES:Boolean = false;
     
      /** Graph3d that draws to world space */     
      public static var world:AxGraph;
      /** Graph3d that drawse to screen space */
      public static var screen:AxGraph;
      /** Graph3d that draws to starmap */
      public static var starMap:AxGraph;
         
      /** Matrix used to transform co-ords to destination */
      public var transformationMatrix:Matrix3D;
      /** Shader used for drawing solid color objects */
      public var solidColorShader:AxShader;
      /** Shader used for drawing texture objects */
      public var textureShader:AxShader;
      /** Shader used for drawing texture objects with a color matrix*/
      public var textureShaderAdv:AxShader;
      /** Context used to render items */
      public var context:Context3D;
     
     
      // vertex data... note: these could be static if needed, unless I want to create a hi-res instance
     
      /** Defines a simple quad of co-ords (0,0), (1,1).  This can be scaled or rotated to draw any rectangular object */
      private var quadVertexBuffer:VertexBuffer3D;
      private var quadVertexData:Vector.<Number>;
      private var quadIndexBuffer:IndexBuffer3D;
     
      /** Defines vertexes for a circle */
      private var circleVertexBuffer:VertexBuffer3D;
      private var circleVertexData:Vector.<Number>;
      private var circleIndexBuffer:IndexBuffer3D;     
     
      /** Color used to draw objects */
      public var drawColor:Vector.<Number>
     
      /** Transforms the UV cords of a texture.  Used for rendering a section of a texture*/
      public var uvOffset:Vector.<Number>
      /** Transforms the UV cords of a texture.  Used for rendering a section of a texture*/       
      public var uvMultiplier:Vector.<Number>     
     
      public var blend:AxBlendMode = AxBlendMode.BLEND;
     
      /** Matrix used for drawing objects */
      protected var matrix:Matrix3D;
           
      /** if true screen coords will be used */
      private var useScreenCoords:Boolean = false;
                     
      public function AxGraph(transformationMatrix:Matrix3D)
      {         
         this.solidColorShader = AxCache.shader("GraphColorShader", VERTEX_SHADER, FRAGMENT_SHADER_SOLID_COLOR, 4);         
         this.textureShader = AxCache.shader("GraphTextureShader", VERTEX_SHADER, FRAGMENT_SHADER_TEXTURE, 4);
         this.textureShaderAdv = AxCache.shader("GraphTextureShaderAdv", VERTEX_SHADER, FRAGMENT_SHADER_TEXTURE_ADV, 4);
         this.drawColor = Vector.<Number>([0,1,1,1]);                       
         this.matrix = new Matrix3D();
         this.uvOffset = new Vector.<Number>(4,0);         
         this.uvMultiplier = new Vector.<Number>(4,1);         
         this.transformationMatrix = transformationMatrix;
         if (!context)
            context = Ax.context;
         this.context = context;
         
         createVertexData();         
      }     
     
      /**
       * Creates default screen and world graphics outputs using given matrixes
       */
      public static function Initilize(screenMatrix:Matrix3D,worldMatrix:Matrix3D,starMapMatrix:Matrix3D):void
      {
         AxGraph.screen = new AxGraph(screenMatrix);         
         AxGraph.world = new AxGraph(worldMatrix);
         AxGraph.starMap = new AxGraph(starMapMatrix);
      }
         
     
      /**
       * draws a rectangle from x,y to x2,y2
       */
      public function drawRect(x:Number,y:Number,x2:Number,y2:Number,color:AxColor,thickness:Number = 1):void
      {
         // if true uses the polygon function to draw the rectangle.  Has the advantage of the corners looking better (but I can
         // fix this with the draw lines aswell) but it's about twice as slow... which is a shame as I thought it might be faster
         const USE_POLYGON_METHOD:Boolean = false;
                 
         if (USE_POLYGON_METHOD)
         {         
            var data:Vector.<Number> = new Vector.<Number>(4*4);         
            data[0*4+0] = x;
            data[0*4+1] = y;
            data[1*4+0] = x2;
            data[1*4+1] = y;
            data[2*4+0] = x2;
            data[2*4+1] = y2;
            data[3*4+0] = x;
            data[3*4+1] = y2;         
            drawPolygon(0,0,1,color,data,-1,thickness,true);
         } else
         {
            drawLine(x+thickness/2,y,x2-thickness/2,y,color,thickness);
            drawLine(x2,y-thickness/2,x2,y2+thickness/2,color,thickness);
            drawLine(x2-thickness/2,y2,x+thickness/2,y2,color,thickness);
            drawLine(x,y2+thickness/2,x,y-thickness/2,color,thickness);   
         }         
      }         
     
      /**
       * draws a filled rectangle from x,y to x2,y2
       */
      public function fillRect(x:Number,y:Number,x2:Number,y2:Number,color:AxColor):void
      {
         //not the greatest solution, but this will work.  Just draw one really thick line.
         var width: Number = x2-x;
         var height: Number = y2-y;     
         drawLine(x,y+height/2,x+width,y+height/2,color,height);     
      }
     
      /**
       * Draws a polygon frame at given location
       *
       * todo: support non closed polygons
       *
       * @data: List of vertex locations in the format x1,y1,u1,v1,x2,y2,u2,v2 etc
       * @closed: If true a final line will be drawn between the last and first vertex
       */
      public function drawPolygon(x:Number,y:Number,scale:Number,color:AxColor,data:Vector.<Number>,vertexs:Number = -1,thickness:Number=1, closed:Boolean = true):void
      {
                 
         if (vertexs < 0)
            vertexs = data.length/4;
         
         // create vertex data
         var polygonVertexBuffer:VertexBuffer3D;
         var vertexData:Vector.<Number>;
         var polygonIndexBuffer:IndexBuffer3D;
         var indexData:Vector.<uint>;
         
         var tangent: Vector3D = new Vector3D();
      
         vertexData = new Vector.<Number>(vertexs*2*4,0);
         indexData = new Vector.<uint>(vertexs*6,0);
         
         for (var pointOn:int = 0;pointOn <= vertexs-1;pointOn++)                 
         {   
            var thisPoint:int = pointOn;
            var nextPoint:int = (pointOn + 1) % vertexs;
           
         
            if ((!closed) && (pointOn == vertexs-1))
            {
               // if we are an open polygon and this is the last vertex, reuse the last tangent rather than getting a tangent to the first
               // vertex... as that would warp the last line in the polygon
            } else
            {
               tangent.y = data[thisPoint*4+0]-data[nextPoint*4+0];
               tangent.x = data[nextPoint*4+1]-data[thisPoint*4+1];
            }
           
         tangent.normalize();
           
            // calculate vertex points with given thickness
            vertexData[0+0+pointOn*8] = x+scale*data[0+thisPoint*4]+tangent.x;
            vertexData[0+1+pointOn*8] = y+scale*data[1+thisPoint*4]+tangent.y;           
            vertexData[4+0+pointOn*8] = x+scale*data[0+thisPoint*4]-tangent.x;
            vertexData[4+1+pointOn*8] = y+scale*data[1+thisPoint*4]-tangent.y;
           
            if (DEBUG_DRAW_POLYGON_VERTEXES)
            {
               fillCircle(x+scale*data[0+thisPoint*4],y+scale*data[1+thisPoint*4],5,AxColor.fromHex(0xFFFF0000));
               fillCircle(vertexData[0+0+pointOn*8],vertexData[0+1+pointOn*8],2,AxColor.fromHex(0xFFFFFF00));
               fillCircle(vertexData[4+0+pointOn*8],vertexData[4+1+pointOn*8],2,AxColor.fromHex(0xFFFFFF00));
            }
           
           
           
            indexData[0+pointOn*6] = 0+thisPoint*2;
            indexData[1+pointOn*6] = 0+nextPoint*2;
            indexData[2+pointOn*6] = 1+thisPoint*2;
            indexData[3+pointOn*6] = 0+nextPoint*2;
            indexData[4+pointOn*6] = 1+nextPoint*2;
            indexData[5+pointOn*6] = 1+thisPoint*2;                     
         }
         
         
         polygonVertexBuffer = context.createVertexBuffer(vertexs*2,4);
         polygonVertexBuffer.uploadFromVector(vertexData, 0, vertexs*2);
         
         polygonIndexBuffer = context.createIndexBuffer(vertexs*6);
         polygonIndexBuffer.uploadFromVector(indexData, 0, vertexs * 6);
         
         matrix.identity();                 
         matrix.append(transformationMatrix);
         
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;                 
         
         context.setProgram(solidColorShader.program);
         context.setBlendFactors(blend.source, blend.destination);           
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, drawColor);
         context.setVertexBufferAt(0, polygonVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);         
         context.setVertexBufferAt(1, polygonVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
         context.drawTriangles(polygonIndexBuffer,0,closed ? vertexs * 2 : (vertexs-1) * 2);         
         context.setVertexBufferAt(0, null, 0, Context3DVertexBufferFormat.FLOAT_2);
         context.setVertexBufferAt(1, null, 2, Context3DVertexBufferFormat.FLOAT_2);                     
      }               
     
      /**
       * Draws an unfilled circle at x,y of given radius
       */
      public function drawCircle(x:Number,y:Number,radius:Number,color:AxColor,thickness:Number=1):void
      {   
         drawPolygon(x,y,radius,color,circleVertexData,36,thickness);
      }
           
      /**
       * Draws an circle segment at x,y of given radius and angles
       */
      public function drawSegment(x:Number,y:Number,radius:Number,startAngle:Number,endAngle:Number,color:AxColor):void
      {           
         drawArc(x,y,radius/2,startAngle,endAngle,color,radius);
      }
     
     
      /**
       * Draws an arc at x,y of given radius and angles
       */
      public function drawArc(x:Number,y:Number,radius:Number,startAngle:Number,endAngle:Number,color:AxColor,thickness:Number=1):void
      {   
         var vertexes:int = 8;
         var arcLength:Number = radius * Math.PI * 2 * (Math.abs(endAngle-startAngle)/360);         
         if (arcLength > 100) vertexes = 16;         
         if (arcLength > 200) vertexes = 24;
         if (arcLength > 400) vertexes = 32;
         if (arcLength > 800) vertexes = 64;         
                 
         var vertexData:Vector.<Number> = new Vector.<Number>
         vertexData.length = vertexes*4;
         vertexData.fixed = true;
         for (var vertexOn: int = 0;vertexOn < vertexes;vertexOn ++)
         {
            var factor:Number = vertexOn/(vertexes-1);           
           
            //var radian:Number = (startAngle+(factor)*(endAngle-startAngle))*AxU.D2R;
         var radian:Number = (startAngle+(factor)*(endAngle-startAngle))*57.29577951308232088;
            vertexData[vertexOn*4+0] = Math.sin(radian);
            vertexData[vertexOn*4+1] = -Math.cos(radian);
            vertexData[vertexOn*4+2] = 0;
            vertexData[vertexOn*4+3] = 0;           
         }
         
         drawPolygon(x,y,radius,color,vertexData,vertexes,thickness,false);
      }
     
      /**
       * draws a filled circle at x,y of given radius
       */
      public function fillCircle(x:Number,y:Number,radius:Number,color:AxColor):void
      {         
         
         matrix.identity();   
         matrix.appendScale(radius,radius,1);         
         matrix.appendTranslation(x,y,0);         
         matrix.append(transformationMatrix);
         
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;
                           
         context.setProgram(solidColorShader.program);
         context.setBlendFactors(blend.source, blend.destination);
                 
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);         
         context.setVertexBufferAt(0, circleVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); //load xy         
         context.setVertexBufferAt(1, circleVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); //loud uv
         context.drawTriangles(circleIndexBuffer);               
      }         
           
      /**
       * draws a line from x,y to x2,y2
       */
      public function drawLine(x:Number,y:Number,x2:Number,y2:Number,color:AxColor,thickness:Number = 1):void
      {                       
         if (thickness == 0) return;
                           
         var length:Number = Math.sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y))+1;         
         var angle:Number = AxU.getAngle(x,y,x2,y2)/Math.PI*180;
                 
         matrix.identity();   
         matrix.appendTranslation(-0.5,0,0);
         matrix.appendScale(thickness,-length,1);
         matrix.appendRotation(90+angle, Vector3D.Z_AXIS);         
         matrix.appendTranslation(x,y,0);         
         matrix.append(transformationMatrix);
                             
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;                 
                 
         context.setProgram(solidColorShader.program);
         context.setBlendFactors(blend.source, blend.destination);           
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, drawColor);
         context.setVertexBufferAt(0, quadVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);         
         context.setVertexBufferAt(1, quadVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
         context.drawTriangles(quadIndexBuffer);         
         context.setVertexBufferAt(0, null, 0, Context3DVertexBufferFormat.FLOAT_2);
         context.setVertexBufferAt(1, null, 2, Context3DVertexBufferFormat.FLOAT_2);
                           
      }
     
      /**
       * Creates vertex buffers, and indexes used for drawing
       */
      private function createVertexData():void
      {
         //LINE:
         quadVertexBuffer = context.createVertexBuffer(4, 4);
         quadVertexData = Vector.<Number>([           
            0,       0,      0,      0,         
            1,      0,      1,      0,
            0,      1,      0,      1,
            1,      1,      1,      1,]);                                     
         quadVertexBuffer.uploadFromVector(quadVertexData, 0, 4);         
         quadIndexBuffer = context.createIndexBuffer(6);
         quadIndexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 1, 2, 3]), 0, 6);
                 
         //CIRCLE:
         const segments:int = 36;
         
         var midPointVertex:int = segments;
         
         circleVertexBuffer = context.createVertexBuffer(segments+1,4);
         circleVertexData = new Vector.<Number>;         
         //circumfrance points
         for (var cnt:int = 0;cnt < segments;cnt++)
         {
            circleVertexData.push(Math.sin(cnt*360/segments*Math.PI/180));
            circleVertexData.push(-Math.cos(cnt*360/segments*Math.PI/180));
            circleVertexData.push(0);
            circleVertexData.push(0);
         }
         //center point
         circleVertexData.push(0);circleVertexData.push(0);circleVertexData.push(0);circleVertexData.push(0);
         
         circleVertexBuffer.uploadFromVector(circleVertexData,0,segments+1);     
         
         circleIndexBuffer = context.createIndexBuffer(segments*3);
         var tmp:Vector.<uint> = new Vector.<uint>;
         for (cnt = 0;cnt < segments;cnt++)
         {
            tmp.push(midPointVertex);
            tmp.push(cnt);
            if (cnt == (segments-1))
               tmp.push(0);
            else
               tmp.push(cnt+1);
         }         
         circleIndexBuffer.uploadFromVector(tmp,0,segments*3);               
      }
     
      /** creates a blank texture used to draw objects.
       * Note: not really sure why this is needed, but I can't get drawing to work without
       */
      protected function createTexture():void
      {
         var bitmap:BitmapData;
         bitmap = new BitmapData(1, 1, true, 0x000000);                 
      }
     
      /**
       * The vertex shader for this sprite.
       */
      private static const VERTEX_SHADER:Array = [     
         "m44 op, va0, vc0",
         "mul vt1, va1, vc5",     
         "add v1, vt1, vc4",      //pass uv to fragment shader
         //"mov v1, va1",
      ];
     
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_SOLID_COLOR:Array = [
         "mov oc, fc0"         
      ];     
     
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_TEXTURE:Array = [
         "tex ft0, v1, fs0 <2d,linear,mipnone>",
         "mul ft0, ft0, fc0",         
         //"add ft0, ft0, fc1",                 
         "mov oc, ft0"         
      ];
     
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_TEXTURE_ADV:Array = [
         "tex ft0, v1, fs0 <2d,linear,mipnone>",     
         "m44, ft0, ft0, fc2",                   
         "mul ft0, ft0, fc0",                                 
         "mov oc, ft0"                                             
      ];
           
   }   
   
}


It works sweet in AxState.Draw() but I had it not working in AxSprite.Draw(). It seems to get a Texture Conflict at that point. But however I dont care. As long it works _somehow_ I feel happy.


Edit: you can avoid this by using FIRST the draw function and then update up to the sprite .. like here:
Code: Select all
PxGraph.screen.drawCircle(100, 100, 30, new AxColor(0, 1, 0), 2);
super.draw();


unfortunatly it works somethimes. not always ...

arkeus: any clue why? I tryed to solve it with an context.setTextureAt(0, null) .. but that dont seems to solve it.
tharo
Corporal
 
Posts: 15
Joined: Fri Mar 29, 2013 4:31 am

Re: Draw a line

Postby Arkeus » Fri Jun 21, 2013 5:58 pm

Could you describe in more detail the error you're seeing? Also the exact error message. Might be able to help...
Image
User avatar
Arkeus
Site Admin
 
Posts: 363
Joined: Mon Mar 26, 2012 12:43 am

Re: Draw a line

Postby tharo » Sat Jun 22, 2013 4:14 am

Code: Select all
Error: Error #3697: Eine Textur ist an Sampler 0 gebunden, wird aber nicht vom Fragment-Programm verwendet.
   at flash.display3D::Context3D/drawTriangles()
   at org.axgl::AxSprite/draw()[D:\lib\axgl\axgl_0_9_3\src\org\axgl\AxSprite.as:445]
   at info.orpg.som.Acteurs::Player/draw()[D:\som\src\info\orpg\som\Acteurs\Player.as:34]
   at org.axgl::AxGroup/draw()[D:\lib\axgl\axgl_0_9_3\src\org\axgl\AxGroup.as:124]
   at org.axgl::AxGroup/draw()[D:\lib\axgl\axgl_0_9_3\src\org\axgl\AxGroup.as:124]
   at info.orpg.som::GameState/draw()[D:\som\src\info\orpg\som\GameState.as:75]
   at org.axgl::Ax/draw()[D:\lib\axgl\axgl_0_9_3\src\org\axgl\Ax.as:613]
   at org.axgl::Ax/onEnterFrame()[D:\lib\axgl\axgl_0_9_3\src\org\axgl\Ax.as:537]


"A Texture was found on sampler 0, but dont get used by the frament Shader" - I hate non english error Messages thats why I wasnt googling it.

Following google and the Adobe Homepage this have to be avoided by setting the texture to null ... in Order to do kind of cleanup.
Problem ist:
  • AxSprite is always Setting the texture to null
  • even if you set it to null multiple times, like before or right AFTER drawing the circle its still causing the error

But here is a special one:
It seems to be caused depend on _when_ the AxSprite.draw() get called.
If it is the very first sprite you dont get this error. As soon you use one of the line functions in the .draw() of any other sprite, but in the first, you will cause this error again.

In other words: Dont know how to solve it. The texture cleanup in AxSprite seems okay, but yet the error occours like it is not.
tharo
Corporal
 
Posts: 15
Joined: Fri Mar 29, 2013 4:31 am

Re: Draw a line

Postby Arkeus » Sat Jun 22, 2013 1:07 pm

My guess is:

Code: Select all
         context.setProgram(solidColorShader.program);

You should change that to:

Code: Select all
         if (solidColorShader != Ax.shader) {
            Ax.context.setProgram(solidColorShader.program);
            Ax.shader = solidColorShader;
         }


AxSprite (and all the other objects) cache the current shader, so that if its drawing multiple things that use the same shader in a row, it doesn't have to reload it. Since you're changing the shader, but it still thinks its the axsprite shader, when it draws an axsprite it'll stick with the current shader (which is the axgraph one) when trying to draw the sprite.

You might have to change it in multiple places if the program is set in multiple places in that code.

(It's likely he got this working with an older version of Axel that didn't have this logic and such.)
Image
User avatar
Arkeus
Site Admin
 
Posts: 363
Joined: Mon Mar 26, 2012 12:43 am

Re: Draw a line

Postby tharo » Sun Jun 23, 2013 12:30 am

Thanks. That did it!

So heres the final Class for everyone that would like to use it hopefully it might find his way to the official AxGL branch soon :)

Code: Select all
package org.axgl
{
   import flash.display.BitmapData;
   import flash.display3D.Context3D;
   import flash.display3D.Context3DCompareMode;
   import flash.display3D.Context3DProgramType;
   import flash.display3D.Context3DTriangleFace;
   import flash.display3D.Context3DVertexBufferFormat;
   import flash.display3D.IndexBuffer3D;
   import flash.display3D.VertexBuffer3D;
   import flash.display3D.textures.Texture;
   import flash.display3D.textures.TextureBase;
   import flash.geom.Matrix;
   import flash.geom.Matrix3D;
   import flash.geom.Rectangle;
   import flash.geom.Transform;
   import flash.geom.Vector3D;
   
   import org.axgl.*;
   import org.axgl.util.*;
   import org.axgl.render.*;
   
   /**
    * Allows for drawing of basic shapes in 3d space
    */
   public class AxGraph
   {     
     
      /** If enabled polygons will also draw there vertexes (including tangents).  Used for debugging. */
      public static const DEBUG_DRAW_POLYGON_VERTEXES:Boolean = false;
     
      /** Graph3d that draws to world space */     
      public static var world:AxGraph;
      /** Graph3d that drawse to screen space */
      public static var screen:AxGraph;
      /** Graph3d that draws to starmap */
      public static var starMap:AxGraph;
         
      /** Matrix used to transform co-ords to destination */
      public var transformationMatrix:Matrix3D;
      /** Shader used for drawing solid color objects */
      public var solidColorShader:AxShader;
      /** Shader used for drawing texture objects */
      public var textureShader:AxShader;
      /** Shader used for drawing texture objects with a color matrix*/
      public var textureShaderAdv:AxShader;
      /** Context used to render items */
      public var context:Context3D;
     
     
      // vertex data... note: these could be static if needed, unless I want to create a hi-res instance
     
      /** Defines a simple quad of co-ords (0,0), (1,1).  This can be scaled or rotated to draw any rectangular object */
      private var quadVertexBuffer:VertexBuffer3D;
      private var quadVertexData:Vector.<Number>;
      private var quadIndexBuffer:IndexBuffer3D;
     
      /** Defines vertexes for a circle */
      private var circleVertexBuffer:VertexBuffer3D;
      private var circleVertexData:Vector.<Number>;
      private var circleIndexBuffer:IndexBuffer3D;     
     
      /** Color used to draw objects */
      public var drawColor:Vector.<Number>
     
      /** Transforms the UV cords of a texture.  Used for rendering a section of a texture*/
      public var uvOffset:Vector.<Number>
      /** Transforms the UV cords of a texture.  Used for rendering a section of a texture*/       
      public var uvMultiplier:Vector.<Number>     
     
      public var blend:AxBlendMode = AxBlendMode.BLEND;
     
      /** Matrix used for drawing objects */
      protected var matrix:Matrix3D;
           
      /** if true screen coords will be used */
      private var useScreenCoords:Boolean = false;
                     
      public function AxGraph(transformationMatrix:Matrix3D)
      {         
         this.solidColorShader = AxCache.shader("GraphColorShader", VERTEX_SHADER, FRAGMENT_SHADER_SOLID_COLOR, 4);         
         this.textureShader = AxCache.shader("GraphTextureShader", VERTEX_SHADER, FRAGMENT_SHADER_TEXTURE, 4);
         this.textureShaderAdv = AxCache.shader("GraphTextureShaderAdv", VERTEX_SHADER, FRAGMENT_SHADER_TEXTURE_ADV, 4);
         this.drawColor = Vector.<Number>([0,1,1,1]);                       
         this.matrix = new Matrix3D();
         this.uvOffset = new Vector.<Number>(4,0);         
         this.uvMultiplier = new Vector.<Number>(4,1);         
         this.transformationMatrix = transformationMatrix;
         if (!context)
            context = Ax.context;
         this.context = context;
         
         createVertexData();         
      }     
     
      /**
       * Creates default screen and world graphics outputs using given matrixes
       */
      public static function Initilize(screenMatrix:Matrix3D,worldMatrix:Matrix3D,starMapMatrix:Matrix3D):void
      {
         AxGraph.screen = new AxGraph(screenMatrix);         
         AxGraph.world = new AxGraph(worldMatrix);
         AxGraph.starMap = new AxGraph(starMapMatrix);
      }
         
     
      /**
       * draws a rectangle from x,y to x2,y2
       */
      public function drawRect(x:Number,y:Number,x2:Number,y2:Number,color:AxColor,thickness:Number = 1):void
      {
         // if true uses the polygon function to draw the rectangle.  Has the advantage of the corners looking better (but I can
         // fix this with the draw lines aswell) but it's about twice as slow... which is a shame as I thought it might be faster
         const USE_POLYGON_METHOD:Boolean = false;
                 
         if (USE_POLYGON_METHOD)
         {         
            var data:Vector.<Number> = new Vector.<Number>(4*4);         
            data[0*4+0] = x;
            data[0*4+1] = y;
            data[1*4+0] = x2;
            data[1*4+1] = y;
            data[2*4+0] = x2;
            data[2*4+1] = y2;
            data[3*4+0] = x;
            data[3*4+1] = y2;         
            drawPolygon(0,0,1,color,data,-1,thickness,true);
         } else
         {
            drawLine(x+thickness/2,y,x2-thickness/2,y,color,thickness);
            drawLine(x2,y-thickness/2,x2,y2+thickness/2,color,thickness);
            drawLine(x2-thickness/2,y2,x+thickness/2,y2,color,thickness);
            drawLine(x,y2+thickness/2,x,y-thickness/2,color,thickness);   
         }         
      }         
     
      /**
       * draws a filled rectangle from x,y to x2,y2
       */
      public function fillRect(x:Number,y:Number,x2:Number,y2:Number,color:AxColor):void
      {
         //not the greatest solution, but this will work.  Just draw one really thick line.
         var width: Number = x2-x;
         var height: Number = y2-y;     
         drawLine(x,y+height/2,x+width,y+height/2,color,height);     
      }
     
      /**
       * Draws a polygon frame at given location
       *
       * todo: support non closed polygons
       *
       * @data: List of vertex locations in the format x1,y1,u1,v1,x2,y2,u2,v2 etc
       * @closed: If true a final line will be drawn between the last and first vertex
       */
      public function drawPolygon(x:Number,y:Number,scale:Number,color:AxColor,data:Vector.<Number>,vertexs:Number = -1,thickness:Number=1, closed:Boolean = true):void
      {
                 
         if (vertexs < 0)
            vertexs = data.length/4;
         
         // create vertex data
         var polygonVertexBuffer:VertexBuffer3D;
         var vertexData:Vector.<Number>;
         var polygonIndexBuffer:IndexBuffer3D;
         var indexData:Vector.<uint>;
         
         var tangent: Vector3D = new Vector3D();
      
         vertexData = new Vector.<Number>(vertexs*2*4,0);
         indexData = new Vector.<uint>(vertexs*6,0);
         
         for (var pointOn:int = 0;pointOn <= vertexs-1;pointOn++)                 
         {   
            var thisPoint:int = pointOn;
            var nextPoint:int = (pointOn + 1) % vertexs;
           
         
            if ((!closed) && (pointOn == vertexs-1))
            {
               // if we are an open polygon and this is the last vertex, reuse the last tangent rather than getting a tangent to the first
               // vertex... as that would warp the last line in the polygon
            } else
            {
               tangent.y = data[thisPoint*4+0]-data[nextPoint*4+0];
               tangent.x = data[nextPoint*4+1]-data[thisPoint*4+1];
            }
           
         tangent.normalize();
           
            // calculate vertex points with given thickness
            vertexData[0+0+pointOn*8] = x+scale*data[0+thisPoint*4]+tangent.x;
            vertexData[0+1+pointOn*8] = y+scale*data[1+thisPoint*4]+tangent.y;           
            vertexData[4+0+pointOn*8] = x+scale*data[0+thisPoint*4]-tangent.x;
            vertexData[4+1+pointOn*8] = y+scale*data[1+thisPoint*4]-tangent.y;
           
            if (DEBUG_DRAW_POLYGON_VERTEXES)
            {
               fillCircle(x+scale*data[0+thisPoint*4],y+scale*data[1+thisPoint*4],5,AxColor.fromHex(0xFFFF0000));
               fillCircle(vertexData[0+0+pointOn*8],vertexData[0+1+pointOn*8],2,AxColor.fromHex(0xFFFFFF00));
               fillCircle(vertexData[4+0+pointOn*8],vertexData[4+1+pointOn*8],2,AxColor.fromHex(0xFFFFFF00));
            }
           
           
           
            indexData[0+pointOn*6] = 0+thisPoint*2;
            indexData[1+pointOn*6] = 0+nextPoint*2;
            indexData[2+pointOn*6] = 1+thisPoint*2;
            indexData[3+pointOn*6] = 0+nextPoint*2;
            indexData[4+pointOn*6] = 1+nextPoint*2;
            indexData[5+pointOn*6] = 1+thisPoint*2;                     
         }
         
         
         polygonVertexBuffer = context.createVertexBuffer(vertexs*2,4);
         polygonVertexBuffer.uploadFromVector(vertexData, 0, vertexs*2);
         
         polygonIndexBuffer = context.createIndexBuffer(vertexs*6);
         polygonIndexBuffer.uploadFromVector(indexData, 0, vertexs * 6);
         
         matrix.identity();                 
         matrix.append(transformationMatrix);
         
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;                 
         
         //context.setProgram(solidColorShader.program);
       if (solidColorShader != Ax.shader) {
            Ax.context.setProgram(solidColorShader.program);
            Ax.shader = solidColorShader;
         }
      
         context.setBlendFactors(blend.source, blend.destination);           
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, drawColor);
         context.setVertexBufferAt(0, polygonVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);         
         context.setVertexBufferAt(1, polygonVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
         context.drawTriangles(polygonIndexBuffer,0,closed ? vertexs * 2 : (vertexs-1) * 2);         
         context.setVertexBufferAt(0, null, 0, Context3DVertexBufferFormat.FLOAT_2);
         context.setVertexBufferAt(1, null, 2, Context3DVertexBufferFormat.FLOAT_2);                     
      }               
     
      /**
       * Draws an unfilled circle at x,y of given radius
       */
      public function drawCircle(x:Number,y:Number,radius:Number,color:AxColor,thickness:Number=1):void
      {   
         drawPolygon(x,y,radius,color,circleVertexData,36,thickness);
      }
           
      /**
       * Draws an circle segment at x,y of given radius and angles
       */
      public function drawSegment(x:Number,y:Number,radius:Number,startAngle:Number,endAngle:Number,color:AxColor):void
      {           
         drawArc(x,y,radius/2,startAngle,endAngle,color,radius);
      }
     
     
      /**
       * Draws an arc at x,y of given radius and angles
       */
      public function drawArc(x:Number,y:Number,radius:Number,startAngle:Number,endAngle:Number,color:AxColor,thickness:Number=1):void
      {   
         var vertexes:int = 8;
         var arcLength:Number = radius * Math.PI * 2 * (Math.abs(endAngle-startAngle)/360);         
         if (arcLength > 100) vertexes = 16;         
         if (arcLength > 200) vertexes = 24;
         if (arcLength > 400) vertexes = 32;
         if (arcLength > 800) vertexes = 64;         
                 
         var vertexData:Vector.<Number> = new Vector.<Number>
         vertexData.length = vertexes*4;
         vertexData.fixed = true;
         for (var vertexOn: int = 0;vertexOn < vertexes;vertexOn ++)
         {
            var factor:Number = vertexOn/(vertexes-1);           
           
            //var radian:Number = (startAngle+(factor)*(endAngle-startAngle))*AxU.D2R;
         var radian:Number = (startAngle+(factor)*(endAngle-startAngle))*57.29577951308232088;
            vertexData[vertexOn*4+0] = Math.sin(radian);
            vertexData[vertexOn*4+1] = -Math.cos(radian);
            vertexData[vertexOn*4+2] = 0;
            vertexData[vertexOn*4+3] = 0;           
         }
         
         drawPolygon(x,y,radius,color,vertexData,vertexes,thickness,false);
      }
     
      /**
       * draws a filled circle at x,y of given radius
       */
      public function fillCircle(x:Number,y:Number,radius:Number,color:AxColor):void
      {         
         
         matrix.identity();   
         matrix.appendScale(radius,radius,1);         
         matrix.appendTranslation(x,y,0);         
         matrix.append(transformationMatrix);
         
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;
                           
         //context.setProgram(solidColorShader.program);
       if (solidColorShader != Ax.shader) {
            Ax.context.setProgram(solidColorShader.program);
            Ax.shader = solidColorShader;
         }
         context.setBlendFactors(blend.source, blend.destination);
                 
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);         
         context.setVertexBufferAt(0, circleVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); //load xy         
         context.setVertexBufferAt(1, circleVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); //loud uv
         context.drawTriangles(circleIndexBuffer);               
      }         
           
      /**
       * draws a line from x,y to x2,y2
       */
      public function drawLine(x:Number,y:Number,x2:Number,y2:Number,color:AxColor,thickness:Number = 1):void
      {                       
         if (thickness == 0) return;
                           
         var length:Number = Math.sqrt((x2-x)*(x2-x)+(y2-y)*(y2-y))+1;         
         var angle:Number = AxU.getAngle(x,y,x2,y2)/Math.PI*180;
                 
         matrix.identity();   
         matrix.appendTranslation(-0.5,0,0);
         matrix.appendScale(thickness,-length,1);
         matrix.appendRotation(90+angle, Vector3D.Z_AXIS);         
         matrix.appendTranslation(x,y,0);         
         matrix.append(transformationMatrix);
                             
         drawColor[0] = color.red;
         drawColor[1] = color.green;
         drawColor[2] = color.blue;
         drawColor[3] = color.alpha;                 
                 
         //context.setProgram(solidColorShader.program);
       if (solidColorShader != Ax.shader) {
            Ax.context.setProgram(solidColorShader.program);
            Ax.shader = solidColorShader;
         }
         context.setBlendFactors(blend.source, blend.destination);           
         context.setTextureAt(0, null);
         context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, matrix, true);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, drawColor);
         context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, drawColor);
         context.setVertexBufferAt(0, quadVertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);         
         context.setVertexBufferAt(1, quadVertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2);
         context.drawTriangles(quadIndexBuffer);         
         context.setVertexBufferAt(0, null, 0, Context3DVertexBufferFormat.FLOAT_2);
         context.setVertexBufferAt(1, null, 2, Context3DVertexBufferFormat.FLOAT_2);
                           
      }
     
      /**
       * Creates vertex buffers, and indexes used for drawing
       */
      private function createVertexData():void
      {
         //LINE:
         quadVertexBuffer = context.createVertexBuffer(4, 4);
         quadVertexData = Vector.<Number>([           
            0,       0,      0,      0,         
            1,      0,      1,      0,
            0,      1,      0,      1,
            1,      1,      1,      1,]);                                     
         quadVertexBuffer.uploadFromVector(quadVertexData, 0, 4);         
         quadIndexBuffer = context.createIndexBuffer(6);
         quadIndexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 1, 2, 3]), 0, 6);
                 
         //CIRCLE:
         const segments:int = 36;
         
         var midPointVertex:int = segments;
         
         circleVertexBuffer = context.createVertexBuffer(segments+1,4);
         circleVertexData = new Vector.<Number>;         
         //circumfrance points
         for (var cnt:int = 0;cnt < segments;cnt++)
         {
            circleVertexData.push(Math.sin(cnt*360/segments*Math.PI/180));
            circleVertexData.push(-Math.cos(cnt*360/segments*Math.PI/180));
            circleVertexData.push(0);
            circleVertexData.push(0);
         }
         //center point
         circleVertexData.push(0);circleVertexData.push(0);circleVertexData.push(0);circleVertexData.push(0);
         
         circleVertexBuffer.uploadFromVector(circleVertexData,0,segments+1);     
         
         circleIndexBuffer = context.createIndexBuffer(segments*3);
         var tmp:Vector.<uint> = new Vector.<uint>;
         for (cnt = 0;cnt < segments;cnt++)
         {
            tmp.push(midPointVertex);
            tmp.push(cnt);
            if (cnt == (segments-1))
               tmp.push(0);
            else
               tmp.push(cnt+1);
         }         
         circleIndexBuffer.uploadFromVector(tmp,0,segments*3);               
      }
     
      /** creates a blank texture used to draw objects.
       * Note: not really sure why this is needed, but I can't get drawing to work without
       */
      protected function createTexture():void
      {
         var bitmap:BitmapData;
         bitmap = new BitmapData(1, 1, true, 0x000000);                 
      }
     
      /**
       * The vertex shader for this sprite.
       */
      private static const VERTEX_SHADER:Array = [     
         "m44 op, va0, vc0",
         "mul vt1, va1, vc5",     
         "add v1, vt1, vc4",      //pass uv to fragment shader
         //"mov v1, va1",
      ];
     
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_SOLID_COLOR:Array = [
         "mov oc, fc0"         
      ];     
     
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_TEXTURE:Array = [
         "tex ft0, v1, fs0 <2d,linear,mipnone>",
         "mul ft0, ft0, fc0",         
         //"add ft0, ft0, fc1",                 
         "mov oc, ft0"         
      ];
     
      /**
       * The fragment shader for this sprite.
       */
      private static const FRAGMENT_SHADER_TEXTURE_ADV:Array = [
         "tex ft0, v1, fs0 <2d,linear,mipnone>",     
         "m44, ft0, ft0, fc2",                   
         "mul ft0, ft0, fc0",                                 
         "mov oc, ft0"                                             
      ];
           
   }   
   
}


Image
tharo
Corporal
 
Posts: 15
Joined: Fri Mar 29, 2013 4:31 am

Re: Draw a line

Postby monsterkillu » Thu Feb 20, 2014 9:24 am

tharo wrote:Thanks. That did it!

So heres the final Class for everyone that would like to use it hopefully it might find his way to the official AxGL branch soon :)



Hi, I've been trying to get it work ... Not sure why .. at first i got the error "All buffers need to be cleared every frame before drawing."(in drawline method) when i used it with Axel 0.9.3 .. I switched back to 0.9.2 and the error is gone but i couldn't get the line on the Screen (or the world) .. Could you show me a working code along with the class ....
monsterkillu
Private
 
Posts: 1
Joined: Thu Feb 20, 2014 9:14 am


Return to Help

Who is online

Users browsing this forum: No registered users and 1 guest

cron