ฉันจะโคจรกล้องไปยังจุดที่เป็นเป้าหมายได้อย่างไร


18

ฉันวาดฉากที่กล้องเคลื่อนไหวอย่างอิสระเกี่ยวกับจักรวาล คลาสกล้องจะติดตามตำแหน่งมุมมอง (หรือดู ) ตำแหน่งของกล้องและเวกเตอร์ขึ้น เวกเตอร์ / คะแนนเหล่านี้จะถูกส่งผ่านไปยัง gluLookAt

แพนและซูมนั้นแทบไม่น่าเชื่อ อย่างไรก็ตามฉันกำลังค้นหาการหมุนเกี่ยวกับจุดที่มองว่ามีปัญหามากกว่านี้ ฉันต้องการที่จะเขียน Camera.rotate ฟังก์ชั่นที่ใช้เวลา 2 มุมหนึ่งที่หมุนขึ้น / ลงและหนึ่งที่หมุนซ้าย / ขวาพร้อมทรงกลมจินตนาการว่าเป็นศูนย์กลางเกี่ยวกับการดูที่จุด

มีวิธีง่าย ๆ ในการทำเช่นนี้?

ฉันอ่านสั้น ๆ เกี่ยวกับควอเทอร์เนี่ยน แต่ฉันอยากจะดูว่ามีวิธีแก้ปัญหาที่ง่ายกว่านี้หรือไม่หากการสร้างฉากของฉันค่อนข้างง่าย


คุณมีอะไรในกล่องเครื่องมือของคุณที่จะหมุนจุดรอบจุดกำเนิดให้แกนและมุม?
sam hocevar

ไม่มีอะไรอื่นนอกจากความเข้าใจหลวมของฉันเกี่ยวกับ Quaternions ไม่ ยิ่งฉันดูสิ่งนี้ฉันคิดว่า Quaternions อาจเป็นคำตอบ อย่างไรก็ตามฉันไม่แน่ใจวิธีคำนวณค่าแกน x, y และ z ที่จะใช้ในสูตร Quaternion
ลุค

ฉันจะไม่บอกคุณว่าการเล่นควอเทอร์เนียนไม่ใช่วิธีที่จะไป พวกเขาเป็นทางออกที่ดีในการแก้ไขปัญหาของคุณ แต่คุณจะต้องมีคลาส quaternion และวิธีการโต้ตอบกับ GL และ GLU และฉันรู้สึกว่าคุณควรพยายามทำความคุ้นเคยกับเมทริกซ์การแปลง คนอื่นอาจไม่เห็นด้วย
sam hocevar

พิจารณาสิ่งที่คุณทำการหมุนในการใช้การหมุนเพื่อย้ายไปยังพื้นที่ของโลกหรือสำหรับการย้ายไปยังพื้นที่ของกล้องที่แตกต่าง
Charlie

คำตอบ:


25

สิ่งที่คุณขอเรียกว่าการหมุน Arcball Quaternions เป็นคำตอบที่ง่ายถ้าคุณเข้าใจว่ามันทำงานอย่างไร คุณสามารถบรรลุเป้าหมายเดียวกันได้โดยไม่ต้องมีคำถาม

requisites ก่อน

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

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

