บางคนสามารถอธิบาย (เหตุผล) ความหมายของโคลัมกับแถวหลักในการคูณ / การเรียงต่อกันได้หรือไม่


11

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

สิ่งที่ฉันไม่เข้าใจคือสิ่งที่มีความหมายโดยเฉพาะ 'notational Convention' - จากบทความที่นี่และที่นี่ผู้เขียนยืนยันว่ามันไม่ต่างกับวิธีการจัดเก็บเมทริกซ์หรือโอนไปยัง GPU แต่ในวินาที หน้าเมทริกซ์นั้นเห็นได้ชัดว่าไม่เทียบเท่ากับวิธีการวางในหน่วยความจำสำหรับแถวหลัก และถ้าฉันดูเมทริกซ์ที่มีประชากรในโปรแกรมของฉันฉันจะเห็นส่วนประกอบการแปลที่ใช้องค์ประกอบที่ 4, 8 และ 12

ระบุว่า:

"โพสต์การคูณด้วยเมทริกซ์คอลัมน์หลักสร้างผลลัพธ์เช่นเดียวกับการคูณล่วงหน้าด้วยเมทริกซ์แถวหลัก"

ทำไมในตัวอย่างของรหัสต่อไปนี้:

        Matrix4 r = t3 * t2 * t1;
        Matrix4 r2 = t1.Transpose() * t2.Transpose() * t3.Transpose();

Does r! = r2และเหตุใด pos3! = pos สำหรับ :

        Vector4 pos = wvpM * new Vector4(0f, 15f, 15f, 1);
        Vector4 pos3 = wvpM.Transpose() * new Vector4(0f, 15f, 15f, 1);

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

สิ่งหนึ่งที่ไม่ช่วยให้สิ่งนี้ชัดเจนยิ่งขึ้นคือเมื่อให้กับ DirectX แล้วเมทริกซ์ WVP สำคัญของคอลัมน์ของฉันถูกใช้อย่างประสบความสำเร็จในการแปลงจุดยอดด้วยการเรียก HLSL: mul (vector, matrix) ซึ่งน่าจะส่งผลให้เวกเตอร์ แถวหลักดังนั้นเมทริกซ์คอลัมน์หลักที่ได้จากห้องสมุดคณิตศาสตร์ของฉันจะทำงานอย่างไร



คำตอบ:


11

ถ้าฉันดูเมทริกซ์ที่มีประชากรในโปรแกรมของฉันฉันจะเห็นส่วนประกอบการแปลที่ใช้องค์ประกอบที่ 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*BA*BT

ดังนั้นการคูณเมทริกซ์จะสมเหตุสมผลถ้าทั้งสองเมทริกซ์ (และจำไว้ว่า: การคูณเวกเตอร์ / เมทริกซ์เป็นแค่การคูณเมทริกซ์) จะถูกเก็บไว้ในการเรียงลำดับหลักเดียวกัน

แล้วเวกเตอร์คอลัมน์หลักหรือแถวหลักคืออะไร มันเป็นทั้งและไม่ใช่ตามที่ระบุไว้ก่อนหน้า มันเป็นคอลัมน์ที่สำคัญก็ต่อเมื่อมันถูกใช้เป็นเมทริกซ์คอลัมน์และมันก็เป็นเมเจอร์คอลัมน์เมื่อมันถูกใช้เป็นเมทริกซ์แถว

ดังนั้นถ้าคุณมีเมทริกซ์ A ซึ่งเป็นคอลัมน์หลักx*Aหมายความว่า ... ไม่มีอะไร ก็หมายความว่าแต่นั่นไม่ใช่สิ่งที่คุณต้องการจริงๆ ในทำนองเดียวกันจะทำการคูณการย้ายหากเป็นแถวหลักx*ATA*xA

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

เหตุใดในโค้ดต่อไปนี้จึง r! = r2

เพราะรหัสของคุณเสียและบั๊กกี้ ศาสตร์ หากคุณไม่ได้รับผลลัพธ์นี้แสดงว่าการทดสอบความเท่าเทียมของคุณนั้นผิด (ปัญหาความแม่นยำจุดลอยตัว) หรือรหัสการคูณเมทริกซ์ของคุณเสียA * (B * C) == (CT * BT) * AT

ทำไม pos3! = pos สำหรับ

เพราะนั่นไม่สมเหตุสมผล วิธีเดียวที่จะเป็นจริงจะเป็นอย่างไรถ้า และนั่นเป็นความจริงของเมทริกซ์สมมาตรA * t == AT * tA == AT


