การหมุนกล้อง 3D


9

ได้โปรดยกโทษให้ฉันด้วย แต่ฉันต้องการความช่วยเหลือและฉันติดอยู่กับเรื่องนี้มาสองสามสัปดาห์แล้วตอนนี้ฉันไม่มีความคืบหน้าและทุกที่ที่ฉันไปและฉันเห็นคำตอบที่ต่างออกไป ฉันมีเคล็ดลับและคำแนะนำเพียงพอตอนนี้ฉันแค่ต้องการใครสักคนที่จะให้คำตอบสำหรับฉันที่จะทำงานย้อนกลับจากเพราะฉันไม่เข้าใจ

สิ่งที่ทำให้เรื่องนี้เกิดความสับสนมากที่สุดคือวิธีที่ทุกคนใช้ชุดของการประชุมหรือกฎระเบียบที่แตกต่างกันและคำตอบของพวกเขาขึ้นอยู่กับการประชุมของพวกเขาเอง

ดังนั้นนี่คือชุดของการประชุมที่ฉันสร้างขึ้นตามสิ่งที่ดูเหมือนจะเป็นเรื่องธรรมดาและมีเหตุผลที่สุด:

  1. กฎมือขวาสำหรับแกน
  2. Positive Y เพิ่มขึ้น Positive Z กำลังเข้าหาผู้ชม Positive X อยู่ทางขวา
  3. Row Major matrixes, transposed เมื่อถูกส่งไปยังเฉดสี
    • Pitch: การหมุนรอบแกน X
    • Yaw: การหมุนรอบแกน y
    • ม้วน: การหมุนเกี่ยวกับแกน z
  4. ลำดับการหมุน: หมุน, ระยะห่าง, Yaw (ถูกต้องไหมมีคนตรวจสอบฉันได้ไหม)
  5. ค่าการหมุนในเชิงบวกมองลงมาจากปลายบวกของแกนผลลัพธ์ในการหมุนตามเข็มนาฬิกา
  6. ทิศทางเริ่มต้นสำหรับการหมุน 0 ในทุกแกนคือเวกเตอร์ที่ชี้ไปที่ลบ Y

.. ได้รับอนุสัญญาเหล่านั้น (โดยทั้งหมดแก้ไขฉันถ้าพวกเขาผิด!) วิธีหนึ่ง:

  • เขียนฟังก์ชั่น LookAt หรือไม่ (lookAt (ตำแหน่งเวกเตอร์, เลนส์เวกเตอร์, เวกเตอร์ขึ้นไป))
  • คำนวณเมทริกซ์การหมุน (การหมุน (x, y, z))

ฉันลองตอบคำถามสองข้อนี้อย่างน้อย 3 สัปดาห์ที่ผ่านมาฉันได้เขียนฟังก์ชัน LookAt & Rotation Matrix ใหม่อย่างน้อย 30 ครั้งฉันได้ทดสอบวิธีการมากมายและอ่านเนื้อหาที่ฉันเคยเห็น เว็บไซต์หลายร้อยแห่งและอ่านคำถามที่ตอบแล้วคัดลอกรหัสของคนอื่นและไม่มีอะไรที่ฉันทำมาจนถึงตอนนี้ทุกอย่างก็ให้ผลลัพธ์ที่ผิด ซึ่งบางตัวได้สร้างเอาท์พุทที่แปลกประหลาดเฮฮาไม่ได้ใกล้เคียงกับการหมุนที่ถูกต้อง

ฉันทำงานเกี่ยวกับเรื่องนี้ทุกคืนยกเว้นเมื่อคืนเพราะฉันรู้สึกหงุดหงิดมากกับความล้มเหลวซ้ำ ๆ ที่ฉันต้องหยุดและหยุดพัก

โปรดแสดงให้ฉันเห็นว่าวิธีการที่ถูกต้องคืออะไรฉันจึงสามารถทำงานย้อนกลับจากนั้นและหาวิธีการทำงานฉันแค่ไม่ได้รับคำตอบที่ถูกต้องและนี่ทำให้ฉันบ้าไปหน่อย!

ฉันกำลังเขียนใน Java แต่ฉันจะใช้รหัสที่เขียนในภาษาใด ๆ รหัสการแสดงผล 3 มิติส่วนใหญ่ของฉันทำงานได้อย่างยอดเยี่ยมจริงๆมันเป็นเพียงคณิตศาสตร์ที่ฉันไม่เข้าใจ

อัปเดต: แก้ไขแล้ว

ขอขอบคุณสำหรับความช่วยเหลือของคุณ! ตอนนี้ฉันมีฟังก์ชั่น LookAt ที่ใช้งานได้จริงที่ฉันเข้าใจแล้วและฉันก็ไม่มีความสุข (ถ้ามีใครอยากเห็นมันด้วยทุกวิถีทางถาม)

