LEVEL 2 · ระดับกลาง
Armature — ทำไมกระดูกเป็นแค่ระบบพิกัด
คำว่า "กระดูก" หลอกให้คิดว่ามันเป็นของแข็งที่ดันเนื้อให้ขยับ ถ้าคิดแบบนั้น พอเจอกรณีที่เนื้อบิดผิดรูปคุณจะหาไม่เจอว่าผิดตรงไหน เพราะกระดูกก็ดู "ถูก" ไปหมด
ของจริง: กระดูกไม่ได้ดันอะไรเลย มันคือระบบพิกัดที่มีพ่อมีลูก และการหมุนพ่อ ทำให้ทุกอย่างที่วัดจากพ่อเปลี่ยนตาม โดยที่ค่าของลูกไม่ถูกแตะ
upper_arm · forearm ไม่ถูกแตะเลย ค่าหมุนของมันยัง (0, 0, 0) แต่หัวกระดูกย้ายจาก (0, 0, 1) ไป (0, -1, 0) — ค่าของลูกคือค่าเทียบพ่อ เสมอลองสร้างกระดูกสองท่อนต่อกัน แล้วหมุนแค่ท่อนล่าง:
=== ท่าพัก — ยังไม่หมุนอะไร ===
upper_arm rotation_euler ที่เก็บไว้ = (0.0, 0.0, 0.0) องศา
upper_arm หัวกระดูกในพิกัดโลก = (0.0, 0.0, 0.0)
forearm rotation_euler ที่เก็บไว้ = (0.0, 0.0, 0.0) องศา
forearm หัวกระดูกในพิกัดโลก = (0.0, 0.0, 1.0)
=== หมุนเฉพาะ upper_arm 90 องศารอบแกน X ===
upper_arm rotation_euler ที่เก็บไว้ = (90.0, -0.0, 0.0) องศา
upper_arm หัวกระดูกในพิกัดโลก = (0.0, 0.0, 0.0)
forearm rotation_euler ที่เก็บไว้ = (0.0, 0.0, 0.0) องศา ← ยัง 0 อยู่
forearm หัวกระดูกในพิกัดโลก = (0.0, -1.0, -0.0) ← แต่ย้ายที่แล้วforearm ไม่เคยถูกแตะ ค่าหมุนของมันยังเป็นศูนย์ทุกแกน แต่มันย้ายจาก (0, 0, 1) ไปอยู่ (0, -1, 0)
ค่าของกระดูกลูกไม่เคยเป็นตำแหน่งจริง มันคือตำแหน่ง เทียบกับพ่อ เสมอ
7.1 ทำไมออกแบบแบบนี้
เพราะมันตรงกับสิ่งที่คุณอยากสั่งจริง ๆ เวลาขยับร่างกาย
ตอนคุณงอศอก คุณไม่ได้คิดว่า "ย้ายมือไปพิกัด (0.3, -0.5, 1.2)" คุณคิดว่า "งอศอก 40 องศา" — แล้วมือก็ไปเอง เพราะมือติดอยู่กับปลายแขน ระบบพิกัดซ้อนกันจึงเป็นการเข้ารหัสความจริงข้อนี้ลงในโครงสร้างข้อมูล
7.2 ผลที่ตามมา ที่ต้องรู้ล่วงหน้า
เมื่อค่าของลูกเป็นค่าเทียบพ่อ สองอย่างนี้จะตามมาเสมอ:
- ความผิดพลาดสะสมลงข้างล่าง — หมุนไหล่ผิด 5 องศา ปลายนิ้วเคลื่อนไปไกลกว่านั้นมาก
- แก้ปลายทางไม่ได้ตรง ๆ — อยากให้มือไปแตะจุดหนึ่ง ต้องไล่หมุนทีละข้อจากต้นทาง ซึ่งช้าและน่ารำคาญ
ข้อหลังนี่เองคือปัญหาที่ IK เกิดมาเพื่อแก้ (บทที่ 9) แต่ก่อนจะไปถึงตรงนั้น ต้องผ่านจุดที่มือใหม่พังบ่อยที่สุดก่อน