Xoay camera 3D


9

Xin vui lòng, tha thứ cho tôi, nhưng tôi cần sự giúp đỡ và tôi đã bị mắc kẹt trong vài tuần nay, tôi không tiến bộ và ở mọi nơi tôi đến và tôi thấy một câu trả lời khác, mọi thứ tôi thử đều không hoạt động. Tôi đã có đủ lời khuyên và lời khuyên, bây giờ tôi thực sự chỉ cần ai đó cho tôi câu trả lời để tôi làm việc ngược từ đó vì tôi không thể hiểu điều này.

Điều khiến chủ đề này trở nên khó hiểu nhất là cách mọi người sử dụng một tập hợp các quy ước hoặc quy tắc khác nhau và câu trả lời của họ dựa trên các quy ước của riêng họ mà không xác định chúng là gì.

Vì vậy, đây là tập hợp các quy ước mà tôi đã hình thành dựa trên những gì có vẻ phổ biến và hợp lý nhất:

  1. Quy tắc bàn tay phải cho trục.
  2. Tích cực Y lên, Tích cực Z hướng về phía người xem, Tích cực X ở bên phải.
  3. Hàng ma trận chính, hoán vị khi gửi đến shader.
    • Cao độ: xoay quanh trục X
    • Yaw: xoay quanh trục y
    • Cuộn: xoay quanh trục z
  4. Thứ tự xoay: Roll, Pitch, Yaw (điều này có đúng không? Ai đó có thể kiểm tra tôi về điều này không?)
  5. Các giá trị xoay dương, nhìn xuống từ đầu dương của một trục, dẫn đến xoay theo chiều kim đồng hồ.
  6. Hướng mặc định cho xoay 0 trên tất cả các trục là một vectơ chỉ xuống âm Y.

.. đưa ra những quy ước đó (bằng mọi cách có thể sửa cho tôi nếu chúng sai!), làm thế nào để thực hiện:

  • Viết hàm LookAt? (lookAt (vị trí vectơ, tiêu điểm của vectơ, vectơ lên))
  • Tính ma trận quay. (xoay (x, y, z))

Tôi đã cố gắng tự trả lời hai câu hỏi này ít nhất trong 3 tuần qua, tôi đã viết lại chức năng Ma trận Xoay vòng & Xoay vòng của mình ít nhất 30 lần, tôi đã thử nghiệm hàng tá phương pháp và đọc qua tài liệu tôi đã thấy Hàng trăm trang web và đọc nhiều câu hỏi đã trả lời, sao chép mã của người khác và cho đến nay tôi chưa làm gì, mọi thứ đều tạo ra kết quả sai. Một số trong đó đã tạo ra một số đầu ra kỳ quái vui nhộn thậm chí không gần với xoay chính xác.

Tôi đã làm việc về điều này mỗi đêm, ngoại trừ đêm qua vì tôi quá thất vọng với thất bại lặp đi lặp lại đến mức tôi phải dừng lại và nghỉ ngơi.

Xin vui lòng, chỉ cho tôi biết phương pháp chính xác là gì để tôi có thể làm việc ngược từ đó và tìm ra cách nó hoạt động, tôi chỉ không nhận được câu trả lời đúng và điều này làm tôi phát điên lên một chút!

Tôi đang viết bằng Java nhưng tôi sẽ lấy mã được viết bằng bất kỳ ngôn ngữ nào, hầu hết mã kết xuất 3D của tôi thực sự hoạt động khá tuyệt vời, đó chỉ là những phép toán mà tôi không thể hiểu được.

CẬP NHẬT: GIẢI QUYẾT

Cảm ơn sự giúp đỡ của bạn! Bây giờ tôi có một chức năng LookAt hoạt động mà tôi thực sự hiểu và tôi không thể hạnh phúc hơn (nếu ai đó muốn xem nó bằng mọi cách hãy hỏi).

Tôi đã thử lại trong việc tạo ma trận xoay dựa trên các biến pitch / yaw / roll và nó dường như thất bại, nhưng tôi đã quyết định bỏ qua việc cố gắng sử dụng các góc euler cho máy ảnh tự do vì nó có vẻ không phù hợp với thay vào đó, tôi sẽ tạo ra một lớp bậc bốn, có thể gặp may mắn hơn khi đi theo con đường đó, nếu không tôi sẽ sử dụng cao độ / ngáp làm tọa độ hình cầu và dựa vào hàm LookAt hoạt động mới để xoay.

Nếu bất cứ ai khác đang đối mặt với một vấn đề tương tự và muốn hỏi tôi câu hỏi, hãy thoải mái.

Ít nhất tôi không bị mắc kẹt nữa, cảm ơn vì sự giúp đỡ!

Câu trả lời:


14

Những gì bạn đang tìm kiếm có thể được tìm thấy trong lời giải thích rất tốt này: http://www.songho.ca/opengl/gl_transform.html

Nhưng vì tôi thấy nó khó hiểu khi không nắm tay nên tôi sẽ cố gắng giải thích nó ở đây.

Tại thời điểm này, bạn cần xem xét 5 hệ tọa độ và cách chúng liên quan với nhau. Đó là tọa độ cửa sổ, tọa độ thiết bị chuẩn hóa, tọa độ mắt, tọa độ thế giới và tọa độ đối tượng.

Các tọa độ cửa sổ có thể được xem là các pixel "vật lý" trên màn hình của bạn. Chúng là tọa độ mà hệ thống cửa sổ đề cập đến và nếu bạn vận hành ở độ phân giải gốc của màn hình, đây thực sự là các pixel riêng lẻ. Hệ tọa độ cửa sổ là các số nguyên 2D và có liên quan đến cửa sổ của bạn. Ở đây x + ở bên trái và y + nằm xuống với gốc ở góc trên cùng bên trái. Bạn gặp những điều này khi bạn gọi ví dụ glViewport.

