Làm thế nào tôi có thể tìm thấy quả cầu lớn nhất vừa vặn bên trong một sự thất vọng?


12

Làm thế nào để bạn tìm thấy quả cầu lớn nhất mà bạn có thể vẽ trong phối cảnh?

Nhìn từ trên xuống, nó sẽ là thế này:

nhập mô tả hình ảnh ở đây

Đã thêm: ở phía bên phải, tôi đã đánh dấu bốn điểm Tôi nghĩ chúng ta biết điều gì đó. Chúng ta có thể hủy bỏ tất cả tám góc của Frusum và các trung tâm của gần và xa kết thúc. Vì vậy, chúng ta biết điểm 1, 3 và 4. Chúng ta cũng biết rằng điểm 2 có cùng khoảng cách từ 3 với 4 là từ 3. Vì vậy, chúng ta có thể tính điểm gần nhất trên dòng 1 đến 4 đến điểm 2 để có được trung tâm? Nhưng toán học và mã thực tế thoát khỏi tôi.

Tôi muốn vẽ các mô hình (có dạng hình cầu và tôi có một hình cầu giới hạn nhỏ) cho càng lớn càng tốt.

Cập nhật: Tôi đã cố gắng thực hiện phương pháp tiếp cận hai mặt phẳng theo đề xuất của bobobobo và Nathan Reed :

function getFrustumsInsphere(viewport,invMvpMatrix) {
    var midX = viewport[0]+viewport[2]/2,
        midY = viewport[1]+viewport[3]/2,
        centre = unproject(midX,midY,null,null,viewport,invMvpMatrix),
        incircle = function(a,b) {
            var c = ray_ray_closest_point_3(a,b);
            a = a[1]; // far clip plane
            b = b[1]; // far clip plane
            c = c[1]; // camera
            var A = vec3_length(vec3_sub(b,c)),
                B = vec3_length(vec3_sub(a,c)),
                C = vec3_length(vec3_sub(a,b)),
                P = 1/(A+B+C),
                x = ((A*a[0])+(B*a[1])+(C*a[2]))*P,
                y = ((A*b[0])+(B*b[1])+(C*b[2]))*P,
                z = ((A*c[0])+(B*c[1])+(C*c[2]))*P;
            c = [x,y,z]; // now the centre of the incircle
            c.push(vec3_length(vec3_sub(centre[1],c))); // add its radius
            return c;
        },
        left = unproject(viewport[0],midY,null,null,viewport,invMvpMatrix),
        right = unproject(viewport[2],midY,null,null,viewport,invMvpMatrix),
        horiz = incircle(left,right),
        top = unproject(midX,viewport[1],null,null,viewport,invMvpMatrix),
        bottom = unproject(midX,viewport[3],null,null,viewport,invMvpMatrix),
        vert = incircle(top,bottom);
    return horiz[3]<vert[3]? horiz: vert;
}

Tôi thừa nhận tôi đang bay nó; Tôi đang cố gắng điều chỉnh mã 2D bằng cách mở rộng nó thành 3 chiều. Nó không tính toán chính xác; điểm trung tâm của hình cầu dường như nằm trên đường thẳng giữa máy ảnh và góc trên bên trái mỗi lần và nó quá lớn (hoặc quá gần). Có bất kỳ sai lầm rõ ràng trong mã của tôi? Liệu cách tiếp cận, nếu cố định, làm việc?


Có phải hình cầu phải hoàn toàn ở phía bên của mặt phẳng xa như trong ảnh không?
Mikael Högström

@ MikaelHögström Tôi tưởng tượng họ sẽ có, để lớn nhất có thể?
Sẽ

Hmm tôi đoán nó phụ thuộc vào mục đích của bạn ... Nếu bạn vẽ một quả cầu với một nửa ngoài mặt phẳng xa thì nó sẽ lớn hơn nhưng có lẽ điều đó đi ngược lại mục đích của bạn?
Mikael Högström

@ MikaelHögström aha Tôi hiểu câu hỏi của bạn; vâng tôi muốn toàn bộ mô hình được vẽ, không có mặt phẳng xa nào cắt qua nó.
Sẽ

Câu trả lời:


12

Tôi sẽ cho rằng sự thất vọng của bạn là đối xứng, vì bản vẽ của bạn dường như gợi ý như vậy. Có ba ràng buộc (hai nếu sự thất vọng của bạn là 2D):

A. quả cầu không thể lớn hơn khoảng cách giữa các mặt phẳng gần và xa

Nếu Dlà khoảng cách gần, ràng buộc đầu tiên chỉ đơn giản là:

R  D / 2

B. hình cầu không thể phát triển rộng hơn các mặt phẳng bên

Bây giờ đối với các ràng buộc khác, giả sử αlà nửa góc của sự thất vọng và Llà nửa chiều rộng của mặt phẳng xa, như trong bản vẽ này:

bực bội

Công thức đầu tiên được đưa ra bởi lượng giác trong tam giác. Thứ hai đến từ tổng các góc của một tam giác. Điều này cho chúng ta ràng buộc thứ hai:

R  L tan((π - 2α) / 4)

Nếu sự thất vọng của bạn là 3D, bạn sẽ có một ràng buộc thứ ba với các giá trị Lαgiá trị mới.

Kết quả cuối cùng

Các Rgiá trị mà bạn đang tìm kiếm là minmột trong ba giới hạn.

