Browse Source

Added simple Canvas outline rendering.

Mark Sibly 8 years ago
parent
commit
706cdfb885
1 changed files with 241 additions and 7 deletions
  1. 241 7
      modules/mojo/graphics/canvas.monkey2

+ 241 - 7
modules/mojo/graphics/canvas.monkey2

@@ -1,6 +1,24 @@
 
 
 Namespace mojo.graphics
 Namespace mojo.graphics
 
 
+#rem monkeydoc Outline modes.
+
+Outline modes are used with the [[Canvas.OutlineMode]] property and control the style
+of outline drawn.
+
+| OutlineMode	| Description
+|:--------------|:-----------
+| None			| Outlines disabled.
+| Solid			| Solid outlines.
+| Smooth		| Smooth outlines.
+
+#end
+Enum OutlineMode
+	None=0
+	Solid=1
+	Smooth=2
+End
+
 #rem monkeydoc The Canvas class.
 #rem monkeydoc The Canvas class.
 
 
 Canvas objects are used to perform rendering to either a mojo [[app.View]] or an 'off screen' [[mojo.graphics.Image]].
 Canvas objects are used to perform rendering to either a mojo [[app.View]] or an 'off screen' [[mojo.graphics.Image]].
@@ -65,6 +83,9 @@ Class Canvas
 		LineWidth=0
 		LineWidth=0
 		LineSmoothing=False
 		LineSmoothing=False
 		TextureFilteringEnabled=true
 		TextureFilteringEnabled=true
+		OutlineMode=OutlineMode.None
+		OutlineColor=Color.Yellow
+		OutlineWidth=0
 		
 		
 		ClearMatrix()
 		ClearMatrix()
 	End
 	End
@@ -292,6 +313,50 @@ Class Canvas
 		_tanvec=_matrix.i.Normalize()
 		_tanvec=_matrix.i.Normalize()
 	End
 	End
 	
 	
+	#rem monkeydoc The current outline mode.
+	
+	Outline modes control the style of outlines drawn.
+	
+	See the [[OutlineMode]] enum for a list of possible values.
+	
+	#end
+	Property OutlineMode:OutlineMode()
+		
+		Return _outlineMode
+	
+	Setter( mode:OutlineMode )
+		
+		_outlineMode=mode
+	End
+	
+	#rem monkeydoc The current outline color.
+	
+	#end
+	Property OutlineColor:Color()
+		
+		Return _outlineColor
+		
+	Setter( color:Color )
+		
+		_outlineColor=color
+
+		Local a:=_outlineColor.a * 255.0
+		
+		_outlinepmcolor=UInt(a) Shl 24 | UInt(_outlineColor.b*a) Shl 16 | UInt(_outlineColor.g*a) Shl 8 | UInt(_outlineColor.r*a)
+	End
+	
+	#rem monkeydoc The current outline width.
+	
+	#end
+	Property OutlineWidth:Float()
+		
+		Return _outlineWidth
+		
+	Setter( width:Float )
+		
+		_outlineWidth=width
+	End
+	
 	#rem monkeydoc Pushes the drawing matrix onto the internal matrix stack.
 	#rem monkeydoc Pushes the drawing matrix onto the internal matrix stack.
 	
 	
 	#end
 	#end
@@ -403,6 +468,76 @@ Class Canvas
 		DrawPoint( v.x,v.y )
 		DrawPoint( v.x,v.y )
 	End
 	End
 	
 	