ฉันลองอีกครั้งในการสร้างเมทริกซ์การหมุนตามตัวแปร pitch / yaw / roll และดูเหมือนว่าจะล้มเหลวอีกครั้ง แต่ฉันตัดสินใจทิ้งความพยายามที่จะใช้มุมออยเลอร์สำหรับกล้อง freelook เนื่องจากดูเหมือนว่าจะไม่เหมาะสำหรับ บทบาทแทนฉันจะสร้างคลาส quaternion อาจมีโชคที่ดีกว่าที่จะลงไปในเส้นทางนั้นมิฉะนั้นฉันจะใช้วิธี pitch / yaw เป็นพิกัดทรงกลมและอาศัยฟังก์ชัน LookAt ที่ทำงานใหม่สำหรับการหมุน

หากใครก็ตามประสบปัญหาคล้ายกันและต้องการถามคำถามกับฉัน

อย่างน้อยฉันก็ไม่ติดขัดอีกต่อไปขอบคุณสำหรับความช่วยเหลือ!

คำตอบ:


15

สิ่งที่คุณกำลังมองหาสามารถพบได้ในคำอธิบายที่ดีมากนี้: http://www.songho.ca/opengl/gl_transform.html

แต่เมื่อฉันพบว่ามันสับสนโดยไม่ต้องใช้มือจับฉันจะพยายามอธิบายที่นี่

ณ จุดนี้คุณต้องพิจารณาระบบการประสานงาน 5 ระบบและความสัมพันธ์ระหว่างกัน เหล่านี้คือพิกัดหน้าต่างพิกัดอุปกรณ์ปกติพิกัดตาพิกัดโลกและพิกัดวัตถุ

พิกัดหน้าต่างสามารถมองเห็นเป็นพิกเซล "กายภาพ" บนหน้าจอของคุณ นี่เป็นพิกัดที่ระบบหน้าต่างอ้างอิงถึงและหากคุณใช้งานในความละเอียดดั้งเดิมของจอภาพนี่เป็นพิกเซลแต่ละพิกเซล ระบบพิกัดหน้าต่างเป็นจำนวนเต็ม 2D และสัมพันธ์กับหน้าต่างของคุณ นี่คือ x + ที่เหลือและ y + ลงด้วยจุดกำเนิดที่มุมซ้ายบน glViewportคุณพบเหล่านี้เมื่อคุณตัวอย่างเช่นการโทร

ชุดที่สองคือพิกัดอุปกรณ์ปกติ สิ่งเหล่านี้อ้างถึงการตั้งค่าพื้นที่โดยพอร์ตมุมมองที่ใช้งานอยู่ พื้นที่ที่มองเห็นได้ของพอร์ตมุมมองเริ่มจาก -1 ถึง +1 ดังนั้นจึงมีจุดกำเนิดอยู่ตรงกลาง x + ถูกทิ้งและ y + ขึ้น คุณยังมี z + คือ "out" ของฉาก นี่คือสิ่งที่คุณอธิบายใน 1

คุณไม่สามารถควบคุมวิธีการที่คุณได้รับจากพิกัดอุปกรณ์ที่ได้รับการทำให้เป็นมาตรฐานไปยังพิกัดหน้าต่างซึ่งจะทำเพื่อคุณโดยปริยาย การควบคุมเดียวที่คุณมีคือผ่านglViewportหรือคล้ายกัน

เมื่อทำงานกับ openGL ผลลัพธ์สุดท้ายของคุณจะอยู่ในพิกัดอุปกรณ์ปกติ ดังนั้นคุณต้องกังวลว่าจะทำให้ฉากของคุณแสดงผลได้อย่างไร หากคุณตั้งค่าเมทริกซ์การฉายและแบบจำลองมุมมองเป็นเมทริกซ์เอกลักษณ์คุณสามารถวาดในพิกัดเหล่านี้ได้โดยตรง ตัวอย่างนี้ใช้เมื่อใช้เอฟเฟ็กต์แบบเต็มหน้าจอ

ถัดไปคือพิกัดตา นี่คือโลกที่เห็นจากกล้อง ผลที่ตามมาคือจุดกำเนิดอยู่ในกล้องและมีแกนแนวตั้งเหมือนกันกับการใช้พิกัดของอุปกรณ์

เพื่อให้ได้จากพิกัดตาไปยังอุปกรณ์พิกัดคุณสร้างเมทริกซ์การฉาย ที่ง่ายที่สุดคือการฉายภาพ orthographic ที่เพียงแค่ปรับค่าที่เหมาะสม การฉายภาพมุมมองมีความซับซ้อนมากขึ้นและเกี่ยวข้องกับมุมมองการจำลอง

ในที่สุดคุณก็มีระบบพิกัดโลก นี่คือระบบพิกัดที่โลกของคุณถูกกำหนดและกล้องของคุณเป็นส่วนหนึ่งของโลกนี้ นี่มันเป็นสิ่งสำคัญที่จะทราบว่าการหมุนแกนเป็นเพียงที่คุณกำหนดพวกเขา ถ้าคุณชอบ z + เหมือนว่ามันก็โอเคอยู่แล้ว