Làm thế nào để có được các tham số

Nếu bạn có thể loại bỏ sự thất vọng trong chế độ xem hoặc không gian thế giới, bạn có thể tính L, D và α theo cách sau, trong đó các Pđiểm từ mặt phẳng gần và các Qđiểm nằm từ mặt phẳng xa:

công thức2

Mũi tên có nghĩa là vectơ, trên mạng là sản phẩm chấm và | | chỉ ra chiều dài của một vectơ. Thay thế Q2bằng Q3P2bằng P3để có L và α theo chiều dọc.


Làm thế nào, từ sự thất vọng (được tính bằng cách không dự đoán các điểm quan sát để đến gần và xa), bạn có xác định trường nhìn không? Và trong 3D chỉ có hai lựa chọn chứ không phải ba, phải không? Những nỗ lực của tôi để đưa thuật toán của bạn vào mã luôn mang lại cho tôi rất lớn R.
Will

@ Tôi sẽ thêm một bản vẽ thứ hai với các công thức hy vọng sẽ có ích.
sam hocevar

2

Trong 2D: coi sự thất vọng là một hình tam giác (2D)

nhập mô tả hình ảnh ở đây

Sau đó, bạn muốn tìm vòng tròn của tam giác.

Là một vấn đề 3D, bạn cần tìm ra nguồn cảm hứng của một kim tự tháp dựa trên hình vuông.

Nếu tôi có công thức tôi sẽ in nó ở đây, nhưng than ôi, tôi không biết công thức.


2
Có lẽ đủ để tìm thấy vòng tròn của sự thất vọng dọc hoặc ngang trong 2D, bất cứ điều gì có FOV nhỏ hơn, ít nhất là cho sự thất vọng "tiêu chuẩn" (không bị cắt hoặc bất cứ điều gì).
Nathan Reed

1

Quả cầu lớn nhất có thể sẽ chạm vào mặt phẳng xa (sử dụng thuật ngữ cho chế độ xem ở đây) ngay tại trung tâm. Nó cũng sẽ chạm vào các mặt phẳng trên / dưới hoặc trái / phải, tùy thuộc vào góc nào của foV nhỏ hơn. Tôi phải nói rằng tôi không có bằng chứng toán học thực sự cho những giả định đó, nhưng họ nên đúng. Có lẽ ai đó có một ý tưởng về cách chứng minh điều này.

Một Sphere có thể được xác định bởi điểm trung tâm của nó và bán kính. Cx và Cy giống như trung tâm của phi cơ.

Cz và bán kính có thể thu được bằng cách giải hệ phương trình dựa trên các giả định được liệt kê ở trên.

T là một trong các mặt phẳng đáy / đỉnh hoặc mặt phẳng trái / phải (xem ở trên) với t1, t2 và t3 là vectơ chuẩn hóa bình thường và t4 là khoảng cách từ gốc. f là trung tâm của phi cơ.

t1 * cx + t2 * cy + t3 * cz - t4 = r

-fz + cz = r

t1 * cx + t2 * cy + t3 * cz - t4 = -fz + cz

t1 * cx + t2 * cy + fz - t2 = + cz - t3 * cz

t1 * cx + t2 * cy - fz - t2 = cz * (1 - t3)

cz = (t1 * cx + t2 * cy - fz - t2) / (1 - t3)

r sau đó được tính bằng cách chèn cz vào đây: -fz + cz = r

Bạn có thể nhận được tất cả các mặt phẳng từ Ma trận Chiếu bạn đang sử dụng. (Không phải ViewProjection trong trường hợp này)

sau đó bạn phải di chuyển quả cầu sang đúng không gian: C '= nghịch đảo (Xem) * C


1

Tôi đang cố gắng làm điều gì đó tương tự, và trong trường hợp của tôi, tốc độ quan trọng hơn độ chính xác miễn là quả cầu không tồn tại bên ngoài bất kỳ giới hạn nào của sự thất vọng.

Nếu bạn tính khoảng cách ngắn nhất giữa các đường thẳng (hoặc các mặt trong 3d), khoảng cách ngắn nhất được tìm thấy có thể được sử dụng làm đường kính của một vòng tròn / cảm hứng nằm hoàn toàn bên trong sự thất vọng. Nguồn gốc của incircle / Insphere có thể chỉ đơn giản là trung bình của tất cả các đỉnh (tổng & chia). Nó sẽ khá nhanh và cũng hoạt động cho tất cả các loại khối đa diện lồi.

Hạn chế duy nhất là hình tròn hoặc hình cầu sẽ không nhất thiết phải là hình tròn hoặc hình tròn lớn nhất có thể. Đối với một sự thất vọng với nhiều âm lượng và một cạnh rất ngắn, vòng tròn / hình cầu sẽ chia sẻ ít không gian bực bội hơn có thể.

Một ý tưởng khác

Nếu bạn muốn nguồn cảm hứng của chế độ xem 3D và bạn có ma trận phối cảnh được sử dụng để xây dựng sự thất vọng này, thì bạn có thể chỉ cần sử dụng ma trận đó trên cảm hứng của khối đơn vị, và đó sẽ là một nguồn cảm hứng hoàn hảo cho sự thất vọng. (Đường kính của hình khối là chiều dài của một trong các cạnh của khối lập phương, tâm là giữa của khối lập phương là trung bình của các đỉnh của khối lập phương)

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.