我在3d中使用如何使用鼠标在飞机上拾取点的平面

时间:2014-07-26 13:06:19

标签: c# opengl mouseevent opentk raycasting

在c#中使用Opentk绘制XY和Z的方格。 现在如何使用光线投射方法在网格上选取一个点。 如何在方块上获得与鼠标坐标相关的点。 任何帮助将不胜感激。

视口如下:

    private void SetupViewport()
    {
        int w = m_OpenTKGLControl_DrawingArea.Width;
        int h = m_OpenTKGLControl_DrawingArea.Height;

        // prevent divide by 0 error when minimised
        if (w == 0)
            h = 1;

        GL.Viewport(0, 0, w, h);
        GL.MatrixMode(MatrixMode.Projection);
        GL.LoadIdentity();
        perspectiveGL(45, (double)w / h, 0.1, 10000);
        GL.MatrixMode(MatrixMode.Modelview);
        GL.LoadIdentity();
    }

这是透视功能:

    // Replaces gluPerspective. Sets the frustum to perspective mode.
    // fovY     - Field of vision in degrees in the y direction
    // aspect   - Aspect ratio of the viewport
    // zNear    - The near clipping distance
    // zFar     - The far clipping distance
    void perspectiveGL(double fovY, double aspect, double zNear, double zFar)
    {
        const double pi = 3.1415926535897932384626433832795;
        double fW, fH;
        fH = System.Math.Tan((fovY / 2) / 180 * pi) * zNear;
        fH = System.Math.Tan(fovY / 360 * pi) * zNear;
        fW = fH * aspect;
        GL.Frustum(-fW, fW, -fH, fH, zNear, zFar);
    }

这是glcontrol的绘画功能

    private void m_OpenTKGLControl_DrawingArea_Paint(object sender, PaintEventArgs e)
    {
        if (!loaded) // Play nice
            return;

        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
        GL.LoadIdentity();

        GL.Translate(0, 0, -zoom);
        GL.Translate(tx, ty, 0);
        GL.Rotate(rotx, 1, 0, 0);
        GL.Rotate(roty, 0, 1, 0);


        //if (m_pointT_current_cursor.X < 100)
        {
            GL.PushMatrix(); //set where to start the current object transformations
            GL.Color3(1.0, 1.0, 0);
            GL.Begin(BeginMode.Lines);
            GL.Vertex3(0.0, 0.0, 0.0);
            GL.Vertex3(0.0, 0.0, 10.0);//x axis
            GL.End();
            GL.PopMatrix();
        }

        double grid_width = 10.0;


        // Draw a white grid "floor" for the tetrahedron to sit on.
        GL.Color3(Color.FromArgb(68, 68, 68));
        GL.Begin(BeginMode.Lines);

        for (double i = -grid_width / 2.0; i <= grid_width / 2.0; i += 1.0)
        {
            if (i != 0.0)
            {
                GL.Vertex3(i, 0.0, grid_width / 2.0); GL.Vertex3(i, 0.0, -grid_width / 2.0);
                GL.Vertex3(grid_width / 2.0, 0.0, i); GL.Vertex3(-grid_width / 2.0, 0.0, i);
            }
        }
        GL.End();

        GL.Color3(1.0, 0, 0);
        GL.Begin(BeginMode.Lines);
        GL.Vertex3(-grid_width / 2.0, 0, 0); GL.Vertex3(grid_width / 2.0, 0, 0);//x axis
        GL.End();

        GL.Color3(0, 1.0, 0);
        GL.Begin(BeginMode.Lines);
        GL.Vertex3(0, -grid_width / 2.0, 0); GL.Vertex3(0, grid_width / 2.0, 0);//y axis
        GL.End();

        GL.Color3(0, 0, 1.0);
        GL.Begin(BeginMode.Lines);
        GL.Vertex3(0, 0, -grid_width / 2.0); GL.Vertex3(0, 0, grid_width / 2.0);//z axis
        GL.End();

        GL.Begin(BeginMode.Points);        // Draw The Cube Using quads
        for (int i = 0; i < m_list_point_cloud.Count(); i++)
        {
            GL.Color3(Color.FromArgb(m_list_point_cloud[i].RED, m_list_point_cloud[i].GREEN, m_list_point_cloud[i].BLUE));    // Color
            GL.Vertex3(m_list_point_cloud[i].X, m_list_point_cloud[i].Y, m_list_point_cloud[i].Z);
            GL.PointSize(1);
        }
        GL.End();            // End Drawing The Point cloud

        GL.Flush();

        m_OpenTKGLControl_DrawingArea.SwapBuffers();
    }