+	Private
+
+	Method DrawOutlineLine( x0:Float,y0:Float,x1:Float,y1:Float )
+		
+'		x0+=.5;y0+=.5;x1+=.5;y1+=.5
+		
+		Local blendMode:=_outlineMode=OutlineMode.Smooth ? BlendMode.Alpha Else BlendMode.Opaque
+		
+		Local pmcolor:=_pmcolor
+		
+		_pmcolor=_outlinepmcolor
+		
+		If _outlineWidth<=0
+			AddDrawOp( _shader,_material,blendMode,2,1 )
+			AddPointVertex( x0,y0,0,0 )
+			AddPointVertex( x1,y1,1,1 )
+			_pmcolor=pmcolor
+			Return
+		Endif
+		
+		Local dx:=y0-y1,dy:=x1-x0
+		Local sc:=0.5/Sqrt( dx*dx+dy*dy )*_outlineWidth
+		dx*=sc;dy*=sc
+		
+		If _outlineMode=OutlineMode.Solid
+			AddDrawOp( _shader,_material,_blendMode,4,1 )
+'			AddPointVertex( x0-dx-dy,y0-dy+dx,0,0 )
+'			AddPointVertex( x0+dx-dy,y0+dy+dx,0,0 )
+'			AddPointVertex( x1+dx+dy,y1+dy-dx,0,0 )
+'			AddPointVertex( x1-dx+dy,y1-dy-dx,0,0 )
+			AddPointVertex( x0-dx,y0-dy,0,0 )
+			AddPointVertex( x0+dx,y0+dy,0,0 )
+			AddPointVertex( x1+dx,y1+dy,0,0 )
+			AddPointVertex( x1-dx,y1-dy,0,0 )
+			_pmcolor=pmcolor
+			Return
+		End
+		
+		AddDrawOp( _shader,_material,blendMode,4,2 )
+
+		AddPointVertex( x0,y0,0,0 )
+		AddPointVertex( x1,y1,0,0 )
+		_pmcolor=0
+		AddPointVertex( x1-dx,y1-dy,0,0 )
+		AddPointVertex( x0-dx,y0-dy,0,0 )
+
+		AddPointVertex( x0+dx,y0+dy,0,0 )
+		AddPointVertex( x1+dx,y1+dy,0,0 )
+		_pmcolor=_outlinepmcolor
+		AddPointVertex( x1,y1,0,0 )
+		AddPointVertex( x0,y0,0,0 )
+		
+		_pmcolor=pmcolor
+	End
+	
+	Method DrawOutlineLine( v0:Vec2f,v1:Vec2f )
+		
+		DrawOutlineLine( v0.x,v0.y,v1.x,v1.y )
+	End
+	
+	Method DrawOutline( rect:Rectf )
+		
+		DrawOutlineLine( rect.min.x,rect.min.y,rect.max.x,rect.min.y )
+		DrawOutlineLine( rect.max.x,rect.min.y,rect.max.x,rect.max.y )
+		DrawOutlineLine( rect.max.x,rect.max.y,rect.min.x,rect.max.y )
+		DrawOutlineLine( rect.min.x,rect.max.y,rect.min.x,rect.min.y )
+	End
+	
+	Public
+	
 	#rem monkeydoc Draws a line.
 	#rem monkeydoc Draws a line.
 
 
 	Draws a line in the current [[Color]] using the current [[BlendMode]].
 	Draws a line in the current [[Color]] using the current [[BlendMode]].
@@ -431,10 +566,7 @@ Class Canvas
 			Return
 			Return
 		Endif
 		Endif
 		
 		
-'		x0+=.5
-'		y0+=.5
-'		x1+=.5
-'		y1+=.5
+'		x0+=.5;y0+=.5;x1+=.5;y1+=.5
 		
 		
 		Local dx:=y0-y1,dy:=x1-x0
 		Local dx:=y0-y1,dy:=x1-x0
 		Local sc:=0.5/Sqrt( dx*dx+dy*dy )*_lineWidth
 		Local sc:=0.5/Sqrt( dx*dx+dy*dy )*_lineWidth
@@ -467,6 +599,7 @@ Class Canvas
 	End
 	End
 	
 	
 	Method DrawLine( v0:Vec2f,v1:Vec2f )
 	Method DrawLine( v0:Vec2f,v1:Vec2f )
+		
 		DrawLine( v0.x,v0.y,v1.x,v1.y )
 		DrawLine( v0.x,v0.y,v1.x,v1.y )
 	End
 	End
 	
 	
