2009-03-11 34 views
8

Được rồi, đây là một cái gì đó mà nên là một câu hỏi ma trận đơn giản, nhưng sự hiểu biết của tôi về ma trận là hơi hạn chế. Đây là kịch bản: Tôi có một sprite 1px x 1px mà tôi muốn chia tỷ lệ bởi số tiền x và y (số tiền khác nhau ở mỗi bên), và sau đó tôi muốn xoay sprite theo một góc nào đó, và sau đó tôi muốn có thể chính xác vị trí toàn bộ điều (từ phía trên bên trái hoặc trung tâm, làm cho không có sự khác biệt với tôi).Làm thế nào để xoay, chia tỷ lệ và dịch một ma trận cùng một lúc trong C#?

Cho đến nay mã của tôi là mơ hồ gần, nhưng nó có xu hướng được tắt bởi một số lượng ngẫu nhiên tùy thuộc vào góc tôi vượt qua trong

tôi sẽ nghĩ rằng điều này sẽ làm điều đó:.

 Point center = new Point(50, 50); 
     float width = 60; 
     float height = 100; 
     float angle = 0.5; 
     Vector3 axis = new Vector3(center.X, center.Y, 0); 
     axis.Normalize(); 
     Matrix m = Matrix.Scaling(width, height, 0) * 
      Matrix.RotationAxis(axis, angle) * 
      Matrix.Translation(center.X, center.Y, 0); 

Nhưng nó có xu hướng thu nhỏ quy mô của đường dây xoay xuống, mặc dù tôi nghĩ nó định vị nó đúng.

Tôi cũng đã thử điều này:

Matrix m = Matrix.Transformation2D(new Vector2(center.X, center.Y), 0f, 
     new Vector2(width, height), new Vector2(center.X, center.Y), 
     angle, Vector2.Zero); 

Dòng trông giống hệt phải, với kích thước phù hợp chính xác và hình dạng, nhưng tôi không thể vị trí của nó một cách chính xác cả. Nếu tôi sử dụng vector dịch ở cuối cuộc gọi ở trên, hoặc nếu tôi đặt một vị trí bằng cách sử dụng Sprite.Draw, không hoạt động đúng.

Đây là tất cả trong SlimDX. Tôi đang làm gì sai?

Trả lời

12

Tôi vừa trải qua nỗi đau khi học ma trận chuyển đổi, nhưng sử dụng XNA.

Tôi đã tìm thấy thesearticlestobevery hữu ích trong việc hiểu điều gì xảy ra. Các cuộc gọi phương thức rất giống nhau trong XNA và lý thuyết đằng sau tất cả sẽ áp dụng cho bạn, ngay cả với SlimDX.

Từ liếc nhìn mã của bạn, tôi nghĩ bạn nên dịch ngay từ đầu, đến gốc, và sau đó dịch lại ở cuối, đến vị trí cuối cùng, mặc dù tôi vẫn còn một chút người mới cũng.

Trình tự tôi sẽ làm điều đó trong là:

  • Dịch gốc
  • Scale
  • Xoay
  • Dịch vị trí mong muốn

Lý do để dịch về nguồn gốc đầu tiên là các phép quay được dựa trên nguồn gốc. Do đó để xoay một cái gì đó về một điểm nhất định, đặt điểm đó trên nguồn gốc trước khi quay.

+1

Hmm ... điều này có vẻ rất gần. Các bước dịch gốc, tỉ lệ và xoay hoạt động rất tốt, nhưng sau đó khi tôi cố dịch sang vị trí mong muốn nó hoạt động thực sự lạ - tôi thay đổi x coodinate, và nó di chuyển trong cả x và y. Tôi nghĩ rằng nó đang dịch trong không gian xoay ... – x4000

+0

Một điều chưa rõ ràng đối với tôi là làm thế nào để dịch sang nguồn gốc. Tôi có hai điểm, cộng thêm một điểm thứ ba ở giữa họ. Tôi đã dịch trung tâm sang nguồn gốc, nhưng tôi có nên dịch theo cách khác không? – x4000

+1

Thay vì dịch lại về nơi bạn muốn, bạn có thể thay đổi vị trí của nơi bạn vẽ không? –

1

Điều bạn cần làm là thực hiện từng bước chuyển đổi một lần. Đầu tiên, bạn có cần vẽ nó không. Đó là nơi bạn mong đợi nó. Sau đó, ném vào xoay, và sau đó dịch. Điều này sẽ giúp phát hiện các giả định không chính xác.