ที่จะได้รับจากพิกัดโลกเพื่อพิกัดตาคุณกำหนดเมทริกซ์มุมมอง lookAtซึ่งสามารถทำได้กับสิ่งที่ต้องการ สิ่งที่เมทริกซ์นี้ทำคือ "ย้าย" โลกเพื่อให้กล้องอยู่ที่จุดกำเนิดและมองลงไปที่แกน z

ในการคำนวณดูเมทริกซ์นั้นง่ายมากคุณต้องเปลี่ยนกล้อง โดยทั่วไปคุณจำเป็นต้องกำหนดเมทริกซ์ต่อไปนี้:

M=x[1]Y[1]Z[1]-พี[1]x[2]Y[2]Z[2]-พี[2]x[3]Y[3]Z[3]-พี[3]0001

สามารถใช้เวกเตอร์ x, y และ z ได้โดยตรงจากกล้อง ในกรณีที่มองคุณจะได้รับมาจากเป้าหมายตา (กลาง) และค่าขึ้น ชอบมาก

Z=nโอRม.aล.ผมZอี(อีYอี-เสื้อaRก.อีเสื้อ)x=nโอRม.aล.ผมZอี(ยูพี×Z)Y=Zx

แต่ถ้าคุณมีค่าเหล่านี้อยู่รอบตัวคุณก็สามารถเอามันไปได้

การรับ p ค่อนข้างยุ่งยากกว่าเล็กน้อย มันไม่ได้เป็นตำแหน่งในพิกัดโลก แต่ตำแหน่งในพิกัดกล้อง วิธีแก้ไขง่ายๆที่นี่คือการเริ่มต้นเมทริกซ์สองตัวอันที่มีเพียง x, y และ z และอีกอันที่มี -eye และคูณพวกมันเข้าด้วยกัน ผลลัพธ์คือเมทริกซ์มุมมอง

สำหรับวิธีนี้อาจดูในรหัส:

mat4 lookat(vec3 eye, vec3 target, vec3 up)
{
    vec3 zaxis = normalize(eye - target);    
    vec3 xaxis = normalize(cross(up, zaxis));
    vec3 yaxis = cross(zaxis, xaxis);     

    mat4 orientation(
       xaxis[0], yaxis[0], zaxis[0], 0,
       xaxis[1], yaxis[1], zaxis[1], 0,
       xaxis[2], yaxis[2], zaxis[2], 0,
         0,       0,       0,     1);

    mat4 translation(
              1,       0,       0, 0,
              0,       1,       0, 0, 
              0,       0,       1, 0,
        -eye[0], -eye[1], -eye[2], 1);

    return orientation * translation;
}

รหัสเต็ม

และในที่สุดเพื่อความสมบูรณ์คุณยังมีระบบพิกัดวัตถุ นี่คือระบบพิกัดที่เก็บตาข่าย ด้วยความช่วยเหลือของโมเดลเมทริกซ์พิกัดตาข่ายจะถูกแปลงเป็นระบบพิกัดโลก ในทางปฏิบัติโมเดลและเมทริกซ์มุมมองจะรวมกันเป็นเมทริกซ์โมเดลวิว


1
ถ้าฉันสามารถลงคะแนนคำตอบนี้ร้อยครั้งฉันจะ ขอบคุณสำหรับคำตอบที่ละเอียดถี่ถ้วนและสมบูรณ์เกี่ยวกับทุกสิ่งที่ฉันสับสนและจัดหารหัส & ลิงก์ด้วย! ฉันใช้เวลาทั้งวันในการอ่านหนังสือคณิตศาสตร์เกี่ยวกับเรื่องนี้และด้วยคำตอบของคุณและโค้ดตัวอย่างและหน้าเชื่อมโยงหากนี่ยังไม่เพียงพอสำหรับฉันที่จะเข้าใจสิ่งนี้ฉันควรเลิกตอนนี้ ถ้าฉันสามารถขอคำอธิบายได้เพียงครั้งเดียวในตัวอย่างสุดท้ายของรหัสฉันจะพูดได้ไหมว่าเมทริกซ์เหล่านั้นอยู่ในลำดับหลักของคอลัมน์และอีกอันหนึ่งข้างต้นอยู่ในแถวหลัก?
เกรดี้

นี่คือความสับสนเล็กน้อยเมทริกซ์เป็นคอลัมน์ที่สำคัญ แต่คอลัมน์อยู่ในแถว ดังนั้นในการแมปคณิตศาสตร์จริงกับรหัสที่คุณต้องการในการแปลงเมทริกซ์ ดูgithub.com/rioki/glm/blob/master/src/matrix.h#l72นี้แผนที่ตรงกับ openGL float[16]และวิธีการที่มันจะถ้าใช้
rioki

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