ระบบพิกัด OpenGL เป็นมือซ้ายหรือมือขวา?


89

ฉันพยายามทำความเข้าใจระบบพิกัด OpenGL อย่างไรก็ตามบทช่วยสอนบางส่วนกล่าวว่าระบบพิกัดเริ่มต้นเป็นมือซ้าย (ดูhttp://www.c-sharpcorner.com/UploadFile/jeradus/OpenGLBasics11172005014307AM/OpenGLBasics.aspx ) และอื่น ๆ บอกว่าเป็นมือขวา (ดูที่http: // www .falloutsoftware.com / tutorials / gl / gl0.htm ) ข้อใดถูกต้อง? ฉันเข้าใจว่าเราสามารถแปลงค่าหนึ่งไปเป็นอีกแบบหนึ่งได้โดยการมิเรอร์ แต่ฉันต้องการทราบพิกัดเริ่มต้น



3
สิ่งนี้ไม่ได้ขึ้นอยู่กับวิธีการเขียนการแปลงของคุณในเฉดสีดังนั้นจึงขึ้นอยู่กับคุณทั้งหมดหรือไม่?
jcoder

แค่สองเซ็นต์ของฉันevl.uic.edu/ralph/508S98/coordinates.htmlมันมีภาพที่อธิบายตัวเองไม่กี่ภาพ
rraallvv

ฉันไม่คิดว่าคุณจะพิจารณาอัปเดตคำตอบที่คุณยอมรับ?
Jonathan Mee

คำตอบ:


134

มีความสับสนบางอย่างที่นี่

ใส่คำอธิบายภาพที่นี่

OpenGL เป็นมือขวาในพื้นที่วัตถุและพื้นที่โลก

แต่ในพื้นที่หน้าต่าง (พื้นที่หน้าจอ aka) เรากำลังทันใดนั้นมือซ้าย

มันเกิดขึ้นได้อย่างไร?

วิธีที่เราได้รับจากมือขวาไปมือซ้ายคือรายการมาตราส่วน z เชิงลบในเมทริกซ์glOrthoหรือการglFrustumฉายภาพ การสเกล z คูณ -1 (ในขณะที่ปล่อย x และ y เหมือนเดิม) มีผลในการเปลี่ยนความถนัดของระบบพิกัด

สำหรับ glFrustum

ใส่คำอธิบายภาพที่นี่ ใส่คำอธิบายภาพที่นี่

ห่างไกลและอยู่ใกล้กับที่ควรจะเป็นบวกกับไกล > ใกล้ พูดไกล = 1000 และใกล้ = 1 จากนั้น C = - (1001) / (999) = -1.002

ดูที่นี่สำหรับรายละเอียดเพิ่มเติมและไดอะแกรม

จากมุมมองของ orthographic glOrtho จะสร้างเมทริกซ์ดังนี้:

ใส่คำอธิบายภาพที่นี่

นี่ซ้าย , ขวา , ด้านล่างและด้านบนเป็นเพียงพิกัดสำหรับซ้ายแนวตั้ง , แนวตั้ง , แนวนอนด้านล่าง , ด้านบนแนวระนาบตัด (รับผิดชอบ)

ใกล้และไกลเครื่องบิน แต่มีการระบุไว้แตกต่างกัน ใกล้พารามิเตอร์ถูกกำหนดให้เป็น

  • ใกล้: ระยะทางไปยังระนาบการตัดความลึกที่ใกล้กว่า ระยะนี้จะเป็นลบหากเครื่องบินอยู่ด้านหลังผู้ชม

และไกล:

  • zFar ระยะทางไปยังระนาบการตัดความลึกที่ไกลขึ้น ระยะนี้จะเป็นลบหากเครื่องบินอยู่ด้านหลังผู้ชม

ที่นี่เรามีปริมาณการดูตามรูปแบบบัญญัติทั่วไป

บัญญัติ

เพราะ Z คูณคือ (-2 / (ไกลใกล้)) เครื่องหมายลบได้อย่างมีประสิทธิภาพเครื่องชั่ง Z โดย -1 ซึ่งหมายความว่า "z" หันไปทางซ้ายในระหว่างการเปลี่ยนแปลงการรับชมซึ่งไม่เป็นที่รู้จักสำหรับคนส่วนใหญ่เนื่องจากพวกเขาทำงานใน OpenGL เป็นระบบพิกัด "มือขวา"

ดังนั้นถ้าคุณโทร

glOrthof(-1, 1, -1, 1, 10, -10) ; // near=10, FAR=-10,

แล้วใกล้ PLANE เป็น10 หน่วยข้างหน้าของคุณ คุณอยู่ที่ไหน? ทำไมที่จุดเริ่มต้นโดยให้แกน x อยู่ทางขวาแกน y อยู่ด้านบนของศีรษะและจมูกของคุณชี้ไปที่แกน z เชิงลบ (นั่นคือค่าเริ่มต้น"โดยค่าเริ่มต้นกล้องจะอยู่ที่จุดเริ่มต้น ชี้ลงแกน z เชิงลบและมีเวกเตอร์ขึ้นเป็น (0, 1, 0) " ) ระนาบใกล้จึงอยู่ที่ z = -10 เครื่องบินห่างไกลเป็น10 หน่วยที่อยู่เบื้องหลังคุณที่ Z


1
"เวกเตอร์ข้างหน้าถูกทำให้เป็นลบใน gluLookAt" - คุณสามารถยืนยันได้หรือไม่ว่าเป็นเช่นนั้น ไม่ใช่ gluPerspective หรือ glFrustum หรือ glOrtho?
Kos

1
จู่ๆเราก็ถนัดซ้ายตั้งแต่พื้นที่คลิปเป็นต้นไปไม่ใช่แค่พื้นที่หน้าต่าง
legends2k

3
+1 สำหรับคำตอบทั้งหมด -1 (รอแทนที่จะเป็น -2) สำหรับ"วิธีที่เราได้รับจากมือขวาไปมือซ้ายเป็นเพราะเวกเตอร์ข้างหน้าถูกลบล้างในการใช้งานมาตรฐานของ gluLookAt () ซึ่งเป็นฟังก์ชัน ทุกคนใช้เพื่อสร้างเมทริกซ์มุมมองเมื่อคุณลบล้างเวกเตอร์ข้างหน้าสิ่งนี้จะมีผลในการเปลี่ยนความถนัดของระบบพิกัด " ซึ่งเป็นเพียงขยะ ...
Christian Rau

2
... การลบเวกเตอร์ไปข้างหน้าในการgluLookAtคำนวณไม่มีผลอะไรกับการเปลี่ยนความถนัดของพื้นที่พิกัดนั่นเป็นเพียงวิธีคำนวณเมทริกซ์นี้ (และในความเป็นจริงแล้ว + z เป็น"ถอยหลัง"ในพื้นที่ทางขวา) gluLookAtไม่ทำอะไรอื่นนอกจากคำนวณการเปลี่ยนแปลงร่างกายแบบแข็งธรรมดา (การหมุน + การแปล) ในพื้นที่ทางขวามือ เป็นเมทริกซ์การฉายภาพที่ใช้โดยไปป์ไลน์ฟังก์ชันคงที่ (และโดยปกติจะใช้เฉดสีด้วย) ซึ่งทำการเปลี่ยนแปลงความถนัดมือจริงในการปฏิเสธองค์ประกอบ z ตามที่คุณได้ระบุไว้ในคำตอบของคุณแล้ว
Christian Rau

2
@bobobobo คุณจะบอกว่าถ้าคุณคำนวณเมทริกซ์มุมมองของคุณโดยใช้ฟังก์ชันการหมุนและการแปลเท่านั้น (ซึ่งฉันเดาว่าคุณคงไม่ได้กล่าวหาว่าเปลี่ยนความถนัดมือ) แทนgluLookAtจะไม่มีการเปลี่ยนแปลงพื้นฐานในขณะที่gluLookAtทำหรือไม่? ไม่แน่นอน (เนื่องจากคุณอาจทราบดีว่าไม่ใช่"ทุกคน" ที่ใช้gluLookAtสำหรับการคำนวณเมทริกซ์มุมมอง) เนื่องจากคุณควรทราบว่าgluLookAtไม่มีอะไรอื่นนอกจากการเรียกการหมุนเวียนและการแปลจำนวนมาก (แม้ว่าพวกเขาจะปลอมตัวเป็นการเปลี่ยนแปลงคำ"ระดับสูง" ของ พื้นฐาน " ) โดยไม่มีการสะท้อนกลับมาเกี่ยวข้อง
Christian Rau

27

ตามค่าเริ่มต้นพิกัดอุปกรณ์ที่เป็นมาตรฐานจะอยู่ทางซ้าย

glDepthRange เป็นค่าเริ่มต้น [0, 1] (ใกล้ไกล) ทำให้แกน + z ชี้ไปที่หน้าจอและ + x ไปทางขวาและ + y ขึ้นเป็นระบบมือซ้าย

การเปลี่ยนช่วงความลึกเป็น [1, 0] จะทำให้ระบบถนัดขวา

อ้างคำตอบก่อนหน้าจาก Nicol : (ขีดฆ่าคืองานของฉันอธิบายด้านล่าง)

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

เมื่อคุณทิ้งไปป์ไลน์ฟังก์ชันคงที่คุณจะจัดการกับ "clip-space" โดยตรง ข้อกำหนด OpenGL กำหนดพื้นที่คลิปเป็นระบบพิกัดที่เป็นเนื้อเดียวกัน 4D เมื่อคุณติดตามการแปลงผ่านพิกัดอุปกรณ์ที่เป็นมาตรฐานและลงไปที่พื้นที่หน้าต่างคุณจะพบสิ่งนี้

พื้นที่หน้าต่างอยู่ในพื้นที่พิกเซลของหน้าต่าง จุดเริ่มต้นอยู่ที่มุมล่างซ้ายโดย + Y จะขึ้นและ + X ไปทางขวา ฟังดูคล้ายกับระบบพิกัดทางขวามาก แล้ว Z ล่ะ?

ช่วงความลึกเริ่มต้น (glDepthRange) กำหนดค่า Z ใกล้ 0 และค่าไกล Z เพื่อหนึ่ง ดังนั้น + Z จะห่างจากตัวแสดง

นั่นคือระบบพิกัดทางซ้าย ใช่คุณสามารถเปลี่ยนการทดสอบเชิงลึกจาก GL_LESS เป็น GL_GREATER และเปลี่ยน glDepthRange จาก [0, 1] เป็น [1, 0] แต่สถานะเริ่มต้นของ OpenGL คือการทำงานในระบบพิกัดมือซ้าย และไม่มีการแปลงใดที่จำเป็นเพื่อให้ได้พื้นที่หน้าต่างจากสเปซคลิปลบล้าง Z ดังนั้นสเปซคลิปเอาท์พุตของจุดยอด (หรือเรขาคณิต) Shader จึงเป็นสเปซที่ถนัดซ้าย (นะมันคือสเปซที่เป็นเนื้อเดียวกัน 4D ดังนั้น ยากที่จะตรึงความถนัดลง)

ในไปป์ไลน์ฟังก์ชั่นคงที่เมทริกซ์การฉายภาพมาตรฐาน (ผลิตโดย glOrtho, glFrustum และสิ่งที่คล้ายกัน) ทั้งหมดจะเปลี่ยนจากพื้นที่สำหรับคนถนัดขวาเป็นมือซ้าย พวกเขาพลิกความหมายของ Z; เพียงตรวจสอบเมทริกซ์ที่พวกเขาสร้างขึ้น ในช่องว่างสายตา + Z จะเคลื่อนเข้าหาผู้ชม ในพื้นที่หลังการฉายภาพจะเคลื่อนออกไป

ฉันสงสัยว่า Microsoft (และ GLide) ไม่สนใจที่จะทำการปฏิเสธในเมทริกซ์การฉายของพวกเขา

ฉันโจมตีส่วนหนึ่งเนื่องจากมันแตกต่างจากสิ่งที่ฉันค้นพบ

การเปลี่ยน DepthRange หรือ DepthFunc และการใช้ ClearDepth (0) ก็ใช้งานได้ แต่เมื่อใช้ทั้งสองอย่างพวกเขาจะยกเลิกซึ่งกันและกันกลับเป็นระบบมือซ้าย


ช่วงความลึกต้องไม่เป็น [1, -1] ฉันคิดว่าคุณหมายถึง [1, 0] นอกจากนี้ก่อนหน้านี้ได้รับการชี้ให้เห็นแล้ว
Nicol Bolas

คำตอบของคุณดีมากแย่เกินไปสำหรับคำถาม DirectX คุณควรโพสต์ใหม่ที่นี่!
hultqvist

3
@SigTerm ทำไมคุณคิดว่าการแก้ไขข้อเท็จไม่คุ้มค่า? ฉันใช้เวลาหลายชั่วโมงในการแก้ไขปัญหาพิกัดจุดยอดและการสร้างการหมุนเมทริกซ์เพียงเพื่อที่จะพบว่าระบบพิกัดเริ่มต้นนั้นไม่ได้ใช้มือขวา
hultqvist

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

1
ฉันพบว่าคำตอบนั้นให้ความกระจ่างมากและมันก็ปรากฏขึ้นในการค้นหาดังนั้นมันจึงคุ้มค่าสำหรับฉัน
เรียนรู้ OpenGL ES

13

NDC เท่านั้น

คุณควรสังเกตว่าOpenGL เท่านั้นที่รู้ NDC! และนั่นคือระบบพิกัดทางซ้าย

ไม่ว่าคุณจะใช้ระบบพิกัดใด - ระบบพิกัดแกนมือซ้ายหรือมือขวา - ทั้งหมดจะต้องสะท้อนไปที่ NDC หากคุณต้องการคุณสามารถจัดการพื้นที่โลกได้ทั้งหมดในฐานะระบบพิกัดมือซ้าย

ทำไมเราจึงใช้ระบบพิกัดทางขวาในอวกาศ?

ฉันคิดว่ามันเป็นเรื่องธรรมดา มันก็ไม่ บางทีมันแค่ต้องการแยกจาก DirectX


3
ฉันคิดว่าสิ่งนี้ไม่ได้รับการทำซ้ำมากพอ แผนภาพทั้งหมดเหล่านี้แสดง "modeling transform", "view transform", "perspective transform" ไม่สามารถแสดงได้ว่าไม่ใช่ส่วนที่แท้จริงของ OpenGL คุณสามารถทำการแปลงทั้งหมดของคุณด้วยตนเองมีหรือไม่มีเฉดสีมีหรือไม่มีเมทริกซ์ก็ได้
ทอม

3
อาจจะดีกว่าถ้าทำซ้ำเพื่อรวมคำว่า "พิกัดอุปกรณ์ที่เป็นมาตรฐาน"
Tommy

6
OpenGL มาก่อน DirectX ภายในไม่กี่ปีดังนั้น OpenGL จึงไม่ได้พยายามแยกตัวเองออกจาก DirectX อย่างแน่นอน Alex St. John หัวหน้าผู้พัฒนา DirectX ได้กล่าวว่าการตัดสินใจของไมโครซอฟท์ในการเลือกใช้ระบบประสานงานมือซ้ายนั้น "ส่วนหนึ่งมาจากความชอบส่วนตัว" และ "เป็นการเลือกโดยพลการ"
Chris Nolet

สิ่งนี้ไม่ถูกต้องทั้งหมด OpenGL ยังรู้ระบบพิกัดการตัดเนื่องจากการตัดเกิดขึ้นในนั้น ระบบพิกัดคลิปมีความถนัดเช่นเดียวกับระบบพิกัด NDC
plasmacel

7

หนังสือ "คู่มือการเขียนโปรแกรม WebGl" โดย Kouichi Matsuda ใช้เวลาเกือบสิบหน้าใน "WebGl / OpenGl: Left or Right Handed?"

ตามหนังสือ:

  • ในทางปฏิบัติคนส่วนใหญ่ใช้ระบบคนถนัดขวา

  • OpenGl เป็นระบบมือซ้ายภายใน

  • ภายในลึกกว่านั้นจริงๆแล้วมันก็ไม่ใช่เช่นกัน ที่ด้านล่างสุด OpenGl ไม่สนใจค่า z ลำดับที่คุณวาดสิ่งต่างๆจะกำหนดสิ่งที่วาดไว้ด้านบน (วาดสามเหลี่ยมก่อนจากนั้นรูปสี่เหลี่ยมรูปสี่เหลี่ยมจะแทนที่รูปสามเหลี่ยม)

ฉันไม่เห็นด้วยกับคำว่า "มันไม่ใช่" แต่นั่นอาจเป็นคำถามเชิงปรัชญาอยู่ดี


7
The order in which you draw things determines what is drawn on top (draw a triangle first, then a quad, the quad overrides the triangle). นี่เป็นความจริงในกรณีที่ไม่มีการทดสอบเชิงลึก ในกรณีที่มีการทดสอบเชิงลึกค่า z ของชิ้นส่วนจะถูกเปรียบเทียบกับค่าในบัฟเฟอร์ความลึกและชิ้นส่วนจะถูกทิ้งหากไม่ผ่านการทดสอบความลึกดังนั้นรูปสี่เหลี่ยมอาจเขียนทับสามเหลี่ยมหรือไม่ก็ได้ขึ้นอยู่กับความลึกและ ใช้ฟังก์ชันความลึก
chrisvarnz

3

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

แก้ไข: หากคุณไม่ไว้วางใจฉันเพียงแค่ทดลองในจุดยอด Shader ของคุณโดยการเพิ่มเมทริกซ์การแปลและคุณสามารถดูได้อย่างง่ายดายว่า Opengl ถนัดซ้ายหรือไม่


0

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

บัฟเฟอร์เชิงลึกค่อนข้างตรงกันข้ามและนี่คือจุดที่ NDC (Normalized Device Coordinates) เข้ามามีบทบาท หากผ่าน GL_LESS ไปยัง glDepthFunc หมายความว่าพิกเซลจะวาดเมื่อพวกเขาอยู่ใกล้คุณมากกว่าที่มีอยู่แล้วในบัฟเฟอร์ความลึกพิกเซลจะถือว่าอยู่ในระบบพิกัดทางซ้าย

มีอีกหนึ่งระบบพิกัดและนั่นคือวิวพอร์ต! ระบบพิกัดของวิวพอร์ตคือ + x ชี้ไปทางขวาและ + y ชี้ลง ฉันคิดว่า ณ จุดนี้ความถนัดมือนั้นน่าเบื่อเพราะเราจัดการกับ x, y ณ จุดนี้เท่านั้น

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

ของเคี้ยว. มันไม่สมเหตุสมผลที่จะเรียกทิศทาง z ของระบบพิกัดมือขวาว่าเป็นเวกเตอร์ไปข้างหน้า :) ฉันคิดว่า Microsoft ตระหนักถึงสิ่งนี้เมื่อพวกเขาออกแบบ Direct3D

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