2014-09-05 15 views
5

Tôi đang triển khai biểu đồ 2D trong WPF bằng thư viện SharpGL. Tôi đã quản lý để vẽ một số đối tượng nguyên thủy trên màn hình và tôi cần phải phát hiện nhấp chuột vào các đối tượng này.SharpGL- Phát hiện nhấp chuột trên các yếu tố OpenGL Sử dụng lựa chọn và chọn

Tôi đã xem xét hướng dẫn OpenGL về cách thực hiện lựa chọn và chọn đối tượng đồ họa, nhưng tôi không quản lý để làm cho nó hoạt động. Trong ứng dụng thử nghiệm của tôi, tôi vẽ ba hình tam giác trên màn hình và khi nhấp chuột xảy ra, tôi vẽ ba tam giác giống nhau ở chế độ GL_SELECT với hy vọng phát hiện xem có bất kỳ hình tam giác nào đã được nhấp vào hay không. Tôi không chắc đây có phải là cách tiếp cận chính xác hay không. Kiểm tra lần truy cập luôn trả về tất cả các phần tử từ bộ đệm chọn.

Tôi biết rằng các tham số chiều rộng và chiều cao trong PickMatrix không chính xác và tôi không thực sự chắc chắn giá trị chính xác sẽ là gì. Có chiều rộng và chiều cao của toàn bộ khung nhìn không?

private void OpenGLControl_OpenGLDraw(object sender, SharpGL.SceneGraph.OpenGLEventArgs args) 
{ 
    //// Get the OpenGL object. 
    OpenGL gl = args.OpenGL; 

    //set background to white 
    gl.ClearColor(1.0f, 1.0f, 1.0f, 1.0f); 

    //// Clear the color and depth buffer. 
    gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); 
    DrawScene(); 
    gl.Flush(); 
} 

private void DrawScene() 
{ 
    OpenGL gl = openGLControl.OpenGL; 
    gl.Color(1.0, 0.0, 0.0); 
    DrawTriangle(-0.2, 0.6, 0.0, 0.8, 0.2, 0.6); 

    gl.Color(0.0, 1.0, 0.0); 
    DrawTriangle(-0.2, 0.2, 0.0, 0.4, 0.2, 0.2); 

    gl.Color(0.0, 0.0, 1.0); 
    DrawTriangle(-0.2, -0.2, 0.0, 0.0, 0.2, -0.2); 
} 

private void SelectObjects(double mouseDownX, double mouseDownY) 
{ 
    OpenGL gl = openGLControl.OpenGL; 
    int BUFSIZE = 512; 

    uint[] selectBuf = new uint[BUFSIZE]; 

    gl.SelectBuffer(BUFSIZE, selectBuf); 
    gl.RenderMode(OpenGL.GL_SELECT); 

    gl.InitNames(); 
    gl.PushName(0); 

    int[] viewport = new int[4]; 
    gl.GetInteger(OpenGL.GL_VIEWPORT, viewport); 

    //how to define the width and height of an element? 
    gl.PickMatrix(mouseDownX, (double)(viewport[3] - mouseDownY), 50.0, 50.0, viewport); 

    gl.LoadIdentity(); 

    gl.LoadName(1); 
    gl.Color(1.0, 0.0, 0.0); 
    DrawTriangle(-0.2, 0.6, 0.0, 0.8, 0.2, 0.6); 

    gl.LoadName(2); 
    gl.Color(0.0, 1.0, 0.0); 
    DrawTriangle(-0.2, 0.2, 0.0, 0.4, 0.2, 0.2); 

    gl.LoadName(3); 
    gl.Color(0.0, 0.0, 1.0); 
    DrawTriangle(-0.2, -0.2, 0.0, 0.0, 0.2, -0.2); 

    gl.Flush(); 
    int hits = gl.RenderMode(OpenGL.GL_RENDER); 
    processHits(hits, selectBuf); 
} 

