List <Face> GetCandidateFaces(Vector3 position)
        {
            List <Face> faces = new List <Face>();

            Common.PriorityQueue <float, Vertex> q = new Common.PriorityQueue <float, Vertex>();
            foreach (Vertex v in vertices)
            {
                float d = (v.Translation - position).Length();
                if (d < 30)
                {
                    q.Enqueue(d, v);
                }
            }
            if (q.Count() < 3)
            {
                return(faces);
            }
            Vertex a_ = q.Dequeue(), b_ = q.Dequeue();

            while (!q.IsEmpty)
            {
                Vertex  a = a_, b = b_, c = q.Dequeue();
                Vector3 minX = Common.Math.MinX(a.Translation, b.Translation, c.Translation);
                if (b.Translation == minX)
                {
                    Common.Math.Swap(ref a, ref b);
                }
                else if (c.Translation == minX)
                {
                    Common.Math.Swap(ref a, ref c);
                }
                if (Vector2.Dot(Common.Math.ToVector2(
                                    Common.Math.PerpendicularXY(b.Translation - a.Translation)),
                                Common.Math.ToVector2(c.Translation - a.Translation))
                    > 0)
                {
                    Common.Math.Swap(ref b, ref c);
                }

                var f = new Face(this);
                f.Vertices[0] = a;
                f.Vertices[1] = b;
                f.Vertices[2] = c;

                float   d;
                Vector2 uv;
                if (f.Intersect(worldProbing.ScreenRay(), out d, out uv))
                {
                    faces.Add(f);
                }
            }
            return(faces);
        }
