ใช้ Quaternions: ฉันจะทำอะไรกับพวกเขา? (ไม่มีคณิตศาสตร์)


24

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

เท่าที่ฉันเข้าใจ:

Quaternion สามารถอธิบาย 2 สิ่ง:

  1. การวางแนวปัจจุบันของวัตถุ 3 มิติ
  2. การแปลงการหมุนที่วัตถุทำได้ (rotationChange)

คุณสามารถทำอะไรกับ Quaternion:

คูณ:

  1. Quaternion endOrientation = การหมุน QuaternionChange * Quaternion currentOrientation;

    ตัวอย่างเช่น: วัตถุ 3 มิติของฉันหันไปทางซ้าย 90 องศา - และการหมุนของฉันฉันคูณคือการหมุน 180 องศาไปทางขวาในที่สุดวัตถุ 3 มิติของฉัน 90 °หันไปทางขวา

  2. Quaternion rotationChange = Quaternion endRotation * Quaternion.Inverse (startRotation);

    ด้วยวิธีนี้คุณจะได้รับการหมุนเปลี่ยนซึ่งสามารถนำไปใช้กับการวางแนวอื่น

  3. Vector3 endPostion = การหมุน Quaternion เปลี่ยน * Vector3 currentPosition;

    ตัวอย่างเช่น: วัตถุ 3 มิติของฉันอยู่ในตำแหน่ง (0,0,0) และการหมุนของฉันฉันคูณคือการหมุน 180 องศาไปทางขวาการวางตำแหน่งของฉันเป็นอะไรที่คล้ายกัน (0, -50,0) ภายใน Quaternion นั้นมีแกน - และหมุนรอบแกนนั้น คุณหันจุดรอบแกน Y องศานั้น

  4. Vector3 rotatedOffsetVector = การหมุน Quaternion เปลี่ยน * Vector3 currentOffsetVector;

    ตัวอย่างเช่น: ทิศทางเริ่มต้นของฉันแสดงขึ้น - (0,1,0) และการหมุนของฉันฉันคูณคือการหมุน 180 องศาไปทางขวาทิศทางสิ้นสุดของฉันแสดงลง (0, -1,0)

การผสม (Lerp และ Slerp):

  1. Quaternion currentOrientation = Quaternion.Slerp (startOrientation, endOrientation, interpolator)

    ถ้าผู้แก้ไขคือ 1: currentOrientation = endOrientation

    ถ้าตัวแก้ไขคือ 0: currentOrientation = startOrientation

    Slerp interpolates แม่นยำยิ่งขึ้น Lerp interpolates ปฏิบัติมากขึ้น

คำถามของฉัน:

ทุกอย่างที่ฉันอธิบายจนถึงตอนนี้ถูกต้องหรือไม่?

นั่นคือ "ทั้งหมด" ที่คุณสามารถทำได้กับ Quaternions (obv. ไม่ได้)

คุณสามารถทำอะไรกับพวกเขาได้อีก?

ผลิตภัณฑ์ Dot และผลิตภัณฑ์ Cross ระหว่าง 2 Quaternions มีประโยชน์อย่างไร

แก้ไข:

อัปเดตคำถามพร้อมคำตอบ


สมมติว่าคุณไม่มี 2 แต่มีnทิศทางที่แตกต่างกัน (ทัศนคติ, ท่าทาง, ฯลฯ ) จากนั้นคุณสามารถหาค่าเฉลี่ยได้โดยใช้ตุ้มน้ำหนักทำการสรุป slerp / lerp อย่างมีประสิทธิภาพ นอกจากนี้คุณยังสามารถแปลงควอเทอเรียนเป็นโรเตอร์ซึ่งเทียบเท่ากับการใช้ความเร็วเชิงมุมในระยะเวลาหนึ่งกับร่างกายที่แข็งเกร็ง ดังนั้นคุณสามารถอธิบายการรวมความเร็วเชิงมุมกับควอเทอร์เนียนได้เช่นกัน นอกจากนี้คุณยังสามารถประมาณได้ว่าการหมุนของทิศทางสองแบบนั้นแตกต่างกันอย่างไร
teodron

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

