Slerping กระจกหมุน


9

ฉันหมุนตัวละครเกมของฉันเพื่อดูที่เป้าหมายโดยใช้รหัสต่อไปนี้:

        transform.rotation = Quaternion.Slerp(startQuaternion, lookQuaternion, turningNormalizer*turningSpeed/10f)

startQuaternion เป็นการหมุนปัจจุบันของตัวละครเมื่อกำหนดเป้าหมายใหม่

lookQuaternion เป็นทิศทางที่ตัวละครควรมองและมันก็เป็นแบบนี้:

    destinationVector = currentWaypoint.transform.position - transform.position;
    lookQuaternion = Quaternion.LookRotation(destinationVector, Vector3.up);

TurningNormalizer เพิ่งTime.deltaTimeเพิ่มขึ้นและturningSpeedเป็นค่าคงที่ที่กำหนดในตัวแก้ไข

ปัญหาคือในขณะที่ตัวละครเปลี่ยนตามที่ควรจะเป็นส่วนใหญ่มันมีปัญหาเมื่อมันต้องเข้าใกล้ 180 องศา จากนั้นในบางครั้งก็กระวนกระวายใจและสะท้อนการหมุน:

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

ในภาพที่วาดไม่ดีตัวละคร (ด้านขวา) จะเริ่มหันไปทางวงกลมทางด้านซ้าย แทนที่จะแค่หมุนไปทางซ้ายหรือขวามันเริ่มต้น "mirror dance" นี้:

  1. มันเริ่มหมุนไปทางด้านหน้าใหม่
  2. จากนั้นมันก็หันไปที่มุมเดียวกันทันที แต่อยู่อีกด้านหนึ่งและหมุนไปเรื่อย ๆ

มันเป็นการ“ ทำมิเรอร์” นาน ๆ จนกว่ามันจะมองไปที่เป้าหมาย นี่คือสิ่งที่มี quaternions, slerping / lerping หรืออย่างอื่น?

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

หลักสูตรนี้ทำให้เกิดคำถามเพิ่มเติมทำไมตัวละครไม่สามารถเคลื่อนไหวและหมุนในเวลาเดียวกันโดยไม่มีปัญหา รหัสที่ใช้สำหรับการเคลื่อนไหว:

transform.Translate(Vector3.forward * runningSpeed/10f * Time.deltaTime);

'lookQuaternion' กำลังถูกอัพเดททุกเฟรมหรือไม่? ถ้าเป็นเช่นนั้นข้อสันนิษฐานของฉันคือความไม่ถูกต้องเล็ก ๆ บางอย่างกำลังนำไปสู่การกระวนกระวายใจที่ผู้เล่น 'ดู' การหมุนของมุมมองและทิศทางใหม่ในการมองนั้นอยู่อีกด้านหนึ่งของ 'ข้างหลัง' ... .
Steven Stadnicki

คำตอบ:


5

แต่ละการวางแนวในพื้นที่ 3 มิติสามารถแสดงได้ด้วย 2 หน่วย quaternions ที่แตกต่างกันqและ-q(เมื่อตะกี้ส่วนประกอบฉลาดq) ตัวอย่างเช่นการวางแนวที่แสดงโดยเมทริกซ์เอกลักษณ์ 3x3 Iสามารถแสดงด้วย 2 quaternions:

 q:  { 0,  0,  0},  1
-q:  {-0, -0, -0}, -1

ทั้งสองเป็นตัวแทนของการวางแนวเดียวกันในพื้นที่ 3 มิติผลิตภัณฑ์จุดของพวกเขาเป็นอย่างแน่นอน-1แต่ละคนอยู่ในซีกโลกอื่นตรงด้านตรงข้ามของ hypersphere

ผลลัพธ์ที่คุณสังเกตได้เมื่อ slerp ใช้ส่วนโค้งยาวกว่าในการหมุนคือเมื่อ slerping ระหว่าง 2 quaternions ที่ไม่ได้อยู่ในซีกโลกเดียวกัน หากสิ่งนั้นเกิดขึ้นเพียงแค่ลบหนึ่งในนั้นก่อนที่จะ slerping พวกเขาแล้ว slerp จะใช้ส่วนโค้งที่สั้นกว่า

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


ฉันสงสัยว่าฉันเข้าใจคุณถูกต้องหรือไม่ขณะที่ฉันลองมัน if(Quaternion.Dot (lookQuaternion, startQuaternion) < 0) { startQuaternion = Quaternion.Inverse(startQuaternion); }แต่ไม่ได้แก้ไขปัญหา ขออภัยสำหรับรูปแบบที่ไม่ดีฉันไม่สามารถเชื่องส่วนความคิดเห็นนี้
Esa

เกือบ แต่ไม่ได้นั่นคือการดำเนินการที่แตกต่างกันมากกว่าInverse ฉันไม่ได้ใช้ C # แต่จากหน้าตาของ docu ดูเหมือนว่าคุณสามารถใช้ฟังก์ชันลบได้โดยตรง Negateif(Quaternion.Dot (lookQuaternion, q) < 0) { q.x = -q.x; q.y = -q.y; q.z = -q.z; q.w = -q.w; }
Maik Semder

if(Quaternion.Dot (lookQuaternion, startQuaternion) < 0) { startQuaternion = Quaternion.Negate(startQuaternion); }
Maik Semder

ฉันเกรงว่าสิ่งเหล่านี้จะไม่สามารถแก้ไขปัญหาได้ ฉันได้อัปเดตคำถามแล้ว
Esa

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

1

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

นี่คือสิ่งที่ทำให้เกิดการสะท้อนโดยทั่วไปทุกครั้งที่คุณกำลังแก้ไขมันจะหันไปทางอื่นในขณะที่ยังคงรักษามุมไว้

ตามลิงค์นี้

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

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


1

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

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

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

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

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