2009-04-19 18:07:22 +00:00
#region = = = = = = = = = = = = = = = = = = Copyright ( c ) 2007 Pascal vd Heiden
/ *
* Copyright ( c ) 2007 Pascal vd Heiden , www . codeimp . com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* /
#endregion
#region = = = = = = = = = = = = = = = = = = Namespaces
using System ;
using System.Collections.Generic ;
using System.Drawing ;
2019-01-14 18:07:08 +00:00
using System.Net ;
2009-04-19 18:07:22 +00:00
using CodeImp.DoomBuilder.Map ;
using CodeImp.DoomBuilder.Geometry ;
using CodeImp.DoomBuilder.Data ;
using CodeImp.DoomBuilder.Editing ;
2013-04-11 11:04:16 +00:00
using CodeImp.DoomBuilder.GZBuilder.Data ; //mxd
2013-11-27 12:45:28 +00:00
using CodeImp.DoomBuilder.Config ; //mxd
2018-02-03 20:31:34 +00:00
using CodeImp.DoomBuilder.GZBuilder ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
/ * This renders a 2D presentation of the map . This is done in several
* layers which each are optimized for a different purpose . Set the
* PresentationLayer ( s ) to specify how to present these layers .
* /
2013-07-29 08:50:50 +00:00
internal sealed class Renderer2D : Renderer , IRenderer2D
2009-04-19 18:07:22 +00:00
{
#region = = = = = = = = = = = = = = = = = = Constants
private const float FSAA_FACTOR = 0.6f ;
2015-08-04 23:28:02 +00:00
private const int MAP_CENTER_SIZE = 16 ; //mxd
2015-08-03 22:02:39 +00:00
private const float THING_ARROW_SIZE = 1.4f ;
//private const float THING_ARROW_SHRINK = 2f;
2015-07-14 23:34:31 +00:00
//private const float THING_CIRCLE_SIZE = 1f;
2013-11-27 12:45:28 +00:00
private const float THING_SPRITE_SHRINK = 2f ;
2010-08-16 13:31:53 +00:00
private const int THING_BUFFER_SIZE = 100 ;
2013-07-29 08:50:50 +00:00
private const float MINIMUM_THING_RADIUS = 1.5f ; //mxd
2016-04-01 10:49:19 +00:00
private const float MINIMUM_SPRITE_RADIUS = 8.0f ; //mxd
2016-04-04 22:20:49 +00:00
internal const float FIXED_THING_SIZE = 48.0f ; //mxd
2009-04-19 18:07:22 +00:00
internal const int NUM_VIEW_MODES = 4 ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Rendertargets
2019-08-18 05:43:46 +00:00
private Plotter gridplotter ;
private Plotter plotter ;
private Texture thingstex ;
2009-04-19 18:07:22 +00:00
private Texture overlaytex ;
private Texture surfacetex ;
// Rendertarget sizes
private Size windowsize ;
// Vertices to present the textures
private VertexBuffer screenverts ;
private FlatVertex [ ] backimageverts ;
// Batch buffer for things rendering
private VertexBuffer thingsvertices ;
// Render settings
private int vertexsize ;
private RenderLayers renderlayer = RenderLayers . None ;
2009-06-04 20:21:31 +00:00
// Surfaces
private SurfaceManager surfaces ;
2009-04-19 18:07:22 +00:00
// View settings (world coordinates)
private ViewMode viewmode ;
private float scale ;
private float scaleinv ;
private float offsetx ;
private float offsety ;
private float translatex ;
private float translatey ;
private float linenormalsize ;
2015-08-31 22:06:44 +00:00
private float minlinelength ; //mxd. Linedef should be longer than this to be rendered
private float minlinenormallength ; //mxd. Linedef direction indicator should be longer than this to be rendered
2016-06-16 22:05:17 +00:00
private bool drawmapcenter = true ; //mxd
private bool lastdrawmapcenter = true ; //mxd
2009-04-19 18:07:22 +00:00
private float lastgridscale = - 1f ;
2016-12-27 13:59:20 +00:00
private float lastgridsize ;
2009-04-19 18:07:22 +00:00
private float lastgridx ;
private float lastgridy ;
2010-08-14 09:30:54 +00:00
private RectangleF viewport ;
private RectangleF yviewport ;
2009-04-19 18:07:22 +00:00
2019-08-16 11:38:53 +00:00
// Spaghetti
Matrix viewmatrix = Matrix . Identity ;
Matrix worldmatrix = Matrix . Identity ;
// Presentation
private Presentation present ;
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public float OffsetX { get { return offsetx ; } }
public float OffsetY { get { return offsety ; } }
public float TranslateX { get { return translatex ; } }
public float TranslateY { get { return translatey ; } }
public float Scale { get { return scale ; } }
public int VertexSize { get { return vertexsize ; } }
2016-06-16 22:05:17 +00:00
public bool DrawMapCenter { get { return drawmapcenter ; } set { drawmapcenter = value ; } } //mxd
2009-04-19 18:07:22 +00:00
public ViewMode ViewMode { get { return viewmode ; } }
2009-06-04 20:21:31 +00:00
public SurfaceManager Surfaces { get { return surfaces ; } }
2013-06-13 11:32:00 +00:00
public RectangleF Viewport { get { return viewport ; } } //mxd
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
2019-08-09 21:22:16 +00:00
internal Renderer2D ( RenderDevice graphics ) : base ( graphics )
2009-04-19 18:07:22 +00:00
{
2009-06-04 20:21:31 +00:00
// Create surface manager
surfaces = new SurfaceManager ( ) ;
2009-04-19 18:07:22 +00:00
// Create rendertargets
CreateRendertargets ( ) ;
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
2016-02-01 22:04:00 +00:00
public override void Dispose ( )
2009-04-19 18:07:22 +00:00
{
// Not already disposed?
if ( ! isdisposed )
{
// Destroy rendertargets
DestroyRendertargets ( ) ;
2009-06-04 20:21:31 +00:00
// Dispose surface manager
surfaces . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
// Done
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Presenting
// This sets the presentation to use
public void SetPresentation ( Presentation present )
{
this . present = new Presentation ( present ) ;
}
// This draws the image on screen
2019-08-16 09:24:22 +00:00
public void Present ( )
2009-04-19 18:07:22 +00:00
{
2010-08-22 12:09:32 +00:00
General . Plugins . OnPresentDisplayBegin ( ) ;
2009-04-19 18:07:22 +00:00
2019-08-08 01:19:11 +00:00
// Start drawing
graphics . StartRendering ( true , General . Colors . Background . ToColorValue ( ) ) ;
2009-04-19 18:07:22 +00:00
2019-08-08 01:19:11 +00:00
// Renderstates that count for this whole sequence
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
2019-08-16 11:07:57 +00:00
graphics . SetVertexBuffer ( screenverts ) ;
2019-08-16 11:38:53 +00:00
worldmatrix = Matrix . Identity ;
2009-04-19 18:07:22 +00:00
2019-08-08 01:19:11 +00:00
// Go for all layers
foreach ( PresentLayer layer in present . layers )
{
2019-08-14 10:36:33 +00:00
ShaderName aapass ;
2009-04-19 18:07:22 +00:00
2019-08-08 01:19:11 +00:00
// Set blending mode
switch ( layer . blending )
{
case BlendingMode . None :
2019-08-09 22:46:51 +00:00
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
break ;
2019-08-08 01:19:11 +00:00
case BlendingMode . Mask :
2019-08-09 22:46:51 +00:00
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( true ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
break ;
2019-08-08 01:19:11 +00:00
case BlendingMode . Alpha :
2019-08-09 22:46:51 +00:00
graphics . SetAlphaBlendEnable ( true ) ;
graphics . SetAlphaTestEnable ( false ) ;
graphics . SetSourceBlend ( Blend . SourceAlpha ) ;
graphics . SetDestinationBlend ( Blend . InverseSourceAlpha ) ;
2019-12-16 02:52:37 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-08 01:19:11 +00:00
break ;
case BlendingMode . Additive :
2019-08-09 22:46:51 +00:00
graphics . SetAlphaBlendEnable ( true ) ;
graphics . SetAlphaTestEnable ( false ) ;
graphics . SetSourceBlend ( Blend . SourceAlpha ) ;
graphics . SetDestinationBlend ( Blend . One ) ;
2019-12-16 02:52:37 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-08 01:19:11 +00:00
break ;
2009-04-19 18:07:22 +00:00
}
2019-08-08 01:19:11 +00:00
// Check which pass to use
2019-08-14 10:36:33 +00:00
if ( layer . antialiasing & & General . Settings . QualityDisplay ) aapass = ShaderName . display2d_fsaa ; else aapass = ShaderName . display2d_normal ;
2009-04-19 18:07:22 +00:00
2019-08-08 01:19:11 +00:00
// Render layer
switch ( layer . layer )
{
// BACKGROUND
case RendererLayer . Background :
if ( ( backimageverts = = null ) | | ( General . Map . Grid . Background . Texture = = null ) ) break ;
2019-08-13 00:43:01 +00:00
graphics . SetShader ( aapass ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Grid . Background . Texture ) ;
2019-09-04 02:54:08 +00:00
graphics . SetSamplerState ( TextureAddress . Wrap ) ;
2019-08-17 01:08:34 +00:00
SetDisplay2DSettings ( 1f / windowsize . Width , 1f / windowsize . Height , FSAA_FACTOR , layer . alpha , false , true ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 , backimageverts ) ;
2019-08-16 11:07:57 +00:00
graphics . SetVertexBuffer ( screenverts ) ;
2019-08-08 01:19:11 +00:00
break ;
// GRID
case RendererLayer . Grid :
2019-08-13 00:43:01 +00:00
graphics . SetShader ( aapass ) ;
2019-08-18 05:43:46 +00:00
graphics . SetTexture ( gridplotter . Texture ) ;
2019-09-04 02:54:08 +00:00
graphics . SetSamplerState ( TextureAddress . Wrap ) ;
2019-08-18 05:43:46 +00:00
SetDisplay2DSettings ( 1f / gridplotter . Width , 1f / gridplotter . Height , FSAA_FACTOR , layer . alpha , false , true ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2019-08-08 01:19:11 +00:00
break ;
// GEOMETRY
case RendererLayer . Geometry :
2019-08-13 00:43:01 +00:00
graphics . SetShader ( aapass ) ;
2019-08-18 05:43:46 +00:00
graphics . SetTexture ( plotter . Texture ) ;
2019-09-04 02:54:08 +00:00
graphics . SetSamplerState ( TextureAddress . Wrap ) ;
2019-08-18 05:43:46 +00:00
SetDisplay2DSettings ( 1f / plotter . Width , 1f / plotter . Height , FSAA_FACTOR , layer . alpha , false , false ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2019-08-08 01:19:11 +00:00
break ;
// THINGS
case RendererLayer . Things :
2019-08-13 00:43:01 +00:00
graphics . SetShader ( aapass ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( thingstex ) ;
2019-09-04 02:54:08 +00:00
graphics . SetSamplerState ( TextureAddress . Clamp ) ;
2019-08-18 05:43:46 +00:00
SetDisplay2DSettings ( 1f / thingstex . Width , 1f / thingstex . Height , FSAA_FACTOR , layer . alpha , false , true ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2019-08-08 01:19:11 +00:00
break ;
// OVERLAY
case RendererLayer . Overlay :
2019-08-13 00:43:01 +00:00
graphics . SetShader ( aapass ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( overlaytex ) ;
2019-09-04 02:54:08 +00:00
graphics . SetSamplerState ( TextureAddress . Wrap ) ;
2019-08-18 05:43:46 +00:00
SetDisplay2DSettings ( 1f / overlaytex . Width , 1f / overlaytex . Height , FSAA_FACTOR , layer . alpha , false , true ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2019-08-08 01:19:11 +00:00
break ;
// SURFACE
case RendererLayer . Surface :
2019-08-13 00:43:01 +00:00
graphics . SetShader ( aapass ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( surfacetex ) ;
2019-09-04 02:54:08 +00:00
graphics . SetSamplerState ( TextureAddress . Wrap ) ;
2019-08-18 05:43:46 +00:00
SetDisplay2DSettings ( 1f / overlaytex . Width , 1f / overlaytex . Height , FSAA_FACTOR , layer . alpha , false , true ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2019-08-08 01:19:11 +00:00
break ;
}
2009-04-19 18:07:22 +00:00
}
2019-08-08 01:19:11 +00:00
// Done
graphics . FinishRendering ( ) ;
graphics . Present ( ) ;
// Release binds
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( null ) ;
2019-08-16 11:07:57 +00:00
graphics . SetVertexBuffer ( null ) ;
2009-04-19 18:07:22 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Management
// This is called before a device is reset
// (when resized or display adapter was changed)
public override void UnloadResource ( )
{
// Destroy rendertargets
DestroyRendertargets ( ) ;
}
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public override void ReloadResource ( )
{
// Re-create rendertargets
CreateRendertargets ( ) ;
}
// This resets the graphics
2016-01-14 22:15:54 +00:00
/ * public override void Reset ( )
2009-04-19 18:07:22 +00:00
{
UnloadResource ( ) ;
ReloadResource ( ) ;
2016-01-14 22:15:54 +00:00
} * /
2009-04-19 18:07:22 +00:00
// This destroys the rendertargets
public void DestroyRendertargets ( )
{
// Trash rendertargets
2019-08-18 05:43:46 +00:00
if ( plotter ! = null ) plotter . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
if ( thingstex ! = null ) thingstex . Dispose ( ) ;
if ( overlaytex ! = null ) overlaytex . Dispose ( ) ;
if ( surfacetex ! = null ) surfacetex . Dispose ( ) ;
2019-08-18 05:43:46 +00:00
if ( gridplotter ! = null ) gridplotter . Dispose ( ) ;
2009-04-19 18:07:22 +00:00
if ( screenverts ! = null ) screenverts . Dispose ( ) ;
thingstex = null ;
2019-08-18 05:43:46 +00:00
gridplotter = null ;
2009-04-19 18:07:22 +00:00
screenverts = null ;
overlaytex = null ;
surfacetex = null ;
// Trash things batch buffer
if ( thingsvertices ! = null ) thingsvertices . Dispose ( ) ;
thingsvertices = null ;
lastgridscale = - 1f ;
2016-12-27 13:59:20 +00:00
lastgridsize = 0.0f ;
2009-04-19 18:07:22 +00:00
}
// Allocates new image memory to render on
2019-08-16 09:24:22 +00:00
public void CreateRendertargets ( )
2009-04-19 18:07:22 +00:00
{
// Destroy rendertargets
DestroyRendertargets ( ) ;
2019-12-16 04:54:44 +00:00
2009-04-19 18:07:22 +00:00
// Get new width and height
windowsize . Width = graphics . RenderTarget . ClientSize . Width ;
windowsize . Height = graphics . RenderTarget . ClientSize . Height ;
// Create rendertargets textures
2019-08-18 05:43:46 +00:00
plotter = new Plotter ( windowsize . Width , windowsize . Height ) ;
gridplotter = new Plotter ( windowsize . Width , windowsize . Height ) ;
thingstex = new Texture ( windowsize . Width , windowsize . Height ) ;
2019-08-09 21:15:48 +00:00
overlaytex = new Texture ( windowsize . Width , windowsize . Height ) ;
surfacetex = new Texture ( windowsize . Width , windowsize . Height ) ;
2009-04-19 18:07:22 +00:00
// Clear rendertargets
2019-08-08 01:19:11 +00:00
graphics . ClearTexture ( General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , thingstex ) ;
graphics . ClearTexture ( General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , overlaytex ) ;
2009-04-19 18:07:22 +00:00
// Create vertex buffers
2019-08-16 09:24:22 +00:00
screenverts = new VertexBuffer ( ) ;
thingsvertices = new VertexBuffer ( ) ;
2019-08-16 11:07:57 +00:00
graphics . SetBufferData ( thingsvertices , THING_BUFFER_SIZE * 12 , VertexFormat . Flat ) ;
2009-04-19 18:07:22 +00:00
// Make screen vertices
2019-08-20 10:45:23 +00:00
FlatVertex [ ] verts = CreateScreenVerts ( new Size ( windowsize . Width , windowsize . Height ) ) ;
2019-08-15 00:52:21 +00:00
graphics . SetBufferData ( screenverts , verts ) ;
2009-04-19 18:07:22 +00:00
// Force update of view
lastgridscale = - 1f ;
2016-12-27 13:59:20 +00:00
lastgridsize = 0.0f ;
2009-04-19 18:07:22 +00:00
lastgridx = 0.0f ;
lastgridy = 0.0f ;
UpdateTransformations ( ) ;
2019-12-25 15:26:30 +00:00
if ( General . Map ! = null & & General . Map . Config ! = null )
{
// [ZZ] old texture is Gone here. Redraw
2019-12-26 12:33:23 +00:00
plotter . Clear ( ) ;
gridplotter . Clear ( ) ;
RenderBackgroundGrid ( ) ;
SetupBackground ( ) ;
2019-12-25 15:26:30 +00:00
gridplotter . DrawContents ( graphics ) ;
plotter . DrawContents ( graphics ) ;
}
2009-04-19 18:07:22 +00:00
}
// This makes screen vertices for display
2014-05-20 09:09:28 +00:00
private static FlatVertex [ ] CreateScreenVerts ( Size texturesize )
2009-04-19 18:07:22 +00:00
{
FlatVertex [ ] screenverts = new FlatVertex [ 4 ] ;
2019-08-20 10:45:23 +00:00
screenverts [ 0 ] . x = 0.0f ;
screenverts [ 0 ] . y = 0.0f ;
screenverts [ 0 ] . c = - 1 ;
screenverts [ 0 ] . u = 0.0f ;
screenverts [ 0 ] . v = 0.0f ;
screenverts [ 1 ] . x = texturesize . Width ;
screenverts [ 1 ] . y = 0.0f ;
screenverts [ 1 ] . c = - 1 ;
screenverts [ 1 ] . u = 1.0f ;
screenverts [ 1 ] . v = 0.0f ;
screenverts [ 2 ] . x = 0.0f ;
screenverts [ 2 ] . y = texturesize . Height ;
screenverts [ 2 ] . c = - 1 ;
screenverts [ 2 ] . u = 0.0f ;
screenverts [ 2 ] . v = 1.0f ;
screenverts [ 3 ] . x = texturesize . Width ;
screenverts [ 3 ] . y = texturesize . Height ;
screenverts [ 3 ] . c = - 1 ;
screenverts [ 3 ] . u = 1.0f ;
screenverts [ 3 ] . v = 1.0f ;
return screenverts ;
2009-04-19 18:07:22 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = View
// This changes view mode
public void SetViewMode ( ViewMode mode )
{
viewmode = mode ;
}
// This changes view position
public void PositionView ( float x , float y )
{
// Change position in world coordinates
offsetx = x ;
offsety = y ;
UpdateTransformations ( ) ;
}
// This changes zoom
public void ScaleView ( float scale )
{
// Change zoom scale
this . scale = scale ;
UpdateTransformations ( ) ;
// Show zoom on main window
General . MainWindow . UpdateZoom ( scale ) ;
}
// This updates some maths
private void UpdateTransformations ( )
{
scaleinv = 1f / scale ;
translatex = - offsetx + ( windowsize . Width * 0.5f ) * scaleinv ;
translatey = - offsety - ( windowsize . Height * 0.5f ) * scaleinv ;
linenormalsize = 10f * scaleinv ;
2015-08-31 22:06:44 +00:00
minlinelength = linenormalsize * 0.0625f ; //mxd
minlinenormallength = linenormalsize * 2f ; //mxd
2012-09-07 10:45:49 +00:00
2013-09-11 09:47:53 +00:00
vertexsize = ( int ) ( 1.7f * General . Settings . GZVertexScale2D * scale + 0.5f ) ; //mxd. added GZVertexScale2D
2009-04-19 18:07:22 +00:00
if ( vertexsize < 0 ) vertexsize = 0 ;
if ( vertexsize > 4 ) vertexsize = 4 ;
2012-09-07 10:45:49 +00:00
2019-08-20 10:45:23 +00:00
viewmatrix = Matrix . Scaling ( 2.0f / windowsize . Width , - 2.0f / windowsize . Height , 1.0f ) * Matrix . Translation ( - 1.0f , 1.0f , 0.0f ) ;
2010-08-14 09:30:54 +00:00
Vector2D lt = DisplayToMap ( new Vector2D ( 0.0f , 0.0f ) ) ;
2013-09-11 08:49:45 +00:00
Vector2D rb = DisplayToMap ( new Vector2D ( windowsize . Width , windowsize . Height ) ) ;
2010-08-14 09:30:54 +00:00
viewport = new RectangleF ( lt . x , lt . y , rb . x - lt . x , rb . y - lt . y ) ;
yviewport = new RectangleF ( lt . x , rb . y , rb . x - lt . x , lt . y - rb . y ) ;
2009-04-19 18:07:22 +00:00
}
// This sets the world matrix for transformation
private void SetWorldTransformation ( bool transform )
{
if ( transform )
{
Matrix translate = Matrix . Translation ( translatex , translatey , 0f ) ;
Matrix scaling = Matrix . Scaling ( scale , - scale , 1f ) ;
2019-08-16 11:38:53 +00:00
worldmatrix = translate * scaling ;
2009-04-19 18:07:22 +00:00
}
else
{
2019-08-16 11:38:53 +00:00
worldmatrix = Matrix . Identity ;
2009-04-19 18:07:22 +00:00
}
}
2019-08-16 11:07:57 +00:00
2019-08-17 01:08:34 +00:00
private void SetDisplay2DSettings ( float texelx , float texely , float fsaafactor , float alpha , bool bilinear , bool flipY = false )
2019-08-16 11:07:57 +00:00
{
2020-01-03 01:22:33 +00:00
Vector4f values = new Vector4f ( texelx , texely , fsaafactor , alpha ) ;
2019-08-16 11:07:57 +00:00
graphics . SetUniform ( UniformName . rendersettings , values ) ;
2019-08-17 01:08:34 +00:00
if ( flipY )
2019-08-22 16:43:54 +00:00
graphics . SetUniform ( UniformName . projection , worldmatrix * viewmatrix * Matrix . Scaling ( 1f , - 1f , 1f ) ) ;
2019-08-17 01:08:34 +00:00
else
2019-08-22 16:43:54 +00:00
graphics . SetUniform ( UniformName . projection , worldmatrix * viewmatrix ) ;
2019-12-29 17:54:22 +00:00
graphics . SetSamplerFilter ( bilinear ? TextureFilter . Linear : TextureFilter . Nearest ) ;
2019-08-16 11:07:57 +00:00
}
private void SetThings2DSettings ( float alpha )
{
2020-01-03 01:22:33 +00:00
Vector4f values = new Vector4f ( 0.0f , 0.0f , 1.0f , alpha ) ;
2019-08-16 11:07:57 +00:00
graphics . SetUniform ( UniformName . rendersettings , values ) ;
2019-08-22 16:43:54 +00:00
graphics . SetUniform ( UniformName . projection , worldmatrix * viewmatrix ) ;
2019-08-16 11:07:57 +00:00
}
//mxd. Used to render models
private void SetThings2DTransformSettings ( Matrix world )
{
2019-08-22 16:43:54 +00:00
graphics . SetUniform ( UniformName . projection , world * viewmatrix ) ;
2019-08-16 11:07:57 +00:00
}
/// <summary>
/// This unprojects display coordinates (screen space) to map coordinates
/// </summary>
public Vector2D DisplayToMap ( Vector2D mousepos )
2009-04-19 18:07:22 +00:00
{
return mousepos . GetInvTransformed ( - translatex , - translatey , scaleinv , - scaleinv ) ;
}
2009-08-21 14:11:18 +00:00
/// <summary>
/// This projects map coordinates to display coordinates (screen space)
/// </summary>
public Vector2D MapToDisplay ( Vector2D mappos )
{
return mappos . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Colors
// This returns the color for a thing
public PixelColor DetermineThingColor ( Thing t )
{
// Determine color
2015-12-14 12:34:31 +00:00
if ( t . Selected ) return General . Colors . Selection ;
//mxd. If thing is light, set it's color to light color:
2018-02-03 20:31:34 +00:00
if ( t . DynamicLightType ! = null )
2014-12-03 23:15:26 +00:00
{
2018-02-03 20:31:34 +00:00
if ( t . DynamicLightType . LightDef = = GZGeneral . LightDef . VAVOOM_GENERIC ) //vavoom light
2013-09-11 09:47:53 +00:00
return new PixelColor ( 255 , 255 , 255 , 255 ) ;
2018-02-03 20:31:34 +00:00
if ( t . DynamicLightType . LightDef = = GZGeneral . LightDef . VAVOOM_COLORED ) //vavoom colored light
2013-09-11 09:47:53 +00:00
return new PixelColor ( 255 , ( byte ) t . Args [ 1 ] , ( byte ) t . Args [ 2 ] , ( byte ) t . Args [ 3 ] ) ;
2019-01-14 18:07:08 +00:00
if ( t . DynamicLightType . LightType = = GZGeneral . LightType . SPOT )
{
if ( t . Fields . ContainsKey ( "arg0str" ) )
{
PixelColor pc ;
ZDoom . ZDTextParser . GetColorFromString ( t . Fields [ "arg0str" ] . Value . ToString ( ) , out pc ) ;
pc . a = 255 ;
return pc ;
}
return new PixelColor ( 255 , ( byte ) ( ( t . Args [ 0 ] & 0xFF0000 ) > > 16 ) , ( byte ) ( ( t . Args [ 0 ] & 0x00FF00 ) > > 8 ) , ( byte ) ( ( t . Args [ 0 ] & 0x0000FF ) ) ) ;
}
2013-09-11 09:47:53 +00:00
return new PixelColor ( 255 , ( byte ) t . Args [ 0 ] , ( byte ) t . Args [ 1 ] , ( byte ) t . Args [ 2 ] ) ;
}
return t . Color ;
2009-04-19 18:07:22 +00:00
}
// This returns the color for a vertex
public int DetermineVertexColor ( Vertex v )
{
// Determine color
if ( v . Selected ) return ColorCollection . SELECTION ;
2013-03-18 13:52:27 +00:00
return ColorCollection . VERTICES ;
2009-04-19 18:07:22 +00:00
}
// This returns the color for a linedef
public PixelColor DetermineLinedefColor ( Linedef l )
{
2013-07-29 08:50:50 +00:00
if ( l . Selected ) return General . Colors . Selection ;
//mxd. Impassable lines
2014-12-03 23:15:26 +00:00
if ( l . ImpassableFlag )
{
2013-07-29 08:50:50 +00:00
if ( l . ColorPresetIndex ! = - 1 )
return General . Map . ConfigSettings . LinedefColorPresets [ l . ColorPresetIndex ] . Color ;
return General . Colors . Linedefs ;
2009-04-19 18:07:22 +00:00
}
2013-03-18 13:52:27 +00:00
2013-07-29 08:50:50 +00:00
//mxd. Passable lines
if ( l . ColorPresetIndex ! = - 1 )
return General . Map . ConfigSettings . LinedefColorPresets [ l . ColorPresetIndex ] . Color . WithAlpha ( General . Settings . DoubleSidedAlphaByte ) ;
return General . Colors . Linedefs . WithAlpha ( General . Settings . DoubleSidedAlphaByte ) ;
2009-04-19 18:07:22 +00:00
}
2013-07-29 08:50:50 +00:00
//mxd. This collects indices of linedefs, which are parts of sectors with 3d floors
2014-12-03 23:15:26 +00:00
public void UpdateExtraFloorFlag ( )
{
2015-07-28 15:04:21 +00:00
HashSet < int > tags = new HashSet < int > ( ) ;
2013-07-29 08:50:50 +00:00
//find lines with 3d floor action and collect sector tags
2014-12-03 23:15:26 +00:00
foreach ( Linedef l in General . Map . Map . Linedefs )
{
if ( l . Action = = 160 )
{
2015-07-26 23:35:34 +00:00
int sectortag = ( General . Map . UDMF | | ( l . Args [ 1 ] & 8 ) ! = 0 ) ? l . Args [ 0 ] : l . Args [ 0 ] + ( l . Args [ 4 ] < < 8 ) ;
2015-07-28 15:04:21 +00:00
if ( sectortag ! = 0 & & ! tags . Contains ( sectortag ) ) tags . Add ( sectortag ) ;
2013-07-29 08:50:50 +00:00
}
}
2013-05-20 10:43:34 +00:00
2013-07-29 08:50:50 +00:00
//find lines, which are related to sectors with 3d floors, and collect their valuable indices
2014-12-03 23:15:26 +00:00
foreach ( Linedef l in General . Map . Map . Linedefs )
{
2015-07-28 15:04:21 +00:00
if ( l . Front ! = null & & l . Front . Sector ! = null & & l . Front . Sector . Tag ! = 0 & & tags . Overlaps ( l . Front . Sector . Tags ) )
2014-12-03 23:15:26 +00:00
{
2013-07-29 08:50:50 +00:00
l . ExtraFloorFlag = true ;
continue ;
}
2015-07-28 15:04:21 +00:00
if ( l . Back ! = null & & l . Back . Sector ! = null & & l . Back . Sector . Tag ! = 0 & & tags . Overlaps ( l . Back . Sector . Tags ) )
2014-12-03 23:15:26 +00:00
{
2013-07-29 08:50:50 +00:00
l . ExtraFloorFlag = true ;
continue ;
2013-05-20 10:43:34 +00:00
}
2013-07-29 08:50:50 +00:00
l . ExtraFloorFlag = false ;
2013-05-20 10:43:34 +00:00
}
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Start / Finish
// This begins a drawing session
2019-08-22 13:52:17 +00:00
public bool StartPlotter ( bool clear )
2009-04-19 18:07:22 +00:00
{
2015-12-14 12:34:31 +00:00
if ( renderlayer ! = RenderLayers . None )
{
#if DEBUG
throw new InvalidOperationException ( "Renderer starting called before finished previous layer. Call Finish() first!" ) ;
#else
return false ; //mxd. Can't render. Most probably because previous frame or render layer wasn't finished yet.
#endif
}
2013-03-18 13:52:27 +00:00
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Plotter ;
// Rendertargets available?
2019-08-18 05:43:46 +00:00
if ( plotter ! = null )
2009-04-19 18:07:22 +00:00
{
// Redraw grid when structures image was cleared
if ( clear )
{
2013-05-20 10:43:34 +00:00
plotter . Clear ( ) ;
2009-04-19 18:07:22 +00:00
RenderBackgroundGrid ( ) ;
SetupBackground ( ) ;
}
// Ready for rendering
UpdateTransformations ( ) ;
return true ;
}
2013-07-29 08:50:50 +00:00
// Can't render!
Finish ( ) ;
return false ;
2009-04-19 18:07:22 +00:00
}
// This begins a drawing session
2013-07-29 08:50:50 +00:00
public bool StartThings ( bool clear )
2009-04-19 18:07:22 +00:00
{
2015-12-14 12:34:31 +00:00
if ( renderlayer ! = RenderLayers . None )
{
#if DEBUG
throw new InvalidOperationException ( "Renderer starting called before finished previous layer. Call Finish() first!" ) ;
#else
return false ; //mxd. Can't render. Most probably because previous frame or render layer wasn't finished yet.
#endif
}
2013-03-18 13:52:27 +00:00
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Things ;
// Rendertargets available?
if ( thingstex ! = null )
{
// Set the rendertarget to the things texture
2019-08-08 01:19:11 +00:00
graphics . StartRendering ( clear , General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , thingstex , false ) ;
2013-07-29 08:50:50 +00:00
2019-08-08 01:19:11 +00:00
// Ready for rendering
UpdateTransformations ( ) ;
return true ;
2009-04-19 18:07:22 +00:00
}
2013-07-29 08:50:50 +00:00
// Can't render!
Finish ( ) ;
return false ;
2009-04-19 18:07:22 +00:00
}
// This begins a drawing session
2013-07-29 08:50:50 +00:00
public bool StartOverlay ( bool clear )
2009-04-19 18:07:22 +00:00
{
2015-12-14 12:34:31 +00:00
if ( renderlayer ! = RenderLayers . None )
{
#if DEBUG
throw new InvalidOperationException ( "Renderer starting called before finished previous layer. Call Finish() first!" ) ;
#else
return false ; //mxd. Can't render. Most probably because previous frame or render layer wasn't finished yet.
#endif
}
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Overlay ;
// Rendertargets available?
if ( overlaytex ! = null )
{
// Set the rendertarget to the things texture
2019-08-08 01:19:11 +00:00
graphics . StartRendering ( clear , General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , overlaytex , false ) ;
2013-07-29 08:50:50 +00:00
2019-08-08 01:19:11 +00:00
// Ready for rendering
UpdateTransformations ( ) ;
return true ;
2009-04-19 18:07:22 +00:00
}
2013-07-29 08:50:50 +00:00
// Can't render!
Finish ( ) ;
return false ;
2009-04-19 18:07:22 +00:00
}
// This ends a drawing session
public void Finish ( )
{
2019-08-18 05:43:46 +00:00
// Draw plotter contents
2009-04-19 18:07:22 +00:00
if ( renderlayer = = RenderLayers . Plotter )
{
2019-08-18 05:43:46 +00:00
plotter . DrawContents ( graphics ) ;
2009-04-19 18:07:22 +00:00
}
// Clean up things / overlay
if ( ( renderlayer = = RenderLayers . Things ) | | ( renderlayer = = RenderLayers . Overlay ) | | ( renderlayer = = RenderLayers . Surface ) )
{
// Stop rendering
graphics . FinishRendering ( ) ;
}
// Done
renderlayer = RenderLayers . None ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Background
// This sets up background image vertices
private void SetupBackground ( )
{
// Only if a background image is set
2014-01-13 08:06:56 +00:00
if ( ( General . Map . Grid . Background ! = null ) & & ! ( General . Map . Grid . Background is UnknownImage ) )
2009-04-19 18:07:22 +00:00
{
2014-01-13 08:06:56 +00:00
Vector2D backoffset = new Vector2D ( General . Map . Grid . BackgroundX , General . Map . Grid . BackgroundY ) ;
Vector2D backimagesize = new Vector2D ( General . Map . Grid . Background . ScaledWidth , General . Map . Grid . Background . ScaledHeight ) ;
Vector2D backimagescale = new Vector2D ( General . Map . Grid . BackgroundScaleX , General . Map . Grid . BackgroundScaleY ) ;
// Scale the background image size
backimagesize * = backimagescale ;
2009-04-19 18:07:22 +00:00
// Make vertices
backimageverts = CreateScreenVerts ( windowsize ) ;
// Determine map coordinates for view window
2020-01-07 21:26:21 +00:00
Vector2D lbpos = DisplayToMap ( new Vector2D ( 0f , windowsize . Height ) ) ;
Vector2D rtpos = DisplayToMap ( new Vector2D ( windowsize . Width , 0 ) ) ;
2009-04-19 18:07:22 +00:00
// Offset by given background offset
2020-01-07 21:26:21 +00:00
lbpos - = backoffset ;
rtpos - = backoffset ;
2009-04-19 18:07:22 +00:00
// Calculate UV coordinates
// NOTE: backimagesize.y is made negative to match Doom's coordinate system
2020-01-07 21:26:21 +00:00
backimageverts [ 0 ] . u = lbpos . x / backimagesize . x ;
backimageverts [ 0 ] . v = lbpos . y / - backimagesize . y ;
backimageverts [ 1 ] . u = rtpos . x / backimagesize . x ;
backimageverts [ 1 ] . v = lbpos . y / - backimagesize . y ;
backimageverts [ 2 ] . u = lbpos . x / backimagesize . x ;
backimageverts [ 2 ] . v = rtpos . y / - backimagesize . y ;
backimageverts [ 3 ] . u = rtpos . x / backimagesize . x ;
backimageverts [ 3 ] . v = rtpos . y / - backimagesize . y ;
2009-04-19 18:07:22 +00:00
}
else
{
// No background image
backimageverts = null ;
}
}
// This renders all grid
2019-08-22 13:52:17 +00:00
private void RenderBackgroundGrid ( )
2009-04-19 18:07:22 +00:00
{
// Do we need to redraw grid?
2017-01-06 10:01:59 +00:00
if ( lastgridsize ! = General . Map . Grid . GridSizeF | | lastgridscale ! = scale | |
2016-06-16 22:05:17 +00:00
lastgridx ! = offsetx | | lastgridy ! = offsety | | drawmapcenter ! = lastdrawmapcenter )
2009-04-19 18:07:22 +00:00
{
gridplotter . Clear ( ) ;
2015-08-04 23:28:02 +00:00
if ( General . Settings . RenderGrid ) //mxd
{
2019-01-19 08:02:54 +00:00
bool transformed = Math . Abs ( General . Map . Grid . GridOriginX ) > 1e-4 | | Math . Abs ( General . Map . Grid . GridOriginY ) > 1e-4 | | Math . Abs ( General . Map . Grid . GridRotate ) > 1e-4 ;
2009-04-19 18:07:22 +00:00
2019-01-14 18:07:08 +00:00
if ( transformed )
{
// Render normal grid
RenderGridTransformed ( General . Map . Grid . GridSizeF , General . Map . Grid . GridRotate ,
General . Map . Grid . GridOriginX , General . Map . Grid . GridOriginY , General . Colors . Grid , gridplotter ) ;
// Render 64 grid
if ( General . Map . Grid . GridSizeF < = 64 )
{
RenderGridTransformed ( 64f , General . Map . Grid . GridRotate ,
General . Map . Grid . GridOriginX , General . Map . Grid . GridOriginY , General . Colors . Grid64 , gridplotter ) ;
}
}
else
{
// Render normal grid
RenderGrid ( General . Map . Grid . GridSizeF , General . Colors . Grid , gridplotter ) ;
// Render 64 grid
if ( General . Map . Grid . GridSizeF < = 64 ) RenderGrid ( 64f , General . Colors . Grid64 , gridplotter ) ;
}
2015-08-04 23:28:02 +00:00
}
else
{
//mxd. Render map format bounds
Vector2D tl = new Vector2D ( General . Map . Config . LeftBoundary , General . Map . Config . TopBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D rb = new Vector2D ( General . Map . Config . RightBoundary , General . Map . Config . BottomBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
PixelColor g = General . Colors . Grid64 ;
2019-12-16 02:15:53 +00:00
gridplotter . DrawGridLineH ( ( int ) tl . y , ( int ) tl . x , ( int ) rb . x , ref g ) ;
gridplotter . DrawGridLineH ( ( int ) rb . y , ( int ) tl . x , ( int ) rb . x , ref g ) ;
gridplotter . DrawGridLineV ( ( int ) tl . x , ( int ) tl . y , ( int ) rb . y , ref g ) ;
gridplotter . DrawGridLineV ( ( int ) rb . x , ( int ) tl . y , ( int ) rb . y , ref g ) ;
2015-08-04 23:28:02 +00:00
}
2009-04-19 18:07:22 +00:00
2013-09-11 09:47:53 +00:00
//mxd. Render center of map
2016-06-16 22:05:17 +00:00
if ( drawmapcenter )
{
2019-09-10 23:26:59 +00:00
Vector2D center = new Vector2D ( 0 , 0 ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
2016-06-16 22:05:17 +00:00
int cx = ( int ) center . x ;
int cy = ( int ) center . y ;
PixelColor c = General . Colors . Highlight ;
2019-12-16 02:15:53 +00:00
gridplotter . DrawLineSolid ( cx , cy + MAP_CENTER_SIZE , cx , cy - MAP_CENTER_SIZE , ref c ) ;
gridplotter . DrawLineSolid ( cx - MAP_CENTER_SIZE , cy , cx + MAP_CENTER_SIZE , cy , ref c ) ;
2016-06-16 22:05:17 +00:00
}
2012-06-28 21:19:32 +00:00
2019-08-15 00:52:21 +00:00
// Done
2019-08-18 05:43:46 +00:00
gridplotter . DrawContents ( graphics ) ;
2009-04-19 18:07:22 +00:00
lastgridscale = scale ;
2017-01-06 10:01:59 +00:00
lastgridsize = General . Map . Grid . GridSizeF ;
2009-04-19 18:07:22 +00:00
lastgridx = offsetx ;
lastgridy = offsety ;
2016-06-16 22:05:17 +00:00
lastdrawmapcenter = drawmapcenter ; //mxd
2009-04-19 18:07:22 +00:00
}
}
2019-01-14 18:07:08 +00:00
// This renders the grid with a transform applied
private void RenderGridTransformed ( float size , float angle , float originx , float originy , PixelColor c , Plotter gridplotter )
{
2019-12-16 02:15:53 +00:00
uint mask = 0x55555555 ;
2019-01-14 18:07:08 +00:00
//mxd. Increase rendered grid size if needed
if ( ! General . Settings . DynamicGridSize & & size * scale < = 6f )
do { size * = 2 ; } while ( size * scale < = 6f ) ;
float sizeinv = 1f / size ;
2019-01-27 23:27:14 +00:00
if ( float . IsInfinity ( size ) | | size < 1e-10 )
{
return ;
}
2019-01-14 18:07:08 +00:00
// Determine map coordinates for view window
2019-01-16 06:44:38 +00:00
Vector2D ltview = DisplayToMap ( new Vector2D ( 0 , 0 ) ) ;
Vector2D rbview = DisplayToMap ( new Vector2D ( windowsize . Width , windowsize . Height ) ) ;
Vector2D mapsize = rbview - ltview ;
2019-01-14 18:07:08 +00:00
Vector2D ltbound = new Vector2D ( General . Map . Config . LeftBoundary , General . Map . Config . TopBoundary ) ;
Vector2D rbbound = new Vector2D ( General . Map . Config . RightBoundary , General . Map . Config . BottomBoundary ) ;
// Translate top left boundary and right bottom boundary of map to screen coords
Vector2D tlb = ltbound . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D rbb = rbbound . GetTransformed ( translatex , translatey , scale , - scale ) ;
2019-01-16 06:44:38 +00:00
Vector2D center = GridSetup . SnappedToGrid ( 0.5f * ( ltview + rbview ) , size , sizeinv , angle , originx , originy ) ;
2019-01-14 18:07:08 +00:00
// Get the angle vectors for the gridlines
Vector2D dx = new Vector2D ( ( float ) Math . Cos ( angle ) , ( float ) Math . Sin ( angle ) ) ;
Vector2D dy = new Vector2D ( ( float ) - Math . Sin ( angle ) , ( float ) Math . Cos ( angle ) ) ;
float maxextent = Math . Max ( mapsize . x , mapsize . y ) ;
RectangleF bounds = new RectangleF ( tlb . x , tlb . y , rbb . x - tlb . x , rbb . y - tlb . y ) ;
2019-01-16 06:44:38 +00:00
bounds . Intersect ( new RectangleF ( 0 , 0 , windowsize . Width , windowsize . Height ) ) ;
2019-01-14 18:07:08 +00:00
bool xminintersect = true , xmaxintersect = true , yminintersect = true , ymaxintersect = true ;
int num = 0 ;
while ( xminintersect | | xmaxintersect | | yminintersect | | ymaxintersect ) {
2019-01-27 23:27:14 +00:00
if ( num > 1e6 )
{
// just in case garbage inputs breaks the algorithm and causes an infinite loop
break ;
}
2019-01-16 06:44:38 +00:00
Vector2D xminstart = center - num * size * dy ;
Vector2D xmaxstart = center + num * size * dy ;
Vector2D yminstart = center - num * size * dx ;
Vector2D ymaxstart = center + num * size * dx ;
2019-01-14 18:07:08 +00:00
Line2D xminscanline = new Line2D ( xminstart - dx * maxextent , xminstart + dx * maxextent ) ;
Line2D xmaxscanline = new Line2D ( xmaxstart - dx * maxextent , xmaxstart + dx * maxextent ) ;
Line2D yminscanline = new Line2D ( yminstart - dy * maxextent , yminstart + dy * maxextent ) ;
Line2D ymaxscanline = new Line2D ( ymaxstart - dy * maxextent , ymaxstart + dy * maxextent ) ;
Line2D xminplotline = xminscanline . GetTransformed ( translatex , translatey , scale , - scale ) ;
Line2D xmaxplotline = xmaxscanline . GetTransformed ( translatex , translatey , scale , - scale ) ;
Line2D yminplotline = yminscanline . GetTransformed ( translatex , translatey , scale , - scale ) ;
Line2D ymaxplotline = ymaxscanline . GetTransformed ( translatex , translatey , scale , - scale ) ;
xminplotline = Line2D . ClipToRectangle ( xminplotline , bounds , out xminintersect ) ;
xmaxplotline = Line2D . ClipToRectangle ( xmaxplotline , bounds , out xmaxintersect ) ;
yminplotline = Line2D . ClipToRectangle ( yminplotline , bounds , out yminintersect ) ;
ymaxplotline = Line2D . ClipToRectangle ( ymaxplotline , bounds , out ymaxintersect ) ;
if ( xminintersect )
{
2019-12-16 02:15:53 +00:00
gridplotter . DrawLineSolid ( ( int ) xminplotline . v1 . x , ( int ) xminplotline . v1 . y , ( int ) xminplotline . v2 . x , ( int ) xminplotline . v2 . y , ref c , mask ) ;
2019-01-14 18:07:08 +00:00
}
if ( xmaxintersect )
{
2019-12-16 02:15:53 +00:00
gridplotter . DrawLineSolid ( ( int ) xmaxplotline . v1 . x , ( int ) xmaxplotline . v1 . y , ( int ) xmaxplotline . v2 . x , ( int ) xmaxplotline . v2 . y , ref c , mask ) ;
2019-01-14 18:07:08 +00:00
}
if ( yminintersect )
{
2019-12-16 02:15:53 +00:00
gridplotter . DrawLineSolid ( ( int ) yminplotline . v1 . x , ( int ) yminplotline . v1 . y , ( int ) yminplotline . v2 . x , ( int ) yminplotline . v2 . y , ref c , mask ) ;
2019-01-14 18:07:08 +00:00
}
if ( ymaxintersect )
{
2019-12-16 02:15:53 +00:00
gridplotter . DrawLineSolid ( ( int ) ymaxplotline . v1 . x , ( int ) ymaxplotline . v1 . y , ( int ) ymaxplotline . v2 . x , ( int ) ymaxplotline . v2 . y , ref c , mask ) ;
2019-01-14 18:07:08 +00:00
}
num + + ;
}
}
2009-04-19 18:07:22 +00:00
// This renders the grid
private void RenderGrid ( float size , PixelColor c , Plotter gridplotter )
{
Vector2D pos = new Vector2D ( ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
//mxd. Increase rendered grid size if needed
2015-08-20 14:09:28 +00:00
if ( ! General . Settings . DynamicGridSize & & size * scale < = 6f )
do { size * = 2 ; } while ( size * scale < = 6f ) ;
2013-12-17 08:19:40 +00:00
float sizeinv = 1f / size ;
2009-04-19 18:07:22 +00:00
2013-12-17 08:19:40 +00:00
// Determine map coordinates for view window
2015-12-27 21:54:50 +00:00
Vector2D ltpos = DisplayToMap ( new Vector2D ( 0 , 0 ) ) ;
Vector2D rbpos = DisplayToMap ( new Vector2D ( windowsize . Width , windowsize . Height ) ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Clip to nearest grid
ltpos = GridSetup . SnappedToGrid ( ltpos , size , sizeinv ) ;
rbpos = GridSetup . SnappedToGrid ( rbpos , size , sizeinv ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Translate top left boundary and right bottom boundary of map to screen coords
2015-12-27 21:54:50 +00:00
Vector2D tlb = new Vector2D ( General . Map . Config . LeftBoundary , General . Map . Config . TopBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D rbb = new Vector2D ( General . Map . Config . RightBoundary , General . Map . Config . BottomBoundary ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Draw all horizontal grid lines
2015-12-27 21:54:50 +00:00
float ystart = rbpos . y > General . Map . Config . BottomBoundary ? rbpos . y : General . Map . Config . BottomBoundary ;
float yend = ltpos . y < General . Map . Config . TopBoundary ? ltpos . y : General . Map . Config . TopBoundary ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
for ( float y = ystart ; y < yend + size ; y + = size )
{
if ( y > General . Map . Config . TopBoundary ) y = General . Map . Config . TopBoundary ;
else if ( y < General . Map . Config . BottomBoundary ) y = General . Map . Config . BottomBoundary ;
2010-08-13 18:32:21 +00:00
2015-12-27 21:54:50 +00:00
float from = tlb . x < 0 ? 0 : tlb . x ;
float to = rbb . x > windowsize . Width ? windowsize . Width : rbb . x ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
pos . y = y ;
pos = pos . GetTransformed ( translatex , translatey , scale , - scale ) ;
2010-08-13 18:32:21 +00:00
2019-12-29 18:04:33 +00:00
gridplotter . DrawGridLineH ( ( int ) Math . Round ( pos . y + 0.49999f ) , ( int ) from , ( int ) to , ref c ) ;
2019-12-16 06:32:01 +00:00
}
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
// Draw all vertical grid lines
2015-12-27 21:54:50 +00:00
float xstart = ltpos . x > General . Map . Config . LeftBoundary ? ltpos . x : General . Map . Config . LeftBoundary ;
float xend = rbpos . x < General . Map . Config . RightBoundary ? rbpos . x : General . Map . Config . RightBoundary ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
for ( float x = xstart ; x < xend + size ; x + = size )
{
if ( x > General . Map . Config . RightBoundary ) x = General . Map . Config . RightBoundary ;
else if ( x < General . Map . Config . LeftBoundary ) x = General . Map . Config . LeftBoundary ;
2010-08-13 18:32:21 +00:00
2015-12-27 21:54:50 +00:00
float from = tlb . y < 0 ? 0 : tlb . y ;
float to = rbb . y > windowsize . Height ? windowsize . Height : rbb . y ;
2010-08-13 18:32:21 +00:00
2013-12-17 08:19:40 +00:00
pos . x = x ;
pos = pos . GetTransformed ( translatex , translatey , scale , - scale ) ;
2019-12-16 06:32:01 +00:00
gridplotter . DrawGridLineV ( ( int ) pos . x , ( int ) Math . Round ( from + 0.49999f ) , ( int ) Math . Round ( to + 0.49999f ) , ref c ) ;
}
2009-04-19 18:07:22 +00:00
}
2015-08-04 23:28:02 +00:00
//mxd
internal void GridVisibilityChanged ( )
{
lastgridscale = - 1 ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Things
// This makes vertices for a thing
// Returns false when not on the screen
2016-04-01 10:49:19 +00:00
private bool CreateThingBoxVerts ( Thing t , ref FlatVertex [ ] verts , ref List < Line3D > bboxes , Dictionary < Thing , Vector3D > thingsByPosition , int offset , PixelColor c , byte bboxalpha )
2009-04-19 18:07:22 +00:00
{
2013-07-29 08:50:50 +00:00
if ( t . Size * scale < MINIMUM_THING_RADIUS ) return false ; //mxd. Don't render tiny little things
2013-11-27 12:45:28 +00:00
2016-02-22 15:20:08 +00:00
// Determine sizes
2016-04-04 12:09:38 +00:00
float circlesize , bboxsize ;
if ( t . FixedSize & & scale > 1.0f )
{
circlesize = t . Size ;
bboxsize = - 1 ;
}
else if ( General . Settings . FixedThingsScale & & t . Size * scale > FIXED_THING_SIZE )
{
circlesize = FIXED_THING_SIZE ;
bboxsize = t . Size * scale ;
}
else
{
circlesize = t . Size * scale ;
bboxsize = - 1 ;
}
2016-04-01 10:49:19 +00:00
float screensize = ( bboxsize > 0 ? bboxsize : circlesize ) ; //mxd
2009-04-19 18:07:22 +00:00
// Transform to screen coordinates
Vector2D screenpos = ( ( Vector2D ) t . Position ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Check if the thing is actually on screen
2016-02-22 15:20:08 +00:00
if ( ( ( screenpos . x + screensize ) < = 0.0f ) | | ( ( screenpos . x - screensize ) > = windowsize . Width ) | |
( ( screenpos . y + screensize ) < = 0.0f ) | | ( ( screenpos . y - screensize ) > = windowsize . Height ) )
2013-11-27 12:45:28 +00:00
return false ;
2013-07-29 08:50:50 +00:00
2013-11-27 12:45:28 +00:00
// Get integral color
int color = c . ToInt ( ) ;
// Setup fixed rect for circle
verts [ offset ] . x = screenpos . x - circlesize ;
verts [ offset ] . y = screenpos . y - circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0f ;
verts [ offset ] . v = 0f ;
offset + + ;
verts [ offset ] . x = screenpos . x + circlesize ;
verts [ offset ] . y = screenpos . y - circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0.5f ;
verts [ offset ] . v = 0f ;
offset + + ;
verts [ offset ] . x = screenpos . x - circlesize ;
verts [ offset ] . y = screenpos . y + circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0f ;
verts [ offset ] . v = 1f ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] . x = screenpos . x + circlesize ;
verts [ offset ] . y = screenpos . y + circlesize ;
verts [ offset ] . c = color ;
verts [ offset ] . u = 0.5f ;
verts [ offset ] . v = 1f ;
//mxd. Add to list
thingsByPosition . Add ( t , screenpos ) ;
2013-07-29 08:50:50 +00:00
2016-02-22 15:20:08 +00:00
//mxd. Add bounding box?
if ( bboxsize > 0 )
{
PixelColor boxcolor = c . WithAlpha ( bboxalpha ) ;
Vector2D tl = new Vector2D ( screenpos . x - bboxsize , screenpos . y - bboxsize ) ;
Vector2D tr = new Vector2D ( screenpos . x + bboxsize , screenpos . y - bboxsize ) ;
Vector2D bl = new Vector2D ( screenpos . x - bboxsize , screenpos . y + bboxsize ) ;
Vector2D br = new Vector2D ( screenpos . x + bboxsize , screenpos . y + bboxsize ) ;
bboxes . Add ( new Line3D ( tl , tr , boxcolor , false ) ) ;
bboxes . Add ( new Line3D ( tr , br , boxcolor , false ) ) ;
bboxes . Add ( new Line3D ( bl , br , boxcolor , false ) ) ;
bboxes . Add ( new Line3D ( tl , bl , boxcolor , false ) ) ;
}
2013-11-27 12:45:28 +00:00
// Done
return true ;
}
//mxd
2016-04-01 10:49:19 +00:00
private void CreateThingArrowVerts ( Thing t , ref FlatVertex [ ] verts , Vector3D screenpos , int offset )
2014-12-03 23:15:26 +00:00
{
2013-11-27 12:45:28 +00:00
// Determine size
2016-04-04 12:09:38 +00:00
float arrowsize ;
if ( t . FixedSize & & scale > 1.0f )
arrowsize = t . Size * THING_ARROW_SIZE ;
else if ( General . Settings . FixedThingsScale & & t . Size * scale > FIXED_THING_SIZE )
arrowsize = FIXED_THING_SIZE * THING_ARROW_SIZE ;
else
arrowsize = t . Size * scale * THING_ARROW_SIZE ;
2013-11-27 12:45:28 +00:00
// Setup rotated rect for arrow
float sinarrowsize = ( float ) Math . Sin ( t . Angle + Angle2D . PI * 0.25f ) * arrowsize ;
float cosarrowsize = ( float ) Math . Cos ( t . Angle + Angle2D . PI * 0.25f ) * arrowsize ;
2016-04-01 10:49:19 +00:00
// Sprite is not rendered?
float ut , ub , ul , ur ;
if ( screenpos . z < 0 )
{
ul = 0.625f ;
ur = 0.874f ;
ut = - 0.039f ;
ub = 0.46f ;
}
else
{
ul = 0.501f ;
ur = 0.999f ;
ut = 0.001f ;
ub = 0.999f ;
}
2013-11-27 12:45:28 +00:00
verts [ offset ] . x = screenpos . x + sinarrowsize ;
verts [ offset ] . y = screenpos . y + cosarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ul ;
verts [ offset ] . v = ut ;
2013-11-27 12:45:28 +00:00
offset + + ;
verts [ offset ] . x = screenpos . x - cosarrowsize ;
verts [ offset ] . y = screenpos . y + sinarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ur ;
verts [ offset ] . v = ut ;
2013-11-27 12:45:28 +00:00
offset + + ;
verts [ offset ] . x = screenpos . x + cosarrowsize ;
verts [ offset ] . y = screenpos . y - sinarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ul ;
verts [ offset ] . v = ub ;
2013-11-27 12:45:28 +00:00
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] . x = screenpos . x - sinarrowsize ;
verts [ offset ] . y = screenpos . y - cosarrowsize ;
verts [ offset ] . c = - 1 ;
2016-04-01 10:49:19 +00:00
verts [ offset ] . u = ur ;
verts [ offset ] . v = ub ;
2013-11-27 12:45:28 +00:00
}
//mxd
2016-04-08 14:02:08 +00:00
private static void CreateThingSpriteVerts ( Vector2D screenpos , float width , float height , ref FlatVertex [ ] verts , int offset , int color , bool mirror )
2014-05-20 09:09:28 +00:00
{
2016-04-08 14:02:08 +00:00
float ul = ( mirror ? 1f : 0f ) ;
float ur = ( mirror ? 0f : 1f ) ;
2013-11-27 12:45:28 +00:00
// Setup fixed rect for circle
verts [ offset ] . x = screenpos . x - width ;
verts [ offset ] . y = screenpos . y - height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ul ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 0 ;
offset + + ;
verts [ offset ] . x = screenpos . x + width ;
verts [ offset ] . y = screenpos . y - height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ur ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 0 ;
offset + + ;
verts [ offset ] . x = screenpos . x - width ;
verts [ offset ] . y = screenpos . y + height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ul ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 1 ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] = verts [ offset - 2 ] ;
offset + + ;
verts [ offset ] . x = screenpos . x + width ;
verts [ offset ] . y = screenpos . y + height ;
verts [ offset ] . c = color ;
2016-04-08 14:02:08 +00:00
verts [ offset ] . u = ur ;
2013-11-27 12:45:28 +00:00
verts [ offset ] . v = 1 ;
2009-04-19 18:07:22 +00:00
}
// This draws a set of things
2010-08-16 13:31:53 +00:00
private void RenderThingsBatch ( ICollection < Thing > things , float alpha , bool fixedcolor , PixelColor c )
2009-04-19 18:07:22 +00:00
{
// Anything to render?
2010-08-16 13:31:53 +00:00
if ( things . Count > 0 )
2009-04-19 18:07:22 +00:00
{
// Make alpha color
2019-08-16 03:37:03 +00:00
Color4 alphacolor = new Color4 ( 1.0f , 1.0f , 1.0f , alpha ) ;
2016-02-23 13:55:53 +00:00
bool isthingsmode = ( General . Editing . Mode . GetType ( ) . Name = = "ThingsMode" ) ;
2009-04-19 18:07:22 +00:00
// Set renderstates for things rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( true ) ;
graphics . SetSourceBlend ( Blend . SourceAlpha ) ;
graphics . SetDestinationBlend ( Blend . InverseSourceAlpha ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-22 16:43:54 +00:00
graphics . SetUniform ( UniformName . texturefactor , alphacolor ) ;
2019-08-16 11:07:57 +00:00
graphics . SetVertexBuffer ( thingsvertices ) ;
2010-08-16 13:31:53 +00:00
2015-08-03 22:02:39 +00:00
// Set things texture
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Data . ThingTexture . Texture ) ; //mxd
2009-04-19 18:07:22 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . things2d_thing ) ;
2019-08-16 11:07:57 +00:00
SetThings2DSettings ( alpha ) ;
2010-08-16 13:31:53 +00:00
2010-08-16 17:53:28 +00:00
// Determine next lock size
2010-08-16 13:31:53 +00:00
int locksize = ( things . Count > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : things . Count ;
2013-11-27 12:45:28 +00:00
FlatVertex [ ] verts = new FlatVertex [ THING_BUFFER_SIZE * 6 ] ;
2016-02-22 15:20:08 +00:00
List < Line3D > bboxes = new List < Line3D > ( locksize ) ; //mxd
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2013-11-27 12:45:28 +00:00
Dictionary < int , List < Thing > > thingsByType = new Dictionary < int , List < Thing > > ( ) ;
Dictionary < int , List < Thing > > modelsByType = new Dictionary < int , List < Thing > > ( ) ;
2016-04-01 10:49:19 +00:00
Dictionary < Thing , Vector3D > thingsByPosition = new Dictionary < Thing , Vector3D > ( ) ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// Go for all things
2010-08-16 13:31:53 +00:00
int buffercount = 0 ;
int totalcount = 0 ;
2009-04-19 18:07:22 +00:00
foreach ( Thing t in things )
{
2015-08-03 22:02:39 +00:00
//mxd. Highlighted thing should be rendered separately
if ( ! fixedcolor & & t . Highlighted ) continue ;
2016-07-04 18:25:47 +00:00
// Collect models
2016-07-11 22:13:43 +00:00
if ( t . RenderMode = = ThingRenderMode . MODEL | | t . RenderMode = = ThingRenderMode . VOXEL )
2014-12-03 23:15:26 +00:00
{
2013-11-27 12:45:28 +00:00
if ( ! modelsByType . ContainsKey ( t . Type ) ) modelsByType . Add ( t . Type , new List < Thing > ( ) ) ;
modelsByType [ t . Type ] . Add ( t ) ;
}
2013-09-11 09:47:53 +00:00
// Create vertices
2015-12-28 15:01:53 +00:00
PixelColor tc = fixedcolor ? c : DetermineThingColor ( t ) ;
2016-02-23 13:55:53 +00:00
byte bboxalpha = ( byte ) ( alpha * ( ( ! fixedcolor & & ! t . Selected & & isthingsmode ) ? 128 : 255 ) ) ;
2016-02-22 15:20:08 +00:00
if ( CreateThingBoxVerts ( t , ref verts , ref bboxes , thingsByPosition , buffercount * 6 , tc , bboxalpha ) )
2014-12-03 23:15:26 +00:00
{
2010-08-16 13:31:53 +00:00
buffercount + + ;
2013-11-27 12:45:28 +00:00
//mxd
if ( ! thingsByType . ContainsKey ( t . Type ) ) thingsByType . Add ( t . Type , new List < Thing > ( ) ) ;
thingsByType [ t . Type ] . Add ( t ) ;
}
2010-08-16 13:31:53 +00:00
totalcount + + ;
// Buffer filled?
if ( buffercount = = locksize )
2009-04-19 18:07:22 +00:00
{
2010-08-16 17:53:28 +00:00
// Write to buffer
2019-08-16 11:23:25 +00:00
graphics . SetBufferSubdata ( thingsvertices , verts , buffercount * 6 ) ;
2010-08-16 13:31:53 +00:00
// Draw!
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2010-08-16 13:31:53 +00:00
buffercount = 0 ;
2010-08-16 17:53:28 +00:00
// Determine next lock size
locksize = ( ( things . Count - totalcount ) > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : ( things . Count - totalcount ) ;
2009-04-19 18:07:22 +00:00
}
}
2010-08-16 17:53:28 +00:00
// Write to buffer
2019-08-16 11:23:25 +00:00
if ( buffercount > 0 ) graphics . SetBufferSubdata ( thingsvertices , verts , buffercount * 6 ) ;
2010-08-16 13:31:53 +00:00
// Draw what's still remaining
if ( buffercount > 0 )
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2013-11-27 12:45:28 +00:00
//mxd. Render sprites
int selectionColor = General . Colors . Selection . ToInt ( ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . things2d_sprite ) ;
2013-11-27 12:45:28 +00:00
2014-12-03 09:06:05 +00:00
foreach ( KeyValuePair < int , List < Thing > > group in thingsByType )
{
2016-04-01 22:23:05 +00:00
// Skip when all things of this type will be rendered as models
2016-07-11 22:13:43 +00:00
if ( ( group . Value [ 0 ] . RenderMode = = ThingRenderMode . MODEL | | group . Value [ 0 ] . RenderMode = = ThingRenderMode . VOXEL )
& & ( General . Settings . GZDrawModelsMode = = ModelRenderMode . ALL ) ) continue ;
2016-04-01 22:23:05 +00:00
2013-11-27 12:45:28 +00:00
// Find thing information
ThingTypeInfo info = General . Map . Data . GetThingInfo ( group . Key ) ;
// Find sprite texture
if ( info . Sprite . Length = = 0 ) continue ;
2016-04-08 14:02:08 +00:00
// Sort by sprite angle...
Dictionary < int , List < Thing > > thingsbyangle = new Dictionary < int , List < Thing > > ( group . Value . Count ) ;
if ( info . SpriteFrame . Length = = 8 )
2016-04-01 22:23:05 +00:00
{
2016-04-08 14:02:08 +00:00
foreach ( Thing t in group . Value )
2016-04-04 12:09:38 +00:00
{
2016-04-08 14:02:08 +00:00
// Choose which sprite angle to show
int spriteangle = General . ClampAngle ( - t . AngleDoom + 270 ) / 45 ; // Convert to [0..7] range
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Add to collection
if ( ! thingsbyangle . ContainsKey ( spriteangle ) ) thingsbyangle . Add ( spriteangle , new List < Thing > ( ) ) ;
thingsbyangle [ spriteangle ] . Add ( t ) ;
2016-04-04 12:09:38 +00:00
}
2016-04-08 14:02:08 +00:00
}
else
{
thingsbyangle [ 0 ] = group . Value ;
}
2016-04-04 12:09:38 +00:00
2016-04-08 14:02:08 +00:00
foreach ( KeyValuePair < int , List < Thing > > framegroup in thingsbyangle )
{
SpriteFrameInfo sfi = info . SpriteFrame [ framegroup . Key ] ;
ImageData sprite = General . Map . Data . GetSpriteImage ( sfi . Sprite ) ;
if ( sprite = = null ) continue ;
2013-11-27 12:45:28 +00:00
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( sprite . Texture ) ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Determine next lock size
locksize = ( framegroup . Value . Count > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : framegroup . Value . Count ;
verts = new FlatVertex [ THING_BUFFER_SIZE * 6 ] ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Go for all things
buffercount = 0 ;
totalcount = 0 ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
foreach ( Thing t in framegroup . Value )
{
2016-07-11 22:13:43 +00:00
if ( ( t . RenderMode = = ThingRenderMode . MODEL | | t . RenderMode = = ThingRenderMode . VOXEL )
& & ( ( General . Settings . GZDrawModelsMode = = ModelRenderMode . SELECTION & & t . Selected ) | | ( General . Settings . GZDrawModelsMode = = ModelRenderMode . ACTIVE_THINGS_FILTER & & alpha = = 1.0f ) ) )
2016-04-08 14:02:08 +00:00
continue ;
bool forcespriterendering ;
float spritewidth , spriteheight , spritescale ;
// Determine sizes
if ( t . FixedSize & & scale > 1.0f )
{
spritescale = 1.0f ;
forcespriterendering = true ; // Always render sprite when thing size is affected by FixedSize setting
}
else if ( General . Settings . FixedThingsScale & & t . Size * scale > FIXED_THING_SIZE )
{
spritescale = FIXED_THING_SIZE / t . Size ;
forcespriterendering = true ; // Always render sprite when thing size is affected by FixedThingsScale setting
}
else
{
spritescale = scale ;
forcespriterendering = false ;
}
// Calculate scaled sprite size
if ( sprite . Width > sprite . Height )
{
spritewidth = ( t . Size - THING_SPRITE_SHRINK ) * spritescale ;
spriteheight = spritewidth * ( ( float ) sprite . Height / sprite . Width ) ;
}
else if ( sprite . Width < sprite . Height )
{
spriteheight = ( t . Size - THING_SPRITE_SHRINK ) * spritescale ;
spritewidth = spriteheight * ( ( float ) sprite . Width / sprite . Height ) ;
}
else
{
spritewidth = ( t . Size - THING_SPRITE_SHRINK ) * spritescale ;
spriteheight = spritewidth ;
}
float spritesize = Math . Max ( spritewidth , spriteheight ) ;
if ( ! forcespriterendering & & spritesize < MINIMUM_SPRITE_RADIUS )
{
// Hackish way to tell arrow rendering code to draw bigger arrow...
Vector3D v = thingsByPosition [ t ] ;
v . z = - 1 ;
thingsByPosition [ t ] = v ;
// Don't render tiny little sprites
continue ;
}
CreateThingSpriteVerts ( thingsByPosition [ t ] , spritewidth , spriteheight , ref verts , buffercount * 6 , ( t . Selected ? selectionColor : 0xFFFFFF ) , sfi . Mirror ) ;
buffercount + + ;
totalcount + + ;
// Buffer filled?
if ( buffercount = = locksize )
{
// Write to buffer
2019-08-16 11:23:25 +00:00
graphics . SetBufferSubdata ( thingsvertices , verts , buffercount * 6 ) ;
2016-04-08 14:02:08 +00:00
// Draw!
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2016-04-08 14:02:08 +00:00
buffercount = 0 ;
// Determine next lock size
locksize = ( ( framegroup . Value . Count - totalcount ) > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : ( framegroup . Value . Count - totalcount ) ;
}
2013-11-27 12:45:28 +00:00
}
2016-04-08 14:02:08 +00:00
// Write to buffer
2019-08-16 11:23:25 +00:00
graphics . SetBufferSubdata ( thingsvertices , verts , buffercount * 6 ) ;
2013-11-27 12:45:28 +00:00
2016-04-08 14:02:08 +00:00
// Draw what's still remaining
2019-08-16 05:12:26 +00:00
if ( buffercount > 0 ) graphics . Draw ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2016-04-08 14:02:08 +00:00
}
2013-11-27 12:45:28 +00:00
}
2012-04-17 19:13:47 +00:00
2013-11-27 12:45:28 +00:00
//mxd. Render thing arrows
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Data . ThingTexture . Texture ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . things2d_thing ) ;
2013-11-27 12:45:28 +00:00
2013-12-03 10:50:33 +00:00
// Determine next lock size
locksize = ( thingsByPosition . Count > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : thingsByPosition . Count ;
verts = new FlatVertex [ THING_BUFFER_SIZE * 6 ] ;
2013-11-27 12:45:28 +00:00
// Go for all things
buffercount = 0 ;
totalcount = 0 ;
2016-04-01 10:49:19 +00:00
foreach ( KeyValuePair < Thing , Vector3D > group in thingsByPosition )
2014-12-03 09:06:05 +00:00
{
2013-11-27 12:45:28 +00:00
if ( ! group . Key . IsDirectional ) continue ;
CreateThingArrowVerts ( group . Key , ref verts , group . Value , buffercount * 6 ) ;
buffercount + + ;
totalcount + + ;
// Buffer filled?
2014-12-03 09:06:05 +00:00
if ( buffercount = = locksize )
{
2013-11-27 12:45:28 +00:00
// Write to buffer
2019-08-16 11:23:25 +00:00
graphics . SetBufferSubdata ( thingsvertices , verts , buffercount * 6 ) ;
2013-11-27 12:45:28 +00:00
// Draw!
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2013-11-27 12:45:28 +00:00
buffercount = 0 ;
// Determine next lock size
2013-12-03 10:50:33 +00:00
locksize = ( ( thingsByPosition . Count - totalcount ) > THING_BUFFER_SIZE ) ? THING_BUFFER_SIZE : ( thingsByPosition . Count - totalcount ) ;
2013-11-27 12:45:28 +00:00
}
}
// Write to buffer
2019-08-16 11:23:25 +00:00
if ( buffercount > 0 ) graphics . SetBufferSubdata ( thingsvertices , verts , buffercount * 6 ) ;
2013-11-27 12:45:28 +00:00
// Draw what's still remaining
if ( buffercount > 0 )
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , buffercount * 2 ) ;
2013-11-27 12:45:28 +00:00
2013-09-11 09:47:53 +00:00
//mxd. Render models
2015-12-28 15:01:53 +00:00
if ( General . Settings . GZDrawModelsMode ! = ModelRenderMode . NONE )
2014-10-20 12:16:51 +00:00
{
2013-09-11 09:47:53 +00:00
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetAlphaBlendEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-09 22:46:51 +00:00
graphics . SetFillMode ( FillMode . Wireframe ) ;
2012-04-17 19:13:47 +00:00
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . things2d_fill ) ;
2012-07-28 20:36:28 +00:00
2015-07-05 23:20:18 +00:00
Color4 cSelection = General . Colors . Selection . ToColorValue ( ) ;
Color4 cWire = ( ( c . ToInt ( ) = = General . Colors . Highlight . ToInt ( ) ) ? General . Colors . Highlight . ToColorValue ( ) : General . Colors . ModelWireframe . ToColorValue ( ) ) ;
cSelection . Alpha = ( ( alpha < 1.0f ) ? alpha * 0.25f : 0.6f ) ;
cWire . Alpha = cSelection . Alpha ;
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
Matrix viewscale = Matrix . Scaling ( scale , - scale , 0.0f ) ;
2013-07-29 08:50:50 +00:00
2015-12-28 15:01:53 +00:00
foreach ( KeyValuePair < int , List < Thing > > group in modelsByType )
2014-10-20 12:16:51 +00:00
{
2016-04-01 10:49:19 +00:00
ModelData mde = General . Map . Data . ModeldefEntries [ group . Key ] ;
2014-10-20 12:16:51 +00:00
foreach ( Thing t in group . Value )
{
2015-06-27 09:10:24 +00:00
if ( ( General . Settings . GZDrawModelsMode = = ModelRenderMode . SELECTION & & ! t . Selected ) | | ( General . Settings . GZDrawModelsMode = = ModelRenderMode . ACTIVE_THINGS_FILTER & & alpha < 1.0f ) ) continue ;
2014-12-22 21:36:49 +00:00
Vector2D screenpos = ( ( Vector2D ) t . Position ) . GetTransformed ( translatex , translatey , scale , - scale ) ;
Model rendering (all modes): UDMF scale, pitch and roll are now displayed.
Thing Edit Form, UDMF: added controls for setting pitch, roll, scale, render style, fill color, alpha, health and score.
Visual mode, UDMF: UDMF scale is now applied when rendering sprites.
Added Thing Statistics form (Edit -> View Thing Types...), which shows all loaded thing types with some additional info.
Visual mode: sprites with negative ScaleX and positive ScaleY were not rendered properly.
Classic modes: display was not updated after loading a sprite.
Current testing engine change was not saved on closing the program when no other game configuration settings were changed.
2014-04-30 10:01:22 +00:00
float modelScale = scale * t . ActorScale . Width * t . ScaleX ;
2013-11-27 12:45:28 +00:00
//should we render this model?
2015-06-22 19:52:23 +00:00
if ( ( ( screenpos . x + mde . Model . Radius * modelScale ) < = 0.0f ) | | ( ( screenpos . x - mde . Model . Radius * modelScale ) > = windowsize . Width ) | |
( ( screenpos . y + mde . Model . Radius * modelScale ) < = 0.0f ) | | ( ( screenpos . y - mde . Model . Radius * modelScale ) > = windowsize . Height ) )
2013-11-27 12:45:28 +00:00
continue ;
2014-05-03 14:44:59 +00:00
2019-08-14 10:36:33 +00:00
graphics . SetUniform ( UniformName . FillColor , ( t . Selected ? cSelection : cWire ) ) ;
2013-07-30 09:25:27 +00:00
2015-12-28 15:01:53 +00:00
// Set transform settings
float sx = t . ScaleX * t . ActorScale . Width ;
float sy = t . ScaleY * t . ActorScale . Height ;
Matrix modelscale = Matrix . Scaling ( sx , sx , sy ) ;
2016-07-17 00:00:29 +00:00
Matrix rotation = Matrix . RotationY ( - t . RollRad ) * Matrix . RotationX ( - t . PitchRad ) * Matrix . RotationZ ( t . Angle ) ;
2015-12-28 15:01:53 +00:00
Matrix position = Matrix . Translation ( screenpos . x , screenpos . y , 0.0f ) ;
Matrix world = General . Map . Data . ModeldefEntries [ t . Type ] . Transform * modelscale * rotation * viewscale * position ;
2019-08-16 11:07:57 +00:00
SetThings2DTransformSettings ( world ) ;
2015-12-28 15:01:53 +00:00
2019-08-16 09:24:22 +00:00
// Draw
2019-08-13 02:12:04 +00:00
foreach ( Mesh mesh in mde . Model . Meshes ) mesh . Draw ( graphics ) ;
2013-07-29 08:50:50 +00:00
}
}
2012-07-28 20:36:28 +00:00
2013-11-27 12:45:28 +00:00
//Done with this pass
2019-08-09 22:46:51 +00:00
graphics . SetFillMode ( FillMode . Solid ) ;
2013-09-11 09:47:53 +00:00
}
2012-04-17 19:13:47 +00:00
2016-02-22 15:20:08 +00:00
//mxd. Render thing boxes
RenderArrows ( bboxes , false ) ;
2009-04-19 18:07:22 +00:00
}
}
2010-08-16 13:31:53 +00:00
// This adds a thing in the things buffer for rendering
public void RenderThing ( Thing t , PixelColor c , float alpha )
{
List < Thing > things = new List < Thing > ( 1 ) ;
things . Add ( t ) ;
RenderThingsBatch ( things , alpha , true , c ) ;
}
// This adds a thing in the things buffer for rendering
public void RenderThingSet ( ICollection < Thing > things , float alpha )
{
RenderThingsBatch ( things , alpha , false , new PixelColor ( ) ) ;
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Surface
// This redraws the surface
public void RedrawSurface ( )
{
2013-07-29 08:50:50 +00:00
if ( renderlayer ! = RenderLayers . None ) return ; //mxd
2009-04-19 18:07:22 +00:00
renderlayer = RenderLayers . Surface ;
2019-08-20 10:45:23 +00:00
// Recreate render targets if the window was resized
if ( windowsize . Width ! = graphics . RenderTarget . ClientSize . Width | | windowsize . Height ! = graphics . RenderTarget . ClientSize . Height )
CreateRendertargets ( ) ;
2009-04-19 18:07:22 +00:00
// Rendertargets available?
if ( surfacetex ! = null )
{
// Set the rendertarget to the surface texture
2019-08-08 01:19:11 +00:00
graphics . StartRendering ( true , General . Colors . Background . WithAlpha ( 0 ) . ToColorValue ( ) , surfacetex , false ) ;
// Set transformations
UpdateTransformations ( ) ;
// Set states
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( true ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2009-06-04 20:21:31 +00:00
2019-08-08 01:19:11 +00:00
// Prepare for rendering
switch ( viewmode )
{
case ViewMode . Brightness :
surfaces . RenderSectorBrightness ( yviewport ) ;
surfaces . RenderSectorSurfaces ( graphics ) ;
break ;
2009-06-04 20:21:31 +00:00
2019-08-08 01:19:11 +00:00
case ViewMode . FloorTextures :
surfaces . RenderSectorFloors ( yviewport ) ;
surfaces . RenderSectorSurfaces ( graphics ) ;
break ;
2009-06-04 20:21:31 +00:00
2019-08-08 01:19:11 +00:00
case ViewMode . CeilingTextures :
surfaces . RenderSectorCeilings ( yviewport ) ;
surfaces . RenderSectorSurfaces ( graphics ) ;
break ;
2009-04-19 18:07:22 +00:00
}
}
// Done
Finish ( ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Overlay
// This renders geometry
// The geometry must be a triangle list
public void RenderGeometry ( FlatVertex [ ] vertices , ImageData texture , bool transformcoords )
{
if ( vertices . Length > 0 )
{
2014-02-21 14:42:12 +00:00
Texture t ;
2009-04-19 18:07:22 +00:00
if ( texture ! = null )
{
t = texture . Texture ;
}
else
{
2009-06-04 20:21:31 +00:00
t = General . Map . Data . WhiteTexture . Texture ;
2009-04-19 18:07:22 +00:00
}
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( t ) ;
2009-04-19 18:07:22 +00:00
SetWorldTransformation ( transformcoords ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2009-04-19 18:07:22 +00:00
// Draw
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , vertices . Length / 3 , vertices ) ;
2009-04-19 18:07:22 +00:00
}
}
2013-12-10 12:19:27 +00:00
//mxd
2014-12-03 23:15:26 +00:00
public void RenderHighlight ( FlatVertex [ ] vertices , int color )
{
2013-12-10 12:19:27 +00:00
if ( vertices . Length < 3 ) return ;
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2013-12-10 12:19:27 +00:00
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( true ) ;
2019-08-14 10:36:33 +00:00
graphics . SetUniform ( UniformName . FillColor , new Color4 ( color ) ) ;
2019-08-16 11:07:57 +00:00
SetThings2DSettings ( 1.0f ) ;
2013-12-10 12:19:27 +00:00
2019-08-13 02:12:04 +00:00
// Draw
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . things2d_fill ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleList , 0 , vertices . Length / 3 , vertices ) ;
2013-12-10 12:19:27 +00:00
}
2016-05-19 21:44:39 +00:00
//mxd. This renders text (DB2 compatibility)
[Obsolete("Method is deprecated, please use RenderText(ITextLabel label) method instead.")]
public void RenderText ( TextLabel label ) { RenderText ( ( ITextLabel ) label ) ; }
2009-04-19 18:07:22 +00:00
// This renders text
2016-04-25 14:48:39 +00:00
public void RenderText ( ITextLabel label )
2009-04-19 18:07:22 +00:00
{
2016-03-30 23:25:03 +00:00
//mxd. Update the text if needed
2019-08-15 00:52:21 +00:00
label . Update ( graphics , translatex , translatey , scale , - scale ) ;
Sectors, Linedefs, Things modes: optimized text label rendering.
Fixed, Things mode: in some cases selection labels were not updated after editing a thing.
Fixed, Things mode: selection labels were positioned incorrectly on things with FixedSize setting.
Fixed, Sectors mode: fixed a crash when selecting self-referencing sector when selection labels were enabled.
Fixed, Visual mode: in some cases Auto-align texture actions were not working when "use long texture names" Map Options setting was enabled.
Fixed, MD2/MD3 loader: available animation frames upper bound check was performed incorrectly, which would cause a crash in some very special cases.
Fixed, Game configurations: most Hexen/ZDoom teleport actions use TeleportDests as teleport targets, not MapSpots.
2016-04-05 22:24:36 +00:00
if ( label . SkipRendering ) return ;
2009-04-19 18:07:22 +00:00
2016-03-30 23:25:03 +00:00
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( true ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( label . Texture ) ;
2016-03-30 23:25:03 +00:00
SetWorldTransformation ( false ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , false ) ;
graphics . SetVertexBuffer ( label . VertexBuffer ) ;
2016-03-30 23:25:03 +00:00
// Draw
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2016-03-30 23:25:03 +00:00
}
//mxd. This renders text
2016-04-25 14:48:39 +00:00
public void RenderText ( IList < ITextLabel > labels )
2016-03-30 23:25:03 +00:00
{
// Update labels
int skipped = 0 ;
2016-04-25 14:48:39 +00:00
foreach ( ITextLabel label in labels )
2009-04-19 18:07:22 +00:00
{
2016-03-30 23:25:03 +00:00
// Update the text if needed
2019-08-15 00:52:21 +00:00
label . Update ( graphics , translatex , translatey , scale , - scale ) ;
Sectors, Linedefs, Things modes: optimized text label rendering.
Fixed, Things mode: in some cases selection labels were not updated after editing a thing.
Fixed, Things mode: selection labels were positioned incorrectly on things with FixedSize setting.
Fixed, Sectors mode: fixed a crash when selecting self-referencing sector when selection labels were enabled.
Fixed, Visual mode: in some cases Auto-align texture actions were not working when "use long texture names" Map Options setting was enabled.
Fixed, MD2/MD3 loader: available animation frames upper bound check was performed incorrectly, which would cause a crash in some very special cases.
Fixed, Game configurations: most Hexen/ZDoom teleport actions use TeleportDests as teleport targets, not MapSpots.
2016-04-05 22:24:36 +00:00
if ( label . SkipRendering ) skipped + + ;
2016-03-30 23:25:03 +00:00
}
if ( labels . Count = = skipped ) return ;
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( true ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , false ) ;
2016-03-30 23:25:03 +00:00
2016-04-25 14:48:39 +00:00
foreach ( ITextLabel label in labels )
2016-03-30 23:25:03 +00:00
{
// Text is created?
if ( ! label . SkipRendering )
{
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( label . Texture ) ;
2019-08-16 11:07:57 +00:00
graphics . SetVertexBuffer ( label . VertexBuffer ) ;
2016-03-30 23:25:03 +00:00
// Draw
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 ) ;
2016-03-30 23:25:03 +00:00
}
2009-04-19 18:07:22 +00:00
}
}
// This renders a rectangle with given border size and color
public void RenderRectangle ( RectangleF rect , float bordersize , PixelColor c , bool transformrect )
{
FlatQuad [ ] quads = new FlatQuad [ 4 ] ;
/ *
* Rectangle setup :
*
* - - - - - - - - - - - - - - - - - - - - - - - - - -
* | ___________0____________ |
* | | | |
* | | | |
* | | | |
* | 2 | | 3 |
* | | | |
* | | | |
* | __ | __________________ | __ |
* | 1 |
* - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Don ' t you just love ASCII art ?
* /
// Calculate positions
Vector2D lt = new Vector2D ( rect . Left , rect . Top ) ;
Vector2D rb = new Vector2D ( rect . Right , rect . Bottom ) ;
if ( transformrect )
{
lt = lt . GetTransformed ( translatex , translatey , scale , - scale ) ;
rb = rb . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Make quads
quads [ 0 ] = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y , rb . x , lt . y - bordersize ) ;
quads [ 1 ] = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , rb . y + bordersize , rb . x , rb . y ) ;
quads [ 2 ] = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y - bordersize , lt . x + bordersize , rb . y + bordersize ) ;
quads [ 3 ] = new FlatQuad ( PrimitiveType . TriangleStrip , rb . x - bordersize , lt . y - bordersize , rb . x , rb . y + bordersize ) ;
quads [ 0 ] . SetColors ( c . ToInt ( ) ) ;
quads [ 1 ] . SetColors ( c . ToInt ( ) ) ;
quads [ 2 ] . SetColors ( c . ToInt ( ) ) ;
quads [ 3 ] . SetColors ( c . ToInt ( ) ) ;
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Data . WhiteTexture . Texture ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2009-04-19 18:07:22 +00:00
// Draw
quads [ 0 ] . Render ( graphics ) ;
quads [ 1 ] . Render ( graphics ) ;
quads [ 2 ] . Render ( graphics ) ;
quads [ 3 ] . Render ( graphics ) ;
}
// This renders a filled rectangle with given color
public void RenderRectangleFilled ( RectangleF rect , PixelColor c , bool transformrect )
{
// Calculate positions
Vector2D lt = new Vector2D ( rect . Left , rect . Top ) ;
Vector2D rb = new Vector2D ( rect . Right , rect . Bottom ) ;
if ( transformrect )
{
lt = lt . GetTransformed ( translatex , translatey , scale , - scale ) ;
rb = rb . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Make quad
FlatQuad quad = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y , rb . x , rb . y ) ;
quad . SetColors ( c . ToInt ( ) ) ;
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Data . WhiteTexture . Texture ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2009-04-19 18:07:22 +00:00
// Draw
quad . Render ( graphics ) ;
}
2009-08-02 18:48:38 +00:00
// This renders a filled rectangle with given color
public void RenderRectangleFilled ( RectangleF rect , PixelColor c , bool transformrect , ImageData texture )
{
// Calculate positions
Vector2D lt = new Vector2D ( rect . Left , rect . Top ) ;
Vector2D rb = new Vector2D ( rect . Right , rect . Bottom ) ;
if ( transformrect )
{
lt = lt . GetTransformed ( translatex , translatey , scale , - scale ) ;
rb = rb . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Make quad
FlatQuad quad = new FlatQuad ( PrimitiveType . TriangleStrip , lt . x , lt . y , rb . x , rb . y ) ;
quad . SetColors ( c . ToInt ( ) ) ;
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( texture . Texture ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2009-08-02 18:48:38 +00:00
// Draw
quad . Render ( graphics ) ;
}
2012-09-17 21:57:08 +00:00
//mxd
2016-02-22 15:20:08 +00:00
public void RenderArrows ( ICollection < Line3D > lines ) { RenderArrows ( lines , true ) ; }
public void RenderArrows ( ICollection < Line3D > lines , bool transformcoords )
2014-12-03 23:15:26 +00:00
{
2015-06-24 21:21:19 +00:00
if ( lines . Count = = 0 ) return ;
2015-08-08 21:56:43 +00:00
int pointscount = 0 ;
2015-12-14 12:34:31 +00:00
// Translate to screen coords, determine renderability
foreach ( Line3D line in lines )
{
2016-02-22 15:20:08 +00:00
// Calculate screen positions?
if ( transformcoords )
{
line . Start2D = ( ( Vector2D ) line . Start ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //start
line . End2D = ( ( Vector2D ) line . End ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //end
}
2015-12-14 12:34:31 +00:00
float maxx = Math . Max ( line . Start2D . x , line . End2D . x ) ;
float minx = Math . Min ( line . Start2D . x , line . End2D . x ) ;
float maxy = Math . Max ( line . Start2D . y , line . End2D . y ) ;
float miny = Math . Min ( line . Start2D . y , line . End2D . y ) ;
// Too small / not on screen?
if ( ( ( line . End2D - line . Start2D ) . GetLengthSq ( ) < MINIMUM_SPRITE_RADIUS ) | | ( ( maxx < = 0.0f ) | | ( minx > = windowsize . Width ) | | ( maxy < = 0.0f ) | | ( miny > = windowsize . Height ) ) )
{
line . SkipRendering = true ;
}
else
{
pointscount + = ( line . RenderArrowhead ? 6 : 2 ) ; // 4 extra points for the arrowhead
line . SkipRendering = false ;
}
}
// Anything to do?
2015-08-08 21:56:43 +00:00
if ( pointscount < 2 ) return ;
FlatVertex [ ] verts = new FlatVertex [ pointscount ] ;
2015-06-24 21:21:19 +00:00
float scaler = 16f / scale ;
2013-06-13 11:32:00 +00:00
2015-06-24 21:21:19 +00:00
// Create verts array
2015-08-08 21:56:43 +00:00
pointscount = 0 ;
foreach ( Line3D line in lines )
2015-06-24 21:21:19 +00:00
{
2015-12-14 12:34:31 +00:00
if ( line . SkipRendering ) continue ;
2015-12-28 15:01:53 +00:00
int color = line . Color . ToInt ( ) ;
2015-08-08 21:56:43 +00:00
// Add regular points
2015-12-14 12:34:31 +00:00
verts [ pointscount ] . x = line . Start2D . x ;
verts [ pointscount ] . y = line . Start2D . y ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] . c = color ;
pointscount + + ;
2015-12-14 12:34:31 +00:00
verts [ pointscount ] . x = line . End2D . x ;
verts [ pointscount ] . y = line . End2D . y ;
2015-08-08 21:56:43 +00:00
verts [ pointscount ] . c = color ;
pointscount + + ;
// Add arrowhead
2015-12-14 12:34:31 +00:00
if ( line . RenderArrowhead )
2015-08-08 21:56:43 +00:00
{
float angle = line . GetAngle ( ) ;
2015-12-14 12:34:31 +00:00
Vector2D a1 = new Vector2D ( line . End . x - scaler * ( float ) Math . Sin ( angle - 0.46f ) , line . End . y + scaler * ( float ) Math . Cos ( angle - 0.46f ) ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //arrowhead end 1
Vector2D a2 = new Vector2D ( line . End . x - scaler * ( float ) Math . Sin ( angle + 0.46f ) , line . End . y + scaler * ( float ) Math . Cos ( angle + 0.46f ) ) . GetTransformed ( translatex , translatey , scale , - scale ) ; //arrowhead end 2
2015-08-08 21:56:43 +00:00
verts [ pointscount ] = verts [ pointscount - 1 ] ;
verts [ pointscount + 1 ] . x = a1 . x ;
verts [ pointscount + 1 ] . y = a1 . y ;
verts [ pointscount + 1 ] . c = color ;
verts [ pointscount + 2 ] = verts [ pointscount - 1 ] ;
verts [ pointscount + 3 ] . x = a2 . x ;
verts [ pointscount + 3 ] . y = a2 . y ;
verts [ pointscount + 3 ] . c = color ;
pointscount + = 4 ;
}
2015-06-24 21:21:19 +00:00
}
2012-09-17 21:57:08 +00:00
2015-06-24 21:21:19 +00:00
// Write to buffer
2019-08-16 09:24:22 +00:00
VertexBuffer vb = new VertexBuffer ( ) ;
2019-08-15 00:52:21 +00:00
graphics . SetBufferData ( vb , verts ) ;
2015-06-24 21:21:19 +00:00
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Data . WhiteTexture . Texture ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2013-06-13 11:32:00 +00:00
2015-06-24 21:21:19 +00:00
// Draw
2019-08-16 11:07:57 +00:00
graphics . SetVertexBuffer ( vb ) ;
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . LineList , 0 , pointscount / 2 ) ;
2015-06-24 21:21:19 +00:00
vb . Dispose ( ) ;
2012-09-17 21:57:08 +00:00
}
2009-04-19 18:07:22 +00:00
// This renders a line with given color
public void RenderLine ( Vector2D start , Vector2D end , float thickness , PixelColor c , bool transformcoords )
{
FlatVertex [ ] verts = new FlatVertex [ 4 ] ;
// Calculate positions
if ( transformcoords )
{
start = start . GetTransformed ( translatex , translatey , scale , - scale ) ;
end = end . GetTransformed ( translatex , translatey , scale , - scale ) ;
}
// Calculate offsets
Vector2D delta = end - start ;
Vector2D dn = delta . GetNormal ( ) * thickness ;
// Make vertices
verts [ 0 ] . x = start . x - dn . x + dn . y ;
verts [ 0 ] . y = start . y - dn . y - dn . x ;
verts [ 0 ] . z = 0.0f ;
verts [ 0 ] . c = c . ToInt ( ) ;
verts [ 1 ] . x = start . x - dn . x - dn . y ;
verts [ 1 ] . y = start . y - dn . y + dn . x ;
verts [ 1 ] . z = 0.0f ;
verts [ 1 ] . c = c . ToInt ( ) ;
verts [ 2 ] . x = end . x + dn . x + dn . y ;
verts [ 2 ] . y = end . y + dn . y - dn . x ;
verts [ 2 ] . z = 0.0f ;
verts [ 2 ] . c = c . ToInt ( ) ;
verts [ 3 ] . x = end . x + dn . x - dn . y ;
verts [ 3 ] . y = end . y + dn . y + dn . x ;
verts [ 3 ] . z = 0.0f ;
verts [ 3 ] . c = c . ToInt ( ) ;
// Set renderstates for rendering
2019-08-09 22:46:51 +00:00
graphics . SetCullMode ( Cull . None ) ;
graphics . SetZEnable ( false ) ;
graphics . SetAlphaBlendEnable ( false ) ;
graphics . SetAlphaTestEnable ( false ) ;
2019-08-16 12:01:27 +00:00
graphics . SetUniform ( UniformName . texturefactor , new Color4 ( 1f , 1f , 1f , 1f ) ) ;
2019-08-22 16:43:54 +00:00
SetWorldTransformation ( false ) ;
2019-08-14 10:36:33 +00:00
graphics . SetShader ( ShaderName . display2d_normal ) ;
2019-08-17 01:21:11 +00:00
graphics . SetTexture ( General . Map . Data . WhiteTexture . Texture ) ;
2019-08-16 11:07:57 +00:00
SetDisplay2DSettings ( 1f , 1f , 0f , 1f , General . Settings . ClassicBilinear ) ;
2009-04-19 18:07:22 +00:00
// Draw
2019-08-16 05:12:26 +00:00
graphics . Draw ( PrimitiveType . TriangleStrip , 0 , 2 , verts ) ;
2009-04-19 18:07:22 +00:00
}
#endregion
#region = = = = = = = = = = = = = = = = = = Geometry
// This renders the linedefs of a sector with special color
public void PlotSector ( Sector s , PixelColor c )
{
// Go for all sides in the sector
foreach ( Sidedef sd in s . Sidedefs )
{
// Render this linedef
PlotLinedef ( sd . Line , c ) ;
// Render the two vertices on top
PlotVertex ( sd . Line . Start , DetermineVertexColor ( sd . Line . Start ) ) ;
PlotVertex ( sd . Line . End , DetermineVertexColor ( sd . Line . End ) ) ;
}
}
// This renders the linedefs of a sector
public void PlotSector ( Sector s )
{
// Go for all sides in the sector
foreach ( Sidedef sd in s . Sidedefs )
{
// Render this linedef
PlotLinedef ( sd . Line , DetermineLinedefColor ( sd . Line ) ) ;
// Render the two vertices on top
PlotVertex ( sd . Line . Start , DetermineVertexColor ( sd . Line . Start ) ) ;
PlotVertex ( sd . Line . End , DetermineVertexColor ( sd . Line . End ) ) ;
}
2019-12-14 23:58:11 +00:00
}
2009-04-19 18:07:22 +00:00
// This renders a simple line
2016-06-16 22:05:17 +00:00
public void PlotLine ( Vector2D start , Vector2D end , PixelColor c ) { PlotLine ( start , end , c , 0.0625f ) ; }
public void PlotLine ( Vector2D start , Vector2D end , PixelColor c , float lengthscaler )
2009-04-19 18:07:22 +00:00
{
// Transform coordinates
Vector2D v1 = start . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D v2 = end . GetTransformed ( translatex , translatey , scale , - scale ) ;
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
2016-06-16 22:05:17 +00:00
if ( ( v2 - v1 ) . GetLengthSq ( ) < linenormalsize * lengthscaler ) return ;
2009-04-19 18:07:22 +00:00
// Draw line
2019-12-25 00:54:05 +00:00
plotter . DrawLineSolid ( ( int ) v1 . x , TransformY ( ( int ) v1 . y ) , ( int ) v2 . x , TransformY ( ( int ) v2 . y ) , ref c ) ;
2009-04-19 18:07:22 +00:00
}
2019-12-14 23:58:11 +00:00
private Vector2D TransformY ( Vector2D v )
{
return new Vector2D ( v . x , TransformY ( v . y ) ) ;
}
private float TransformY ( float y )
{
return windowsize . Height - y ;
}
private int TransformY ( int y )
{
return windowsize . Height - y ;
}
2009-04-19 18:07:22 +00:00
// This renders a single linedef
public void PlotLinedef ( Linedef l , PixelColor c )
{
// Transform vertex coordinates
Vector2D v1 = l . Start . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D v2 = l . End . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
float lengthsq = ( v2 - v1 ) . GetLengthSq ( ) ;
if ( lengthsq < minlinelength ) return ; //mxd
2009-04-19 18:07:22 +00:00
2013-05-20 10:43:34 +00:00
// Draw line. mxd: added 3d-floor indication
2014-12-03 23:15:26 +00:00
if ( l . ExtraFloorFlag & & General . Settings . GZMarkExtraFloors )
2019-12-29 18:04:33 +00:00
plotter . DrawLine3DFloor ( ( int ) v1 . x , TransformY ( ( int ) v1 . y ) , ( int ) v2 . x , TransformY ( ( int ) v2 . y ) , ref c , General . Colors . ThreeDFloor ) ;
2014-12-03 23:15:26 +00:00
else
2019-12-16 02:15:53 +00:00
plotter . DrawLineSolid ( ( int ) v1 . x , TransformY ( ( int ) v1 . y ) , ( int ) v2 . x , TransformY ( ( int ) v2 . y ) , ref c ) ;
2009-04-19 18:07:22 +00:00
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
if ( lengthsq < minlinenormallength ) return ; //mxd
2009-04-19 18:07:22 +00:00
// Calculate normal indicator
float mx = ( v2 . x - v1 . x ) * 0.5f ;
float my = ( v2 . y - v1 . y ) * 0.5f ;
// Draw normal indicator
2019-12-14 23:58:11 +00:00
plotter . DrawLineSolid ( ( int ) ( v1 . x + mx ) , TransformY ( ( int ) ( v1 . y + my ) ) ,
2009-04-19 18:07:22 +00:00
( int ) ( ( v1 . x + mx ) - ( my * l . LengthInv ) * linenormalsize ) ,
2019-12-16 02:15:53 +00:00
TransformY ( ( int ) ( ( v1 . y + my ) + ( mx * l . LengthInv ) * linenormalsize ) ) , ref c ) ;
2009-04-19 18:07:22 +00:00
}
// This renders a set of linedefs
public void PlotLinedefSet ( ICollection < Linedef > linedefs )
{
// Go for all linedefs
2015-08-31 22:06:44 +00:00
foreach ( Linedef l in linedefs )
{
// Transform vertex coordinates
Vector2D v1 = l . Start . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
Vector2D v2 = l . End . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
//mxd. Should we bother?
float lengthsq = ( v2 - v1 ) . GetLengthSq ( ) ;
if ( lengthsq < minlinelength ) continue ; //mxd
// Determine color
PixelColor c = DetermineLinedefColor ( l ) ;
// Draw line. mxd: added 3d-floor indication
if ( l . ExtraFloorFlag & & General . Settings . GZMarkExtraFloors )
2019-12-29 18:04:33 +00:00
plotter . DrawLine3DFloor ( ( int ) v1 . x , TransformY ( ( int ) v1 . y ) , ( int ) v2 . x , TransformY ( ( int ) v2 . y ) , ref c , General . Colors . ThreeDFloor ) ;
2015-08-31 22:06:44 +00:00
else
2019-12-16 02:15:53 +00:00
plotter . DrawLineSolid ( ( int ) v1 . x , TransformY ( ( int ) v1 . y ) , ( int ) v2 . x , TransformY ( ( int ) v2 . y ) , ref c ) ;
2015-08-31 22:06:44 +00:00
//mxd. Should we bother?
if ( lengthsq < minlinenormallength ) continue ; //mxd
// Calculate normal indicator
float mx = ( v2 . x - v1 . x ) * 0.5f ;
float my = ( v2 . y - v1 . y ) * 0.5f ;
// Draw normal indicator
2019-12-14 23:58:11 +00:00
plotter . DrawLineSolid ( ( int ) ( v1 . x + mx ) , TransformY ( ( int ) ( v1 . y + my ) ) ,
2015-08-31 22:06:44 +00:00
( int ) ( ( v1 . x + mx ) - ( my * l . LengthInv ) * linenormalsize ) ,
2019-12-16 02:15:53 +00:00
TransformY ( ( int ) ( ( v1 . y + my ) + ( mx * l . LengthInv ) * linenormalsize ) ) , ref c ) ;
2015-08-31 22:06:44 +00:00
}
2009-04-19 18:07:22 +00:00
}
// This renders a single vertex
public void PlotVertex ( Vertex v , int colorindex )
{
// Transform vertex coordinates
Vector2D nv = v . Position . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Draw pixel here
2019-12-16 02:15:53 +00:00
plotter . DrawVertexSolid ( ( int ) nv . x , TransformY ( ( int ) nv . y ) , vertexsize , ref General . Colors . Colors [ colorindex ] , ref General . Colors . BrightColors [ colorindex ] , ref General . Colors . DarkColors [ colorindex ] ) ;
2009-04-19 18:07:22 +00:00
}
// This renders a single vertex at specified coordinates
public void PlotVertexAt ( Vector2D v , int colorindex )
{
// Transform vertex coordinates
Vector2D nv = v . GetTransformed ( translatex , translatey , scale , - scale ) ;
// Draw pixel here
2019-12-16 02:15:53 +00:00
plotter . DrawVertexSolid ( ( int ) nv . x , TransformY ( ( int ) nv . y ) , vertexsize , ref General . Colors . Colors [ colorindex ] , ref General . Colors . BrightColors [ colorindex ] , ref General . Colors . DarkColors [ colorindex ] ) ;
2009-04-19 18:07:22 +00:00
}
// This renders a set of vertices
public void PlotVerticesSet ( ICollection < Vertex > vertices )
{
// Go for all vertices
foreach ( Vertex v in vertices ) PlotVertex ( v , DetermineVertexColor ( v ) ) ;
}
#endregion
}
}