ฉันจะหาทรงกลมที่ใหญ่ที่สุดที่อยู่ใน frustum ได้อย่างไร


12

คุณจะพบทรงกลมที่ใหญ่ที่สุดที่คุณสามารถวาดในมุมมองได้อย่างไร

ดูจากด้านบนมันเป็นเช่นนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ที่เพิ่มเข้ามา: บน frustum ด้านขวาฉันได้ทำเครื่องหมายสี่จุดที่ฉันคิดว่าเรารู้อะไรเกี่ยวกับ เราสามารถปลดโปรเจ็กต์ทั้งแปดมุมของ frusum และศูนย์กลางของใกล้และไกลสุด เรารู้จุดที่ 1, 3 และ 4 เราก็รู้ว่าจุดที่ 2 คือระยะห่างเดียวกันจาก 3 เท่ากับ 4 จาก 3 ดังนั้นเราสามารถคำนวณจุดที่ใกล้ที่สุดในบรรทัดที่ 1 ถึง 4 ถึงจุดที่ 2 เพื่อให้ได้ ศูนย์? แต่คณิตศาสตร์และรหัสที่แท้จริงช่วยฉันได้

ฉันต้องการวาดแบบจำลอง (ซึ่งเป็นทรงกลมโดยประมาณและที่ฉันมีทรงกลมมินิบัสที่ล้อมรอบ) มีขนาดใหญ่ที่สุดเท่าที่จะเป็นไปได้

อัปเดต: ฉันได้พยายามใช้แนวทาง incircle-on-two- planeตามที่Bobobobo และ 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;
}

ฉันยอมรับว่าฉันปีก ฉันกำลังพยายามปรับโค้ด 2Dโดยขยายเป็น 3 มิติ มันไม่ได้คำนวณ insphere อย่างถูกต้อง ดูเหมือนว่าจุดศูนย์กลางของทรงกลมจะอยู่ในแนวระหว่างกล้องกับมุมบนซ้ายในแต่ละครั้งและมีขนาดใหญ่เกินไป (หรือใกล้เกินไป) มีรหัสข้อผิดพลาดที่ชัดเจนหรือไม่? วิธีการทำงานถ้าแก้ไขแล้วทำงานได้หรือไม่


ทรงกลมต้องอยู่ที่ด้านข้างของระนาบไกลอย่างที่เห็นในภาพหรือไม่?
Mikael Högström

@ MikaelHögströmฉันคิดว่าพวกเขาน่าจะเป็นใหญ่ที่สุดเท่าที่จะเป็นไปได้?
จะ

อืมฉันคิดว่ามันขึ้นอยู่กับจุดประสงค์ของคุณ ... ถ้าคุณวาดทรงกลมที่มีครึ่งหนึ่งไกลออกไปไกลกว่านั้นมันก็จะใหญ่กว่า แต่นั่นอาจจะขัดกับวัตถุประสงค์ของคุณ?
Mikael Högström

@ MikaelHögström aha ฉันเข้าใจคำถามของคุณ ใช่ฉันต้องการวาดรูปแบบทั้งหมดไม่ไกลเครื่องบินตัดผ่านมัน
จะ

คำตอบ:


12

ฉันจะสมมติว่า frustum ของคุณสมมาตรเนื่องจากรูปวาดของคุณดูเหมือนจะแนะนำเช่นนั้น มีข้อ จำกัด อยู่สามข้อ (สองข้อถ้า frustum ของคุณคือ 2D):

A. ทรงกลมไม่สามารถมีขนาดใหญ่กว่าระยะห่างระหว่างระนาบใกล้และไกล

ถ้าDเป็นระยะทางใกล้ - ไกลข้อ จำกัด แรกคือ:

R  D / 2

B. ทรงกลมไม่สามารถเติบโตได้กว้างกว่าระนาบด้านข้าง

ทีนี้สำหรับข้อ จำกัด อื่น ๆ สมมุติว่าαเป็นครึ่งมุมของ frustum และLเป็นครึ่งกว้างของระนาบไกลดังที่แสดงในภาพวาดนี้:

frustum

สูตรแรกให้โดยตรีโกณมิติในรูปสามเหลี่ยม ที่สองมาจากผลรวมของมุมสามเหลี่ยม ซึ่งทำให้เรามีข้อ จำกัด ที่สอง:

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

หาก frustum ของคุณเป็น 3 มิติคุณจะมีข้อ จำกัด ที่สามที่มีค่าLและαค่าใหม่

ผลสุดท้าย

Rค่าที่คุณกำลังมองหาเป็นminของสามขอบเขต

วิธีรับพารามิเตอร์

หากคุณสามารถปลดโปรเจ็กต์ frustum ในมุมมองหรือพื้นที่โลกคุณสามารถคำนวณ L, D และαด้วยวิธีต่อไปนี้โดยที่Pจุดมาจากระนาบใกล้และQจุดมาจากระนาบไกล:

Formula2

ลูกศรหมายถึงเวกเตอร์“.” เป็นผลิตภัณฑ์ดอทและ || ระบุความยาวของเวกเตอร์ แทนที่Q2ด้วยQ3และP2ด้วยP3เพื่อให้ได้ L และαในมิติแนวตั้ง