@@ -478,13 +611,22 @@ Class Canvas
 
 
 	#End
 	#End
 	Method DrawTriangle( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float )
 	Method DrawTriangle( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float )
+		
 		AddDrawOp( _shader,_material,_blendMode,3,1 )
 		AddDrawOp( _shader,_material,_blendMode,3,1 )
 		AddVertex( x0,y0,0,0 )
 		AddVertex( x0,y0,0,0 )
 		AddVertex( x1,y1,1,0 )
 		AddVertex( x1,y1,1,0 )
 		AddVertex( x2,y2,1,1 )
 		AddVertex( x2,y2,1,1 )
+		
+		If _outlineMode=OutlineMode.None Return
+		
+		DrawOutlineLine( x0,y0,x1,y1 )
+		DrawOutlineLine( x1,y1,x2,y2 )
+		DrawOutlineLine( x2,y2,x0,y0 )
+				
 	End
 	End
 	
 	
 	Method DrawTriangle( v0:Vec2f,v1:Vec2f,v2:Vec2f )
 	Method DrawTriangle( v0:Vec2f,v1:Vec2f,v2:Vec2f )
+		
 		DrawTriangle( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y )
 		DrawTriangle( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y )
 	End
 	End
 
 
@@ -496,14 +638,23 @@ Class Canvas
 
 
 	#end
 	#end
 	Method DrawQuad( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float,x3:Float,y3:Float )
 	Method DrawQuad( x0:Float,y0:Float,x1:Float,y1:Float,x2:Float,y2:Float,x3:Float,y3:Float )
+		
 		AddDrawOp( _shader,_material,_blendMode,4,1 )
 		AddDrawOp( _shader,_material,_blendMode,4,1 )
 		AddVertex( x0,y0,0,0 )
 		AddVertex( x0,y0,0,0 )
 		AddVertex( x1,y1,1,0 )
 		AddVertex( x1,y1,1,0 )
 		AddVertex( x2,y2,1,1 )
 		AddVertex( x2,y2,1,1 )
 		AddVertex( x3,y3,0,1 )
 		AddVertex( x3,y3,0,1 )
+		
+		If _outlineMode=OutlineMode.None Return
+		
+		DrawOutlineLine( x0,y0,x1,y1 )
+		DrawOutlineLine( x1,y1,x2,y2 )
+		DrawOutlineLine( x2,y2,x3,y3 )
+		DrawOutlineLine( x3,y3,x0,y0 )
 	End
 	End
 
 
 	Method DrawQuad( v0:Vec2f,v1:Vec2f,v2:Vec2f,v3:Vec2f )
 	Method DrawQuad( v0:Vec2f,v1:Vec2f,v2:Vec2f,v3:Vec2f )
+		
 		DrawQuad( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y,v3.x,v3.y )
 		DrawQuad( v0.x,v0.y,v1.x,v1.y,v2.x,v2.y,v3.x,v3.y )
 	End
 	End
 
 
@@ -515,7 +666,10 @@ Class Canvas
 
 
 	#end
 	#end
 	Method DrawRect( x:Float,y:Float,w:Float,h:Float )
 	Method DrawRect( x:Float,y:Float,w:Float,h:Float )
+		
+		DrawQuad( x,y,x+w,y,x+w,y+h,x,y+h )
 	
 	
+		#rem
 		Local x0:=x,y0:=y,x1:=x+w,y1:=y+h
 		Local x0:=x,y0:=y,x1:=x+w,y1:=y+h
 		
 		
 		AddDrawOp( _shader,_material,_blendMode,4,1 )
 		AddDrawOp( _shader,_material,_blendMode,4,1 )
@@ -524,42 +678,60 @@ Class Canvas
 		AddVertex( x1,y0,1,0 )
 		AddVertex( x1,y0,1,0 )
 		AddVertex( x1,y1,1,1 )
 		AddVertex( x1,y1,1,1 )
 		AddVertex( x0,y1,0,1 )
 		AddVertex( x0,y1,0,1 )