@Nicol ทุกอย่างเริ่มคลิกแล้ว มีความสับสนเนื่องจากการตัดการเชื่อมต่อระหว่างสิ่งที่ผมเห็นและสิ่งที่ฉันคิดว่าฉันควรจะเป็นห้องสมุดของฉัน (นำมาจากความจริง) ประกาศคอลัมน์หลัก (และคำสั่งซื้อทั้งหมดคูณ ฯลฯ เป็นไปตามนี้) ยังมีหน่วยความจำรูปแบบเป็นแถว - สำคัญ (ตัดสินโดยดัชนีการแปลและความจริง HLSL ทำงานอย่างถูกต้องโดยใช้เมทริกซ์ที่ไม่ได้เปลี่ยน) ฉันเห็นตอนนี้อย่างไรก็ตามวิธีนี้ไม่ได้อยู่ในความขัดแย้ง ขอบคุณมาก!
sebf

2
ฉันเกือบให้ -1 เพื่อพูดสิ่งต่าง ๆ เช่น "นั่นไม่ใช่เมทริกซ์การแปลปกติ" และ "ซึ่งเป็นขยะที่สุด" จากนั้นคุณก็อธิบายต่อไปอย่างชัดเจนว่าทำไมมันถึงเทียบเท่ากันอย่างสมบูรณ์และดังนั้นจึงไม่เป็น "ธรรมชาติ" อีกต่อไป ทำไมคุณไม่ลองลบเรื่องไร้สาระเล็ก ๆ นั้นตั้งแต่ต้น? คำตอบที่เหลือของคุณค่อนข้างดี (สำหรับผู้ที่สนใจ: steve.hollasch.net/cgindex/math/matrix/column-vec.html )
imre

2
@imre: เพราะมันไม่ใช่เรื่องไร้สาระ การประชุมมีความสำคัญเนื่องจากสับสนที่จะมีสองอนุสัญญา นักคณิตศาสตร์ตั้งรกรากในการประชุมเพื่อการฝึกอบรมเมื่อนานมาแล้ว "การฝึกอบรมการถ่ายโอน" (ตั้งชื่อเพราะพวกเขาถูกย้ายจากมาตรฐาน) เป็นการละเมิดของการประชุมที่ เนื่องจากพวกเขาเทียบเท่าพวกเขาจึงไม่ให้ประโยชน์กับผู้ใช้ และเนื่องจากมันแตกต่างกันและสามารถนำไปใช้ในทางที่ผิดได้จึงสร้างความสับสน หรือจะใช้อีกวิธีหนึ่งถ้าไม่มีเมทริกซ์ transposed, OP จะไม่ถามสิ่งนี้ และดังนั้นอนุสัญญาทางเลือกนี้จะสร้างความสับสน
Nicol Bolas

1
@Nicol: เมทริกซ์ที่มีการแปลในวันที่ 12-13-14 ยังคงเป็นแถวหลัก - ถ้าเราใช้เวกเตอร์แถวด้วย (และคูณเป็น vM) ดู DirectX หรือสามารถดูเป็นคอลัมน์หลักใช้กับคอลัมน์เวกเตอร์ (Mv, OpenGL) มันเหมือนกันจริงๆ ในทางกลับกันหากเมทริกซ์มีการแปลใน 3-7-11 ก็สามารถดูได้ว่าเป็นเมทริกซ์แถวหลักที่มีเวกเตอร์คอลัมน์หรือคอลัมน์หลักที่มีเวกเตอร์แถว รุ่นที่ 12-13-14 นั้นเป็นเรื่องปกติมากขึ้น แต่ในความเห็นของฉัน 1) มันไม่ได้เป็นมาตรฐานจริงๆและ 2) การเรียกมันว่าคอลัมน์หลักอาจทำให้เข้าใจผิดเนื่องจากไม่จำเป็นต้องเป็นเช่นนั้น
imre

1
@imre: มันเป็นมาตรฐาน ถามนักคณิตศาสตร์ที่ผ่านการฝึกอบรมจริง ๆ แล้วการแปลจะไปที่ใดและพวกเขาจะบอกคุณว่ามันไปในคอลัมน์ที่สี่ นักคณิตศาสตร์คิดค้นเมทริกซ์ พวกเขาเป็นคนที่กำหนดอนุสัญญา
Nicol Bolas

3

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