อย่างไรจาก frustum (คำนวณโดยไม่ได้คาดเดาจุดวิวพอร์ตที่จะได้ใกล้และไกล) คุณจะกำหนดเขตการมอง? และในแบบ 3 มิติมีเพียงสองตัวเลือกไม่ใช่สามตัวใช่ไหม? ความพยายามของฉันในการใส่อัลกอริทึมของคุณให้เป็นรหัสให้ฉันใหญ่มากเสมออาร์
จะ

@ ฉันจะเพิ่มรูปวาดที่สองด้วยสูตรที่หวังว่าจะช่วยได้
sam hocevar

2

ใน 2D: พิจารณา frustum เป็นรูปสามเหลี่ยม (2D)

ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นคุณต้องการหาincircleของรูปสามเหลี่ยม

ในฐานะที่เป็นปัญหา 3 มิติคุณจะต้องค้นหาแรงบันดาลใจของปิรามิดที่มีฐานสี่เหลี่ยม

ถ้าฉันมีสูตรฉันจะพิมพ์ที่นี่ แต่อนิจจาฉันไม่ทราบสูตร


2
มันอาจพอเพียงที่จะหา incircle ของ frustum ทั้งแนวตั้งและแนวนอนใน 2D ซึ่งแล้วแต่กรณีที่มี FOV ที่เล็กกว่าอย่างน้อยสำหรับ frusta "มาตรฐาน" (ไม่ตัดหรืออะไรก็ตาม)
นาธานรีด

1

ทรงกลมที่ใหญ่ที่สุดที่เป็นไปได้ควรแตะระนาบไกล ๆ นอกจากนี้ยังจะสัมผัสเครื่องบินบน / ล่างหรือเครื่องบินซ้าย / ขวาขึ้นอยู่กับว่ามุม FoV ใดเล็ก ฉันต้องบอกว่าฉันไม่มีหลักฐานทางคณิตศาสตร์จริงสำหรับสมมติฐานเหล่านั้น แต่พวกเขาควรจะถูกต้อง อาจมีใครบางคนมีความคิดในการพิสูจน์เรื่องนี้

ทรงกลมสามารถกำหนดได้โดยเป็นจุดศูนย์กลางและรัศมี Cx และ Cy เป็นเช่นเดียวกับศูนย์กลางของ Farplane

สามารถรับ Cz และรัศมีได้โดยการแก้ระบบสมการตามสมมติฐานที่กล่าวไว้ข้างต้น

T เป็นระนาบด้านล่าง / ด้านบนหรือระนาบซ้าย / ขวา (ดูด้านบน) ด้วย t1, t2 และ t3 เป็นเวกเตอร์ปกติที่ทำให้เป็นมาตรฐานและ t4 เป็นระยะทางจากจุดกำเนิด f คือศูนย์กลางของ farplane

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)

จากนั้นคำนวณโดยการแทรก cz ลงในส่วนนี้: -fz + cz = r

คุณสามารถรับระนาบทั้งหมดจาก Projection Matrix ที่คุณใช้ (ไม่ใช่ ViewProject ในกรณีนี้)

หลังจากนั้นคุณจะต้องย้ายทรงกลมไปยังพื้นที่ที่เหมาะสม: C '= ผกผัน (ดู) * C


1

ฉันพยายามทำสิ่งที่คล้ายกันและในกรณีของฉันความเร็วนั้นสำคัญยิ่งกว่าความแม่นยำตราบใดที่ทรงกลมไม่มีอยู่นอกขอบเขตของ frustum

หากคุณคำนวณระยะทางที่สั้นที่สุดระหว่าง Linesegs (หรือใบหน้าในแบบ 3 มิติ) ระยะทางที่สั้นที่สุดที่พบสามารถใช้เป็นเส้นผ่านศูนย์กลางของ incircle / insphere ที่อยู่ภายใน Frustum ต้นกำเนิดของ incircle / insphere สามารถเพียงเฉลี่ยของจุดยอดทั้งหมด (ผลรวม & หาร) มันจะค่อนข้างเร็วและใช้ได้กับรูปทรงหลายเหลี่ยมนูนทุกชนิด

ข้อเสียเปรียบเพียงอย่างเดียวคือวงกลมหรือทรงกลมนั้นไม่จำเป็นต้องเป็นวงกลมที่ใหญ่ที่สุดหรือเป็นไปได้ สำหรับ frustum ที่มีปริมาตรมากและหนึ่งขอบที่สั้นมากวงกลม / ทรงกลมจะแบ่งพื้นที่ frustums น้อยกว่าที่เป็นไปได้

ความคิดอื่น

หากคุณต้องการแรงบันดาลใจของมุมมอง 3 มิติ - frustum และคุณมีเมทริกซ์เปอร์สเปคทีฟที่ใช้ในการสร้าง frustum นี้คุณก็สามารถใช้เมทริกซ์นั้นกับอินสตรูเมนต์ของคิวบ์ยูนิตได้ (เส้นผ่านศูนย์กลางของแรงบันดาลใจของลูกบาศก์คือความยาวของหนึ่งในขอบของลูกบาศก์ศูนย์อยู่ตรงกลางของลูกบาศก์ซึ่งเป็นค่าเฉลี่ยของจุดยอดของลูกบาศก์)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.