Bộ thứ hai là tọa độ thiết bị chuẩn hóa. Chúng tham khảo thiết lập không gian bằng cổng xem hoạt động. Vùng hiển thị của cổng xem đi từ -1 đến +1 và do đó có điểm gốc ở giữa. X + là trái và y + lên. Bạn cũng có z + là "out" của cảnh. Đây là những gì bạn mô tả trong 1.

Bạn không có quyền kiểm soát cách bạn nhận được từ tọa độ thiết bị chuẩn hóa đến tọa độ cửa sổ, điều này được thực hiện hoàn toàn cho bạn. Kiểm soát duy nhất bạn có là thông qua glViewporthoặc tương tự.

Khi làm việc với openGL, kết quả cuối cùng của bạn sẽ luôn ở tọa độ thiết bị được chuẩn hóa. Kết quả là bạn cần phải lo lắng làm thế nào để cảnh của bạn được hiển thị trong đó. Nếu bạn đặt ma trận chiếu và mô hình xem mô hình thành ma trận danh tính, bạn có thể vẽ trực tiếp theo các tọa độ này. Điều này là ví dụ được thực hiện khi áp dụng hiệu ứng toàn màn hình.

Tiếp theo là tọa độ mắt. Đây là thế giới như nhìn từ camera. Kết quả là nguồn gốc nằm trong máy ảnh và áp dụng các trục tương tự như tọa độ thiết bị.

Để lấy từ tọa độ mắt đến tọa độ thiết bị, bạn xây dựng ma trận chiếu. Đơn giản nhất là phép chiếu chính tả chỉ chia tỷ lệ các giá trị một cách thích hợp. Hình chiếu phối cảnh phức tạp hơn và liên quan đến phối cảnh mô phỏng.

Cuối cùng bạn có hệ thống tọa độ thế giới. Đây là hệ thống tọa độ trong đó thế giới của bạn được xác định và máy ảnh của bạn là một phần của thế giới này. Ở đây, điều quan trọng cần lưu ý là các hướng trục cũng giống như bạn xác định chúng . Nếu bạn thích z + như lên, điều đó là hoàn toàn tốt.

Để có được từ tọa độ thế giới đến tọa độ mắt, bạn xác định ma trận xem. Điều này có thể được thực hiện với một cái gì đó như lookAt. Những gì ma trận này làm là "di chuyển" thế giới để máy ảnh ở điểm gốc và nhìn xuống trục z.

Để tính toán ma trận xem đơn giản đến mức đáng ngạc nhiên, bạn cần hủy bỏ chuyển đổi của máy ảnh. Về cơ bản, bạn cần xây dựng ma trận sau:

M= =x[1]y[1]z[1]-p[1]x[2]y[2]z[2]-p[2]x[3]y[3]z[3]-p[3]0001

Các vectơ x, y và z có thể được lấy trực tiếp từ máy ảnh. Trong trường hợp từ việc nhìn vào bạn sẽ lấy được chúng từ các giá trị mục tiêu, mắt (giữa) và lên. Thích như vậy:

z= =normmộttôiTôize(eye-tmộtrget)x= =normmộttôiTôize(bạnp×z)y= =zx

Nhưng nếu bạn tình cờ có những giá trị này chỉ nằm xung quanh bạn, bạn có thể lấy chúng như hiện tại.

Bắt p là một chút khó khăn hơn. Nó không phải là vị trí trong tọa độ thế giới mà là vị trí trong tọa độ camera. Một cách giải quyết đơn giản ở đây là khởi tạo hai ma trận, một ma trận chỉ có x, y và z và một ma trận thứ hai với -eye và nhân chúng lại với nhau. Kết quả là ma trận xem.

Đối với cách này có thể tìm trong mã:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

mã đầy đủ

Và cuối cùng để hoàn thiện, bạn cũng có hệ tọa độ đối tượng. Đây là hệ tọa độ trong đó các mắt lưới được lưu trữ. Với sự trợ giúp của ma trận mô hình, tọa độ lưới được chuyển đổi thành hệ tọa độ thế giới. Trong thực tế, ma trận mô hình và khung nhìn được kết hợp thành ma trận khung nhìn mô hình.


1
Nếu tôi có thể bỏ phiếu cho câu trả lời này hàng trăm lần tôi sẽ làm. Cảm ơn bạn đã trả lời kỹ lưỡng và đầy đủ giải quyết mọi thứ tôi đã nhầm lẫn và cung cấp mã & liên kết là tốt! Tôi đã dành cả ngày để đọc sách toán học về chủ đề này và với câu trả lời của bạn và mã ví dụ và trang được liên kết, nếu điều này không đủ để tôi tìm ra điều này thì tôi nên bỏ ngay bây giờ. Nếu tôi có thể yêu cầu chỉ cần làm rõ một lần, trong mẫu mã cuối cùng đó, liệu tôi có đúng không khi nói các ma trận đó theo thứ tự chính của cột và cái ở trên là hàng chính?
Grady

Đây là một chút nhầm lẫn, các ma trận là cột chính, nhưng cột nằm trong hàng. Vì vậy, để ánh xạ toán học thực tế vào mã, bạn cần đặt ma trận. Xem github.com/rioki/glm/blob/master/src/matrix.h#l72 Bản đồ này chính xác với openGL và nó sẽ như thế nào nếu sử dụng float[16].
rioki

Ah tôi đã nghĩ như vậy nhưng chỉ muốn chắc chắn, cảm ơn một lần nữa! Bạn đã giúp đỡ rất nhiều, tôi thực sự đánh giá cao nó.
Tốt nghiệp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.