OpenTK" Picking"不按预期工作

时间:2014-09-15 23:24:08

标签: c# opengl mouse opentk mouse-picking

我试图在我的游戏中实施挑选,并且我确定我遗漏了一些东西,因为挑选的颜色总是返回255,255,255,255或255,0,0,0。这两种颜色似乎是随机发生的,甚至在我多次点击同一个块时也会发生变化。我不知道自己做错了什么,但我真的希望stackoverflow的众神可以帮助我找到解决方案。

这是一张演示输出的图片: enter image description here

这是我的GameClient类: (我为凌乱的代码道歉,我还没有时间组织它)

using System.Drawing;
using GameProject.Game.Framework.DataStructure;
using GameProject.Game.Framework.Generators;
using GameProject.Game.Framework.Geometry;
using System.Diagnostics;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
using GameProject.Game.Client.Widgets;
using QuickFont;

namespace GameProject.Game.Client {
    public class GameClient : GameWindow {

        /**
         * Client Variables
         */
        public const String CLIENT_VERSION = "v0.0.1";
        public const String GAME_NAME = "Voxelbyte";
        public FirstPersonCameraWidget GameCamera;
        private Point _mousePosition;
        private Point _lastMousePosition;
        private bool _centerCursorAfterRelease = false;
        private int _totalVoxelsRenderered;
        private bool _isWireframe = false;
        private Random ClientRandomInstance;
        /**
         * Game Variables
         */
        public VoxelWorld World;
        public uint SelectedVoxelIndex;
        public QFont DeveloperText;
        public TessellatorWidget Tesssellator;

        public GameClient()
            : base( 800 , 600 , GraphicsMode.Default , GAME_NAME ) {
            GL.Enable( EnableCap.DepthTest );
            GL.ClearColor( 0.3f , 0.3f , 0.3f , 0.0f );
        }

        protected override void OnUnload( EventArgs e ) {
            base.OnUnload( e );
            foreach( Voxel voxel in World.VisibleVoxels ) {
                GL.DeleteQueries( 1 , ref voxel.OcclusionID );
            }
        }

        protected override void OnLoad( EventArgs e ) {
            base.OnLoad( e );
            ClientRandomInstance = new Random();
            Tesssellator = new TessellatorWidget();
            DeveloperText = new QFont( "Resources/Fonts/times.ttf" , 14 , FontStyle.Regular );
            GameCamera = new FirstPersonCameraWidget(
                new Vector3( 30.0f , 8.0f , 30.0f ) ,
                0.0f ,
                0.0f ,
                15.0f ,
                0.4f );
            GL.CullFace( CullFaceMode.Back );
            GL.Enable( EnableCap.CullFace );
            World = BattleWorldReader.ReadFromImage(
                WorldGenerator.GenerateRandomWorld( new Size( 50 , 50 ) , 8 , "Sharon Rose Day" ) );
            Stopwatch sw = new Stopwatch();
            sw.Start();
            World.Rebuild();
            sw.Stop();
            Console.WriteLine( "World Generation+Optimization took: {0}ms" , sw.ElapsedMilliseconds );
        }

        protected override void OnMouseMove( MouseMoveEventArgs e ) {
            base.OnMouseMove( e );
            _mousePosition = new Point( e.X , e.Y );
            if( e.Mouse.IsButtonDown( MouseButton.Right ) ) {

            }
        }

        protected override void OnMouseDown( MouseButtonEventArgs e ) {
            base.OnMouseDown( e );
            if( e.Mouse.IsButtonDown( MouseButton.Left ) ) {
                /**
                 * Implement Mouse Picking!
                 * This is your next objective!
                 */
                PickGeometry( e.X , e.Y );
            }
            if( e.Mouse.IsButtonDown( MouseButton.Right ) ) {
                Point nativeMouse = System.Windows.Forms.Cursor.Position;
                _lastMousePosition = nativeMouse;
                Point windowCenter = new Point( Bounds.Left + Bounds.Width / 2 , Bounds.Top + Bounds.Height / 2 );
                System.Windows.Forms.Cursor.Position = windowCenter;
                GameCamera.IsLooking = true;
                this.CursorVisible = false;
            }
        }