+		#end
 	End
 	End
 	
 	
 	Method DrawRect( rect:Rectf )
 	Method DrawRect( rect:Rectf )
+		
 		DrawRect( rect.X,rect.Y,rect.Width,rect.Height )
 		DrawRect( rect.X,rect.Y,rect.Width,rect.Height )
 	End
 	End
 	
 	
 	Method DrawRect( rect:Rectf,srcImage:Image )
 	Method DrawRect( rect:Rectf,srcImage:Image )
+		
 		Local tc:=srcImage.TexCoords
 		Local tc:=srcImage.TexCoords
 		AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,4,1 )
 		AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,4,1 )
+		
 		AddVertex( rect.min.x,rect.min.y,tc.min.x,tc.min.y )
 		AddVertex( rect.min.x,rect.min.y,tc.min.x,tc.min.y )
 		AddVertex( rect.max.x,rect.min.y,tc.max.x,tc.min.y )
 		AddVertex( rect.max.x,rect.min.y,tc.max.x,tc.min.y )
 		AddVertex( rect.max.x,rect.max.y,tc.max.x,tc.max.y )
 		AddVertex( rect.max.x,rect.max.y,tc.max.x,tc.max.y )
 		AddVertex( rect.min.x,rect.max.y,tc.min.x,tc.max.y )
 		AddVertex( rect.min.x,rect.max.y,tc.min.x,tc.max.y )
+
+		If _outlineMode=OutlineMode.None Return
+		
+		DrawOutline( rect )
 	End
 	End
 	
 	
 	Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image )
 	Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image )
+		
 		DrawRect( New Rectf( x,y,x+width,y+height ),srcImage )
 		DrawRect( New Rectf( x,y,x+width,y+height ),srcImage )
 	End
 	End
 	
 	
 	Method DrawRect( rect:Rectf,srcImage:Image,srcRect:Recti )
 	Method DrawRect( rect:Rectf,srcImage:Image,srcRect:Recti )
+		
 		Local s0:=Float(srcImage.Rect.min.x+srcRect.min.x)/srcImage.Texture.Width
 		Local s0:=Float(srcImage.Rect.min.x+srcRect.min.x)/srcImage.Texture.Width
 		Local t0:=Float(srcImage.Rect.min.y+srcRect.min.y)/srcImage.Texture.Height
 		Local t0:=Float(srcImage.Rect.min.y+srcRect.min.y)/srcImage.Texture.Height
 		Local s1:=Float(srcImage.Rect.min.x+srcRect.max.x)/srcImage.Texture.Width
 		Local s1:=Float(srcImage.Rect.min.x+srcRect.max.x)/srcImage.Texture.Width
 		Local t1:=Float(srcImage.Rect.min.y+srcRect.max.y)/srcImage.Texture.Height
 		Local t1:=Float(srcImage.Rect.min.y+srcRect.max.y)/srcImage.Texture.Height
+		
 		AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,4,1 )
 		AddDrawOp( srcImage.Shader,srcImage.Material,srcImage.BlendMode,4,1 )
+		
 		AddVertex( rect.min.x,rect.min.y,s0,t0 )
 		AddVertex( rect.min.x,rect.min.y,s0,t0 )
 		AddVertex( rect.max.x,rect.min.y,s1,t0 )
 		AddVertex( rect.max.x,rect.min.y,s1,t0 )
 		AddVertex( rect.max.x,rect.max.y,s1,t1 )
 		AddVertex( rect.max.x,rect.max.y,s1,t1 )
 		AddVertex( rect.min.x,rect.max.y,s0,t1 )
 		AddVertex( rect.min.x,rect.max.y,s0,t1 )
+
+		If _outlineMode=OutlineMode.None Return
+		
+		DrawOutline( rect )
 	End
 	End
 	
 	
 	Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int )
 	Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int )
