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 ;
using SlimDX ;
using CodeImp.DoomBuilder.Geometry ;
using SlimDX.Direct3D9 ;
using CodeImp.DoomBuilder.Data ;
using CodeImp.DoomBuilder.VisualModes ;
using CodeImp.DoomBuilder.Map ;
2013-04-11 11:04:16 +00:00
using CodeImp.DoomBuilder.GZBuilder.Data ; //mxd
using CodeImp.DoomBuilder.GZBuilder.Geometry ; //mxd
using CodeImp.DoomBuilder.GZBuilder.Rendering ; //mxd
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
#endregion
namespace CodeImp.DoomBuilder.Rendering
{
internal sealed class Renderer3D : Renderer , IRenderer3D
{
#region = = = = = = = = = = = = = = = = = = Constants
private const int RENDER_PASSES = 4 ;
private const float PROJ_NEAR_PLANE = 1f ;
private const float CROSSHAIR_SCALE = 0.06f ;
private const float FOG_RANGE = 0.9f ;
#endregion
#region = = = = = = = = = = = = = = = = = = Variables
// Matrices
private Matrix projection ;
private Matrix view3d ;
private Matrix billboard ;
private Matrix worldviewproj ;
private Matrix view2d ;
private Matrix world ;
private Vector3D cameraposition ;
private int shaderpass ;
// Window size
private Size windowsize ;
// Frustum
private ProjectedFrustum2D frustum ;
// Thing cage
2013-09-11 09:47:53 +00:00
private bool renderthingcages ;
//mxd
private ThingBoundingBox bbox ;
2013-03-18 13:52:27 +00:00
private VisualVertexHandle vertexHandle ;
private SizelessVisualThingCage sizelessThingHandle ;
2013-09-11 09:47:53 +00:00
private List < VisualThing > thingsWithLight ;
private int [ ] lightOffsets ;
private Dictionary < Texture , List < VisualGeometry > > litGeometry ;
private Dictionary < ModelData , List < VisualThing > > thingsWithModel ;
2009-04-19 18:07:22 +00:00
// Crosshair
private FlatVertex [ ] crosshairverts ;
private bool crosshairbusy ;
// Highlighting
private IVisualPickable highlighted ;
private float highlightglow ;
2009-05-05 21:13:50 +00:00
private float highlightglowinv ;
2009-05-04 06:13:56 +00:00
private ColorImage highlightimage ;
private ColorImage selectionimage ;
2009-07-07 14:52:39 +00:00
private bool showselection ;
private bool showhighlight ;
2009-04-19 18:07:22 +00:00
// Geometry to be rendered.
// Each Dictionary in the array is a render pass.
// Each BinaryHeap in the Dictionary contains all geometry that needs
// to be rendered with the associated ImageData.
// The BinaryHeap sorts the geometry by sector to minimize stream switchs.
private Dictionary < ImageData , BinaryHeap < VisualGeometry > > [ ] geometry ;
// Things to be rendered.
// Each Dictionary in the array is a render pass.
// Each VisualThing is inserted in the Dictionary by their texture image.
private Dictionary < ImageData , List < VisualThing > > [ ] things ;
// Things to be rendered, sorted by distance from camera
private BinaryHeap < VisualThing > thingsbydistance ;
2013-03-18 13:52:27 +00:00
//mxd. Visual vertices
private VisualVertex [ ] visualvertices ;
2013-09-11 09:47:53 +00:00
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Properties
public ProjectedFrustum2D Frustum2D { get { return frustum ; } }
public bool DrawThingCages { get { return renderthingcages ; } set { renderthingcages = value ; } }
2014-03-03 09:52:55 +00:00
new public bool FullBrightness { get { return fullbrightness ; } set { fullbrightness = value ; } }
2009-07-07 14:52:39 +00:00
public bool ShowSelection { get { return showselection ; } set { showselection = value ; } }
public bool ShowHighlight { get { return showhighlight ; } set { showhighlight = value ; } }
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Constructor / Disposer
// Constructor
internal Renderer3D ( D3DDevice graphics ) : base ( graphics )
{
// Initialize
CreateProjection ( ) ;
CreateMatrices2D ( ) ;
2013-03-18 13:52:27 +00:00
SetupHelperObjects ( ) ;
2009-05-04 06:13:56 +00:00
SetupTextures ( ) ;
2009-04-19 18:07:22 +00:00
renderthingcages = true ;
2009-07-07 14:52:39 +00:00
showselection = true ;
showhighlight = true ;
2009-04-19 18:07:22 +00:00
// Dummy frustum
frustum = new ProjectedFrustum2D ( new Vector2D ( ) , 0.0f , 0.0f , PROJ_NEAR_PLANE ,
2014-02-21 14:42:12 +00:00
General . Settings . ViewDistance , Angle2D . DegToRad ( General . Settings . VisualFOV ) ) ;
2009-04-19 18:07:22 +00:00
// We have no destructor
GC . SuppressFinalize ( this ) ;
}
// Disposer
internal override void Dispose ( )
{
// Not already disposed?
if ( ! isdisposed )
{
// Clean up
2013-09-11 09:47:53 +00:00
//mxd
if ( bbox ! = null ) bbox . Dispose ( ) ;
2013-03-18 13:52:27 +00:00
if ( vertexHandle ! = null ) vertexHandle . Dispose ( ) ;
if ( sizelessThingHandle ! = null ) sizelessThingHandle . Dispose ( ) ;
2012-04-17 19:13:47 +00:00
2009-05-04 06:13:56 +00:00
if ( selectionimage ! = null ) selectionimage . Dispose ( ) ;
if ( highlightimage ! = null ) highlightimage . Dispose ( ) ;
2013-09-11 09:47:53 +00:00
//mxd
bbox = null ;
2013-03-18 13:52:27 +00:00
vertexHandle = null ;
sizelessThingHandle = null ;
2012-04-17 19:13:47 +00:00
2009-05-04 06:13:56 +00:00
selectionimage = null ;
highlightimage = null ;
2009-04-19 18:07:22 +00:00
// Done
base . Dispose ( ) ;
}
}
#endregion
#region = = = = = = = = = = = = = = = = = = Management
// This is called before a device is reset
// (when resized or display adapter was changed)
public override void UnloadResource ( )
{
crosshairverts = null ;
2013-09-11 09:47:53 +00:00
//mxd
if ( bbox ! = null ) bbox . Dispose ( ) ;
2013-03-18 13:52:27 +00:00
if ( vertexHandle ! = null ) vertexHandle . Dispose ( ) ;
if ( sizelessThingHandle ! = null ) sizelessThingHandle . Dispose ( ) ;
2012-04-17 19:13:47 +00:00
2009-05-04 06:13:56 +00:00
if ( selectionimage ! = null ) selectionimage . Dispose ( ) ;
if ( highlightimage ! = null ) highlightimage . Dispose ( ) ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2013-03-18 13:52:27 +00:00
vertexHandle = null ;
2013-09-11 09:47:53 +00:00
bbox = null ;
2013-03-18 13:52:27 +00:00
sizelessThingHandle = null ;
2012-04-17 19:13:47 +00:00
2009-05-04 06:13:56 +00:00
selectionimage = null ;
highlightimage = null ;
2009-04-19 18:07:22 +00:00
}
// This is called resets when the device is reset
// (when resized or display adapter was changed)
public override void ReloadResource ( )
{
CreateMatrices2D ( ) ;
2013-03-18 13:52:27 +00:00
SetupHelperObjects ( ) ;
2009-05-04 06:13:56 +00:00
SetupTextures ( ) ;
2009-04-19 18:07:22 +00:00
}
// This makes screen vertices for display
private void CreateCrosshairVerts ( Size texturesize )
{
// Determine coordinates
2014-02-21 14:42:12 +00:00
float width = windowsize . Width ;
float height = windowsize . Height ;
float size = height * CROSSHAIR_SCALE ;
2009-04-19 18:07:22 +00:00
RectangleF rect = new RectangleF ( ( width - size ) / 2 , ( height - size ) / 2 , size , size ) ;
// Make vertices
crosshairverts = new FlatVertex [ 4 ] ;
crosshairverts [ 0 ] . x = rect . Left ;
crosshairverts [ 0 ] . y = rect . Top ;
crosshairverts [ 0 ] . c = - 1 ;
crosshairverts [ 0 ] . u = 1f / texturesize . Width ;
crosshairverts [ 0 ] . v = 1f / texturesize . Height ;
crosshairverts [ 1 ] . x = rect . Right ;
crosshairverts [ 1 ] . y = rect . Top ;
crosshairverts [ 1 ] . c = - 1 ;
crosshairverts [ 1 ] . u = 1f - 1f / texturesize . Width ;
crosshairverts [ 1 ] . v = 1f / texturesize . Height ;
crosshairverts [ 2 ] . x = rect . Left ;
crosshairverts [ 2 ] . y = rect . Bottom ;
crosshairverts [ 2 ] . c = - 1 ;
crosshairverts [ 2 ] . u = 1f / texturesize . Width ;
crosshairverts [ 2 ] . v = 1f - 1f / texturesize . Height ;
crosshairverts [ 3 ] . x = rect . Right ;
crosshairverts [ 3 ] . y = rect . Bottom ;
crosshairverts [ 3 ] . c = - 1 ;
crosshairverts [ 3 ] . u = 1f - 1f / texturesize . Width ;
crosshairverts [ 3 ] . v = 1f - 1f / texturesize . Height ;
}
#endregion
2009-05-04 06:13:56 +00:00
#region = = = = = = = = = = = = = = = = = = Resources
2009-04-19 18:07:22 +00:00
2009-05-04 06:13:56 +00:00
// This loads the textures for highlight and selection if we need them
private void SetupTextures ( )
{
if ( ! graphics . Shaders . Enabled )
{
highlightimage = new ColorImage ( General . Colors . Highlight , 32 , 32 ) ;
highlightimage . LoadImage ( ) ;
highlightimage . CreateTexture ( ) ;
selectionimage = new ColorImage ( General . Colors . Selection , 32 , 32 ) ;
selectionimage . LoadImage ( ) ;
selectionimage . CreateTexture ( ) ;
}
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
private void SetupHelperObjects ( ) {
2013-03-18 13:52:27 +00:00
bbox = new ThingBoundingBox ( graphics . Device ) ;
vertexHandle = new VisualVertexHandle ( graphics . Device ) ;
sizelessThingHandle = new SizelessVisualThingCage ( graphics . Device ) ;
2013-09-11 09:47:53 +00:00
}
2009-04-19 18:07:22 +00:00
#endregion
#region = = = = = = = = = = = = = = = = = = Presentation
// This creates the projection
internal void CreateProjection ( )
{
// Calculate aspect
float aspect = ( float ) General . Map . Graphics . RenderTarget . ClientSize . Width /
2014-02-21 14:42:12 +00:00
General . Map . Graphics . RenderTarget . ClientSize . Height ;
2009-04-19 18:07:22 +00:00
// The DirectX PerspectiveFovRH matrix method calculates the scaling in X and Y as follows:
// yscale = 1 / tan(fovY / 2)
// xscale = yscale / aspect
// The fov specified in the method is the FOV over Y, but we want the user to specify the FOV
// over X, so calculate what it would be over Y first;
2014-02-21 14:42:12 +00:00
float fov = Angle2D . DegToRad ( General . Settings . VisualFOV ) ;
2009-04-19 18:07:22 +00:00
float reversefov = 1.0f / ( float ) Math . Tan ( fov / 2.0f ) ;
float reversefovy = reversefov * aspect ;
float fovy = ( float ) Math . Atan ( 1.0f / reversefovy ) * 2.0f ;
// Make the projection matrix
projection = Matrix . PerspectiveFovRH ( fovy , aspect , PROJ_NEAR_PLANE , General . Settings . ViewDistance ) ;
// Apply matrices
ApplyMatrices3D ( ) ;
}
// This creates matrices for a camera view
public void PositionAndLookAt ( Vector3D pos , Vector3D lookat )
{
// Calculate delta vector
cameraposition = pos ;
2014-02-21 14:42:12 +00:00
Vector3D delta = lookat - pos ;
float anglexy = delta . GetAngleXY ( ) ;
float anglez = delta . GetAngleZ ( ) ;
2009-04-19 18:07:22 +00:00
// Create frustum
frustum = new ProjectedFrustum2D ( pos , anglexy , anglez , PROJ_NEAR_PLANE ,
2013-08-08 11:04:13 +00:00
General . Settings . ViewDistance , Angle2D . DegToRad ( General . Settings . VisualFOV ) ) ;
2009-04-19 18:07:22 +00:00
// Make the view matrix
view3d = Matrix . LookAtRH ( D3DDevice . V3 ( pos ) , D3DDevice . V3 ( lookat ) , new Vector3 ( 0f , 0f , 1f ) ) ;
// Make the billboard matrix
billboard = Matrix . RotationZ ( anglexy + Angle2D . PI ) ;
}
// This creates 2D view matrix
private void CreateMatrices2D ( )
{
windowsize = graphics . RenderTarget . ClientSize ;
2014-02-21 14:42:12 +00:00
Matrix scaling = Matrix . Scaling ( ( 1f / windowsize . Width ) * 2f , ( 1f / windowsize . Height ) * - 2f , 1f ) ;
2009-04-19 18:07:22 +00:00
Matrix translate = Matrix . Translation ( - ( float ) windowsize . Width * 0.5f , - ( float ) windowsize . Height * 0.5f , 0f ) ;
view2d = Matrix . Multiply ( translate , scaling ) ;
}
// This applies the matrices
private void ApplyMatrices3D ( )
{
worldviewproj = world * view3d * projection ;
graphics . Shaders . World3D . WorldViewProj = worldviewproj ;
graphics . Device . SetTransform ( TransformState . World , world ) ;
graphics . Device . SetTransform ( TransformState . Projection , projection ) ;
graphics . Device . SetTransform ( TransformState . View , view3d ) ;
}
// This sets the appropriate view matrix
public void ApplyMatrices2D ( )
{
graphics . Device . SetTransform ( TransformState . World , world ) ;
graphics . Device . SetTransform ( TransformState . Projection , Matrix . Identity ) ;
graphics . Device . SetTransform ( TransformState . View , view2d ) ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Start / Finish
// This starts rendering
public bool Start ( )
{
// Start drawing
if ( graphics . StartRendering ( true , General . Colors . Background . ToColorValue ( ) , graphics . BackBuffer , graphics . DepthBuffer ) )
{
2013-09-11 09:47:53 +00:00
// Beginning renderstates
2009-04-19 18:07:22 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . FogEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . FogDensity , 1.0f ) ;
graphics . Device . SetRenderState ( RenderState . FogColor , General . Colors . Background . ToInt ( ) ) ;
graphics . Device . SetRenderState ( RenderState . FogStart , General . Settings . ViewDistance * FOG_RANGE ) ;
graphics . Device . SetRenderState ( RenderState . FogEnd , General . Settings . ViewDistance ) ;
graphics . Device . SetRenderState ( RenderState . FogTableMode , FogMode . Linear ) ;
graphics . Device . SetRenderState ( RenderState . RangeFogEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Shaders . World3D . SetModulateColor ( - 1 ) ;
graphics . Shaders . World3D . SetHighlightColor ( 0 ) ;
2009-04-26 20:20:40 +00:00
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
2009-04-19 18:07:22 +00:00
// Matrices
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
// Highlight
2009-05-04 06:13:56 +00:00
if ( General . Settings . AnimateVisualSelection )
{
2014-05-20 09:09:28 +00:00
float time = Clock . CurrentTime ;
2009-05-06 07:26:12 +00:00
highlightglow = ( float ) Math . Sin ( time / 100.0f ) * 0.1f + 0.4f ;
2013-09-11 09:47:53 +00:00
//mxd. WHY?!
2012-04-17 19:13:47 +00:00
//highlightglowinv = -(float)Math.Sin(time / 100.0f) * 0.1f + 0.4f;
2013-09-11 09:47:53 +00:00
highlightglowinv = - highlightglow + 0.8f ;
2009-05-04 06:13:56 +00:00
}
else
{
2009-05-06 07:26:12 +00:00
highlightglow = 0.4f ;
highlightglowinv = 0.3f ;
2009-05-04 06:13:56 +00:00
}
2009-04-19 18:07:22 +00:00
// Determine shader pass to use
if ( fullbrightness ) shaderpass = 1 ; else shaderpass = 0 ;
// Create crosshair vertices
if ( crosshairverts = = null )
CreateCrosshairVerts ( new Size ( General . Map . Data . Crosshair3D . Width , General . Map . Data . Crosshair3D . Height ) ) ;
// Ready
return true ;
}
else
{
// Can't render now
return false ;
}
}
// This begins rendering world geometry
public void StartGeometry ( )
{
// Make collection
geometry = new Dictionary < ImageData , BinaryHeap < VisualGeometry > > [ RENDER_PASSES ] ;
things = new Dictionary < ImageData , List < VisualThing > > [ RENDER_PASSES ] ;
thingsbydistance = new BinaryHeap < VisualThing > ( ) ;
2013-09-11 09:47:53 +00:00
//mxd
thingsWithModel = new Dictionary < ModelData , List < VisualThing > > ( ) ;
litGeometry = new Dictionary < Texture , List < VisualGeometry > > ( ) ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
for ( int i = 0 ; i < RENDER_PASSES ; i + + )
{
geometry [ i ] = new Dictionary < ImageData , BinaryHeap < VisualGeometry > > ( ) ;
things [ i ] = new Dictionary < ImageData , List < VisualThing > > ( ) ;
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd
if ( General . Settings . GZDrawLights ) {
thingsWithLight = new List < VisualThing > ( ) ;
}
2009-04-19 18:07:22 +00:00
}
// This ends rendering world geometry
public void FinishGeometry ( )
{
2012-08-10 12:08:08 +00:00
//mxd. sort lights
2013-09-11 09:47:53 +00:00
if ( General . Settings . GZDrawLights & & ! fullbrightness & & thingsWithLight . Count > 0 )
updateLights ( ) ;
// Initial renderstates
2009-04-19 18:07:22 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Shaders . World3D . Begin ( ) ;
// SOLID PASS
2012-08-10 12:08:08 +00:00
world = Matrix . Identity ;
2009-04-19 18:07:22 +00:00
ApplyMatrices3D ( ) ;
RenderSinglePass ( ( int ) RenderPass . Solid ) ;
2013-09-11 09:47:53 +00:00
//mxd. Render models, without culling. The way it's done in GZDoom... Fixes Rendering of things like grass and models with negative Scale
2013-03-18 13:52:27 +00:00
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , true ) ;
2013-09-11 09:47:53 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
RenderModels ( ) ;
2013-03-18 13:52:27 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// MASK PASS
2013-09-11 09:47:53 +00:00
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
RenderSinglePass ( ( int ) RenderPass . Mask ) ;
// ALPHA PASS
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
RenderSinglePass ( ( int ) RenderPass . Alpha ) ;
// THINGS
2012-04-17 19:13:47 +00:00
if ( renderthingcages ) RenderThingCages ( ) ;
2009-04-19 18:07:22 +00:00
2013-03-18 13:52:27 +00:00
//mxd. Visual vertices
RenderVertices ( ) ;
2013-09-11 09:47:53 +00:00
//mxd. LINKS
if ( General . Settings . GZShowEventLines ) {
//mxd. gather links
2013-12-23 08:00:19 +00:00
List < Line3D > lines = LinksCollector . GetThingLinks ( thingsbydistance ) ;
2012-09-26 00:04:17 +00:00
if ( lines . Count > 0 ) {
List < Line3D > normalLines = new List < Line3D > ( ) ;
List < Line3D > activatorLines = new List < Line3D > ( ) ;
foreach ( Line3D l in lines ) {
if ( l . LineType = = Line3DType . DEFAULT )
normalLines . Add ( l ) ;
else
activatorLines . Add ( l ) ;
}
if ( normalLines . Count > 0 )
renderArrows ( normalLines , General . Colors . InfoLine . ToColorValue ( ) ) ;
if ( activatorLines . Count > 0 )
renderArrows ( activatorLines , General . Colors . Selection3D . ToColorValue ( ) ) ;
}
2013-09-11 09:47:53 +00:00
}
2012-09-17 15:41:18 +00:00
2009-04-19 18:07:22 +00:00
// ADDITIVE PASS
2012-08-10 12:08:08 +00:00
world = Matrix . Identity ;
2009-04-19 18:07:22 +00:00
ApplyMatrices3D ( ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . One ) ;
RenderSinglePass ( ( int ) RenderPass . Additive ) ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd. LIGHT PASS
2013-12-23 08:00:19 +00:00
if ( ! ( ! General . Settings . GZDrawLights | | fullbrightness | | thingsWithLight . Count = = 0 | | litGeometry . Count = = 0 ) ) {
2013-09-11 09:47:53 +00:00
RenderLights ( litGeometry , thingsWithLight ) ;
}
2009-04-19 18:07:22 +00:00
// Remove references
graphics . Shaders . World3D . Texture1 = null ;
// Done
graphics . Shaders . World3D . End ( ) ;
geometry = null ;
2013-03-18 13:52:27 +00:00
visualvertices = null ; //mxd
2009-04-19 18:07:22 +00:00
}
2013-09-11 09:47:53 +00:00
//mxd
private void updateLights ( ) {
thingsWithLight . Sort ( sortThingsByCameraDistance ) ;
if ( thingsWithLight . Count > General . Settings . GZMaxDynamicLights ) {
List < VisualThing > tl = new List < VisualThing > ( ) ;
for ( int i = 0 ; i < General . Settings . GZMaxDynamicLights ; i + + )
tl . Add ( thingsWithLight [ i ] ) ;
thingsWithLight = tl ;
}
thingsWithLight . Sort ( sortThingsByLightRenderStyle ) ;
lightOffsets = new int [ 3 ] ;
foreach ( VisualThing t in thingsWithLight ) {
//add light to apropriate array.
2013-12-23 08:00:19 +00:00
switch ( t . LightRenderStyle ) {
case DynamicLightRenderStyle . NORMAL :
case DynamicLightRenderStyle . VAVOOM :
lightOffsets [ 0 ] + + ;
break ;
case DynamicLightRenderStyle . ADDITIVE :
lightOffsets [ 1 ] + + ;
break ;
default :
lightOffsets [ 2 ] + + ;
break ;
}
2013-09-11 09:47:53 +00:00
}
}
//mxd
2014-05-20 09:09:28 +00:00
private static int sortThingsByCameraDistance ( VisualThing t1 , VisualThing t2 )
{
2013-09-11 09:47:53 +00:00
if ( t1 . CameraDistance3D = = t2 . CameraDistance3D ) return 0 ;
if ( t1 . CameraDistance3D > t2 . CameraDistance3D ) return 1 ;
return - 1 ;
}
2014-05-20 09:09:28 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2014-05-20 09:09:28 +00:00
private static int sortThingsByLightRenderStyle ( VisualThing t1 , VisualThing t2 )
{
2013-09-11 09:47:53 +00:00
if ( t1 . LightRenderStyle = = t2 . LightRenderStyle ) return 0 ;
if ( t1 . LightRenderStyle > t2 . LightRenderStyle ) return 1 ;
return - 1 ;
}
//mxd.
//I never particularly liked old ThingCages, so I wrote this instead.
//It should render faster and it has fancy arrow! :)
private void RenderThingCages ( ) {
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . SourceAlpha ) ;
graphics . Shaders . World3D . BeginPass ( 16 ) ;
foreach ( VisualThing t in thingsbydistance ) {
// Setup matrix
world = Matrix . Multiply ( t . CageScales , t . Position ) ;
ApplyMatrices3D ( ) ;
// Setup color
2014-02-21 14:42:12 +00:00
Color4 thingColor ;
2013-09-11 09:47:53 +00:00
if ( t . Selected & & showselection ) {
thingColor = General . Colors . Selection3D . ToColorValue ( ) ;
} else {
thingColor = t . Thing . Color . ToColorValue ( ) ;
if ( t ! = highlighted ) thingColor . Alpha = 0.6f ;
}
graphics . Shaders . World3D . VertexColor = thingColor ;
//Render cage
graphics . Shaders . World3D . ApplySettings ( ) ;
2013-03-18 13:52:27 +00:00
if ( t . Sizeless ) {
graphics . Device . SetStreamSource ( 0 , sizelessThingHandle . Shape , 0 , WorldVertex . Stride ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , 3 ) ;
} else {
graphics . Device . SetStreamSource ( 0 , bbox . Cage , 0 , WorldVertex . Stride ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , 12 ) ;
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//and arrow
2013-12-02 09:26:09 +00:00
if ( t . Thing . IsDirectional ) {
float sx = t . CageScales . M11 ;
Matrix arrowScaler = Matrix . Scaling ( sx , sx , sx ) ; //scale arrow evenly based on thing width\depth
if ( t . Sizeless ) {
world = Matrix . Multiply ( arrowScaler , t . Position ) ;
} else {
world = Matrix . Multiply ( arrowScaler , t . Position * Matrix . Translation ( 0.0f , 0.0f , t . CageScales . M33 / 2 ) ) ;
}
Matrix rot = Matrix . RotationZ ( t . Thing . Angle - Angle2D . PI / 2 ) ;
world = Matrix . Multiply ( rot , world ) ;
ApplyMatrices3D ( ) ;
2012-04-17 19:13:47 +00:00
2013-12-02 09:26:09 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . SetStreamSource ( 0 , bbox . Arrow , 0 , WorldVertex . Stride ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , 5 ) ;
}
2013-09-11 09:47:53 +00:00
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Done
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . SetModulateColor ( - 1 ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
}
2012-09-17 15:41:18 +00:00
2013-03-18 13:52:27 +00:00
//mxd
private void RenderVertices ( ) {
if ( visualvertices = = null ) return ;
2013-03-20 10:25:32 +00:00
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . SourceAlpha ) ;
2013-03-18 13:52:27 +00:00
graphics . Shaders . World3D . BeginPass ( 16 ) ;
foreach ( VisualVertex v in visualvertices ) {
world = v . Position ;
ApplyMatrices3D ( ) ;
// Setup color
2014-02-21 14:42:12 +00:00
Color4 color ;
2013-03-18 13:52:27 +00:00
if ( v . Selected & & showselection ) {
color = General . Colors . Selection3D . ToColorValue ( ) ;
} else {
2013-05-02 11:03:16 +00:00
color = v . HaveHeightOffset ? General . Colors . InfoLine . ToColorValue ( ) : General . Colors . Vertices . ToColorValue ( ) ;
2013-03-18 13:52:27 +00:00
if ( v ! = highlighted ) color . Alpha = 0.6f ;
}
graphics . Shaders . World3D . VertexColor = color ;
//Commence drawing!!11
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . SetStreamSource ( 0 , v . CeilingVertex ? vertexHandle . Upper : vertexHandle . Lower , 0 , WorldVertex . Stride ) ;
2013-03-21 11:23:29 +00:00
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , 8 ) ;
2013-03-18 13:52:27 +00:00
}
// Done
graphics . Shaders . World3D . EndPass ( ) ;
2013-03-20 10:25:32 +00:00
graphics . Shaders . World3D . SetModulateColor ( - 1 ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
2013-03-18 13:52:27 +00:00
}
2013-09-11 09:47:53 +00:00
//mxd
private void renderArrows ( List < Line3D > lines , Color4 color ) {
//create vertices
WorldVertex [ ] verts = new WorldVertex [ lines . Count * 6 ] ;
2012-09-17 21:57:08 +00:00
float scaler = 20f ;
2013-09-11 09:47:53 +00:00
for ( int i = 0 ; i < lines . Count ; i + + ) {
WorldVertex endPoint = new WorldVertex ( lines [ i ] . v2 ) ;
2012-09-17 21:57:08 +00:00
float nz = lines [ i ] . GetDelta ( ) . GetNormal ( ) . z * scaler ;
2013-09-11 09:47:53 +00:00
float angle = lines [ i ] . GetAngle ( ) ;
verts [ i * 6 ] = new WorldVertex ( lines [ i ] . v1 ) ;
verts [ i * 6 + 1 ] = endPoint ;
verts [ i * 6 + 2 ] = endPoint ;
2012-09-17 21:57:08 +00:00
verts [ i * 6 + 3 ] = new WorldVertex ( new Vector3D ( lines [ i ] . v2 . x - scaler * ( float ) Math . Sin ( angle - 0.46f ) , lines [ i ] . v2 . y + scaler * ( float ) Math . Cos ( angle - 0.46f ) , lines [ i ] . v2 . z - nz ) ) ;
2013-09-11 09:47:53 +00:00
verts [ i * 6 + 4 ] = endPoint ;
2012-09-17 21:57:08 +00:00
verts [ i * 6 + 5 ] = new WorldVertex ( new Vector3D ( lines [ i ] . v2 . x - scaler * ( float ) Math . Sin ( angle + 0.46f ) , lines [ i ] . v2 . y + scaler * ( float ) Math . Cos ( angle + 0.46f ) , lines [ i ] . v2 . z - nz ) ) ;
2013-09-11 09:47:53 +00:00
}
VertexBuffer vb = new VertexBuffer ( General . Map . Graphics . Device , WorldVertex . Stride * verts . Length , Usage . WriteOnly | Usage . Dynamic , VertexFormat . None , Pool . Default ) ;
DataStream s = vb . Lock ( 0 , WorldVertex . Stride * verts . Length , LockFlags . Discard ) ;
s . WriteRange < WorldVertex > ( verts ) ;
vb . Unlock ( ) ;
s . Dispose ( ) ;
//begin rendering
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . ZWriteEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . SourceAlpha ) ;
graphics . Shaders . World3D . BeginPass ( 16 ) ;
world = Matrix . Identity ;
ApplyMatrices3D ( ) ;
// Setup color
2012-09-26 00:04:17 +00:00
graphics . Shaders . World3D . VertexColor = color ;
2012-09-17 15:41:18 +00:00
2013-09-11 09:47:53 +00:00
//render
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . SetStreamSource ( 0 , vb , 0 , WorldVertex . Stride ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . LineList , 0 , lines . Count * 3 ) ;
2012-09-17 15:41:18 +00:00
2013-09-11 09:47:53 +00:00
// Done
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . SetModulateColor ( - 1 ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
2012-09-17 21:57:08 +00:00
vb . Dispose ( ) ;
2013-09-11 09:47:53 +00:00
}
2009-04-19 18:07:22 +00:00
// This performs a single render pass
private void RenderSinglePass ( int pass )
{
2013-09-11 09:47:53 +00:00
int currentshaderpass = shaderpass ;
2009-05-01 20:31:17 +00:00
int highshaderpass = shaderpass + 2 ;
2009-04-19 18:07:22 +00:00
// Get geometry for this pass
Dictionary < ImageData , BinaryHeap < VisualGeometry > > geopass = geometry [ pass ] ;
// Begin rendering with this shader
graphics . Shaders . World3D . BeginPass ( shaderpass ) ;
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// Render the geometry collected
foreach ( KeyValuePair < ImageData , BinaryHeap < VisualGeometry > > group in geopass )
{
ImageData curtexture ;
// What texture to use?
if ( group . Key is UnknownImage )
curtexture = General . Map . Data . UnknownTexture3D ;
else if ( ( group . Key ! = null ) & & group . Key . IsImageLoaded & & ! group . Key . IsDisposed )
curtexture = group . Key ;
else
curtexture = General . Map . Data . Hourglass3D ;
// Create Direct3D texture if still needed
if ( ( curtexture . Texture = = null ) | | curtexture . Texture . Disposed )
curtexture . CreateTexture ( ) ;
// Apply texture
2009-05-04 06:13:56 +00:00
if ( ! graphics . Shaders . Enabled ) graphics . Device . SetTexture ( 0 , curtexture . Texture ) ;
2009-04-19 18:07:22 +00:00
graphics . Shaders . World3D . Texture1 = curtexture . Texture ;
// Go for all geometry that uses this texture
VisualSector sector = null ;
2013-09-11 09:47:53 +00:00
2009-04-19 18:07:22 +00:00
foreach ( VisualGeometry g in group . Value )
{
// Changing sector?
if ( ! object . ReferenceEquals ( g . Sector , sector ) )
{
// Update the sector if needed
if ( g . Sector . NeedsUpdateGeo ) g . Sector . Update ( ) ;
// Only do this sector when a vertexbuffer is created
2013-09-11 09:47:53 +00:00
//mxd. no Map means that sector was deleted recently, I suppose
if ( g . Sector . GeometryBuffer ! = null & & g . Sector . Sector . Map ! = null )
2009-04-19 18:07:22 +00:00
{
// Change current sector
sector = g . Sector ;
// Set stream source
graphics . Device . SetStreamSource ( 0 , sector . GeometryBuffer , 0 , WorldVertex . Stride ) ;
}
else
{
sector = null ;
}
2012-06-03 15:13:22 +00:00
}
2013-09-11 09:47:53 +00:00
if ( sector ! = null )
2009-04-19 18:07:22 +00:00
{
2009-05-01 20:31:17 +00:00
// Determine the shader pass we want to use for this object
2009-07-07 14:52:39 +00:00
int wantedshaderpass = ( ( ( g = = highlighted ) & & showhighlight ) | | ( g . Selected & & showselection ) ) ? highshaderpass : shaderpass ;
2012-05-13 20:51:41 +00:00
2013-09-11 09:47:53 +00:00
//mxd
2013-12-23 08:00:19 +00:00
if ( ! ( ! General . Settings . GZDrawFog | | fullbrightness | | sector . Sector . Brightness > 247 ) )
2013-09-11 09:47:53 +00:00
wantedshaderpass + = 8 ;
//mxd. Seems that lines rendered with RenderPass.Alpha or RenderPass.Additive aren't affected by dynamic lights in GZDoom
2013-12-23 08:00:19 +00:00
if ( ! ( g . RenderPass = = RenderPass . Alpha | | g . RenderPass = = RenderPass . Additive | | ! General . Settings . GZDrawLights | | fullbrightness | | thingsWithLight . Count = = 0 ) ) {
2013-09-11 09:47:53 +00:00
if ( curtexture . Texture ! = null ) {
if ( ! litGeometry . ContainsKey ( curtexture . Texture ) )
litGeometry [ curtexture . Texture ] = new List < VisualGeometry > ( ) ;
litGeometry [ curtexture . Texture ] . Add ( g ) ;
}
}
2012-04-17 19:13:47 +00:00
2009-05-01 20:31:17 +00:00
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass )
2009-04-19 18:07:22 +00:00
{
graphics . Shaders . World3D . EndPass ( ) ;
2009-05-01 20:31:17 +00:00
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
2009-04-19 18:07:22 +00:00
}
2009-05-04 06:13:56 +00:00
// Set the colors to use
if ( ! graphics . Shaders . Enabled )
{
2009-07-07 14:52:39 +00:00
graphics . Device . SetTexture ( 2 , ( g . Selected & & showselection ) ? selectionimage . Texture : null ) ;
graphics . Device . SetTexture ( 3 , ( ( g = = highlighted ) & & showhighlight ) ? highlightimage . Texture : null ) ;
2009-05-04 06:13:56 +00:00
}
else
{
2013-09-11 09:47:53 +00:00
//mxd. set variables for fog rendering
if ( wantedshaderpass > 7 ) {
graphics . Shaders . World3D . World = world ;
2013-09-11 08:49:45 +00:00
graphics . Shaders . World3D . LightColor = sector . Sector . FogColor ;
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , getFogEnd ( sector . Sector ) ) ;
2013-09-11 09:47:53 +00:00
}
graphics . Shaders . World3D . SetHighlightColor ( CalculateHighlightColor ( ( g = = highlighted ) & & showhighlight , ( g . Selected & & showselection ) ) . ToArgb ( ) ) ;
2009-05-04 06:13:56 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
}
2009-05-01 20:31:17 +00:00
2009-04-19 18:07:22 +00:00
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
// Get things for this pass
Dictionary < ImageData , List < VisualThing > > thingspass = things [ pass ] ;
2009-04-26 20:20:40 +00:00
if ( thingspass . Count > 0 )
2009-04-19 18:07:22 +00:00
{
2009-04-26 20:20:40 +00:00
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Clamp ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Clamp ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Clamp ) ;
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
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ; //mxd. Disable backside culling, because otherwise sprites with positive ScaleY and negative ScaleX will be facing away from the camera...
2009-04-19 18:07:22 +00:00
2009-04-26 20:20:40 +00:00
// Render things collected
foreach ( KeyValuePair < ImageData , List < VisualThing > > group in thingspass )
2009-04-19 18:07:22 +00:00
{
2009-04-26 20:20:40 +00:00
if ( ! ( group . Key is UnknownImage ) )
{
2013-12-23 08:00:19 +00:00
ImageData curtexture ;
2009-04-26 20:20:40 +00:00
// What texture to use?
2013-12-23 08:00:19 +00:00
if ( ( group . Key = = null ) | | ! group . Key . IsImageLoaded | | group . Key . IsDisposed )
2009-04-26 20:20:40 +00:00
curtexture = General . Map . Data . Hourglass3D ;
2013-12-23 08:00:19 +00:00
else
curtexture = group . Key ;
2009-04-19 18:07:22 +00:00
2009-04-26 20:20:40 +00:00
// Create Direct3D texture if still needed
if ( ( curtexture . Texture = = null ) | | curtexture . Texture . Disposed )
curtexture . CreateTexture ( ) ;
2009-04-19 18:07:22 +00:00
2009-04-26 20:20:40 +00:00
// Apply texture
2009-05-04 06:13:56 +00:00
if ( ! graphics . Shaders . Enabled ) graphics . Device . SetTexture ( 0 , curtexture . Texture ) ;
2009-04-26 20:20:40 +00:00
graphics . Shaders . World3D . Texture1 = curtexture . Texture ;
2009-04-19 18:07:22 +00:00
2009-04-26 20:20:40 +00:00
// Render all things with this texture
foreach ( VisualThing t in group . Value )
{
2013-09-11 09:47:53 +00:00
//mxd
if ( t . Thing . IsModel & & General . Settings . GZDrawModels & & ( ! General . Settings . GZDrawSelectedModelsOnly | | t . Selected ) )
continue ;
2012-08-05 19:18:05 +00:00
2013-09-11 09:47:53 +00:00
// Update buffer if needed
t . Update ( ) ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Only do this sector when a vertexbuffer is created
if ( t . GeometryBuffer ! = null ) {
// Determine the shader pass we want to use for this object
int wantedshaderpass = ( ( ( t = = highlighted ) & & showhighlight ) | | ( t . Selected & & showselection ) ) ? highshaderpass : shaderpass ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd. if fog is enagled, switch to shader, which calculates it
2013-09-11 08:49:45 +00:00
if ( General . Settings . GZDrawFog & & ! fullbrightness & & t . Thing . Sector ! = null & & ( t . Thing . Sector . HasFogColor | | t . Thing . Sector . Brightness < 248 ) )
2013-09-11 09:47:53 +00:00
wantedshaderpass + = 8 ;
//mxd. if current thing is light - set it's color to light color
if ( Array . IndexOf ( GZBuilder . GZGeneral . GZ_LIGHTS , t . Thing . Type ) ! = - 1 & & ! fullbrightness ) {
wantedshaderpass + = 4 ; //render using one of passes, which uses World3D.VertexColor
graphics . Shaders . World3D . VertexColor = t . LightColor ;
//mxd. check if Thing is affected by dynamic lights and set color accordingly
} else if ( General . Settings . GZDrawLights & & ! fullbrightness & & thingsWithLight . Count > 0 ) {
Color4 litColor = getLitColorForThing ( t ) ;
if ( litColor . ToArgb ( ) ! = 0 ) {
wantedshaderpass + = 4 ; //render using one of passes, which uses World3D.VertexColor
graphics . Shaders . World3D . VertexColor = new Color4 ( t . VertexColor ) + litColor ;
}
}
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass ) {
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
}
// Set the colors to use
if ( ! graphics . Shaders . Enabled ) {
graphics . Device . SetTexture ( 2 , ( t . Selected & & showselection ) ? selectionimage . Texture : null ) ;
graphics . Device . SetTexture ( 3 , ( ( t = = highlighted ) & & showhighlight ) ? highlightimage . Texture : null ) ;
} else {
graphics . Shaders . World3D . SetHighlightColor ( CalculateHighlightColor ( ( t = = highlighted ) & & showhighlight , ( t . Selected & & showselection ) ) . ToArgb ( ) ) ;
}
// Create the matrix for positioning / rotation
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
world = billboard
* Matrix . Scaling ( t . Thing . ScaleX , t . Thing . ScaleX , t . Thing . ScaleY )
* t . Position ; //mxd
2013-09-11 09:47:53 +00:00
ApplyMatrices3D ( ) ;
//mxd. set variables for fog rendering
if ( wantedshaderpass > 7 ) {
graphics . Shaders . World3D . World = world ;
2012-05-20 00:56:59 +00:00
2013-09-11 08:49:45 +00:00
graphics . Shaders . World3D . LightColor = t . Thing . Sector . FogColor ;
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , getFogEnd ( t . Thing . Sector ) ) ;
2013-09-11 09:47:53 +00:00
}
2012-05-20 00:56:59 +00:00
2013-09-11 09:47:53 +00:00
graphics . Shaders . World3D . ApplySettings ( ) ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Apply buffer
graphics . Device . SetStreamSource ( 0 , t . GeometryBuffer , 0 , WorldVertex . Stride ) ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Render!
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , 0 , t . Triangles ) ;
}
2009-04-19 18:07:22 +00:00
}
}
}
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
// Texture addressing
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressU , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressV , TextureAddress . Wrap ) ;
graphics . Device . SetSamplerState ( 0 , SamplerState . AddressW , TextureAddress . Wrap ) ;
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
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . Counterclockwise ) ; //mxd
2009-04-19 18:07:22 +00:00
}
// Done rendering with this shader
graphics . Shaders . World3D . EndPass ( ) ;
}
2009-05-05 21:13:50 +00:00
2013-09-11 09:47:53 +00:00
//mxd. Dynamic lights pass!
private void RenderLights ( Dictionary < Texture , List < VisualGeometry > > geometry_to_lit , List < VisualThing > lights ) {
2012-08-10 12:08:08 +00:00
graphics . Shaders . World3D . World = Matrix . Identity ;
2013-09-11 09:47:53 +00:00
graphics . Shaders . World3D . BeginPass ( 17 ) ;
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
int i , count ;
Vector4 lpr ;
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . One ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . BlendFactor ) ;
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
foreach ( KeyValuePair < Texture , List < VisualGeometry > > group in geometry_to_lit ) {
graphics . Shaders . World3D . Texture1 = group . Key ;
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
foreach ( VisualGeometry g in group . Value ) {
graphics . Device . SetStreamSource ( 0 , g . Sector . GeometryBuffer , 0 , WorldVertex . Stride ) ;
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
//normal lights
count = lightOffsets [ 0 ] ;
if ( lightOffsets [ 0 ] > 0 ) {
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
for ( i = 0 ; i < count ; i + + ) {
if ( checkBBoxIntersection ( g . BoundingBox , lights [ i ] . BoundingBox ) ) {
2012-08-10 12:08:08 +00:00
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
2013-12-18 09:11:04 +00:00
if ( lpr . W = = 0 ) continue ;
2013-09-11 09:47:53 +00:00
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
2013-12-18 09:11:04 +00:00
//additive lights
2013-09-11 09:47:53 +00:00
if ( lightOffsets [ 1 ] > 0 ) {
count + = lightOffsets [ 1 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
for ( i = lightOffsets [ 0 ] ; i < count ; i + + ) {
if ( checkBBoxIntersection ( g . BoundingBox , lights [ i ] . BoundingBox ) ) {
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
2013-12-18 09:11:04 +00:00
if ( lpr . W = = 0 ) continue ;
2013-09-11 09:47:53 +00:00
graphics . Shaders . World3D . LightColor = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
//negative lights
if ( lightOffsets [ 2 ] > 0 ) {
count + = lightOffsets [ 2 ] ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . ReverseSubtract ) ;
for ( i = lightOffsets [ 0 ] + lightOffsets [ 1 ] ; i < count ; i + + ) {
if ( checkBBoxIntersection ( g . BoundingBox , lights [ i ] . BoundingBox ) ) {
lpr = new Vector4 ( lights [ i ] . Center , lights [ i ] . LightRadius ) ;
2013-12-18 09:11:04 +00:00
if ( lpr . W = = 0 ) continue ;
2013-09-11 09:47:53 +00:00
Color4 lc = lights [ i ] . LightColor ;
graphics . Shaders . World3D . LightColor = new Color4 ( lc . Alpha , ( lc . Green + lc . Blue ) / 2 , ( lc . Red + lc . Blue ) / 2 , ( lc . Green + lc . Red ) / 2 ) ;
graphics . Shaders . World3D . LightPositionAndRadius = lpr ;
graphics . Shaders . World3D . ApplySettings ( ) ;
graphics . Device . DrawPrimitives ( PrimitiveType . TriangleList , g . VertexOffset , g . Triangles ) ;
}
}
}
}
}
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Device . SetRenderState ( RenderState . BlendOperation , BlendOperation . Add ) ;
}
//mxd. render models
private void RenderModels ( ) {
int shaderpass = fullbrightness ? 1 : 4 ;
int currentshaderpass = shaderpass ;
int highshaderpass = shaderpass + 2 ;
// Begin rendering with this shader
graphics . Shaders . World3D . BeginPass ( currentshaderpass ) ;
foreach ( KeyValuePair < ModelData , List < VisualThing > > group in thingsWithModel ) {
foreach ( VisualThing t in group . Value ) {
t . Update ( ) ;
Color4 vertexColor = new Color4 ( t . VertexColor ) ;
vertexColor . Alpha = 1.0f ;
//check if model is affected by dynamic lights and set color accordingly
if ( General . Settings . GZDrawLights & & ! fullbrightness & & thingsWithLight . Count > 0 ) {
Color4 litColor = getLitColorForThing ( t ) ;
graphics . Shaders . World3D . VertexColor = vertexColor + litColor ;
} else {
graphics . Shaders . World3D . VertexColor = vertexColor ;
}
// Determine the shader pass we want to use for this object
int wantedshaderpass = ( ( ( ( t = = highlighted ) & & showhighlight ) | | ( t . Selected & & showselection ) ) ? highshaderpass : shaderpass ) ;
//mxd. if fog is enagled, switch to shader, which calculates it
if ( General . Settings . GZDrawFog & & ! fullbrightness & & t . Thing . Sector ! = null & & ( t . Thing . Sector . HasFogColor | | t . Thing . Sector . Brightness < 248 ) )
wantedshaderpass + = 8 ;
// Switch shader pass?
if ( currentshaderpass ! = wantedshaderpass ) {
graphics . Shaders . World3D . EndPass ( ) ;
graphics . Shaders . World3D . BeginPass ( wantedshaderpass ) ;
currentshaderpass = wantedshaderpass ;
}
// Set the colors to use
if ( ! graphics . Shaders . Enabled ) {
graphics . Device . SetTexture ( 2 , ( t . Selected & & showselection ) ? selectionimage . Texture : null ) ;
graphics . Device . SetTexture ( 3 , ( ( t = = highlighted ) & & showhighlight ) ? highlightimage . Texture : null ) ;
} else {
graphics . Shaders . World3D . SetHighlightColor ( CalculateHighlightColor ( ( t = = highlighted ) & & showhighlight , ( t . Selected & & showselection ) ) . ToArgb ( ) ) ;
}
// Create the matrix for positioning / rotation
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 sx = t . Thing . ScaleX * t . Thing . ActorScale . Width ;
float sy = t . Thing . ScaleY * t . Thing . ActorScale . Height ;
Matrix rotation = Matrix . RotationY ( - ( t . Thing . RollRad - General . Map . Data . ModeldefEntries [ t . Thing . Type ] . RollOffset ) )
* Matrix . RotationX ( - ( t . Thing . PitchRad + General . Map . Data . ModeldefEntries [ t . Thing . Type ] . PitchOffset ) )
* Matrix . RotationZ ( t . Thing . Angle ) ;
2014-05-03 14:44:59 +00:00
world = Matrix . Scaling ( sx , sx , sy ) * rotation * t . Position ;
2013-09-11 09:47:53 +00:00
ApplyMatrices3D ( ) ;
2012-04-17 19:13:47 +00:00
2013-09-11 09:47:53 +00:00
//mxd. set variables for fog rendering
if ( wantedshaderpass > 7 ) {
graphics . Shaders . World3D . World = world ;
2012-05-20 00:56:59 +00:00
2013-09-11 08:49:45 +00:00
graphics . Shaders . World3D . LightColor = t . Thing . Sector . FogColor ;
graphics . Shaders . World3D . CameraPosition = new Vector4 ( cameraposition . x , cameraposition . y , cameraposition . z , getFogEnd ( t . Thing . Sector ) ) ;
2013-09-11 09:47:53 +00:00
}
2012-05-20 00:56:59 +00:00
2013-03-18 13:52:27 +00:00
for ( int i = 0 ; i < group . Key . Model . Meshes . Count ; i + + ) {
2013-09-11 09:47:53 +00:00
if ( ! graphics . Shaders . Enabled ) graphics . Device . SetTexture ( 0 , group . Key . Model . Textures [ i ] ) ;
graphics . Shaders . World3D . Texture1 = group . Key . Model . Textures [ i ] ;
graphics . Shaders . World3D . ApplySettings ( ) ;
// Render!
group . Key . Model . Meshes [ i ] . DrawSubset ( 0 ) ;
}
}
}
graphics . Shaders . World3D . EndPass ( ) ;
}
//mxd. This gets color from dynamic lights based on distance to thing.
//thing position must be in absolute cordinates
//(thing.Position.Z value is relative to floor of the sector the thing is in)
private Color4 getLitColorForThing ( VisualThing t ) {
Color4 litColor = new Color4 ( ) ;
float radius , radiusSquared , distSquared , scaler ;
int sign ;
for ( int i = 0 ; i < thingsWithLight . Count ; i + + ) {
//don't light self
if ( General . Map . Data . GldefsEntries . ContainsKey ( t . Thing . Type ) & & General . Map . Data . GldefsEntries [ t . Thing . Type ] . DontLightSelf & & t . Thing . Index = = thingsWithLight [ i ] . Thing . Index ) {
continue ;
}
distSquared = Vector3 . DistanceSquared ( thingsWithLight [ i ] . Center , t . PositionV3 ) ;
radius = thingsWithLight [ i ] . LightRadius ;
radiusSquared = radius * radius ;
if ( distSquared < radiusSquared ) {
sign = thingsWithLight [ i ] . LightRenderStyle = = DynamicLightRenderStyle . NEGATIVE ? - 1 : 1 ;
scaler = 1 - distSquared / radiusSquared * thingsWithLight [ i ] . LightColor . Alpha ;
litColor . Red + = thingsWithLight [ i ] . LightColor . Red * scaler * sign ;
litColor . Green + = thingsWithLight [ i ] . LightColor . Green * scaler * sign ;
litColor . Blue + = thingsWithLight [ i ] . LightColor . Blue * scaler * sign ;
}
}
return litColor ;
}
//mxd. This returns distance, at which fog color completely replaces texture color for given sector
2014-05-20 09:09:28 +00:00
private static float getFogEnd ( Sector s )
{
2013-09-11 08:49:45 +00:00
float brightness = Math . Max ( 30 , s . Brightness ) ;
if ( s . HasFogColor ) {
if ( s . UsesOutsideFog & & General . Map . Data . MapInfo . OutsideFogDensity > 0 )
2013-09-11 09:47:53 +00:00
return General . Map . Data . MapInfo . OutsideFogDensity ;
2013-09-11 08:49:45 +00:00
if ( ! s . UsesOutsideFog & & General . Map . Data . MapInfo . FogDensity > 0 )
return General . Map . Data . MapInfo . FogDensity ;
return brightness * 11.0f ;
2013-09-11 09:47:53 +00:00
}
2013-09-11 08:49:45 +00:00
return ( float ) Math . Pow ( 2.0f , brightness / 11.0f ) ;
2013-09-11 09:47:53 +00:00
}
2012-05-20 00:56:59 +00:00
2009-05-05 21:13:50 +00:00
// This calculates the highlight/selection color
public Color4 CalculateHighlightColor ( bool ishighlighted , bool isselected )
{
Color4 highlightcolor = isselected ? General . Colors . Selection . ToColorValue ( ) : General . Colors . Highlight . ToColorValue ( ) ;
highlightcolor . Alpha = ishighlighted ? highlightglowinv : highlightglow ;
return highlightcolor ;
}
2009-04-19 18:07:22 +00:00
// This finishes rendering
public void Finish ( )
{
2010-08-22 12:09:32 +00:00
General . Plugins . OnPresentDisplayBegin ( ) ;
2009-04-19 18:07:22 +00:00
// Done
graphics . FinishRendering ( ) ;
graphics . Present ( ) ;
highlighted = null ;
}
#endregion
#region = = = = = = = = = = = = = = = = = = Rendering
// This sets the highlighted object for the rendering
public void SetHighlightedObject ( IVisualPickable obj )
{
highlighted = obj ;
}
// This collects a visual sector's geometry for rendering
public void AddSectorGeometry ( VisualGeometry g )
{
2009-07-04 10:06:35 +00:00
// Must have a texture and vertices
if ( ( g . Texture ! = null ) & & ( g . Triangles > 0 ) )
2009-04-19 18:07:22 +00:00
{
2013-09-11 09:47:53 +00:00
// Texture group not yet collected?
2009-04-19 18:07:22 +00:00
if ( ! geometry [ g . RenderPassInt ] . ContainsKey ( g . Texture ) )
{
// Create texture group
geometry [ g . RenderPassInt ] . Add ( g . Texture , new BinaryHeap < VisualGeometry > ( ) ) ;
}
// Add geometry to texture group
geometry [ g . RenderPassInt ] [ g . Texture ] . Add ( g ) ;
}
}
// This collects a visual sector's geometry for rendering
public void AddThingGeometry ( VisualThing t )
{
2013-09-11 09:47:53 +00:00
//mxd. gater lights
if ( General . Settings . GZDrawLights & & ! fullbrightness & & t . LightType ! = DynamicLightType . NONE ) {
t . UpdateLightRadius ( ) ;
if ( t . LightRadius > 0 ) {
t . CalculateCameraDistance3D ( D3DDevice . V3 ( cameraposition ) ) ;
//t.CameraDistance3D is actually squared distance, hence (t.LightRadius * t.LightRadius)
if ( t . CameraDistance3D < ( t . LightRadius * t . LightRadius ) | | isThingOnScreen ( t . BoundingBox ) ) { //always render light if camera is within it's radius
if ( Array . IndexOf ( GZBuilder . GZGeneral . GZ_ANIMATED_LIGHT_TYPES , t . LightType ) ! = - 1 )
t . UpdateBoundingBox ( ) ;
thingsWithLight . Add ( t ) ;
}
}
}
if ( ! isThingOnScreen ( t . BoundingBox ) ) return ;
//mxd. gather models
2013-07-29 08:50:50 +00:00
if ( t . Thing . IsModel & & General . Settings . GZDrawModels & & ( ! General . Settings . GZDrawSelectedModelsOnly | | t . Selected ) ) {
2013-09-11 09:47:53 +00:00
ModelData mde = General . Map . Data . ModeldefEntries [ t . Thing . Type ] ;
if ( ! thingsWithModel . ContainsKey ( mde ) )
2013-07-29 08:50:50 +00:00
thingsWithModel . Add ( mde , new List < VisualThing > ( ) { t } ) ;
else
thingsWithModel [ mde ] . Add ( t ) ;
2013-09-11 09:47:53 +00:00
}
// Make sure the distance to camera is calculated
t . CalculateCameraDistance ( cameraposition ) ;
thingsbydistance . Add ( t ) ;
// Must have a texture!
if ( t . Texture ! = null )
2009-04-19 18:07:22 +00:00
{
// Texture group not yet collected?
if ( ! things [ t . RenderPassInt ] . ContainsKey ( t . Texture ) )
{
// Create texture group
things [ t . RenderPassInt ] . Add ( t . Texture , new List < VisualThing > ( ) ) ;
}
// Add geometry to texture group
things [ t . RenderPassInt ] [ t . Texture ] . Add ( t ) ;
}
}
2013-03-18 13:52:27 +00:00
//mxd
public void AddVisualVertices ( VisualVertex [ ] verts ) {
visualvertices = verts ;
}
2013-09-11 09:47:53 +00:00
//mxd
private bool isThingOnScreen ( Vector3 [ ] bbox ) {
Vector3D camNormal = Vector3D . FromAngleXYZ ( General . Map . VisualCamera . AngleXY , General . Map . VisualCamera . AngleZ ) ;
Vector3D thingNormal = D3DDevice . V3D ( bbox [ 0 ] ) - cameraposition ; //bbox[0] is always thing center
if ( Vector3D . DotProduct ( camNormal , thingNormal ) < 0 ) return false ; //behind camera plane
int len = bbox . Length ;
Vector3 screenPos ;
int behindCount = 0 ;
int leftCount = 0 ;
int rightCount = 0 ;
int topCount = 0 ;
int bottomCount = 0 ;
for ( int i = 0 ; i < len ; i + + ) {
//check visibility
screenPos = Vector3 . Project ( bbox [ i ] , 0 , 0 , 1 , 1 , PROJ_NEAR_PLANE , General . Settings . ViewDistance , worldviewproj ) ;
if ( screenPos . X > 0 & & screenPos . X < 1 & & screenPos . Y > 0 & & screenPos . Y < 1 )
return true ;
if ( screenPos . Z < 0 )
behindCount + + ;
if ( screenPos . X < 0 )
leftCount + + ;
else if ( screenPos . X > 1 )
rightCount + + ;
if ( screenPos . Y < 0 )
topCount + + ;
else if ( screenPos . Y > 1 )
bottomCount + + ;
}
bool notOnScreen = ( behindCount = = len | | leftCount = = len | | rightCount = = len | | topCount = = len | | bottomCount = = len ) ;
return ! notOnScreen ;
}
//mxd
private static bool checkBBoxIntersection ( Vector3 [ ] bbox1 , Vector3 [ ] bbox2 ) {
Vector3 dist = bbox1 [ 0 ] - bbox2 [ 0 ] ;
Vector3 halfSize1 = bbox1 [ 0 ] - bbox1 [ 1 ] ;
Vector3 halfSize2 = bbox2 [ 0 ] - bbox2 [ 1 ] ;
if ( halfSize1 . X + halfSize2 . X > = Math . Abs ( dist . X ) & & halfSize1 . Y + halfSize2 . Y > = Math . Abs ( dist . Y ) & & halfSize1 . Z + halfSize2 . Z > = Math . Abs ( dist . Z ) )
return true ;
return false ;
}
2012-04-17 19:13:47 +00:00
2009-04-19 18:07:22 +00:00
// This renders the crosshair
public void RenderCrosshair ( )
{
// Set renderstates
2013-09-11 09:47:53 +00:00
graphics . Device . SetRenderState ( RenderState . CullMode , Cull . None ) ;
graphics . Device . SetRenderState ( RenderState . ZEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . AlphaBlendEnable , true ) ;
graphics . Device . SetRenderState ( RenderState . AlphaTestEnable , false ) ;
graphics . Device . SetRenderState ( RenderState . SourceBlend , Blend . SourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . DestinationBlend , Blend . InverseSourceAlpha ) ;
graphics . Device . SetRenderState ( RenderState . TextureFactor , - 1 ) ;
graphics . Device . SetTransform ( TransformState . World , Matrix . Identity ) ;
graphics . Device . SetTransform ( TransformState . Projection , Matrix . Identity ) ;
ApplyMatrices2D ( ) ;
2009-04-19 18:07:22 +00:00
2013-09-11 09:47:53 +00:00
// Texture
if ( crosshairbusy )
{
if ( General . Map . Data . CrosshairBusy3D . Texture = = null ) General . Map . Data . CrosshairBusy3D . CreateTexture ( ) ;
graphics . Device . SetTexture ( 0 , General . Map . Data . CrosshairBusy3D . Texture ) ;
graphics . Shaders . Display2D . Texture1 = General . Map . Data . CrosshairBusy3D . Texture ;
}
else
{
if ( General . Map . Data . Crosshair3D . Texture = = null ) General . Map . Data . Crosshair3D . CreateTexture ( ) ;
graphics . Device . SetTexture ( 0 , General . Map . Data . Crosshair3D . Texture ) ;
graphics . Shaders . Display2D . Texture1 = General . Map . Data . Crosshair3D . Texture ;
}
2009-04-19 18:07:22 +00:00
2013-09-11 09:47:53 +00:00
// Draw
graphics . Shaders . Display2D . Begin ( ) ;
graphics . Shaders . Display2D . SetSettings ( 1.0f , 1.0f , 0.0f , 1.0f , true ) ;
graphics . Shaders . Display2D . BeginPass ( 1 ) ;
graphics . Device . DrawUserPrimitives < FlatVertex > ( PrimitiveType . TriangleStrip , 0 , 2 , crosshairverts ) ;
graphics . Shaders . Display2D . EndPass ( ) ;
graphics . Shaders . Display2D . End ( ) ;
}
2009-04-19 18:07:22 +00:00
// This switches fog on and off
public void SetFogMode ( bool usefog )
{
graphics . Device . SetRenderState ( RenderState . FogEnable , usefog ) ;
}
// This siwtches crosshair busy icon on and off
public void SetCrosshairBusy ( bool busy )
{
crosshairbusy = busy ;
}
2012-04-18 19:34:11 +00:00
2013-09-11 09:47:53 +00:00
//mxd. dbg
//private int lastTick, lastFrameRate, frameRate;
/ * private int calculateFrameRate ( ) {
if ( System . Environment . TickCount - lastTick > = 1000 ) {
lastFrameRate = frameRate ;
frameRate = 0 ;
lastTick = System . Environment . TickCount ;
}
frameRate + + ;
return lastFrameRate ;
} * /
2009-04-19 18:07:22 +00:00
#endregion
}
}