        private void PickGeometry( int x , int y ) {
            Console.WriteLine( "Picking..." );
            /**
             * Draw The Geometry As solid
             * colors
             */
            GL.ClearColor( 1.0f , 1.0f , 1.0f , 1.0f );
            GL.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit );
            GL.DisableClientState( ArrayCap.TextureCoordArray );
            GL.EnableClientState( ArrayCap.ColorArray );
            GL.Disable( EnableCap.Texture2D );
            GameCamera.LookThrough( this , _mousePosition , null ); // Pretty sure I need this
            foreach( Voxel voxel in World.VisibleVoxels ) {
                voxel.IsSelected = false;
                if( GameCamera.Frustum.SphereInFrustum( voxel.Location , 1.8f ) ) {
                    // Lazy generation of random colors; I will improve this later.
                    byte red = ( byte )ClientRandomInstance.Next( 256 );
                    byte green = ( byte )ClientRandomInstance.Next( 256 );
                    byte blue = ( byte )ClientRandomInstance.Next( 256 );
                    voxel.RenderAsColor( red , green , blue );
                }
            }
            /**
             * Get the color of the pixel beneath the mouse cursor
             * 
             * THIS ALWAYS RETURNS 255,255,255,255 FOR SOME REASON
             * 
             */
            byte[] pixel = new byte[ 3 ];
            int[] viewport = new int[ 4 ];
            GL.GetInteger( GetPName.Viewport , viewport );
            GL.ReadPixels( x , viewport[ 2 ] - y , 1 , 1 , PixelFormat.Rgba , PixelType.UnsignedByte , pixel );
            // This color below is always 255,255,255,255 and I don't know why!
            Color pickedColor = Color.FromArgb( pixel[ 0 ] , pixel[ 1 ] , pixel[ 2 ] );
            Console.WriteLine( pickedColor.ToString() );
            Console.WriteLine( "Picking Done" );
        }

        protected override void OnMouseUp( MouseButtonEventArgs e ) {
            base.OnMouseUp( e );
            if( e.Button == MouseButton.Right ) {
                GameCamera.IsLooking = false;
                if( !_centerCursorAfterRelease ) {
                    System.Windows.Forms.Cursor.Position = _lastMousePosition;
                }
                this.CursorVisible = true;
            }
        }

        protected override void OnKeyDown( KeyboardKeyEventArgs e ) {
            base.OnKeyDown( e );
            if( e.Key == Key.F1 ) {
                _isWireframe = !_isWireframe;
            }
        }

        protected override void OnRenderFrame( FrameEventArgs e ) {
            base.OnRenderFrame( e );

            /**
             * Pass 1
             * Normal Rendering
             */
            GL.MatrixMode( MatrixMode.Modelview );
            GL.ClearColor( 0.3f , 0.3f , 0.3f , 1.0f );
            GL.Clear( ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit );
            GL.Enable(EnableCap.Texture2D);
            GL.EnableClientState( ArrayCap.VertexArray );
            GL.EnableClientState( ArrayCap.TextureCoordArray );
            GL.DisableClientState( ArrayCap.ColorArray );
            GameCamera.LookThrough( this , _mousePosition , e );
            foreach( Voxel voxel in World.VisibleVoxels ) {
                if( GameCamera.Frustum.SphereInFrustum( voxel.Location.X , voxel.Location.Y , voxel.Location.Z , 1.8f ) ) {
                    Tesssellator.TessellateUnseenFaces( ref GameCamera , voxel );
                    voxel.Render( GameCamera );
                }
            }
            GL.DisableClientState( ArrayCap.VertexArray );
            GL.DisableClientState( ArrayCap.TextureCoordArray );
            GL.DisableClientState( ArrayCap.ColorArray );
            //RenderDeveloperHud();
            SwapBuffers();
            this.Title = GAME_NAME + " FPS: " + ( int )this.RenderFrequency;
        }

        private void RenderDeveloperHud() {
            QFont.Begin();
            GL.PushMatrix();
            GL.Translate( 0.0f , 5 , 0f );
            DeveloperText.Print( "Voxelbyte" );
            GL.Translate( 0f , 30 , 0f );
            DeveloperText.Print( "X: " + ( int )GameCamera.Location.X );
            GL.Translate( 0f , 24 , 0f );
            DeveloperText.Print( "Y: " + ( int )GameCamera.Location.Y );
            GL.Translate( 0.0f , 24 , 0f );
            DeveloperText.Print( "Z: " + ( int )GameCamera.Location.Z );
            GL.Translate( 0.0f , 24 , 0f );
            DeveloperText.Print( "VIF: " + _totalVoxelsRenderered );
            GL.PopMatrix();
            QFont.End();
        }

        private void CheckKeyboardInput( FrameEventArgs eventArgs ) {
            KeyboardState keyboardState = OpenTK.Input.Keyboard.GetState();
            GameCamera.ProcessMovement( keyboardState , eventArgs );
            if( keyboardState[ Key.Escape ] ) {
                Exit();
            }
        }

        protected override void OnUpdateFrame( FrameEventArgs e ) {
            CheckKeyboardInput( e );
        }

        protected override void OnResize( EventArgs e ) {
            base.OnResize( e );
            GL.Viewport(
                ClientRectangle.X , ClientRectangle.Y , ClientRectangle.Width , ClientRectangle.Height );
            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
                ( float )Math.PI / 4 , ( float )Width / ( float )Height , 0.1f , 1000.0f );
            GL.MatrixMode( MatrixMode.Projection );
            GL.LoadMatrix( ref projection );
        }
    }
}

1 个答案:

答案 0 :(得分:1)

我觉得自己很蠢;像大多数 - 如果不是全部巨大的搞砸,这是由一行代码引起的:

GL.EnableClientState(ArrayCap.VertexArray);

忘记将所有几何图形绘制为纯色之前将其抛入代码中。