Bạn cũng có thể vẽ các đường tạm thời để giúp tìm tọa độ. Ví dụ, nếu bạn kéo dài và xoay và mong đợi điểm cuối của bạn là 0,0. Vẽ một dòng khác với một điểm cuối tại 0,0 sẽ đóng vai trò kiểm tra kép để xem liệu trường hợp đó có thực sự xảy ra hay không.

Đối với vấn đề cụ thể của bạn, sự cố có thể xảy ra với vòng xoay. Sau khi bạn đã thu nhỏ và xoay dòng bây giờ là tắt trung tâm gây ra cho bạn vấn đề khi bạn đang dịch.

Giải pháp chung là di chuyển đường trở lại nguồn gốc thực hiện bất kỳ thao tác nào liên quan đến việc thay đổi hình dạng hoặc hướng của nó. Sau đó bởi vì bạn đang ở một vị trí tốt được biết đến, bạn có thể dịch sang đích cuối cùng của bạn.

PHÓ VỚI NHẬN XÉT

Nếu dịch là một vấn đề và bạn đang chuyển đổi hệ tọa độ sau đó bạn sẽ cần phải viết một hàm chuyển đổi để chuyển đổi giữa hệ thống cũ và cái mới.

Ví dụ: nếu bạn đang quay 45 độ. Trước khi xoay bạn có thể dịch 0,1 để di chuyển lên 1 inch. Sau khi quay, bạn sẽ phải dịch bằng khoảng -70707, 070707 để di chuyển lên 1 inch so với hệ tọa độ gốc.

+0

Tôi đã cố gắng thực hiện từng phần riêng biệt - tôi nên đề cập đến điều đó. Chia tỷ lệ và dịch thuật hoạt động hoàn hảo. Nhưng như bạn nói, khi tôi thêm xoay nó sẽ tắt. Và vâng tôi có biểu tượng tại các điểm tham chiếu để tôi có thể thấy tôi thân thiết đến mức nào. Tôi sẽ cố gắng bù đắp ngay bây giờ. – x4000

+0

Xoay vòng lộn xộn vì xoay vòng về nguồn gốc. –

+0

Bây giờ tôi đã cố gắng di chuyển trở lại nguồn gốc và sau đó dịch trở lại nơi tôi muốn. Điều đó có vẻ gần, nhưng bản dịch bị tắt vì nó đang dịch bên trong không gian tọa độ xoay, có vẻ như vậy. – x4000

1

Bạn có xoay quanh trục chính xác không? Tôi là một newbie tại công cụ ma trận, nhưng có vẻ như với tôi rằng vì sprite tồn tại trong không gian x, y, trục quay nên là Z-Axis - tức là (0,0,1).

+0

Hmm, đó là một điểm tốt, nhưng vòng quay của tôi có vẻ hoạt động tốt khi tôi chỉ thực hiện mở rộng quy mô và vấn đề xuất hiện khi tôi cố gắng định vị nó. Tôi có thể làm bất kỳ hai trong ba công việc này, nhưng có điều gì đó tôi đang làm sai khi đưa tất cả lại với nhau! – x4000

+0

Hey, bắt tốt với trục Z - với ví dụ đầu tiên của tôi ở trên, đó là khá có liên quan. – x4000

3

OK, tính năng này hiện đang hoạt động. Đây là mã làm việc của tôi cho điều này, trong trường hợp ai đó cần nó:

Point sourceLoc = new Point (50, 50); 
    float length = 60; 
    float thickness = 2; 
    float angle = 0.5; 
    Matrix m = Matrix.Scaling(length, thickness, 0) * 
      Matrix.RotationZ(angle) * 
      Matrix.Translation(sourceLoc.X, sourceLoc.Y, 0); 
    sprite.Transform = m; 

    sprite.Draw(this.tx, Vector3.Zero, Vector3.Zero, Color.Red); 

này sẽ vẽ một đường góc cạnh của chiều dài của bạn lựa chọn, với độ dày tương đương với độ dày của bạn lựa chọn (giả sử kết cấu của bạn là một hình ảnh trắng 1x1 pixel). Vị trí nguồn là nơi dòng sẽ phát ra, với bất kỳ góc nào bạn chỉ định (theo radian). Vì vậy, nếu bạn bắt đầu ở số không và tăng bởi một cái gì đó như 0,1 cho đến khi bạn nhấn 2PI, và sau đó thiết lập lại 0, bạn sẽ có một đường quay xung quanh một trung tâm như một bàn tay đồng hồ hoặc quét radar. Đây là những gì tôi đang tìm kiếm - nhờ tất cả những ai đã đóng góp!

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