อีกข้อหนึ่งคือคุณเก็บเมทริกซ์ไว้ในหน่วยความจำตามลำดับแถวหลักหรือคอลัมน์ใหญ่ โปรดทราบว่า "row-Major" และ "column-major" ไม่ใช่คำศัพท์ที่ถูกต้องสำหรับการอภิปรายเกี่ยวกับการประชุม row-vector / column-vector ... แม้ว่าหลายคนจะใช้ผิดวัตถุประสงค์เช่นนั้น เลย์เอาต์หน่วยความจำแบบแถวหลักและแบบคอลัมน์หลักนั้นแตกต่างกันไปตามทรานสโพสต์เช่นกัน

OpenGL ใช้การประชุมเวกเตอร์คอลัมน์และลำดับการเก็บข้อมูลคอลัมน์หลักและ D3D ใช้การประชุมเวกเตอร์แถวและลำดับการจัดเก็บข้อมูลสำคัญแถว (ดี - อย่างน้อย D3DX, ห้องสมุดคณิตศาสตร์ทำ) ดังนั้นทั้งสองยกเลิกยกเลิกและปรากฏ เลย์เอาต์ของหน่วยความจำเดียวกันนั้นใช้ได้ทั้งกับ OpenGL และ D3D นั่นคือรายการ 16 16 ทุ่นลอยที่จัดเก็บตามลำดับในหน่วยความจำจะทำงานเหมือนกันทั้งใน API

นี่อาจเป็นสิ่งที่ผู้คนบอกว่า "มันสร้างความแตกต่างไม่ได้กับวิธีการจัดเก็บเมทริกซ์หรือถ่ายโอนไปยัง GPU"

สำหรับโค้ดของคุณ r! = r2 เนื่องจากกฎสำหรับการโอนย้ายผลิตภัณฑ์คือ (ABC) ^ T = C ^ TB ^ TA ^ T การขนย้ายกระจายไปที่การคูณด้วยความเคารพ ดังนั้นในกรณีของคุณคุณควรได้รับ r.Transpose () == r2 ไม่ใช่ r == r2

ในทำนองเดียวกัน pos! = pos3 เพราะคุณย้าย แต่ไม่ได้กลับคำสั่งการคูณ คุณควรรับ wpvM * localPos == localPos * wvpM.Tranpose () เวกเตอร์จะถูกตีความโดยอัตโนมัติเป็นเวกเตอร์แถวเมื่อคูณที่ด้านซ้ายของเมทริกซ์และเป็นเวกเตอร์คอลัมน์เมื่อคูณที่ด้านขวาของเมทริกซ์ นอกเหนือจากนั้นไม่มีการเปลี่ยนแปลงวิธีการคูณ

ในที่สุด Re: "เมทริกซ์ WVP สำคัญของคอลัมน์ของฉันถูกใช้อย่างประสบความสำเร็จในการแปลงจุดยอดด้วยการเรียก HLSL: mul (vector, matrix)," ฉันไม่แน่ใจเกี่ยวกับเรื่องนี้ แต่อาจสับสน / ข้อผิดพลาดทำให้เมทริกซ์หลุดออกมา ไลบรารี่คณิตศาสตร์ที่เปลี่ยนไปแล้ว


1

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

ในการคูณเมทริกซ์จำนวนคอลัมน์ของเมทริกซ์แรกควรเท่ากับจำนวนแถวของวินาทีที่สอง (คุณสามารถคูณเมทริกซ์ anxm สำหรับ mxk)

จุด (หรือเวกเตอร์) แสดงด้วย 3 องค์ประกอบ (x, y, z) และสามารถพิจารณาได้ทั้งแบบแถวหรือคอลัมน์:

โคลั่ม (ขนาด 3 X 1):

| x |

| Y |

| Z |

หรือ

แถว (ขนาด 1X3):

| x, y, z |

คุณสามารถเลือกการประชุมที่ต้องการมันเป็นเพียงการประชุม ลองเรียกมันว่าเมทริกซ์การแปล หากคุณเลือกการประชุมแรกเพื่อคูณจุด p สำหรับเมทริกซ์คุณต้องใช้การคูณโพสต์:

T * v (ขนาด 3x3 * 3x1)

มิฉะนั้น:

v * T (ขนาด 1x3 * 3x3)

ผู้เขียนยืนยันว่าไม่มีความแตกต่างกับวิธีการจัดเก็บเมทริกซ์หรือถ่ายโอนไปยัง GPU

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