4
"และเพื่อให้สามารถทำงานกับการหมุน 3 มิติได้จำเป็นต้องใช้ Quaternions" ฉันไม่สามารถเน้นได้ว่าประโยคนี้เป็นเท็จเพียงใด คุณสามารถใช้มุมของออยเลอร์หรือ Tait-Bryan สำหรับการพัฒนาเกมปัญหาเดียวคือล็อค gimbal หากคุณต้องการเป็นผู้พัฒนาเกมคุณจะต้องเรียนรู้คณิตศาสตร์ในจุดหนึ่ง
Bálint

1
"ผู้พัฒนาเกม" และ "ไม่ได้เรียนคณิตศาสตร์" เป็นบทกวี
Margaret Bloom

2
ฉันซาบซึ้งในสิ่งที่คุณพยายามทำกับคำถาม แต่คำตอบควรอยู่ในคำตอบไม่ใช่คำถาม สร้างคำตอบ "สรุป" หากคุณคิดว่ามันคุ้มค่าที่จะเปรียบเทียบ
พื้นฐาน

คำตอบ:


23

การคูณ

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

ดังนั้นถ้าฉันต้องการหมุนวัตถุโดยrotationChangeเริ่มจากวัตถุcurrentOrientationฉันจะเขียนดังนี้:

Quaternion newOrientation = rotationChange * currentOrientation;

(เช่นการแปลงสแต็คขึ้นไปทางซ้าย - เหมือนกับการประชุมเมทริกซ์ของ Unity การหมุนขวาสุดจะใช้ครั้งแรก / ที่ปลายสุด "โลคอล")

และถ้าฉันต้องการแปลงทิศทางหรือชดเชยเวกเตอร์ด้วยการหมุนฉันจะเขียนดังนี้:

Vector3 rotatedOffsetVector = rotationChange * currentOffsetVector;

(Unity จะสร้างข้อผิดพลาดในการคอมไพล์ถ้าคุณทำตรงกันข้าม)

การผสม

สำหรับกรณีส่วนใหญ่คุณสามารถหลีกเลี่ยงการหมุนแบบ Lerping นั่นเป็นเพราะมุมที่ใช้ "ภายใต้ประทุน" ใน quaternion เป็นครึ่งหนึ่งมุมของการหมุนทำให้มันอย่างมีนัยสำคัญที่ใกล้ชิดกับการประมาณเชิงเส้นของ Lerp กว่าสิ่งที่ต้องการเมทริกซ์ (ซึ่งโดยทั่วไปจะไม่ Lerp กัน!) ตรวจสอบประมาณ 40 นาทีในวิดีโอนี้สำหรับคำอธิบายเพิ่มเติม

กรณีหนึ่งเมื่อคุณต้องการ Slerp จริงๆก็คือเมื่อคุณต้องการความเร็วที่สม่ำเสมอตลอดเวลาเช่นการสอดแทรกระหว่างคีย์เฟรมบนไทม์ไลน์ของภาพเคลื่อนไหว สำหรับกรณีที่คุณสนใจว่าเอาท์พุทอยู่ตรงกลางระหว่างสองอินพุต (เช่นการผสมเลเยอร์ของภาพเคลื่อนไหว) จากนั้น Lerp จะทำหน้าที่ค่อนข้างดี

อะไรนะ?

สินค้า dotสองยูนิท quaternions ให้โคไซน์ของมุมระหว่างพวกเขาเพื่อให้คุณสามารถใช้ผลิตภัณฑ์จุดเป็นตัวชี้วัดของความคล้ายคลึงกันถ้าคุณจะต้องเปรียบเทียบผลัด นี่เป็นสิ่งที่คลุมเครือเล็กน้อยดังนั้นสำหรับรหัสที่อ่านง่ายกว่านี้ฉันมักจะใช้Quaternion.Angle (a, b)แทนซึ่งชัดเจนกว่าว่าเรากำลังเปรียบเทียบมุมในหน่วยที่คุ้นเคย (องศา)

