Nội suy sử dụng các đường cong Bezier hình khối


7

Tôi đang cố gắng tạo một hàm nội suy cho một thư viện hoạt hình để đạt được hiệu ứng tweening giữa các khung.

Tôi muốn nó hoạt động với các đường cong Bezier. Tôi đã tạo ra một jsFiddle ( ở đây ) về sự tiến bộ của tôi cho đến nay.

Tôi đang cố gắng tạo một tween tuyến tính bằng cách sử dụng định nghĩa bezier này:

{
    p0: new Vector(0,0), //Start point
    p1: new Vector(0,0), //Control point 1
    p2: new Vector(1,1), //Control point 2
    p3: new Vector(1,1)  //End point
}

Tôi đã thực hiện chức năng nội suy từ hướng dẫn này .

var u = 1 - t;
var tt = t*t;
var uu = u*u;
var uuu = uu * u;
var ttt = tt * t;

var p = p0.multiply(uuu);
p = p.add(p1.multiply(3 * uu * t));
p = p.add(p2.multiply(3 * u * tt));
p = p.add(p3.multiply(ttt));

Vấn đề tôi gặp phải là khi tôi chạy chức năng, hình ảnh động dường như không phải là tuyến tính, mà giống như 'dễ dàng thoát ra'.

Lý tưởng nhất là tôi muốn hoạt hình tuyến tính hoạt động giống như quá trình chuyển đổi CSS này .

Bất cứ ai cũng có thể thấy tại sao nó không hoạt hình theo kiểu tuyến tính?


1
Bạn nên có một cái nhìn về Nội suy khối (ẩn). Nó liên quan và là sự lựa chọn tốt hơn imo! blog.demofox.org/2015/08/08/cubic-hermite-interpolation
Alan Wolfe

Câu trả lời:


6

Sau khi chơi với chức năng này nhiều hơn. Tôi nhận ra rằng các điểm điều khiển bezier đang hoạt động tương tự như nam châm.

Nếu tôi trải các điểm điều khiển sao cho chúng được định vị dọc theo một đường thẳng với khoảng cách bằng nhau, thì hoạt ảnh sẽ hoạt động như mong đợi

{
    p0: new Vector(0,0), //Start point
    p1: new Vector(.333,.333), //Control point 1
    p2: new Vector(.666,.666), //Control point 2
    p3: new Vector(1,1)  //End point
}

Tôi hiểu ý bạn là gì. Tuy nhiên, khi tôi đặt điểm kiểm soát đầu tiên đến điểm kết thúc và điểm kiểm soát thứ hai thành điểm bắt đầu, tôi sẽ nhận được hiệu ứng dễ dàng 'nghịch đảo' - Xem tại đây .
Jackson

Xin lỗi vì lỗi toán học trong bình luận trước đó của tôi. Vectơ từ điểm bắt đầu đến điểm kiểm soát đầu tiên là một phần ba vận tốc ban đầu của điểm được nội suy, trong đó đơn vị thời gian là thời lượng nội suy. Tương tự, vectơ từ điểm kiểm soát cuối cùng đến điểm cuối là một phần ba vận tốc cuối cùng. Vì vậy, khoảng cách các điểm kiểm soát bằng nhau ở 1/3 và 2/3 dọc theo đường thẳng sẽ cung cấp cho bạn vận tốc tuyến tính không đổi cho phép nội suy, như bạn mong muốn. Điều này dường như cũng giữ cho các đơn đặt hàng khác của Bézier: nhân vectơ ban đầu hoặc kết thúc với thứ tự để có được vận tốc.
DMGregory

Tôi không nhận thấy câu trả lời này khi tôi thực hiện. Bạn hoàn toàn chính xác rằng các điểm kiểm soát colinear thực hiện phép nội suy tuyến tính. Tốt công việc tìm kiếm giải pháp!
Alan Wolfe

5

Tôi thường giải quyết điều này bằng cách sử dụng spline Catmull-Rom. Thay vì sử dụng các điểm kiểm soát, bạn chỉ cần chỉ định hai điểm mà bạn muốn nội suy, cũng như điểm "trước" và điểm "tiếp theo". Nếu tất cả 4 điểm nằm trên cùng một đường thẳng và cách đều nhau, phép nội suy sẽ là tuyến tính.

