/// <summary>
        /// <see cref="ISceneRenderer.Render"/>
        /// </summary>
        public void Render(ICameraController cam, Dictionary <Node, List <Mesh> > visibleMeshesByNode,
                           bool visibleSetChanged,
                           bool texturesChanged,
                           RenderFlags flags,
                           Renderer renderer)
        {
            GL.Disable(EnableCap.Texture2D);
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
            GL.Enable(EnableCap.DepthTest);

            if (flags.HasFlag(RenderFlags.Wireframe))
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
            }
            var tmp = InitposeMax.X - InitposeMin.X;

            tmp = Math.Max(InitposeMax.Y - InitposeMin.Y, tmp);
            tmp = Math.Max(InitposeMax.Z - InitposeMin.Z, tmp);
            int   logScale = (int)Math.Truncate(Math.Log10(tmp * 10 / 50)); //  Up to 50units max size = 50m: keep scale (for smaller scenes).
            float scale    = 1;

            for (int i = 0; i < logScale; i++)
            {
                scale = scale / 10;
            }
            Owner.Scale = scale;
            if (cam != null)
            {
                //       cam.SetPivot(Owner.Pivot * (float)scale); this does nothing (?) only makes controller dirty
            }
            var view = cam == null?Matrix4.LookAt(0, 10, 5, 0, 0, 0, 0, 1, 0) : cam.GetView();

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref view);
            GL.Scale(scale, scale, scale);
            Owner.MaterialMapper.BeginScene(renderer, flags.HasFlag(RenderFlags.UseSceneLights)); //here we switch on lights

            if (flags.HasFlag(RenderFlags.ShowLightDirection))                                    //switch off for video??
            {
                var dir = new Vector3(1, 1, 0);
                var mat = renderer.LightRotation;
                Vector3.TransformNormal(ref dir, ref mat, out dir);
                OverlayLightSource.DrawLightSource(dir);
            }

            // If textures changed, we may need to upload some of them to VRAM.
            // it is important this happens here and not accidentially while
            // compiling a displist.
            if (texturesChanged)
            {
                UploadTextures();
            }
            UploadDynamicTextures();

            GL.PushMatrix();

            // Build and cache Gl displaylists and update only when the scene changes.
            // when the scene is being animated, this changes each frame
            var animated = Owner.SceneAnimator.IsAnimationActive;

            if (visibleSetChanged || texturesChanged || flags != _lastFlags || (animated && (Owner.NewFrame) || wasAnimated))
            {
                int startList = 4; //we update only 4 animation displists
                if (visibleSetChanged || texturesChanged || flags != _lastFlags)
                {
                    startList = 0;
                }
                _lastFlags = flags;

                // handle opaque geometry
                for (int currDispList = startList; currDispList < _displayListCount; currDispList++)
                {
                    if (_displayList[currDispList, 0] == 0)
                    {
                        _displayList[currDispList, 0] = GL.GenLists(1);
                    }
                    GL.NewList(_displayList[currDispList, 0], ListMode.Compile);
                    var needAlpha = RecursiveRender(Owner.Raw.RootNode, visibleMeshesByNode, flags, animated, currDispList);
                    if (flags.HasFlag(RenderFlags.ShowSkeleton))
                    {
                        RecursiveRenderNoScale(Owner.Raw.RootNode, visibleMeshesByNode, flags, 1.0f / scale, animated, currDispList);
                    }
                    if (flags.HasFlag(RenderFlags.ShowNormals))
                    {
                        RecursiveRenderNormals(Owner.Raw.RootNode, visibleMeshesByNode, flags, 1.0f / scale, animated, Matrix4.Identity, currDispList);
                    }
                    GL.EndList();
                    if (needAlpha)
                    {
                        // handle semi-transparent geometry
                        if (_displayList[currDispList, 1] == 0)
                        {
                            _displayList[currDispList, 1] = GL.GenLists(1);
                        }
                        GL.NewList(_displayList[currDispList, 1], ListMode.Compile);
                        RecursiveRenderWithAlpha(Owner.Raw.RootNode, visibleMeshesByNode, flags, animated, currDispList);
                        GL.EndList();
                    }
                    else if (_displayList[currDispList, 1] != 0)
                    {
                        GL.DeleteLists(_displayList[currDispList, 1], 1);
                        _displayList[currDispList, 1] = 0;
                    }
                }
            }

            Owner.NewFrame = false;
            wasAnimated    = animated;

            /* display lists:
             * 0: Background;
             * 1: Else (always visible);
             * 2: Foreground;
             * 3: GreenScreen;
             * 4: BackgroundAnimated;
             * 5: ElseAnimated (always visible);
             * 6: ForegroundAnimated;
             * 7: GreenScreenAnimated;
             * Animated - list is refreshed each frame
             */
            switch (cam.GetScenePartMode())
            {
            case ScenePartMode.Background:
                if (_displayList[0, 0] != 0)
                {
                    GL.CallList(_displayList[0, 0]);
                }
                if (_displayList[4, 0] != 0)
                {
                    GL.CallList(_displayList[4, 0]);
                }
                if (_displayList[0, 1] != 0)
                {
                    GL.CallList(_displayList[0, 1]);
                }
                if (_displayList[4, 1] != 0)
                {
                    GL.CallList(_displayList[4, 1]);
                }
                break;

            case ScenePartMode.Foreground:
                if (_displayList[2, 0] != 0)
                {
                    GL.CallList(_displayList[2, 0]);
                }
                if (_displayList[6, 0] != 0)
                {
                    GL.CallList(_displayList[6, 0]);
                }
                if (_displayList[2, 1] != 0)
                {
                    GL.CallList(_displayList[2, 1]);
                }
                if (_displayList[6, 1] != 0)
                {
                    GL.CallList(_displayList[6, 1]);
                }
                break;

            case ScenePartMode.Others:
                if (_displayList[1, 0] != 0)
                {
                    GL.CallList(_displayList[1, 0]);
                }
                if (_displayList[5, 0] != 0)
                {
                    GL.CallList(_displayList[5, 0]);
                }
                if (_displayList[1, 1] != 0)
                {
                    GL.CallList(_displayList[1, 1]);
                }
                if (_displayList[5, 1] != 0)
                {
                    GL.CallList(_displayList[5, 1]);
                }
                break;

            case ScenePartMode.GreenScreen:
                if (_displayList[3, 0] != 0)
                {
                    GL.CallList(_displayList[3, 0]);
                }
                if (_displayList[7, 0] != 0)
                {
                    GL.CallList(_displayList[7, 0]);
                }
                if (_displayList[3, 1] != 0)
                {
                    GL.CallList(_displayList[3, 1]);
                }
                if (_displayList[7, 1] != 0)
                {
                    GL.CallList(_displayList[7, 1]);
                }
                break;

            case ScenePartMode.All:
                for (int currDispList = 0; currDispList < _displayListCount; currDispList++)
                {
                    if (_displayList[currDispList, 0] != 0)
                    {
                        GL.CallList(_displayList[currDispList, 0]);
                    }
                    if (_displayList[currDispList, 1] != 0)
                    {
                        GL.CallList(_displayList[currDispList, 1]);
                    }
                }
                break;

            default: break;    //at other modes we do not render anything
            }

            GL.PopMatrix();
            // always switch back to FILL
            Owner.MaterialMapper.EndScene(renderer);
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.Disable(EnableCap.DepthTest);