private void processHits(int hits, uint[] buffer) 
{ 
    uint bufferIterator = 0; 
    for (uint i = 0; i < hits; i++) 
    { 
     uint numberOfNamesInHit = buffer[bufferIterator]; 
     Console.WriteLine("hit: " + i + " number of names in hit " + numberOfNamesInHit); 

     uint lastNameIndex = bufferIterator + 2 + numberOfNamesInHit; 
     for (uint j = bufferIterator + 3; j <= lastNameIndex; j++) 
     { 
      Console.WriteLine("Name is " + buffer[j]); 
     } 

     bufferIterator = bufferIterator + numberOfNamesInHit + 3; 
    } 
} 

private void OnMouseClick(object sender, MouseEventArgs e) 
{ 
    System.Windows.Point position = e.GetPosition(this); 
    SelectObjects(position.X, position.Y); 
} 

Sản lượng luôn luôn là như nhau:

hit: 0 số tên trong hit 1

Tên là 1

hit: Số 1 tên trong hit 1

Tên là 2

h nó: 2 số tên trong hit 1

Tên là 3

Trả lời

3

chiều rộng và chiều cao là kích thước của vùng chọn bằng pixel. Để phát hiện đối tượng dưới con trỏ chuột, 1x1 sẽ ổn (bạn muốn phát hiện những gì nằm dưới một hình chữ nhật màn hình 1 pixel x 1 pixel).

gluPickMatrix cập nhật (nhân) ma trận hiện tại với ma trận chọn. PickMatrix của bạn theo sau bởi LoadIdentity không có bất kỳ ý nghĩa nào, vì glLoadIdentity đặt lại ma trận hiện tại thành danh tính.

Đối với mẫu của bạn để làm việc, trước khi render, thiết lập ma trận của bạn:

glLoadIdentity(); 
setupMyProjMatrix(); 

Trước khi lựa chọn, thiết lập ma trận tương tự, trước nhân với ma trận lựa chọn:

glLoadIdentity(); 
glPickMatrix(); 
setupMyProjMatrix(); 

Trong mẫu của bạn , setupMyProjMatrix() không làm gì cả.

Dù sao, bạn nên tránh sử dụng chọn trong opengl. Đó là một tính năng không được chấp nhận, (bị xóa trong hiện đại gl), khủng khiếp chậm, và đôi khi không phải là rất đáng tin cậy, tùy thuộc vào nhà cung cấp. Bạn nên tự tính toán thử nghiệm lần truy cập.

Bạn sẽ không bao giờ, đừng bao giờ truy vấn bất kỳ thứ gì gl (glGet family). Nó kích thích gian hàng CPU.

Xin lỗi vì tiếng Anh không tốt.

+0

Cảm ơn bạn đã giải thích, tôi đã xóa dòng glLoadIdentitiy và nó hoạt động tốt :) – mobearette

2

Như Olivier đã nói, hãy tránh xa chức năng không dùng nữa.Thay vào đó bạn có thể làm chọn theo 2 cách khác nhau:

  • Pick bằng cách chạy tất cả các đa giác ở mặt trước thông qua một tia-kiểm tra, nơi bạn khởi động một tia từ mắt điểm qua trung tâm của một điểm ảnh (ở gần khoảng cách -plane) cho đến khi nó chạm vào một đa giác hoặc nằm ngoài phạm vi lựa chọn. Giải pháp này không quy mô tốt cho các cảnh phức tạp, nhưng nó khá tầm thường để thực hiện và cung cấp mức độ linh hoạt để xử lý độ trong suốt, vv ..

  • Bạn cũng có thể chọn trong không gian xem bằng cách hiển thị tất cả các đối tượng với một màu-id cho một kết cấu ngoài màn hình. Sau đó, bạn có thể đọc giá trị pixel của việc chọn tọa độ 2D và ánh xạ id màu trở lại đối tượng theo tọa độ lựa chọn đó. Nhược điểm ở đây là việc chọn nhiều đối tượng là khó hơn, và rằng lô được trả lại phải có các thiết lập chọn lọc và đổ bóng thích hợp. Nhược điểm là giải pháp này phụ thuộc vào độ phân giải và không phụ thuộc nhiều vào cảnh phức tạp.

Các vấn đề liên quan