2013-04-13 67 views
15

Giả sử tôi có hộp 3D màu xanh dương (ở đó cạnh trên cùng có màu đỏ).Thứ tự Opengl của phép biến đổi ma trận

  1. Bây giờ tôi gọi glScalef (1, 10, 1).
  2. Sau đó, tôi gọi glRotatef (90, 0, 1, 0).
  3. Sau đó, tôi sẽ hiển thị hình khối.

Điều tôi mong đợi là nhìn thấy mặt đỏ quay về phía màn hình (dọc theo trục Y của mô hình).

Nhưng những gì nhìn thấy là: Mặt đỏ đang đối diện với màn hình (như mong đợi). Tuy nhiên, độ căng xuất hiện trên trục Y của không gian chế độ xem (không phải là mô hình).

Tôi biết rằng nếu tôi đặt tỷ lệ dọc theo trục Z, thì tôi sẽ nhận được kết quả phù hợp. Nhưng sự nhầm lẫn của tôi là tôi nghĩ rằng nhân rộng trên trục Y, sau đó xoay hộp, sẽ cho tôi kết quả đúng.

Tôi đang thiếu gì?

+0

Tôi thích câu trả lời này: http://stackoverflow.com/questions/6118996/matrix-mult-order-in-direct3d – AlvinfromDiaspar

Trả lời

19

OpenGL đọc ma trận của nó trong những gì được gọi là column major order. Kết quả là mỗi phép toán tiếp theo là một phép nhân trước của tất cả các phép toán trước nó, không phải là phép nhân sau. Do đó, mỗi lần gọi cuộc gọi tiếp theo tới hoạt động OpenGL (glScale, glTranslate, glRotate) là điều đầu tiên ảnh hưởng đến đối tượng và ngược lại theo cách bạn viết.

Vì vậy, bạn cần phải thay đổi thứ tự phép nhân của bạn:

glRotatef(90, 0, 1, 0); // Notice how this is the first operation ... 
// ... but will be applied after 
glScalef(1, 10, 1); // This will be applied first, but is the last operation 
// Zany, right? 

Sự thật mà nói, nó cảm thấy ít trực quan khi bạn đang viết chương trình và sử dụng một máy tính để có chỉ định điều theo thứ tự ngược. Nhưng các vị thần đồ họa đã quyết định đó là cách họ muốn ngăn xếp ma trận OpenGL hoạt động (cùng với HLSL, GLSL và các hệ thống khác: xem liên kết ở trên về thứ tự cột lớn).

+2

bạn có thể giải thích những gì lưu trữ dữ liệu theo thứ tự cột lớn có liên quan đến thứ tự hoạt động không? –

+1

Xem http://stackoverflow.com/questions/17717600/confusion-between-c-and-opengl-matrix-order-row-major-vs-column-major để thảo luận tốt hơn. – ToolmakerSteve

+2

Một số thông tin cơ bản về vấn đề này (hoặc lý do của các Thần đồ họa): http://steve.hollasch.net/cgindex/math/matrix/column-vec.html – Vitaly

-1

Nếu bạn có một mảng mà đại diện cho một ma trận 4x4 như thế này:

float mat[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; 

và bạn nạp này thành một ma trận OpenGL, OpenGL sẽ thấy 4 nổi đầu tiên là cột đầu tiên của ma trận, thứ hai 4 nổi dưới dạng cột thứ hai và cột thứ ba nổi như cột thứ 3 của ma trận, v.v.

Vì vậy, cứ 4 phao, OpenGL xem như một cột khác. Điều này được gọi là thứ tự Cột-Lớn. Nó lưu trữ dữ liệu trong cột. Nếu bạn phải chuyển đổi ma trận cột chính, nó sẽ kết thúc dưới dạng ma trận hàng chính và ngược lại.

Vì bạn có ma trận cột chính, bạn cũng cần sử dụng vectơ cột, có nghĩa là thứ tự nhân của bạn sẽ là: M * v.

Để chứng minh điều này cho chính mình, hãy lấy ma trận 2x2 đơn giản với vectơ cột 2x1, nhân với số M * v. Gọi K = transpose (M), và r = vector hàng (1x2).

Sau đó M * v =r * K

Tóm lại, một khi bạn sử dụng một cột hoặc hàng ký hiệu lớn trong mã của bạn, bạn phải dính vào nó.

+1

Thứ tự lưu trữ trong bộ nhớ (hàng chính so với cột-chính) không liên quan đến việc chọn nhân các vectơ làm cột ở bên phải hoặc dưới dạng hàng ở bên trái. Ví dụ, bạn có thể nhân các vectơ từ bên trái trong GLSL, mặc dù các ma trận được lưu trữ theo thứ tự cột lớn. –

+0

Có, bạn có thể nhân từ bên trái trong GLSL, nhưng bạn phải nhớ chuyển đổi ma trận. Đó là lý do tại sao nó chỉ tốt hơn để dính vào một phương pháp thiết lập - ít khó hiểu - chỉ trả lời câu hỏi của racarate. Cảm ơn. – Michael

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