#if TEST
            GL.Enable(EnableCap.ColorMaterial);


            // TEST CODE to visualize mid point (pivot) and origin
            GL.LoadMatrix(ref view);
            GL.Begin(BeginMode.Lines);

            GL.Vertex3((InitposeMin + InitposeMax) * 0.5f * (float)scale);
            GL.Color3(0.0f, 1.0f, 0.0f);
            GL.Vertex3(0, 0, 0);
            GL.Color3(0.0f, 1.0f, 0.0f);
            GL.Vertex3((InitposeMin + InitposeMax) * 0.5f * (float)scale);
            GL.Color3(0.0f, 1.0f, 0.0f);

            GL.Vertex3(10, 10, 10);
            GL.Color3(0.0f, 1.0f, 0.0f);
            GL.End();
#endif
            GL.Disable(EnableCap.Texture2D);
        }
Example #2
0
        /// <summary>
        /// <see cref="ISceneRenderer.Render"/>
        /// </summary>
        public void Render(ICameraController cam, Dictionary <Node, List <Mesh> > visibleMeshesByNode,
                           bool visibleSetChanged,
                           bool texturesChanged,
                           RenderFlags flags,
                           Renderer renderer)
        {
            GL.Disable(EnableCap.Texture2D);
            GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
            GL.Enable(EnableCap.DepthTest);

            // set fixed-function lighting parameters
            GL.ShadeModel(ShadingModel.Smooth);
            GL.LightModel(LightModelParameter.LightModelAmbient, new[] { 0.3f, 0.3f, 0.3f, 1 });
            GL.Enable(EnableCap.Lighting);
            GL.Enable(EnableCap.Light0);


            if (flags.HasFlag(RenderFlags.Wireframe))
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
            }

            var tmp = InitposeMax.X - InitposeMin.X;

            tmp = Math.Max(InitposeMax.Y - InitposeMin.Y, tmp);
            tmp = Math.Max(InitposeMax.Z - InitposeMin.Z, tmp);
            var scale = 2.0f / tmp;

            // TODO: migrate general scale and this snippet to camcontroller code
            if (cam != null)
            {
                cam.SetPivot(Owner.Pivot * (float)scale);
            }
            var view = cam == null?Matrix4.LookAt(0, 10, 5, 0, 0, 0, 0, 1, 0) : cam.GetView();

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref view);

            // light direction
            var dir = new Vector3(1, 1, 0);
            var mat = renderer.LightRotation;

            Vector3.TransformNormal(ref dir, ref mat, out dir);
            GL.Light(LightName.Light0, LightParameter.Position, new float[] { dir.X, dir.Y, dir.Z, 0 });

            // light color
            var col = new Vector3(1, 1, 1);

            col *= (0.25f + 1.5f * GraphicsSettings.Default.OutputBrightness / 100.0f) * 1.5f;

            GL.Light(LightName.Light0, LightParameter.Diffuse, new float[] { col.X, col.Y, col.Z, 1 });
            GL.Light(LightName.Light0, LightParameter.Specular, new float[] { col.X, col.Y, col.Z, 1 });

            if (flags.HasFlag(RenderFlags.Shaded))
            {
                OverlayLightSource.DrawLightSource(dir);
            }


            GL.Scale(scale, scale, scale);


            // If textures changed, we may need to upload some of them to VRAM.
            // it is important this happens here and not accidentially while
            // compiling a displist.
            if (texturesChanged)
            {
                UploadTextures();
            }

            GL.PushMatrix();

            // Build and cache Gl displaylists and update only when the scene changes.
            // when the scene is being animated, this is bad because it changes every
            // frame anyway. In this case  we don't use a displist.
            var animated = Owner.SceneAnimator.IsAnimationActive;

            if (_displayList == 0 || visibleSetChanged || texturesChanged || flags != _lastFlags || animated)
            {
                _lastFlags = flags;

                // handle opaque geometry
                if (!animated)
                {
                    if (_displayList == 0)
                    {
                        _displayList = GL.GenLists(1);
                    }

                    GL.NewList(_displayList, ListMode.Compile);
                }

                var needAlpha = RecursiveRender(Owner.Raw.RootNode, visibleMeshesByNode, flags, animated);

                if (flags.HasFlag(RenderFlags.ShowSkeleton) || flags.HasFlag(RenderFlags.ShowNormals))
                {
                    RecursiveRenderNoScale(Owner.Raw.RootNode, visibleMeshesByNode, flags, 1.0f / scale, animated);
                }

                if (!animated)
                {
                    GL.EndList();
                }

                if (needAlpha)
                {
                    // handle semi-transparent geometry
                    if (!animated)
                    {
                        if (_displayListAlpha == 0)
                        {
                            _displayListAlpha = GL.GenLists(1);
                        }
                        GL.NewList(_displayListAlpha, ListMode.Compile);
                    }
                    RecursiveRenderWithAlpha(Owner.Raw.RootNode, visibleMeshesByNode, flags, animated);

                    if (!animated)
                    {
                        GL.EndList();
                    }
                }
                else if (_displayListAlpha != 0)
                {
                    GL.DeleteLists(_displayListAlpha, 1);
                    _displayListAlpha = 0;
                }
            }

            if (!animated)
            {
                GL.CallList(_displayList);
                if (_displayListAlpha != 0)
                {
                    GL.CallList(_displayListAlpha);
                }
            }

            GL.PopMatrix();

            // always switch back to FILL
            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.Disable(EnableCap.DepthTest);

#if TEST
            GL.Enable(EnableCap.ColorMaterial);


            // TEST CODE to visualize mid point (pivot) and origin
            GL.LoadMatrix(ref view);
            GL.Begin(BeginMode.Lines);

            GL.Vertex3((InitposeMin + InitposeMax) * 0.5f * (float)scale);
            GL.Color3(0.0f, 1.0f, 0.0f);
            GL.Vertex3(0, 0, 0);
            GL.Color3(0.0f, 1.0f, 0.0f);
            GL.Vertex3((InitposeMin + InitposeMax) * 0.5f * (float)scale);
            GL.Color3(0.0f, 1.0f, 0.0f);

            GL.Vertex3(10, 10, 10);
            GL.Color3(0.0f, 1.0f, 0.0f);
            GL.End();
#endif

            GL.Disable(EnableCap.Texture2D);
            GL.Disable(EnableCap.Lighting);
        }