p2 = B * A * p1; // การประชุมครั้งแรก

p3 = p1 * A * B; // อนุสัญญาที่สอง

p2 == p3;


1

ฉันเห็นองค์ประกอบการแปลที่ใช้องค์ประกอบที่ 4, 8 และ 12หมายความว่าการฝึกอบรมของคุณ "ผิดปกติ"

ส่วนประกอบแปลงเสมอระบุเป็นรายการที่# 13 # 14 # 15ของเมทริกซ์การเปลี่ยนแปลง ( นับองค์ประกอบแรกของอาร์เรย์เป็นองค์ประกอบ # 1 )

เมทริกซ์การแปลงหลักแถวมีลักษณะดังนี้:

[ 2 2 2 1 ]   R00 R01 R02 0  
              R10 R11 R12 0 
              R20 R21 R22 0 
              t.x t.y t.z 1 

เมทริกซ์การแปลงคอลัมน์หลักมีลักษณะดังนี้:

 R00 R01 R02 t.x   2  
 R10 R11 R12 t.y   2 
 R20 R21 R22 t.z   2 
  0   0   0   1    1 

แถวเมทริกซ์ที่สำคัญจะระบุลงไปแถว

การประกาศเมทริกซ์เมเจอร์ของแถวด้านบนเป็นอาร์เรย์เชิงเส้นฉันจะเขียน:

ROW_MAJOR = { R00, R01, R02, 0,  // row 1 // very intuitive
              R10, R11, R12, 0,  // row 2
              R20, R21, R22, 0,  // row 3
              t.x, t.y, t.z, 1 } ; // row 4

ดูเป็นธรรมชาติมาก ๆ เนื่องจากการแจ้งให้ทราบล่วงหน้าภาษาอังกฤษเขียนว่า "แถวหลัก" - เมทริกซ์จะปรากฏในข้อความด้านบนเหมือนกับที่อยู่ในคณิตศาสตร์

และนี่คือจุดที่สับสน

มีการระบุเมทริกซ์หลักของคอลัมน์ลงไปที่คอลัมน์

นั่นหมายถึงการระบุเมทริกซ์การแปลงที่สำคัญคอลัมน์เป็นอาร์เรย์เชิงเส้นในรหัสคุณจะต้องเขียน:

    COLUMN_MAJOR = {R00, R10, R20, 0, // COLUMN # 1 // ตอบโต้ได้ง่ายมาก
                     R01, R11, R21, 0,
                     R02, R12, R22, 0,
                     tx, ty, tz, 1};

โปรดทราบว่านี่เป็นเคาน์เตอร์ที่ใช้งานง่ายอย่างสมบูรณ์ !! เมทริกซ์หลักคอลัมน์มีรายการที่ระบุไว้ในคอลัมน์เมื่อเริ่มต้นอาร์เรย์เชิงเส้นดังนั้นบรรทัดแรก

COLUMN_MAJOR = { R00, R10, R20, 0,

ระบุคอลัมน์แรกของเมทริกซ์:

 R00
 R10
 R20
  0 

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

ดังนั้นส่วนประกอบการแปลจะอยู่ที่ดัชนีอาร์เรย์แบบเส้นตรงเสมอ # 13, # 14 และ # 15 (โดยที่องค์ประกอบแรกคือ # 1) ไม่ว่าคุณจะใช้เมทริกซ์แถวหลักหรือการฝึกอบรมเมเจอร์คอลัมน์

เกิดอะไรขึ้นกับรหัสของคุณและทำไมมันจึงใช้งานได้

สิ่งที่เกิดขึ้นในรหัสของคุณคือคุณมีเมทริกซ์หลักคอลัมน์ใช่ แต่คุณวางองค์ประกอบการแปลผิดจุด เมื่อคุณย้ายเมทริกซ์รายการ # 4 ไปที่รายการ # 13 รายการ # 8 ถึง # 13 และรายการ # 12 ถึง # 15 และคุณมีมัน


0

เหตุผลที่แตกต่างก็คือการคูณเมทริกซ์ไม่ได้สลับกัน ด้วยการคูณตัวเลขปกติถ้า A * B = C มันจะตามมาว่า B * A ยัง = C นี่ไม่ใช่กรณีที่มีเมทริกซ์ นั่นเป็นเหตุผลว่าทำไมการเลือกเรื่องที่สำคัญแบบแถวหรือแบบคอลัมน์

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

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