catmull-rom spline

Trong hình trên, có bốn điểm p0, p1, p2 và p3. Dòng mã C ++ sau đây sẽ nội suy giữa p1 và p2, trong đó t nằm trong phạm vi [0 ... 1]:

return p1 + 0.5*t*(p2-p0 + t*(2*p0-5*p1+4*p2-p3 + t*(3*(p1-p2)+p3-p0)));

Bạn có thể nội suy bất kỳ loại giá trị nào, miễn là loại đó hỗ trợ cộng và nhân với một vô hướng.

Nếu các giá trị không nằm trên một dòng hoặc không cách đều nhau, phép nội suy catmull-rom sẽ tạo ra một đường cong trơn tru. Nội suy sẽ không tuyến tính:

đường cong catmull-rom

Nếu không có điểm "trước" hoặc "tiếp theo" (ví dụ: ở đầu hoặc cuối của một loạt các đoạn đường cong), hãy sử dụng các phương trình sau:

p0 = 2 * p1 - p2;
p3 = 2 * p2 - p1;

Cảm ơn vi đa trả lơi. Đây trông giống như một hàm nội suy tốt mà tôi sẽ xem xét.
Jackson

Trong đoạn mã cuối cùng của bạn nếu không có điểm trước hoặc điểm tiếp theo, liệu nó có dịch sang Unity không? Đây có phải chỉ đơn giản là nhân mỗi thành phần vector với 2, sau đó trừ đi các vector khác? Tôi chỉ đang cố gắng hình dung những gì nó thực sự đang làm. Cảm ơn.
Doug.McFarlane

@ Doug.McFarlane - Hai công thức chỉ đơn giản là "phản ánh" điểm. Ví dụ, trong trường hợp p0, hình ảnh một vectơ từ p1 đến p2 và sau đó nhân nó với -1. Kết quả là p0 = p1 + (p1 - p2) = 2 * p1 - p2. Làm điều này, chúng tôi duy trì hướng và khoảng cách thích hợp, dẫn đến nội suy mạch lạc hơn. Bạn cũng có thể đặt p0 thành p1, nhưng sau đó bạn thấy rõ hiệu ứng dễ dàng trong phép nội suy.
Paul Houx

2

Đường cong Bezier vốn dĩ đã tạo nên những đường cong mượt mà. Nội suy tuyến tính đơn giản hơn. Để nội suy tuyến tính hai điểm, bạn chỉ cần áp dụng công thức sau cho thời gian t trong [0,1]:

interpolatedPoint = startPoint * (1 - t) + endPoint * t

Khi t = 0, điểm nội suy chính xác bằng điểm bắt đầu. Tương tự, khi t = 1, điểm nội suy chính xác bằng điểm cuối. Khi t nằm trong khoảng từ 0 đến 1, nó nằm ở đâu đó trên đường thẳng giữa hai điểm.

Tôi đã rẽ nhánh và sửa đổi jsfiddle của bạn để làm rõ: http://jsfiddle.net/kevinAlbs/3em6br3b/1/


Cảm ơn câu trả lời của bạn. Tôi thích hình ảnh động phải linh hoạt để nó có thể là cả tuyến tính hoặc cong bằng cách sử dụng đường cong hình khối.
Jackson

2

Tại sao bạn sử dụng đường cong bezier để thực hiện phép nội suy tuyến tính? Bạn chỉ có thể sử dụng phép nội suy tuyến tính để thực hiện phép nội suy tuyến tính và hoàn toàn không sử dụng các đường cong.

Nếu lý do là bạn muốn có một hệ thống nội suy dựa trên đường cong mục đích tổng quát hơn và bạn đang cố gắng để nó thực hiện phép nội suy tuyến tính cho một trường hợp sử dụng cụ thể, có một cách.

Về cơ bản, các điểm kiểm soát cần phải là điểm trên một dòng. Chẳng hạn, các điểm kiểm soát 0, 0.333, 0.666, 1.0 sẽ cung cấp cho bạn phép nội suy tuyến tính giữa 0 và 1, khi sử dụng đường cong bezier hình khối để thực hiện.

Một lần nữa, nếu bạn muốn nội suy tuyến tính, không có lý do để sử dụng một đường cong.

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.