+
 		DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+width,srcY+height ) )
 		DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+width,srcY+height ) )
 	End
 	End
 	
 	
 	Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int,srcWidth:Int,srcHeight:Int )
 	Method DrawRect( x:Float,y:Float,width:Float,height:Float,srcImage:Image,srcX:Int,srcY:Int,srcWidth:Int,srcHeight:Int )
+
 		DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+srcWidth,srcY+srcHeight ) )
 		DrawRect( New Rectf( x,y,x+width,y+height ),srcImage,New Recti( srcX,srcY,srcX+srcWidth,srcY+srcHeight ) )
 	End
 	End
 	
 	
@@ -601,6 +773,23 @@ Class Canvas
 			Local py:=y0+Sin( th ) * yr
 			Local py:=y0+Sin( th ) * yr
 			AddPointVertex( px,py,0,0 )
 			AddPointVertex( px,py,0,0 )
 		Next
 		Next
+		
+		If _outlineMode=OutlineMode.None Return
+		
+		For Local i:=0 until n
+
+			Local th0:=(i+.5)*TwoPi/n
+			Local px0:=x0+Cos( th0 ) * xr
+			Local py0:=y0+Sin( th0 ) * yr
+			
+			Local th1:=(i+1.5)*TwoPi/n
+			Local px1:=x0+Cos( th1 ) * xr
+			Local py1:=y0+Sin( th1 ) * yr
+			
+			DrawOutlineLine( px0,py0,px1,py1 )
+		
+		Next
+		
 	End
 	End
 	
 	
 	#rem monkeydoc Draws an ellipse.
 	#rem monkeydoc Draws an ellipse.
@@ -619,6 +808,7 @@ Class Canvas
 
 
 	#end
 	#end
 	Method DrawEllipse( x:Float,y:Float,xRadius:Float,yRadius:Float )
 	Method DrawEllipse( x:Float,y:Float,xRadius:Float,yRadius:Float )
+		
 		DrawOval( x-xRadius,y-yRadius,xRadius*2,yRadius*2 )
 		DrawOval( x-xRadius,y-yRadius,xRadius*2,yRadius*2 )
 	End
 	End
 	
 	
@@ -634,32 +824,48 @@ Class Canvas
 
 
 	#end
 	#end
 	Method DrawCircle( x:Float,y:Float,radius:Float )
 	Method DrawCircle( x:Float,y:Float,radius:Float )
+		
 		DrawOval( x-radius,y-radius,radius*2,radius*2 )
 		DrawOval( x-radius,y-radius,radius*2,radius*2 )
 	End
 	End
 
 
 	#rem monkeydoc Draws a polygon.
 	#rem monkeydoc Draws a polygon.
 
 
 	Draws a polygon using the current [[Color]], [[BlendMode]] and [[Matrix]].
 	Draws a polygon using the current [[Color]], [[BlendMode]] and [[Matrix]].
+	
+	The `vertices` array must be at least 2 elements long
 
 
 	@param vertices Array of x/y vertex coordinate pairs.
 	@param vertices Array of x/y vertex coordinate pairs.
 
 
 	#end
 	#end
 	Method DrawPoly( vertices:Float[] )
 	Method DrawPoly( vertices:Float[] )
+		
 		Local order:=vertices.Length/2
 		Local order:=vertices.Length/2
-		DebugAssert( order>0,"Invalid polygon" )
+		DebugAssert( order>=1,"Invalid polygon" )
 		
 		
 		AddDrawOp( _shader,_material,_blendMode,order,1 )
 		AddDrawOp( _shader,_material,_blendMode,order,1 )
 		
 		
 		For Local i:=0 Until order*2 Step 2
 		For Local i:=0 Until order*2 Step 2
+			
 			AddVertex( vertices[i],vertices[i+1],0,0 )
 			AddVertex( vertices[i],vertices[i+1],0,0 )
 		Next
 		Next
