ถ้าฉันดูเมทริกซ์ที่มีประชากรในโปรแกรมของฉันฉันจะเห็นส่วนประกอบการแปลที่ใช้องค์ประกอบที่ 4, 8 และ 12
ก่อนที่ผมจะเริ่มต้นมันเป็นสิ่งสำคัญที่จะเข้าใจ: ที่นี้หมายถึงการฝึกอบรมของคุณมีแถวที่สำคัญ ดังนั้นคุณตอบคำถามนี้:
WVP matrix ของคอลัมน์หลักของฉันถูกใช้อย่างประสบความสำเร็จในการแปลงจุดยอดด้วยการเรียก HLSL: mul (vector, matrix) ซึ่งควรส่งผลให้เวกเตอร์ได้รับการปฏิบัติเหมือนแถวสำคัญดังนั้น matrix matrix คอลัมน์ที่ห้องสมุดคณิตศาสตร์ของฉันทำงานได้อย่างไร
ค่อนข้างง่าย: เมทริกซ์ของคุณเป็นแถวหลัก
ผู้คนจำนวนมากใช้เมทริกซ์แบบแถวหรือทรานสปอนที่พวกเขาลืมว่าเมทริกซ์นั้นไม่ได้มุ่งเน้นตามธรรมชาติ ดังนั้นพวกเขาจึงเห็นเมทริกซ์การแปลดังนี้:
1 0 0 0
0 1 0 0
0 0 1 0
x y z 1
นี่คือเมทริกซ์แปลขนย้าย นั่นไม่ใช่เมทริกซ์การแปลปกติที่ดูเหมือน การแปลจะอยู่ในคอลัมน์ที่ 4 ไม่ใช่แถวที่สี่ บางครั้งคุณอาจเห็นสิ่งนี้ในตำราซึ่งเป็นขยะที่สุด
ง่ายที่จะทราบว่าเมทริกซ์ในอาร์เรย์นั้นเป็นแถวหรือคอลัมน์ใหญ่ หากเป็นแถวหลักการแปลจะถูกเก็บไว้ในดัชนี 3, 7 และ 11 หากเป็นคอลัมน์หลักการแปลจะถูกเก็บไว้ในดัชนี 12, 13 และ 14 แน่นอนดัชนีฐานแน่นอน
ความสับสนของคุณเกิดจากการเชื่อว่าคุณกำลังใช้เมทริกซ์คอลัมน์หลักเมื่อคุณใช้เมตริกแถวหลัก
คำสั่งที่แถวกับคอลัมน์ที่สำคัญคือการประชุมสัญกรณ์เท่านั้นเป็นจริงทั้งหมด กลไกของการคูณเมทริกซ์และการคูณเมทริกซ์ / เวกเตอร์เหมือนกันโดยไม่คำนึงถึงอนุสัญญา
การเปลี่ยนแปลงคือความหมายของผลลัพธ์
เมทริกซ์ 4x4 ทั้งหมดเป็นเพียงตาราง 4x4 ของตัวเลข ไม่จำเป็นต้องอ้างถึงการเปลี่ยนแปลงของระบบพิกัด อย่างไรก็ตามเมื่อคุณกำหนดความหมายให้กับเมทริกซ์เฉพาะตอนนี้คุณจำเป็นต้องรู้ว่าอะไรที่เก็บอยู่ในนั้น
รับเมทริกซ์การแปลที่ฉันแสดงให้คุณข้างต้น นั่นเป็นเมทริกซ์ที่ถูกต้อง คุณสามารถเก็บเมทริกซ์นั้นไว้float[16]
ในหนึ่งในสองวิธี:
float row_major_t[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
float column_major_t[16] = {1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1};
อย่างไรก็ตามฉันบอกว่าเมทริกซ์การแปลนี้ผิดเพราะการแปลผิดที่ ฉันได้กล่าวไว้โดยเฉพาะว่ามันถูกนำไปใช้เทียบกับอนุสัญญามาตรฐานสำหรับวิธีการสร้างเมทริกซ์การแปลซึ่งควรมีลักษณะเช่นนี้:
1 0 0 x
0 1 0 y
0 0 1 z
0 0 0 1
ลองดูวิธีการจัดเก็บเหล่านี้:
float row_major[16] = {1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1};
float column_major[16] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1};
ขอให้สังเกตว่าcolumn_major
เป็นเหมือนกับrow_major_t
เป็น ดังนั้นถ้าเราใช้เมทริกซ์การแปลที่เหมาะสมและเก็บเป็นคอลัมน์หลักมันจะเหมือนกับการแปลงเมทริกซ์นั้นและเก็บไว้เป็นแถวหลัก
นั่นคือสิ่งที่มีความหมายโดยเป็นเพียงการประชุมสัญกรณ์ มีการประชุมสองชุดจริง ๆ คือหน่วยความจำและการขนย้าย ที่เก็บหน่วยความจำคือคอลัมน์เทียบกับแถวหลักขณะที่การโอนย้ายเป็นปกติเทียบกับการย้าย
หากคุณมีเมทริกซ์ที่สร้างขึ้นตามลำดับแถวหลักคุณสามารถรับเอฟเฟกต์เดียวกันได้โดยการสลับเมทริกซ์คอลัมน์หลักของเมทริกนั้น และในทางกลับกัน.
การคูณเมทริกซ์สามารถทำได้ทางเดียวเท่านั้น: รับสองเมทริกซ์ตามลำดับเฉพาะคุณคูณค่าบางค่าเข้าด้วยกันและเก็บผลลัพธ์ ตอนนี้A*B != B*A
แต่รหัสที่มาที่แท้จริงสำหรับเป็นเช่นเดียวกับรหัสสำหรับA*B
B*A
พวกเขาทั้งสองเรียกใช้รหัสเดียวกันเพื่อคำนวณผลลัพธ์
รหัสการคูณเมทริกซ์ไม่สนใจว่าเมทริกซ์จะถูกเก็บในลำดับคอลัมน์หลักหรือแถวหลัก
ไม่สามารถพูดแบบเดียวกันสำหรับการคูณเวกเตอร์ / เมทริกซ์ และนี่คือเหตุผล
การคูณเวกเตอร์ / เมทริกซ์เป็นความเท็จ มันไม่สามารถทำได้ อย่างไรก็ตามคุณสามารถคูณเมทริกซ์ด้วยเมทริกซ์อื่น ดังนั้นหากคุณแกล้งเวกเตอร์เป็นเมทริกซ์คุณก็สามารถคูณเวกเตอร์ / เมทริกซ์ได้อย่างมีประสิทธิภาพเพียงแค่ทำการคูณเมทริกซ์ / เมทริกซ์
เวกเตอร์ 4D ถือได้ว่าเป็นคอลัมน์เวกเตอร์หรือแถวเวกเตอร์ นั่นคือเวกเตอร์ 4D สามารถคิดได้ว่าเป็นเมทริกซ์ 4x1 (จำไว้ว่า: ในรูปของเมทริกซ์, จำนวนแถวมาก่อน) หรือเมทริกซ์ 1x4
แต่นี่คือสิ่ง: กำหนดสองเมทริกซ์ A และ B A*B
จะถูกกำหนดก็ต่อเมื่อจำนวนคอลัมน์ของ A เท่ากับจำนวนแถวของ B ดังนั้นถ้า A เป็นเมทริกซ์ 4x4 ของเรา B ต้องเป็นเมทริกซ์ที่มี 4 แถว ในนั้น. ดังนั้นคุณไม่สามารถดำเนินการA*x
ที่ x เป็นแถวเวกเตอร์ ในทำนองเดียวกันคุณไม่สามารถดำเนินการx*A
ที่ x เป็นคอลัมน์ - เวกเตอร์
ด้วยเหตุนี้ไลบรารีคณิตศาสตร์เมทริกซ์ส่วนใหญ่จึงทำให้สมมติฐานนี้: หากคุณคูณเวกเตอร์กับเมทริกซ์คุณต้องทำการคูณที่ใช้งานได้จริงไม่ใช่ตัวที่ไม่มีเหตุผล
ให้เรานิยามสำหรับเวกเตอร์ 4D ใด ๆ ต่อไปนี้ C
จะเป็นคอลัมน์เวกเตอร์เมทริกซ์รูปแบบของx
และR
จะเป็นแถวเวกเตอร์เมทริกซ์x
รูปแบบของ ให้นี้สำหรับ 4x4 ใดเมทริกซ์ A, แสดงให้เห็นถึงเมทริกซ์คูณโดยคอลัมน์เวกเตอร์A*C
x
และR*A
แสดงเมทริกซ์คูณแถวของเวกเตอร์x
โดย A
แต่ถ้าเราดูสิ่งนี้โดยใช้คณิตศาสตร์เมทริกซ์ที่เข้มงวดเราจะเห็นว่าสิ่งเหล่านี้ไม่เท่ากัน R*A
ไม่สามารถเหมือนกันA*C
ได้ นี่เป็นเพราะแถวเวกเตอร์นั้นไม่เหมือนกับคอลัมน์ - เวกเตอร์ พวกมันไม่ใช่เมทริกซ์เดียวกันดังนั้นพวกมันจึงไม่ให้ผลลัพธ์ที่เหมือนกัน
อย่างไรก็ตามพวกเขามีความสัมพันธ์ในทางเดียว R != C
มันเป็นความจริงว่า อย่างไรก็ตามมันก็เป็นความจริงเช่นกันโดยที่Tคือการดำเนินการแปลงสัญญาณ เมทริกซ์สองตัวเป็นการแปลงผ่านกันR = CT
นี่คือความจริงที่ตลก เนื่องจากเวกเตอร์ถือว่าเป็นเมทริกซ์พวกเขาก็มีคำถามเกี่ยวกับที่เก็บข้อมูลคอลัมน์และแถวหลัก ปัญหาคือว่าพวกเขาทั้งสองมีลักษณะเดียวกัน อาร์เรย์ลอยนั้นเหมือนกันดังนั้นคุณจึงไม่สามารถบอกความแตกต่างระหว่าง R และ C เพียงแค่ดูข้อมูล เพียงวิธีการที่จะบอกความแตกต่างได้โดยวิธีการที่พวกเขาจะใช้
หากคุณมีสองเมทริกซ์ A และ B และ A ถูกเก็บไว้เป็นแถวที่สำคัญและ B เป็นคอลัมน์ที่สำคัญคูณนั้นคือความหมายสมบูรณ์ คุณได้รับเรื่องไร้สาระเป็นผล ก็ไม่ได้จริงๆ ศาสตร์สิ่งที่คุณได้รับจะเทียบเท่ากับการทำ หรือ; พวกมันเหมือนกันทางคณิตศาสตร์AT*B
A*BT
ดังนั้นการคูณเมทริกซ์จะสมเหตุสมผลถ้าทั้งสองเมทริกซ์ (และจำไว้ว่า: การคูณเวกเตอร์ / เมทริกซ์เป็นแค่การคูณเมทริกซ์) จะถูกเก็บไว้ในการเรียงลำดับหลักเดียวกัน
แล้วเวกเตอร์คอลัมน์หลักหรือแถวหลักคืออะไร มันเป็นทั้งและไม่ใช่ตามที่ระบุไว้ก่อนหน้า มันเป็นคอลัมน์ที่สำคัญก็ต่อเมื่อมันถูกใช้เป็นเมทริกซ์คอลัมน์และมันก็เป็นเมเจอร์คอลัมน์เมื่อมันถูกใช้เป็นเมทริกซ์แถว
ดังนั้นถ้าคุณมีเมทริกซ์ A ซึ่งเป็นคอลัมน์หลักx*A
หมายความว่า ... ไม่มีอะไร ก็หมายความว่าแต่นั่นไม่ใช่สิ่งที่คุณต้องการจริงๆ ในทำนองเดียวกันจะทำการคูณการย้ายหากเป็นแถวหลักx*AT
A*x
A
ดังนั้นลำดับของการคูณเวกเตอร์ / เมทริกซ์จึงเปลี่ยนไปขึ้นอยู่กับการเรียงลำดับข้อมูลที่สำคัญของคุณ (และไม่ว่าคุณจะใช้เมทริกซ์ transposed)
เหตุใดในโค้ดต่อไปนี้จึง r! = r2
เพราะรหัสของคุณเสียและบั๊กกี้ ศาสตร์ หากคุณไม่ได้รับผลลัพธ์นี้แสดงว่าการทดสอบความเท่าเทียมของคุณนั้นผิด (ปัญหาความแม่นยำจุดลอยตัว) หรือรหัสการคูณเมทริกซ์ของคุณเสียA * (B * C) == (CT * BT) * AT
ทำไม pos3! = pos สำหรับ
เพราะนั่นไม่สมเหตุสมผล วิธีเดียวที่จะเป็นจริงจะเป็นอย่างไรถ้า และนั่นเป็นความจริงของเมทริกซ์สมมาตรA * t == AT * t
A == AT