最后这是glcontrol的加载函数

    private void m_OpenTKGLControl_DrawingArea_Load(object sender, EventArgs e)
    {
        loaded = true;
        GL.CullFace(CullFaceMode.Back);
        GL.ClearColor(Color.FromArgb(57, 57, 57));
        GL.ClearDepth(1.0); // Enables Clearing Of The Depth Buffer
        GL.DepthFunc(DepthFunction.Lequal); // The Type Of Depth Test To Do
        GL.Enable(EnableCap.DepthTest); // Enables Depth Testing
        GL.Enable(EnableCap.Multisample);
        GL.ShadeModel(ShadingModel.Smooth); // Enables Smooth Color Shading
        GL.Hint(HintTarget.PerspectiveCorrectionHint, // Really Nice Perspective Calculations
                HintMode.Nicest);

        SetupViewport();
    }

1 个答案:

答案 0 :(得分:0)

这是c中有一些变化的代码。 资料来源:{https://sites.google.com/site/vamsikrishnav/gluunproject}

#include <GL/glut.h>
#include <GL/glu.h>
#include <GL/gl.h>

#define HEIGHT 580
#define WIDTH 1000

double objx = 0, objy=0, objz=0;

/*THE FUNCTION TO DRAW THE STUFF ON THE SCREEN*/
void display( )
{
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

    glPushMatrix( );
    //glScalef(2.0f,2.0f,2.0f);
    glRotatef(90,1.0f,3.0f,2.0f); //rotating object continuously by 2 degree
    //The big green floor like polygon
    glBegin( GL_POLYGON );
    glColor3f( 0, 1, 0 );
    glVertex3f( -100, 0,  100  );
    glVertex3f( -100, 0, -100  );
    glVertex3f( 100,  0, -100 );
    glVertex3f( 100,  0, 100 );
    glEnd( );
    glPopMatrix( );

    //The red cube to be drawn at clicked position
    glPushMatrix( );
        glColor3f( 1, 0, 0 );
        glTranslatef( objx, objy, objz );
    glRotatef(90,1.0f,3.0f,2.0f); //rotating object continuously by 2 degree
        glutSolidTeapot( 10 );
    glPopMatrix( );

    glFlush( );
    glutSwapBuffers( );
}

void mouse( int button, int state, int x, int y)
{
    double modelview[16], projection[16];
    int viewport[4];
    float z = 1;

    /*Read the projection, modelview and viewport matrices
    using the glGet functions.*/
    glGetDoublev( GL_PROJECTION_MATRIX, projection );
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
    glGetIntegerv( GL_VIEWPORT, viewport );

    //Read the window z value from the z-buffer 
    glReadPixels( x, viewport[3]-y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z );   

    //Use the gluUnProject to get the world co-ordinates of
    //the point the user clicked and save in objx, objy, objz.
    gluUnProject( x, viewport[3]-y, z, modelview, projection, viewport, &objx, &objy, &objz );
}
void keyboard( unsigned char key, int x, int y )
{
}

void init( int width, int height )
{
        glViewport( 0, 0, width, height );
        glMatrixMode( GL_PROJECTION );
        glLoadIdentity( );
        gluPerspective( 45, 1.33, 0.1, 400 );
        glMatrixMode( GL_MODELVIEW );
        glLoadIdentity( );
        gluLookAt( 0, 100, 200, 0, 0, 0, 0, 1, 0 );
}

int main( int argc, char **argv )
{
        glutInit( &argc, argv );
        //The most important part specify the things your
        //glut window should provide
        glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
        glutInitWindowSize( 640, 480 );
        glutCreateWindow("HI");

        glClearColor( 0, 0, 0, 0 );
        //enable z buffer
        glEnable( GL_DEPTH_TEST );
        //set the value in z-buffer as 1.0
        glClearDepth( 1.0 );
        init( 640, 480 );
        glutDisplayFunc( display );
        glutReshapeFunc( init );
        glutIdleFunc( display );
        glutMouseFunc( mouse );
        glutKeyboardFunc( keyboard );
        glutMainLoop( );
}