+
+		If _outlineMode=OutlineMode.None Or order<3 Return
+		
+		For Local i:=0 Until order-1 
+			
+			Local k:=i*2
+			DrawOutlineLine( vertices[k],vertices[k+1],vertices[k+2],vertices[k+3] )
+		Next
+		
+		Local kn:=(order-1)*2
+		DrawOutlineLine( vertices[kn],vertices[kn+1],vertices[0],vertices[1] )
 	End
 	End
 	
 	
 	#rem monkeydoc Draws a sequence of polygons.
 	#rem monkeydoc Draws a sequence of polygons.
 
 
 	Draws a sequence of polygons using the current [[Color]], [[BlendMode]] and [[Matrix]].
 	Draws a sequence of polygons using the current [[Color]], [[BlendMode]] and [[Matrix]].
 
 
-	@param order The type of polygon: 1=points, 2=lines, 3=triangles, 4=quads, >4=n-gons.
+	@param order The type of polygon: 3=triangles, 4=quads, >4=n-gons.
 
 
 	@param count The number of polygons.
 	@param count The number of polygons.
 	
 	
@@ -667,13 +873,30 @@ Class Canvas
 	
 	
 	#end
 	#end
 	Method DrawPolys( order:Int,count:Int,vertices:Float[] )
 	Method DrawPolys( order:Int,count:Int,vertices:Float[] )
-		DebugAssert( order>0 And count>0 And order*count<=vertices.Length,"Invalid polyon" )
+		
+		DebugAssert( order>=1 And count>0 And order*count<=vertices.Length,"Invalid polyon" )
 
 
 		AddDrawOp( _shader,_material,_blendMode,order,count )
 		AddDrawOp( _shader,_material,_blendMode,order,count )
 		
 		
 		For Local i:=0 Until order*count*2 Step 2
 		For Local i:=0 Until order*count*2 Step 2
+			
 			AddVertex( vertices[i],vertices[i+1],0,0 )
 			AddVertex( vertices[i],vertices[i+1],0,0 )
 		Next
 		Next
+		
+		If _outlineMode=OutlineMode.None Or order<3 Return
+		
+		For Local i:=0 Until count
+			
+			For Local j:=0 Until order-1
+				
+				Local k:=(i*order+j)*2
+				DrawOutlineLine( vertices[k],vertices[k+1],vertices[k+2],vertices[k+3] )
+			Next
+			
+			Local k0:=i*order*2,kn:=(i*order+order-1)*2
+			DrawOutlineLine( vertices[kn],vertices[kn+1],vertices[k0],vertices[k0+1] )
+		Next
+		
 	End
 	End
 	
 	
 	#rem monkeydoc Draws a sequence of primtives.
 	#rem monkeydoc Draws a sequence of primtives.
@@ -1272,6 +1495,12 @@ Class Canvas
 	Field _matrix:=New AffineMat3f
 	Field _matrix:=New AffineMat3f
 	Field _tanvec:Vec2f=New Vec2f( 1,0 )
 	Field _tanvec:Vec2f=New Vec2f( 1,0 )
 	Field _matrixStack:=New Stack<AffineMat3f>
 	Field _matrixStack:=New Stack<AffineMat3f>
+
+	Field _outlineMode:OutlineMode
+	Field _outlineColor:Color
+	Field _outlinepmcolor:UInt
+	Field _outlineSmoothing:Bool
+	Field _outlineWidth:Float
 	
 	
 	Field _rmatrix:=New AffineMat3f
 	Field _rmatrix:=New AffineMat3f
 	Field _rbounds:=New Recti( 0,0,$40000000,$40000000 )
 	Field _rbounds:=New Recti( 0,0,$40000000,$40000000 )
@@ -1357,6 +1586,11 @@ Class Canvas
 		_color=Color.White
 		_color=Color.White
 		_pmcolor=$ffffffff
 		_pmcolor=$ffffffff
 		
 		
+		_outlineMode=OutlineMode.None
+		_outlineColor=Color.Yellow
+		_outlinepmcolor=$ffffffff
+		_outlineWidth=0
+		
 		_matrix=New AffineMat3f
 		_matrix=New AffineMat3f
 	End
 	End