Beispiel #2
0
        public static string ReportCallCounters()
        {
#if META_RESOURCE_MEASURE_CALL_COUNT
            StringBuilder s = new StringBuilder();
            Common.PriorityQueue <int, Common.Tuple <Type, int> > p = new Common.PriorityQueue <int, Common.Tuple <Type, int> >();
            s.AppendLine("Clone calls:");
            p.Clear();
            foreach (var v in cloneCalls)
            {
                p.Enqueue(v.Value, new Common.Tuple <Type, int>(v.Key, v.Value));
            }
            foreach (var v in p)
            {
                s.AppendLine(v.First + ": " + v.Second);
            }
            s.AppendLine().AppendLine("GetHashCode calls:");
            p.Clear();
            foreach (var v in getHashCodeCalls)
            {
                p.Enqueue(v.Value, new Common.Tuple <Type, int>(v.Key, v.Value));
            }
            foreach (var v in p)
            {
                s.AppendLine(v.First + ": " + v.Second);
            }
            s.AppendLine().AppendLine("Equals calls:");
            p.Clear();
            foreach (var v in equalsCalls)
            {
                p.Enqueue(v.Value, new Common.Tuple <Type, int>(v.Key, v.Value));
            }
            foreach (var v in p)
            {
                s.AppendLine(v.First + ": " + v.Second);
            }
            return(s.ToString());
#else
            return("Counters disabled");
#endif
        }
        List<Face> GetCandidateFaces(Vector3 position)
        {
            List<Face> faces = new List<Face>();
            Common.PriorityQueue<float, Vertex> q = new Common.PriorityQueue<float, Vertex>();
            foreach (Vertex v in vertices)
            {
                float d = (v.Translation - position).Length();
                if (d < 30)
                    q.Enqueue(d, v);
            }
            if (q.Count() < 3) return faces;
            Vertex a_ = q.Dequeue(), b_ = q.Dequeue();
            while (!q.IsEmpty)
            {
                Vertex a = a_, b = b_, c = q.Dequeue();
                Vector3 minX = Common.Math.MinX(a.Translation, b.Translation, c.Translation);
                if (b.Translation == minX) Common.Math.Swap(ref a, ref b);
                else if (c.Translation == minX) Common.Math.Swap(ref a, ref c);
                if (Vector2.Dot(Common.Math.ToVector2(
                    Common.Math.PerpendicularXY(b.Translation - a.Translation)),
                    Common.Math.ToVector2(c.Translation - a.Translation))
                    > 0)
                    Common.Math.Swap(ref b, ref c);

                var f = new Face(this);
                f.Vertices[0] = a;
                f.Vertices[1] = b;
                f.Vertices[2] = c;

                float d;
                Vector2 uv;
                if (f.Intersect(worldProbing.ScreenRay(), out d, out uv))
                    faces.Add(f);
            }
            return faces;
        }
        public override void Update(float dtime)
        {
            base.Update(dtime);
            frameId++;
            if (frameId == 2)
            {
                Application.Log("First frame");
                System.Windows.Forms.Cursor.Show(); // Hidden at startup
            }
#if BETA_RELEASE
            ClientProfilers.Program.Stop();
#endif
            if (Settings.DisplayProfilersSystem == ProfilersSystem.Client)
                ClientProfilers.UpdateProfilers();
            else
                PhysicsProfilers.UpdateProfilers();
#if BETA_RELEASE
            ClientProfilers.Program.Start();
            ClientProfilers.Update.Start();
#endif

#if DEBUG
            if (dtime > 0.1)
                RedGate.Profiler.UserEvents.ProfilerEvent.SignalEvent("dtime large: " + dtime + " seconds.");
#endif

            foreach (var file in new List<string>(filesToBeDeleted))
            {
                if (System.IO.File.Exists(file))
                    System.IO.File.Delete(file);
                filesToBeDeleted.Remove(file);
            }

            //if (SoundManager._3DMinMaxDistance != Settings.SoundSettings.MinMaxDistance)
            //    SoundManager._3DMinMaxDistance = Settings.SoundSettings.MinMaxDistance;
            if (SoundManager.Muted != Settings.SoundSettings.Muted)
                SoundManager.Muted = Settings.SoundSettings.Muted;

            if (Program.Settings.FixedFrameStep)
            {
                float d = Program.Settings.FixedFrameStepDTime * Program.Settings.SpeedMultiplier;
                float time = 0.001f * fixedFrameStepSW.ElapsedMilliseconds;
                fixedFrameStepSW.Stop();
                float realD = time - fixedFrameStepLastTime;
                fixedFrameStepLastTime = time;
                if (realD < d)
                    System.Threading.Thread.Sleep((int)(1000 * (d - realD)));
                fixedFrameStepSW.Start();
                FixedFrameStepActivity = realD / d;
            }
            
            dtime = dtime * Program.Settings.SpeedMultiplier;

            FeedackOnlineControl.Visible = Settings.DisplayFeedbackOnlineControl && !FeedbackOnline;
            MouseCursor.Visible = Settings.WindowMode == WindowMode.Fullscreen && cursorHides == 0;
            if (MouseCursor.Visible)
                MouseCursor.Translation = new Vector3(LocalMousePosition.X, LocalMousePosition.Y, 0);

#if ENABLE_PROFILERS
            ClientProfilers.SoundUpdate.Start();
#endif
            ProgramState.UpdateSound(dtime);
#if ENABLE_PROFILERS
            ClientProfilers.SoundUpdate.Stop();
#endif

#if ENABLE_PROFILERS
            ClientProfilers.StateUpdate.Start();
#endif
            ProgramState.Update(dtime);
#if ENABLE_PROFILERS
            ClientProfilers.StateUpdate.Stop();
#endif

            timeouts.Update(dtime);

            if (InputHandler != null)
            {
#if ENABLE_PROFILERS
                ClientProfilers.ProcessMessage.Start();
#endif
                InputHandler.ProcessMessage(MessageType.Update, new UpdateEventArgs { Dtime = dtime });
#if ENABLE_PROFILERS
                ClientProfilers.ProcessMessage.Stop();
#endif
            }
#if ENABLE_PROFILERS
            ClientProfilers.PreRender.Start();
#endif
            programState.PreRender(dtime);
#if ENABLE_PROFILERS
            ClientProfilers.PreRender.Stop();
#endif

            //Device9.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.FromArgb((int)Renderer.Settings.FogColor.W, (int)(Renderer.Settings.FogColor.X * 255), (int)(Renderer.Settings.FogColor.Y * 255), (int)(Renderer.Settings.FogColor.Z * 255)), 1.0f, 0);

            Device9.BeginScene();
#if ENABLE_PROFILERS
            ClientProfilers.Render.Start();
#endif
            ProgramState.Render(dtime);
#if ENABLE_PROFILERS
            ClientProfilers.Render.Stop();
#endif
#if PROFILE_INTERFACERENDERER
            ClientProfilers.InterfaceRender.Start();
#endif
            InterfaceRenderer.Render(dtime);
#if PROFILE_INTERFACERENDERER
            ClientProfilers.InterfaceRender.Stop();
#endif

            if (Settings.DisplayInterfaceClickables)
            {
                BoundingVolumesRenderer.Begin(InterfaceScene.Camera);
                Common.PriorityQueue<float, Entity> clickables = new Common.PriorityQueue<float,Entity>();
                foreach (var v in InterfaceManager.Clickables.All)
                    clickables.Enqueue(v.AbsoluteTranslation.Z, v);
                foreach(var v in clickables)
                    BoundingVolumesRenderer.Draw(v.CombinedWorldMatrix, v.PickingLocalBounding, Color.Red);
                BoundingVolumesRenderer.End();
            }

            Device9.EndScene();

            if (Program.Settings.OutputPNGSequence && Game.Game.Instance != null)
            {
                var bb = Program.Instance.Device9.GetBackBuffer(0, 0);
                SlimDX.Direct3D9.Surface.ToFile(bb, Game.Game.Instance.OutputPNGSequencePath + "\\" +
                    Game.Game.Instance.FrameId + ".tga", SlimDX.Direct3D9.ImageFileFormat.Tga);
            }
#if ENABLE_PROFILERS
            ClientProfilers.Update.Stop();
#endif
        }
        void view_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            Vector3 world;
            nextFace.IsVisible = false;
            if (rightMouseDown) return;
            if (screenToWorld(e.Location, out world))
            {
                hasChanged = true;
                mouseWorld = world;
                if (moving != null)
                {
                    hasChanged = true;
                    moving.Translation = world;
                    foreach (Face f in moving.Faces)
                    {
                        f.Model.Mesh.Dispose();
                        f.Model.Mesh = Meshes.PositionTexcoord(view.Device, Meshes.IndexedTriangle(f.Vertices[0].Translation, f.Vertices[1].Translation, f.Vertices[2].Translation));
                    }
                }
                else
                {
                    Common.PriorityQueue<float, Vertex> q = new Common.PriorityQueue<float, Vertex>();
                    foreach (Vertex v in vertices)
                    {
                        float d = (v.Translation - world).Length();
                        if (d < 100)
                            q.Enqueue(d, v);
                    }
                    if (q.Count() < 3) return;
                    Vertex a_ = q.Dequeue(), b_ = q.Dequeue();
                    while (!q.IsEmpty)
                    {
                        Vertex a = a_, b = b_, c = q.Dequeue();
                        Vector3 minX = Common.Math.MinX(a.Translation, b.Translation, c.Translation);
                        if (b.Translation == minX) Common.Math.Swap(ref a, ref b);
                        else if (c.Translation == minX) Common.Math.Swap(ref a, ref c);
                        if (Vector2.Dot(Common.Math.ToVector2(
                            Common.Math.PerpendicularXY(b.Translation - a.Translation)),
                            Common.Math.ToVector2(c.Translation - a.Translation))
                            > 0)
                            Common.Math.Swap(ref b, ref c);

                        if (!Common.Math.PointInsideXYShape(world, a.Translation, b.Translation, c.Translation))
                            continue;
                        nextFace.IsVisible = true;
                        if (nextFace.Model.Mesh != null) nextFace.Model.Mesh.Dispose();
                        nextFace.Model.Mesh = Meshes.PositionTexcoord(view.Device, Meshes.IndexedTriangle(a.Translation, b.Translation, c.Translation));
                        nextFace.Vertices[0] = a;
                        nextFace.Vertices[1] = b;
                        nextFace.Vertices[2] = c;
                        break;
                    }
                }
            }
        }
        public void Render(float dtime)
        {
            for (int i = 0; i < 16; i++)
            {
                StateManager.SetSamplerState(i, SamplerState.MinFilter, Settings.TextureFilter.TextureFilterMin);
                StateManager.SetSamplerState(i, SamplerState.MagFilter, Settings.TextureFilter.TextureFilterMag);
                StateManager.SetSamplerState(i, SamplerState.MipFilter, Settings.TextureFilter.TextureFilterMip);
                StateManager.SetSamplerState(i, SamplerState.MaxAnisotropy, Settings.TextureFilter.AnisotropicLevel);
            }

            StateManager.SetSamplerState(0, SamplerState.AddressU, TextureAddress.Wrap);
            StateManager.SetSamplerState(0, SamplerState.AddressV, TextureAddress.Wrap);
            StateManager.SetRenderState(RenderState.CullMode, Settings.CullMode);
            StateManager.SetRenderState(RenderState.FillMode, Settings.FillMode);
            StateManager.SetRenderState(RenderState.MultisampleAntialias, true);

            StateManager.SetRenderState(RenderState.AlphaBlendEnable, false);
            StateManager.SetRenderState(RenderState.AlphaTestEnable, true);
            StateManager.SetRenderState(RenderState.AlphaFunc, Compare.GreaterEqual);
            StateManager.SetRenderState(RenderState.ZEnable, true);
            StateManager.SetRenderState(RenderState.ZWriteEnable, true);

            Matrix ViewProjection = Scene.Camera.View * Scene.Camera.Projection;

            #if PROFILE_RENDERER
            var t = System.DateTime.Now;
            #endif

            meshEffect.SetValue(EHCameraPosition, Scene.Camera.Position);
            skinnedMeshEffect.SetValue(EHCameraPosition, Scene.Camera.Position);

            skinnedMeshEffect.SetValue(EHViewProjectionMatrix, ViewProjection);
            meshEffect.SetValue(EHViewProjectionMatrix, ViewProjection);

            foreach (string technique in RenderRoot.Techniques.Keys)
            {
                if (technique.StartsWith("Sk"))
                {
                    if (Settings.RenderSkinnedMeshes)
                    {
                        if (Settings.ShadowsEnable)
                        {
                            skinnedMeshEffect.SetTexture(EHShadowTexture, shadowMap);
                            skinnedMeshEffect.SetValue(EHShadowViewProjection, ShadowMapCamera);
                        }
            #if PROFILES_RENDERER
                        if (RenderSkinnedMeshesStart != null)
                            RenderSkinnedMeshesStart();
            #endif
                        RenderSkinnedMeshes(RenderRoot.Techniques[technique].SkinnedMeshes, skinnedMeshEffect, false, true, ViewProjection, technique);
            #if PROFILES_RENDERER
                        if (RenderSkinnedMeshesStop != null)
                            RenderSkinnedMeshesStop();
            #endif
                    }
                }
                else if (technique.StartsWith("ShadowedSceneI"))
                {
                    if (Settings.RenderXMeshes)
                    {
                        if (Settings.ShadowsEnable)
                        {
                            meshEffect.SetTexture(EHShadowTexture, shadowMap);
                            meshEffect.SetValue(EHShadowViewProjection, ShadowMapCamera);
                        }
            #if PROFILES_RENDERER
                        if (RenderXMeshesStart != null)
                            RenderXMeshesStart();
            #endif
                        RenderXMeshesWithInstancing(RenderRoot.Techniques[technique].Meshes, device, meshEffect, technique);
            #if PROFILES_RENDERER
                        if (RenderXMeshesStop != null)
                            RenderXMeshesStop();
            #endif
                    }
                }
                else if (technique.StartsWith("Sh"))
                {
                    if (settings.RenderXMeshes)
                    {
                        if (Settings.ShadowsEnable)
                        {
                            meshEffect.SetTexture(EHShadowTexture, shadowMap);
                            meshEffect.SetValue(EHShadowViewProjection, ShadowMapCamera);
                        }
            #if PROFILES_RENDERER
                        if (RenderXMeshesStart != null)
                            RenderXMeshesStart();
            #endif
                        RenderXMeshes(RenderRoot.Techniques[technique].Meshes, meshEffect, ViewProjection, technique);
            #if PROFILES_RENDERER
                        if (RenderXMeshesStop != null)
                            RenderAlphaStop();
            #endif
                    }
                }
            }

            #if PROFILE_RENDERER
            rendererProfileLogFile.WriteLine("Render Meshes: " + ((System.DateTime.Now.Second * 1000 + System.DateTime.Now.Millisecond) - (t.Second * 1000 + t.Millisecond)) + " ms");
            #endif

            if (Settings.RenderSplatObjects)
            {
            #if PROFILE_RENDERER
                t = System.DateTime.Now;
            #endif
            #if PROFILES_RENDERER
                if (RenderSplatMapStart != null)
                    RenderSplatMapStart();
            #endif
                if (Settings.ShadowsEnable)
                    splatEffect.SetTexture(EHShadowTexture, shadowMap);

                splatEffect.SetValue(EHTextureSize, (1.0f / Settings.TextureSize));
                splatEffect.SetValue(EHCameraPosition, Scene.Camera.Position);

                if (!Scene.DesignMode)
                {
                    foreach (string technique in RenderRoot.SplatTechniques.Keys)
                    {
                        splatEffect.Technique = technique;

                        splatEffect.Begin(fx);
                        splatEffect.BeginPass(0);

                        foreach (SplatTextureCombination stc in RenderRoot.SplatTechniques[technique].TextureCombinations.Keys)
                        {
                            bool first = true;

                            foreach (Common.Tuple<Model9, Entity, string> ro in RenderRoot.SplatTechniques[technique].TextureCombinations[stc].RenderObjects)
                            {
                                if (ro.Second.ActiveInMain == Frame)
                                {
                                    MetaModel metaModel = GetLatestMetaModel(ro.Second, ro.Third);

                                    if (first)
                                    {
                                        splatEffect.SetTexture(EHSplatTexture1, stc.SplatTexture[0]);
                                        splatEffect.SetTexture(EHSplatTexture2, stc.SplatTexture[1]);

                                        splatEffect.SetTexture(EHBaseTexture, stc.BaseTexture);

                                        splatEffect.SetTexture(EHTerrainTexture1, stc.MaterialTexture[0]);
                                        splatEffect.SetTexture(EHTerrainTexture2, stc.MaterialTexture[1]);
                                        splatEffect.SetTexture(EHTerrainTexture3, stc.MaterialTexture[2]);
                                        splatEffect.SetTexture(EHTerrainTexture4, stc.MaterialTexture[3]);
                                        splatEffect.SetTexture(EHTerrainTexture5, stc.MaterialTexture[4]);
                                        splatEffect.SetTexture(EHTerrainTexture6, stc.MaterialTexture[5]);
                                        splatEffect.SetTexture(EHTerrainTexture7, stc.MaterialTexture[6]);
                                        splatEffect.SetTexture(EHTerrainTexture8, stc.MaterialTexture[7]);

                                        first = false;

                                        UpdateEffectWithMetaModel(splatEffect, metaModel, false);

                                        splatEffect.SetTexture(EHSpecularMap, ro.First.SpecularTexture);
                                    }

                                    Matrix world = metaModel.GetWorldMatrix(Scene.Camera, ro.Second);

                                    splatEffect.SetValue(EHWorldViewProjectionMatrix, world * ViewProjection);
                                    splatEffect.SetValue(EHWorldMatrix, world);
                                    splatEffect.SetValue(EHShadowWorldViewProjection, world * ShadowMapCamera);

                                    splatEffect.CommitChanges();

                                    ro.First.XMesh.DrawSubset(0);
                                }
                            }
                        }

                        splatEffect.EndPass();
                        splatEffect.End();
                    }
                }
                else
                {
                    string techniqueName = "";
                    if (RenderRoot.SplatObjects.Count > 0)
                        techniqueName = "Standard" + GetTechniqueNameExtension(
                            GetLatestMetaModel(RenderRoot.SplatObjects[0].Second, RenderRoot.SplatObjects[0].Third),
                            Settings, techniqueNames);

                    foreach (Common.Tuple<Model9, Entity, string> modelEntity in RenderRoot.SplatObjects)
                    {
                        RenderSplatmappedMesh(modelEntity, techniqueName, ViewProjection);
                    }

                    techniqueName = null;
                }

            #if PROFILE_RENDERER
                rendererProfileLogFile.WriteLine("Render Ground: " + ((System.DateTime.Now.Second * 1000 + System.DateTime.Now.Millisecond) - (t.Second * 1000 + t.Millisecond)) + " ms");
            #endif

            #if PROFILES_RENDERER
                if (RenderSplatMapStop != null)
                    RenderSplatMapStop();
            #endif
            }
            if (Settings.RenderAlphaObjects)
            {
            #if PROFILE_RENDERER
                t = System.DateTime.Now;
            #endif
            #if PROFILES_RENDERER
                if (RenderAlphaStart != null)
                    RenderAlphaStart();
            #endif
                //redundant
                StateManager.SetRenderState(RenderState.AlphaBlendEnable, true);
                StateManager.SetRenderState(RenderState.AlphaTestEnable, true);
                StateManager.SetRenderState(RenderState.AlphaFunc, Compare.GreaterEqual);
                StateManager.SetRenderState(RenderState.ZEnable, true);
                StateManager.SetRenderState(RenderState.ZWriteEnable, false);
                StateManager.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.None);
                StateManager.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear);
                StateManager.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear);
                StateManager.SetSamplerState(0, SamplerState.MaxAnisotropy, 1);

                // source = incoming pixel
                // destination = existing pixel
                // source.alpha * incoming_pixel + (1 - source.alpha) * exisiting_pixel

                StateManager.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
                StateManager.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);

                List<Common.Tuple<Model9, Entity, string, string>> overRidingZBuffer = new List<Common.Tuple<Model9, Entity, string, string>>();
                Common.PriorityQueue<int, Common.Tuple<Model9, Entity, string, string>> queue = new Common.PriorityQueue<int, Common.Tuple<Model9, Entity, string, string>>();

                foreach (Common.Tuple<Model9, Entity, string, string> e in RenderRoot.AlphaObjects)
                {
                    if (e.Second.ActiveInMain == Frame)
                    {
                        MetaModel metaModel = GetLatestMetaModel(e.Second, e.Third);
                        if (metaModel.OverrideZBuffer)
                            overRidingZBuffer.Add(e);
                        else
                        {
                            if (metaModel.DontSort)
                                queue.Enqueue(int.MinValue, e);
                            else if (metaModel.IsWater)
                                queue.Enqueue(int.MinValue + 1, e);
                            else
                            {
                                float distance = (e.Second.Translation - Scene.Camera.Position).Length();
                                queue.Enqueue(-(int)distance, e);
                            }
                        }
                    }
                }

                string previousTechnique = "";

                while (!queue.IsEmpty)
                {
                    Common.Tuple<Model9, Entity, string, string> modelEntity = queue.Dequeue();

                    MetaModel metaModel = GetLatestMetaModel(modelEntity.Second, modelEntity.Third);

                    //if (Settings.TerrainQualityPriorityRelation[Settings.TerrainQuality] + Settings.PriorityRelation[metaModel.Visible] < 3)
                    //    continue;

                    Matrix world = metaModel.GetWorldMatrix(Scene.Camera, modelEntity.Second);

                    if (metaModel.IsWater)
                    {
                        UpdateEffectWithMetaModel(waterEffect, metaModel, false);

                        string str = "NoSpecular";

                        if (settings.LightingQualityPriorityRelation[settings.LightingQuality] + settings.PriorityRelation[metaModel.ReceivesSpecular] > 3)
                            str = "Specular";

                        if (GraphicsDevice.SettingConverters.PixelShaderVersion.Major == 3)
                            str = "3" + str;
                        else
                            str = "2" + str;

                        waterEffect.Technique = "Water" + str;
                        waterOffest.X += dtime;
                        waterOffest.Y += dtime;

                        waterEffect.SetValue(EHWaterOffset, waterOffest);
                        waterEffect.SetValue(EHCamPos, scene.Camera.Position);
                        waterEffect.SetValue(EHSkyHeight, -50.0f);
                        waterEffect.SetValue(EHWorldViewProjectionMatrix, world * ViewProjection);
                        waterEffect.SetValue(EHWorldMatrix, world);
                        waterEffect.SetTexture(EHTexture, modelEntity.First.Texture);
                        waterEffect.SetValue(EHShadowWorldViewProjection, world * ShadowMapCamera);

                        if (modelEntity.First.SpecularTexture != null)
                            waterEffect.SetTexture(EHSpecularMap, modelEntity.First.SpecularTexture);

                        waterEffect.Begin(fx);
                        waterEffect.BeginPass(0);

                        modelEntity.First.XMesh.DrawSubset(0);

                        waterEffect.EndPass();
                        waterEffect.End();
                    }
                    else if (modelEntity.First.SkinnedMesh != null)
                    {
                        foreach (var SM in modelEntity.First.SkinnedMesh.MeshContainers)
                        {
                            if (SM.Second.SkinInfo != null)
                            {
                                skinnedMeshEffect.Technique = "SkinnedMesh" + GetTechniqueNameExtension(metaModel, Settings, techniqueNames);

                                UpdateEffectWithMetaModel(skinnedMeshEffect, metaModel, false);

                                skinnedMeshEffect.SetTexture(EHTexture, modelEntity.First.Texture);

                                if (modelEntity.First.SpecularTexture != null)
                                    skinnedMeshEffect.SetTexture(EHSpecularMap, modelEntity.First.SpecularTexture);

                                skinnedMeshEffect.Begin(fx);
                                skinnedMeshEffect.BeginPass(0);

                                RenderSkinnedMeshWithSkinning(SM, skinnedMeshEffect, false, metaModel.StoredFrameMatrices[SM.Second.MeshData.Mesh]);

                                skinnedMeshEffect.EndPass();
                                skinnedMeshEffect.End();
                            }
                            else if (SM.Second.SkinInfo == null)
                            {
                                if (modelEntity.Forth != previousTechnique)
                                {
                                    meshEffect.Technique = "ShadowedScene" + modelEntity.Forth;
                                    previousTechnique = modelEntity.Forth;
                                }
                                //meshEffect.Technique = "ShadowedScene" + GetTechniqueNameExtension(metaModel, Settings, techniqueNames);

                                UpdateEffectWithMetaModel(meshEffect, metaModel, false);

                                meshEffect.SetTexture(EHTexture, modelEntity.First.Texture);

                                if (modelEntity.First.SpecularTexture != null)
                                    meshEffect.SetTexture(EHSpecularMap, modelEntity.First.SpecularTexture);

                                meshEffect.Begin(fx);
                                meshEffect.BeginPass(0);

                                RenderSkinnedMeshWithoutSkinning(SM, meshEffect, false, ViewProjection, metaModel.StoredFrameMatrices[SM.Second.MeshData.Mesh]);

                                meshEffect.EndPass();
                                meshEffect.End();
                            }
                        }
                    }
                    else if (modelEntity.First.XMesh != null)
                    {
                        if (modelEntity.Forth != previousTechnique)
                        {
                            meshEffect.Technique = "ShadowedScene" + modelEntity.Forth;
                            previousTechnique = modelEntity.Forth;
                        }

                        meshEffect.SetValue(EHShadowWorldViewProjection, world * ShadowMapCamera);
                        meshEffect.SetValue(EHWorldViewProjectionMatrix, world * ViewProjection);
                        meshEffect.SetValue(EHWorldMatrix, world);

                        UpdateEffectWithMetaModel(meshEffect, metaModel, false);

                        meshEffect.SetTexture(EHTexture, modelEntity.First.Texture);

                        if (modelEntity.First.SpecularTexture != null)
                            meshEffect.SetTexture(EHSpecularMap, modelEntity.First.SpecularTexture);

                        meshEffect.Begin(fx);
                        meshEffect.BeginPass(0);

                        modelEntity.First.XMesh.DrawSubset(0);

                        meshEffect.EndPass();
                        meshEffect.End();
                    }
                }

                bool first = true;

                foreach (Common.Tuple<Model9, Entity, string, string> modelEntity in overRidingZBuffer)
                {
                    MetaModel metaModel = null;
                    Matrix world = Matrix.Identity;
                    if (first)
                    {
                        StateManager.SetRenderState(RenderState.ZEnable, false);
                        first = false;
                    }

                    metaModel = GetLatestMetaModel(modelEntity.Second, modelEntity.Third);
                    //if (Settings.TerrainQualityPriorityRelation[Settings.TerrainQuality] + Settings.PriorityRelation[metaModel.Visible] < 3)
                    //    continue;
                    world = metaModel.GetWorldMatrix(Scene.Camera, modelEntity.Second);

                    meshEffect.Technique = "ShadowedScene" + GetTechniqueNameExtension(metaModel, Settings, techniqueNames);

                    meshEffect.SetValue(EHShadowWorldViewProjection, world * ShadowMapCamera);
                    meshEffect.SetValue(EHWorldViewProjectionMatrix, world * ViewProjection);
                    //meshEffect.SetValue(EHNormalMatrix, Matrix.Transpose(Matrix.Invert(world)));
                    meshEffect.SetValue(EHWorldMatrix, world);

                    UpdateEffectWithMetaModel(meshEffect, metaModel, false);

                    meshEffect.SetTexture(EHTexture, modelEntity.First.Texture);

                    if (modelEntity.First.SpecularTexture != null)
                        meshEffect.SetTexture(EHSpecularMap, modelEntity.First.SpecularTexture);

                    meshEffect.Begin(fx);
                    meshEffect.BeginPass(0);

                    modelEntity.First.XMesh.DrawSubset(0);

                    meshEffect.EndPass();
                    meshEffect.End();
                }
            #if PROFILE_RENDERER
                rendererProfileLogFile.WriteLine("Render Alpha Objects: " + ((System.DateTime.Now.Second * 1000 + System.DateTime.Now.Millisecond) - (t.Second * 1000 + t.Millisecond)) + " ms");
            #endif
            #if PROFILES_RENDERER
                if (RenderAlphaStop != null)
                    RenderAlphaStop();
            #endif
            }

            //maybe reset all effect and device variables?

            //skinnedMeshEffect.SetTexture("ShadowMap", null);
            //effect.SetTexture("ShadowMap", null);
            //for (int i = 0; i < 7; i++)
            //    device.SetTexture(i, null);

            //Texture.ToFile(renderedImageTexture, "test.png", ImageFileFormat.Png);

            //var s = shadowMapBack;
            //shadowMapBack = shadowMap;
            //shadowMap = s;
            //lastShadowMapCamera = shadowMapCamera;

            //if (Settings.RenderWithPostEffect)
            //{
            //    // This offsets the post effect quad half a pixel, otherwise it will turn out blurry
            //    ((Software.Meshes.IndexedPlane)screenPlane.MeshDescription).Position =
            //        new Vector3(-1 - 1 / ((float)Scene.Viewport.Width), -1 - 1 / ((float)Scene.Viewport.Height), 0);

            //    var sp = Scene.View.Content.Peek<SlimDX.Direct3D9.Mesh>(screenPlane);

            //    device.EndScene();

            //    device.SetRenderTarget(0, screenRTSurface);
            //    device.DepthStencilSurface = null;

            //    device.Clear(ClearFlags.Target, Color.Black, 1.0f, 0);

            //    device.BeginScene();

            //    //device.DepthStencilSurface = null;
            //    //StateManager.SetRenderState(RenderState.ZEnable, false);
            //    StateManager.SetRenderState(RenderState.AlphaBlendEnable, false);
            //    StateManager.SetRenderState(RenderState.AlphaTestEnable, false);

            //    postEffect.Technique = "Standard";
            //    //Texture.ToFile(renderedImageTexture, "testRenderImage.png", ImageFileFormat.Png);
            //    postEffect.SetTexture(EHTexture, renderedImageTexture);
            //    postEffect.SetValue(EHAdditiveLightFactor, Settings.AdditiveLightColor);
            //    postEffect.SetValue(EHPercentageLightIncrease, Settings.PercentageLightIncrease);
            //    postEffect.SetValue(EHColorChannelPercentageIncrease, Settings.ColorChannelPercentageIncrease);

            //    postEffect.Begin(fx);
            //    postEffect.BeginPass(0);

            //    sp.DrawSubset(0);

            //    postEffect.EndPass();
            //    postEffect.End();

            //    device.DepthStencilSurface = depthBufferScreenSurface;
            //}

            #if RENDERER_STATISTICS
            rendererSatisticsLogFile.WriteLine("Min Instanced Draw Calls: " + minNumberOfInstancedDrawCalls);
            rendererSatisticsLogFile.WriteLine("Max Instanced Draw Calls: " + maxNumberOfInstancedDrawCalls);
            #endif

            #if LOG_RENDERTREE
            totalItemsTheoretically += totalAddedItems;
            totalItemsTheoretically -= totalRemovedItems;
            renderTreeLogFile.WriteLine("Total Items Added: " + totalAddedItems);
            renderTreeLogFile.WriteLine("Total Items Removed: " + totalRemovedItems);
            renderTreeLogFile.WriteLine("Total Items In Tree: " + GetNumberOfItemsInTree());
            renderTreeLogFile.WriteLine("Total Items In Tree Theoretical: " + totalItemsTheoretically);
            totalAddedItems = 0;
            totalRemovedItems = 0;
            #endif
        }
        public void PreRender(float dtime)
        {
            #if RENDERER_STATISTICS
            rendererSatisticsLogFile.WriteLine("==== Frame " + Frame + " ====");
            #endif

            #if LOG_RENDERTREE
            renderTreeLogFile.WriteLine("==== Frame " + Frame + " ====");
            #endif

            #if PROFILE_RENDERER
            rendererProfileLogFile.WriteLine("==== Frame " + Frame + " ====");
            #endif

            UpdateEffect(meshEffect);
            UpdateEffect(skinnedMeshEffect);
            UpdateEffect(splatEffect);
            UpdateEffect(waterEffect);

            if (shadowMapWidth != Settings.ShadowQualityRelation[Settings.ShadowQuality] || shadowsEnable != Settings.ShadowsEnable)
            {
                throw new NotSupportedException("Changing shadowquality is not available in-game");
                //ForceUpdateTree = true;
                //shadowsEnable = Settings.ShadowsEnable;

                //if (shadowsEnable)
                //{
                //    InitShadowBuffersAndMaps(device);
                //}
                //else
                //{
                //    DisableShadowBuffersAndMaps(device);
                //}
            }

            //if (scene.DesignMode || ForceUpdateTree)
            //{
            //    UpdateTree();
            //    ForceUpdateTree = false;
            //}

            if (shadowsEnable)
            {
            #if PROFILE_RENDERER
                var t = System.DateTime.Now;
            #endif
                shadowMapSurface = shadowMap.GetSurfaceLevel(0);
                device.SetRenderTarget(0, shadowMapSurface);
                device.DepthStencilSurface = depthBufferShadowMapSurface;
                device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.White, 1.0f, 0);
                device.BeginScene();

                //check redundant states
                StateManager.SetRenderState(RenderState.AlphaTestEnable, true);
                StateManager.SetRenderState(RenderState.AlphaFunc, Compare.GreaterEqual);
                StateManager.SetRenderState(RenderState.AlphaBlendEnable, false);
                StateManager.SetRenderState(RenderState.ZEnable, true);
                StateManager.SetRenderState(RenderState.ZWriteEnable, true);
                StateManager.SetRenderState(RenderState.MultisampleAntialias, false);

                meshEffect.Technique = "StandardShadowMap";

                meshEffect.Begin(fx);
                meshEffect.BeginPass(0);

                foreach (Common.Tuple<Model9, Entity, string> modelEntity in RenderRoot.SplatObjects)
                {
                    if (modelEntity.Second.ActiveInShadowMap == Frame)
                    {
                        MetaModel metaModel = GetLatestMetaModel(modelEntity.Second, modelEntity.Third);

                        if (Settings.PriorityRelation[metaModel.CastShadows] + Settings.ShadowQualityPriorityRelation[Settings.ShadowQuality] > 3)
                        {
                            UpdateEffectWithMetaModel(meshEffect, metaModel, true);
                            Matrix world = metaModel.GetWorldMatrix(Scene.Camera, modelEntity.Second);

                            meshEffect.SetValue(EHShadowWorldViewProjection, world * ShadowMapCamera);

                            meshEffect.CommitChanges();

                            if (modelEntity.First.XMesh != null)
                                modelEntity.First.XMesh.DrawSubset(0);
                        }
                    }
                }

                meshEffect.EndPass();
                meshEffect.End();

                //skinnedMeshEffect.Technique = "SkinnedMeshShadowMap";
                skinnedMeshEffect.SetValue(EHShadowViewProjection, ShadowMapCamera);

                foreach (string technique in RenderRoot.Techniques.Keys)
                {
                    RenderSkinnedMeshes(RenderRoot.Techniques[technique].SkinnedMeshes, skinnedMeshEffect, true, true, Matrix.Identity, "SkinnedMeshShadowMap");
                }

                //effect.Technique = "StandardShadowMap";

                meshEffect.SetValue(EHShadowViewProjection, ShadowMapCamera);
                meshEffect.Technique = "ShadowMapInstanced";
                meshEffect.Begin(fx);
                meshEffect.BeginPass(0);

                foreach (string technique in RenderRoot.Techniques.Keys)
                {
                    RenderXMeshesWithInstancingShadows(RenderRoot.Techniques[technique].Meshes, device);
                }

                meshEffect.EndPass();
                meshEffect.End();

                if (Settings.RenderAlphaObjects)
                {
                    //redundant states?
                    StateManager.SetRenderState(RenderState.AlphaTestEnable, true);
                    StateManager.SetRenderState(RenderState.AlphaFunc, Compare.GreaterEqual);
                    StateManager.SetRenderState(RenderState.AlphaBlendEnable, true);
                    StateManager.SetRenderState(RenderState.ZEnable, true);
                    StateManager.SetRenderState(RenderState.ZWriteEnable, false);

                    // source = incoming pixel
                    // destination = existing pixel
                    // source.alpha * incoming_pixel + (1 - source.alpha) * exisiting_pixel

                    StateManager.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha);
                    StateManager.SetRenderState(RenderState.DestinationBlend, Blend.InverseSourceAlpha);

                    // make private?
                    Common.PriorityQueue<int, Common.Tuple<Model9, Entity, string, string>> queue = new Common.PriorityQueue<int, Common.Tuple<Model9, Entity, string, string>>();

                    foreach (Common.Tuple<Model9, Entity, string, string> e in RenderRoot.AlphaObjects)
                    {
                        if (e.Second.ActiveInShadowMap == Frame)
                        {
                            float distance = (e.Second.Translation - Scene.Camera.Position).Length();
                            queue.Enqueue(-(int)distance, e);
                        }
                    }

                    while (!queue.IsEmpty)
                    {
                        Common.Tuple<Model9, Entity, string, string> modelEntity = queue.Dequeue();

                        MetaModel metaModel = GetLatestMetaModel(modelEntity.Second, modelEntity.Third);

                        if (Settings.PriorityRelation[metaModel.CastShadows] + Settings.ShadowQualityPriorityRelation[Settings.ShadowQuality] > 3)
                        {
                            Matrix world = metaModel.GetWorldMatrix(Scene.Camera, modelEntity.Second);

                            UpdateEffectWithMetaModel(meshEffect, metaModel, true);

                            if (modelEntity.First.SkinnedMesh != null)
                            {
                                UpdateEffectWithMetaModel(skinnedMeshEffect, metaModel, true);
                                foreach (var SM in modelEntity.First.SkinnedMesh.MeshContainers)
                                {
                                    if (SM.Second.SkinInfo != null)
                                    {
                                        skinnedMeshEffect.Begin(fx);
                                        skinnedMeshEffect.BeginPass(0);

                                        RenderSkinnedMeshWithSkinning(SM, skinnedMeshEffect, true, metaModel.StoredFrameMatrices[SM.Second.MeshData.Mesh]);

                                        skinnedMeshEffect.EndPass();
                                        skinnedMeshEffect.End();
                                    }
                                    else if (SM.Second.SkinInfo == null)
                                    {
                                        meshEffect.Technique = "StandardShadowMap";
                                        meshEffect.Begin(fx);
                                        meshEffect.BeginPass(0);

                                        RenderSkinnedMeshWithoutSkinning(SM, meshEffect, true, Matrix.Identity, metaModel.StoredFrameMatrices[SM.Second.MeshData.Mesh]);

                                        meshEffect.EndPass();
                                        meshEffect.End();
                                    }
                                }
                            }
                            else if (modelEntity.First.XMesh != null)
                            {
                                meshEffect.Technique = "StandardShadowMap";
                                meshEffect.SetValue(EHShadowWorldViewProjection, world * ShadowMapCamera);

                                meshEffect.Begin(fx);
                                meshEffect.BeginPass(0);

                                modelEntity.First.XMesh.DrawSubset(0);

                                meshEffect.EndPass();
                                meshEffect.End();
                            }
                        }
                    }
                }
                device.EndScene();
                //if (shadowMapSurface != null)
                //{
                //    shadowMapSurface.Dispose();
                //    shadowMapSurface = null;
                //}
            #if PROFILE_RENDERER
                rendererProfileLogFile.WriteLine("Render Shadowmap: " + ((System.DateTime.Now.Second * 1000 + System.DateTime.Now.Millisecond) - (t.Second * 1000 + t.Millisecond)) + " ms");
            #endif
            }

            //if (Settings.RenderWithPostEffect)
            //{
            //    renderedImage = renderedImageTexture.GetSurfaceLevel(0);
            //    device.SetRenderTarget(0, renderedImage);
            //    device.DepthStencilSurface = depthBuffForPost;
            //}
            //else
            //{
            device.SetRenderTarget(0, screenRTSurface);
            device.DepthStencilSurface = depthBufferScreenSurface;
            //}
        }