วิธีการแก้

  • รับกล้องขึ้นและขวาเวกเตอร์ โปรดทราบว่าพวกเขาควรจะเป็นมาตรฐาน
  • รับเวกเตอร์จากจุดโฟกัสไปยังกล้อง (camPosition - Focus) นี่คือเวกเตอร์ที่คุณกำลังจะหมุน มาเรียกcamFocusVectorนี้กัน
  • ตัดสินใจว่าคุณต้องการหมุนในรูปหันเห / ระยะห่างที่เกี่ยวข้องกับกล้องมากน้อยเพียงใด
  • สร้างเมทริกซ์การหมุนสองตัว เมทริกซ์การหมุนครั้งที่ 1 จะใช้ค่าสูงสุดของกล้องเป็นแกนและมุมหันเหที่คุณตัดสินใจ เมทริกซ์การหมุนครั้งที่ 2 จะใช้ด้านขวาของกล้องเป็นแกนและมุมพิทช์ที่คุณตัดสินใจ
  • ตอนนี้หมุนcamFocusVectorด้วยเมทริกซ์การหมุนใหม่ นี่คือตำแหน่งใหม่ของกล้องเมื่อเทียบกับจุดกำเนิด แน่นอนว่าเราต้องการให้สัมพันธ์กับจุดโฟกัส ...
  • เพิ่มตำแหน่งจุดโฟกัสไปcamFocusVector นี่คือตำแหน่งใหม่ของกล้องของคุณ แปลกล้องของคุณตาม
  • สุดท้ายขอให้กล้องโฟกัสที่จุดโฟกัสโดยเรียกใช้ฟังก์ชัน lookAt () ของคุณ

คำเตือน

คุณจะต้องระวังในบางกรณีหรือภาวะเอกฐานที่กล้องของคุณจะหยุดทำงาน ยกตัวอย่างเช่น ฉันจะให้คุณหาวิธีจัดการกับสิ่งเหล่านั้น

EDIT1: วิธีการคำนวณเวกเตอร์ออร์โธกราฟปกติของกล้อง

คุณรู้ทิศทางของกล้องแล้ว ((cameraPos - focusPoint). normalize ()) ทีนี้สมมติว่ากล้องของคุณมีค่า + Y (หรือแกนที่มีอยู่ในโลกปัจจุบันของคุณคือ ... ที่ขึ้นอยู่กับคุณ) ตอนนี้เพียงแค่ข้ามทิศทางที่มีขึ้นที่จะได้รับสิทธิ ทำ? Nope! เวกเตอร์อัพของคุณนั้นไม่มีมุมฉากอีกต่อไป ในการแก้ไขปัญหาที่ข้ามที่เหมาะสมกับทิศทางและคุณได้รับใหม่ของคุณขึ้นมา

โปรดทราบว่าGram-Schmidtเป็นสิ่งที่ควรนำมาใช้เพื่อเวกเตอร์แบบออร์โทไนซ์

อีกครั้งจดบันทึก caveats เช่นนี้จะล้มเหลวในการทำงานในบางกรณี ( ทิศทางขนานกับขึ้นตัวอย่าง)


โปรดทราบว่าสามารถใช้เวกเตอร์ที่ถูกต้องโดยใช้normalize(up ^ camFocusVector)(หรือตรงกันข้ามกับถ้าใช้มือซ้าย)
sam hocevar

ดูดีจนถึงตอนนี้ทำงานได้อย่างสวยงามสำหรับการหมุนซ้าย / ขวา (ฉันมีเวกเตอร์ขึ้นเพื่อให้ง่าย) '^' หมายถึงอะไรในความคิดเห็นของคุณ @SamHocevar? นั่นเป็นผลิตภัณฑ์ข้ามหรือไม่ นอกจากนี้ฉันจะคำนวณค่าเวกเตอร์ใหม่ได้อย่างไรเมื่อฉันทำการแปลแล้ว?
ลุค

@Luke: ตรวจสอบ EDIT1 ของฉัน
Samaursa

1
@ Samaursa ขอบคุณมาก ทางออกของคุณทำงานได้อย่างสมบูรณ์และฉันเรียนรู้มากมายในกระบวนการ!
ลุค

2
นี่คือคำตอบที่ยอดเยี่ยมขอบคุณมากสำหรับคำอธิบายของคุณ ในกรณีของฉันฉันต้องการกล้องหมุนเฉพาะจุดเป้าหมายในระนาบ XY เท่านั้นและหลังจากทำการคำนวณทั้งหมดฉันก็ตั้งค่า cameraRight.z เป็น 0 แล้วคำนวณเวกเตอร์ cameraUp สิ่งนี้ให้ผลที่ต้องการ แค่คิดว่าจะแบ่งปัน
codemonkey