วิธีการอำนวยความสะดวกประเภทนี้ที่ Unity นำเสนอสำหรับควอเทอร์เนียนนั้นมีประโยชน์อย่างยิ่ง ในเกือบทุกโครงการฉันใช้อันนี้อย่างน้อยสองสามครั้ง :

Quaternion.LookRotation(Vector3 forward, Vector3 up)

สิ่งนี้สร้างความเป็น quaternion ที่:

  • หมุนโลคัล z + แกนเพื่อชี้ไปตามforwardอาร์กิวเมนต์เวกเตอร์
  • หมุนแกน y + ในท้องถิ่นเพื่อชี้จุดที่ใกล้ที่สุดให้กับupอาร์กิวเมนต์เวกเตอร์หากมีการระบุไว้หรือ(0, 1, 0)หากไม่ได้ระบุไว้

เหตุผลที่ "up" รับเฉพาะ "ใกล้เคียงที่สุด" ก็คือระบบนั้นถูกบ่อนทำลาย หันหน้าไปทาง z + เพื่อforwardใช้สององศาอิสระ (เช่นหันเหและพิทช์) ดังนั้นเรามีอิสระเหลืออีกเพียงหนึ่งระดับ (ม้วน)

ฉันพบว่าบ่อยครั้งที่ฉันต้องการบางสิ่งบางอย่างที่มีคุณสมบัติความถูกต้องตรงข้าม: ฉันต้องการให้ y + ชี้upเฉพาะและ z + ท้องถิ่นเพื่อให้ใกล้เคียงที่สุดforwardกับอิสรภาพที่เหลืออยู่

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

คุณอาจได้รับสิ่งนี้หากคุณต้องการที่อยู่อาศัยป้อมปืนของรถถังเพื่อเผชิญหน้ากับเป้าหมายโดยไม่ต้องหลุดออกจากตัวถังเมื่อเล็งขึ้น / ลง

เราสามารถสร้างฟังก์ชั่นอำนวยความสะดวกของเราเองเพื่อใช้LookRotationในการยกน้ำหนัก:

Quaternion TurretLookRotation(Vector3 approximateForward, Vector3 exactUp)
{
    Quaternion rotateZToUp = Quaternion.LookRotation(exactUp, -approximateForward);
    Quaternion rotateYToZ = Quaternion.Euler(90f, 0f, 0f);

    return rotateZToUp * rotateYToZ;
}

ที่นี่เราหมุนโลคอล y + เป็น z + และโลคอล z + เป็น y

จากนั้นเราก็หมุน Z + ใหม่กับทิศทางของเราขึ้น (เพื่อผลสุทธิคือ Y ท้องถิ่น + แต้มโดยตรงพร้อมexactUp) และใหม่ y + ใกล้เคียงเป็นไปได้ที่จะเมื่อตะกี้ทิศทางไปข้างหน้า (เพื่อผลสุทธิคือ Z ท้องถิ่น + จุดที่ใกล้ที่สุดเท่าที่เป็นไปได้พร้อมapproximateForward)

อีกวิธีที่สะดวกมีประโยชน์คือQuaternion.RotateTowardsซึ่งฉันมักใช้เช่น:

Quaternion newRotation = Quaternion.RotateTowards(
                             oldRotation, 
                             targetRotation,
                             maxDegreesPerSecond * Time.deltaTime
                         );