1

สิ่งที่คุณต้องการคือกล้อง ArcBall ทั่วไปซึ่งโดยทั่วไปคือกล้องที่เก็บตำแหน่งเป้าหมายและช่วยให้คุณย้ายกล้องในลักษณะ "ทรงกลม" รอบ ๆ เป้าหมายนั้น

มันอยู่ใน XNA แต่ IIRC ฉันใช้การติดตั้งนี้มาก่อนและใช้งานได้ดี:

http://roy-t.nl/index.php/2010/02/21/xna-simple-arcballcamera/


การดำเนินงานที่ปรากฏจะย้ายโดยตรงพร้อมเวกเตอร์ที่เหมาะสมซึ่งจะใกล้เคียงกับ arcball ค่าเล็ก ๆ ของจำนวนเงิน เขายังขยับจุด LookAt เหมือนที่ฉันต้องการย้ายกล้อง (ใกล้ แต่แตกต่างกันเล็กน้อย) ฉันเชื่อว่า Samaursa ได้มอบวิธีการที่ง่ายที่สุดในการบรรลุเป้าหมายนี้
ลุค

ขอบคุณสำหรับความคิดเห็นของคุณ. ฉันต้องยอมรับว่าฉันใช้การติดตั้งนี้เป็นบิต "กล่องดำ" แต่ฉันไม่ได้สังเกตเห็นปัญหาใด ๆ คุณอาจจะอธิบายให้กระจ่างเกี่ยวกับวิธีการของ MoveCameraRight / MoveCameraForward? มีการเพิ่มวิธีการเหล่านี้เพื่อเลื่อนกล้องไปรอบ ๆ แต่ไม่ได้เป็นส่วนหนึ่งของส่วนต่อประสาน Arcball หากคุณต้องการหมุนกล้องไปรอบ ๆ เป้าหมายคุณเพียงแค่เปลี่ยนคุณสมบัติ Yaw หรือ Pitch
David Gouveia

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

0

นี่คือรหัสของฉันสำหรับการหมุนไปรอบ ๆ จุดพบว่าตัวเองใช้ซ้ำมาก

float distance;      // Straight line distance between the camera and look at point

// Calculate the camera position using the distance and angles
float camX = distance * -sinf(camAngleX*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));
float camY = distance * -sinf((camAngleY)*(M_PI/180));
float camZ = -distance * cosf((camAngleX)*(M_PI/180)) * cosf((camAngleY)*(M_PI/180));

// Set the camera position and lookat point
gluLookAt(camX,camY,camZ,   // Camera position
          0.0, 0.0, 0.0,    // Look at point
          0.0, 1.0, 0.0);   // Up vector

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

ตอนนี้คุณพูดถึงแล้วฉันคิดว่ามีสองวิธีที่แตกต่างกันในการดูปัญหา ในแอปพลิเคชันของฉันฉันใช้กล้อง ArcBall หมุนรอบเกาะเป้าหมายในทะเลและถ้าฉันใช้อิสรภาพ 3 แกนมันจะดูผิดธรรมดา (เช่นเห็นเกาะคว่ำหรือด้านข้าง)
David Gouveia

ฉันจะทำให้มุมกล้องตรงนี้ได้อย่างไร
rafvasq

0

อัลกอริธึมที่ง่ายมากในการบรรลุซึ่งยอดเยี่ยมมาก:

การเป็น P จุดศูนย์กลางเกี่ยวกับคุณต้องการหมุน (จุด "ดูที่" หรือ "เป้าหมาย"):

translate(-P)

rotate horizontal
rotate vertical

translate(P)

ฉันใช้มันและมันก็ดี

พบแหล่งที่มาที่เว็บไซต์น้องสาว stackoverflow: /programming/287655/opengl-rotating-a-camera-around-a-point

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