สิ่งนี้ช่วยให้เราสามารถเข้าใกล้targetRotationด้วยความเร็วที่สม่ำเสมอและควบคุมได้โดยไม่คำนึงถึงอัตราเฟรม - สำคัญสำหรับการหมุนที่ส่งผลต่อผลลัพธ์ / ความเป็นธรรมของกลไกการเล่นเกม (เช่นการหมุนการเคลื่อนไหวของตัวละครหรือการติดตามป้อมปืน Lerping / Slerping อย่างไร้เดียงสาในสถานการณ์นี้สามารถนำไปสู่กรณีที่การเคลื่อนไหวได้รับปลากะพงขาวที่ความเร็วสูงส่งผลกระทบต่อความสมดุลของเกม (นั่นไม่ได้บอกว่าวิธีการเหล่านี้ผิด - มีวิธีการใช้อย่างถูกต้องโดยไม่เปลี่ยนความเป็นธรรมมันแค่ต้องการการดูแลRotateTowardsให้ทางลัดที่สะดวกสบายที่ดูแลเรื่องนี้ให้เรา)


เคล็ดลับ: เพิ่ม & t = 40m ไปที่ท้าย URL วิดีโอดังนั้นมันจะกระโดดตรงไปที่นั่น (เลือกได้เช่น 40m5s) จุดผลิตภัณฑ์ Quaternion มีประโยชน์เมื่อต้องรับมือกับเกมรูปทรงกลมเช่นกัน - หรือกว้างขึ้นเมื่อปรับทิศทางชิ้นส่วนของทรงกลมที่หมุน
ลุคบริกส์

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

ความคิดที่ดี - เป็นตี 3 ที่นี่ (ดังนั้นฉันคิดว่ามันจะออกมาซึ่งพูดพล่อยๆเล็กน้อย!) แต่ฉันมีความสุขที่จะดึงบางสิ่งบางอย่างร่วมกันในวันพรุ่งนี้ (ถ้าฉันจำได้!)
ลุ

1
แก้ไข: ฉันมีความคิดเล็กน้อยเกี่ยวกับคำตอบดังนั้นจึงยอมรับความท้าทาย! อย่างน้อยฉันจะทำเครื่องหมายว่าเป็นบาดแผลที่หยาบเพื่อให้ผู้คนสามารถรับรู้ถึงการเผาไหม้ตอนดึกที่เข้ามา: P
ลุคบริกส์

เราจะไปที่นั่น! ฉันพยายามที่จะครอบคลุมในความรู้สึกภาพรวมกราฟิกบนพื้นฐานที่คำตอบของคุณครอบคลุมฟังก์ชั่นพื้นฐานที่ดีจริงๆ ฉันคิดว่าถึงเวลานอนแล้ว!
ลุคบริกส์

14

ใช้ผลิตภัณฑ์จุดที่ใด

ในเอกภาพหนึ่งในผู้ใช้ที่พบมากที่สุดของผลิตภัณฑ์จุดคือเมื่อใดก็ตามที่คุณตรวจสอบถ้าสอง quaternions มีค่าเท่ากันผ่านหรือ== !=Unity คำนวณผลิตภัณฑ์ดอทเพื่อตรวจสอบความเหมือนกันมากกว่าการเปรียบเทียบค่า x, y, z, w ภายในโดยตรง มันคุ้มค่าที่จะเก็บไว้ในใจเพราะมันทำให้การโทรมีราคาแพงกว่าที่คุณอาจคาดหวังว่าจะเป็น

เรายังใช้มันในกรณีการใช้งานที่น่าสนใจด้วยเช่นกัน

สนุกไปกับผลิตภัณฑ์ quaternion dot - โลกทรงกลมและวงโคจร

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

ประการแรกเรามีชุดการหมุนทั้งหมดที่ต้องพิจารณา:

  1. (เป็นทางเลือก) ดาวรอบศูนย์กลางกาแลคซี
  2. ดาวเคราะห์รอบดาวฤกษ์
  3. ความเอียงของดาวเคราะห์
  4. การหมุนของดาวเคราะห์
  5. ตำแหน่งของเซลล์กริดใกล้เคียง (หมุนรอบแกนดาวเคราะห์) *
  6. ระนาบการโคจรหลายวง

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

ดาวเคราะห์หมุนรอบ

ที่สำคัญเพื่อให้เราสามารถหมุนและเอียงดาวเคราะห์ได้อย่างถูกต้องในสถานการณ์นี้เราต้องแกนล็อคขั้วเพื่อให้สามารถแกว่งขึ้น / ลงบนภาพด้านบนเท่านั้น (เช่นการแกว่ง "ขึ้น" เมื่อผู้เล่นเดินทาง ทิศตะวันตกเฉียงเหนือ) นั่นคือจุดที่ผลิตภัณฑ์ quaternion dot เข้ามาหากเราไม่ได้ใช้ผลิตภัณฑ์ดอทที่นี่และเพียงแค่คูณความเอียงด้วยซ้ำ

เอียง 'ดาวเคราะห์' อย่างไม่ถูกต้อง

สังเกตว่าเสาของ 'ดาวเคราะห์' ที่โคจรรอบเราเอียงไปทางดวงดาวอย่างไร นี่ไม่ใช่สิ่งที่เกิดขึ้นจริง - การเอียงอยู่ในทิศทางที่แน่นอน

สรุปหัวข้อสั้น ๆ โดยไม่ต้องไปไกลเกินไป:

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

โดยได้รับเพียงมุมที่เราลดลงบางส่วนของการหมุนที่ไม่พึงประสงค์ ในเวลาเดียวกันเราก็ลงเอยด้วยการวัดลองจิจูดซึ่งมีประโยชน์สำหรับการนำทางเช่นเดียวกับสภาพอากาศในท้องถิ่น

* ดาวเคราะห์ถูกสร้างขึ้นจากจำนวนของเซลล์ตาราง แสดงเฉพาะคนใกล้เคียงเท่านั้น


2
นี่เป็นงานที่ยอดเยี่ยมในการกำหนดฉากและกระตุ้นให้เกิดปัญหา แต่ฉันยังคงสับสนเล็กน้อยเกี่ยวกับวิธีการคำนวณทางคณิตศาสตร์ของผลคูณจุด quaternion (เช่น. ผลิตภัณฑ์สเกลาร์dot(a, b) = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.wเมื่อเทียบกับองค์ประกอบ quaternion ซึ่งเราใช้โซ่ร่วมกัน การหมุน) จะช่วยเราแก้ปัญหานี้ ฉันยินดี upvote ถ้าคุณสามารถทำอย่างละเอียดในภายหลังเล็กน้อย (ฉันไม่ได้ตั้งใจที่จะให้คุณจาก slerp ของคุณ ... ฉันหมายถึงการนอนหลับ!)
DMGregory

@DGGory คำตอบสั้น ๆ คือเอียงคือคำตอบหนึ่งที่แปลก ทุกอย่างประกอบไปด้วยดียกเว้นอย่างใดอย่างหนึ่ง (ดาวเคราะห์จะดูเหมือนวอกแวกรอบดาวของมันเป็นอย่างอื่น) ฉัน (หวังว่า!) จะเพิ่มบริบทเพิ่มเติมในวันพรุ่งนี้!
ลุคบริกส์

@DMGregory ฉันได้เพิ่มข้อมูลเพิ่มเติม (ฉันนอนไม่หลับ!) - หวังว่ามันจะชัดเจนขึ้น
ลุคบริกส์

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

@DMGregory ฉันไม่คุ้นเคยกับ quaternions แต่ถ้านี่คือการหมุนบนทรงกลมนี่ก็ไม่ใช่การหมุนขององค์ประกอบ นี่คือการใช้เรขาคณิตทรงกลมกับเวกเตอร์เพื่อคำนวณเวกเตอร์ปกติสำหรับ "เส้น" บนพื้นผิวของทรงกลม AKA เส้นรอบวงใด ๆ อีกครั้งคำตอบนั้นสมเหตุสมผลหรือไม่ทำคำถามนี้ แต่ฉันเชื่อว่าพวกเขาใช้รูปทรงกลม
The Great Duck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.