ระบบสุริยะสามารถแสดงอย่างถูกต้องในอวกาศ 3 มิติโดยใช้คู่ (หรือยาว) ได้หรือไม่?


15

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


คุณกำหนดเป้าหมายภาษาใด: C / C ++ Java? อื่น ๆ อีก?
Laurent Couvidou

4
@lorancou: longไม่เกี่ยวข้องเขาระบุไว้อย่างชัดเจนขนาดของ
DeadMG

@DeadMG ซึ่งสามารถเป็น 32 บิตใน C / C ++ 64 long longบิตเป็นมากกว่า แต่ใช่สิ่งที่เรียกว่า nitpicking ถ้าคุณต้องการ
Laurent Couvidou

เพียงใช้ BigInteger ภาษาส่วนใหญ่มีตัวแปรบางอย่าง - ค่าจำนวนเต็มไม่ จำกัด ขนาด (การใช้งานคือ O (บันทึก (n)))
ashes999

นั่นอาจเป็นคำตอบหากเกมไม่หนักเกินไปในการคำนวณ
Laurent Couvidou

คำตอบ:


11

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

นั่นทำให้ขอบเขตของระบบสุริยะอยู่ที่:

7,376,000,000 km = 7.376x10 ^ 9 km = 7.376x10 ^ 14 cm ≈ 7.4x10 ^ 14 cm

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

printf("%.0Lf\n", 7.4e14);
printf("%.0Lf\n", 7.4e14 + 1.0);
printf("%.0Lf\n", 7.4e14 + 2.0);

Output:
-------
740000000000000
740000000000001
740000000000002

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

ระวังให้ดีนั่นก็เพียงพอแล้วที่จะแสดงมันในแบบจำลองแต่อย่าคาดหวังว่าจะทำให้สิ่งนี้เจ็บปวด คุณจะต้องแปลงเป็น 32 บิตลอยอาจเปลี่ยนแหล่งกำเนิดของคุณเพื่อให้คุณมีความแม่นยำเพียงพอในวัตถุใกล้และคุณอาจต้องพึ่งพา Z- บัฟเฟอร์และกลอุบาย frustum กล้องบางอย่างเพื่อให้สิ่งนี้แสดงอย่างถูกต้อง .

ทีนี้ถ้าคุณอยากให้นักบินอวกาศไปเยี่ยมดาวหางที่อยู่ไกลออกไปในเมฆออร์ตซึ่งใหญ่กว่านั้นมันก็จบแล้ว ประมาณ 10 ^ 16 ซม. คุณจะเริ่มต้นความแม่นยำ:

printf("%.0Lf\n", 1.0e16);
printf("%.0Lf\n", 1.0e16 + 1.0);
printf("%.0Lf\n", 1.0e16 + 2.0);

Output:
-------
10000000000000000
10000000000000000 <-- oops
10000000000000002

และมันก็ยิ่งแย่ลงไปอีกแน่นอน

ดังนั้นหากคุณอยู่ในกรณีนี้คุณอาจต้องการลองใช้โซลูชันขั้นสูงเพิ่มเติม ฉันขอแนะนำให้คุณดูที่บทความของ Peter Freeze ในGame Programming Gems 4: "2.3 การแก้ปัญหาความแม่นยำในพิกัดโลกขนาดใหญ่" IIRC เขาแนะนำให้ใช้ระบบที่เหมาะกับความต้องการของคุณจริง ๆ แล้วมันเป็นช่องว่างที่แตกต่างกันหลายแบบ

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

ขอให้โชคดีกับเกมของคุณ!


1
คำตอบนี้เป็นสิ่งที่ดีเพราะแผนที่จะง่ายขึ้นในพื้นที่จุดลอยตัว 3 มิติที่ชอบโดย OpenGL และ DirectX และมีการอ้างอิงที่ดี ดังนั้นผมจึงได้ทำเครื่องหมายว่าเป็นคำตอบ :)
นิโคลัสฮิลล์

ป :) เป็นโบนัสเช่นนี้เป็นตัวอย่างมากคุณจะพบบางข่าวสารเพิ่มเติมในเชิงลึกเกี่ยวกับการลอยในบล็อกของบรูซดอว์สัน: randomascii.wordpress.com/2012/05/20/...
Laurent Couvidou

17

สมมติว่าดาวพลูโตเป็น "ขอบ" ของระบบสุริยะ (แม้ว่าบางคนบอกว่ามันยาวถึง 3 ปีแสง) ดาวพลูโตที่วงโคจรสูงสุดของมันอยู่ที่ประมาณ 7,376,000,000 กิโลเมตรจากดวงอาทิตย์ นั่นคือ 7.37600 × 10 ^ 14 เซนติเมตร เพิ่มเป็นสองเท่าเพื่อให้ได้เส้นผ่าศูนย์กลางและคุณจะได้1,475,200,000,000,000เซนติเมตร มีขนาดไม่เกิน 64 บิต เนื่องจากความสูงของระบบสุริยะนั้นเล็กน้อยเมื่อเทียบกับเส้นผ่านศูนย์กลางของมันเราจึงเพิกเฉยได้

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

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

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

และทำไมถึงมีความแม่นยำที่ดีเช่นนี้เว้นแต่ว่าคุณจะจำลองวัตถุในระบบสุริยะด้วยความแม่นยำนั้น นั่นคือสิ่งที่คุณจะได้รับปัญหา ปริมาณของดวงอาทิตย์คือ 1.40900 × 10 ^ 18 ลูกบาศก์กิโลเมตร ในระดับลูกบาศก์เซนติเมตรการใช้บิตเดียวเพื่อแสดงว่าพื้นที่นั้น "ว่าง" ใช้เวลา 1.4 × 10 ^ 33 บิตหรือ 1.6 × 10 ^ 23 กิกะไบต์ ฉันคิดว่าคุณไม่มี RAM มากขนาดนั้น


3
จุดที่สวยใน เวอร์ชั่นสั้น: ความแม่นยำของการลอยตัวเป็นสิ่งที่คุณกังวลน้อยที่สุด
aaaaaaaaaaaa

1
คุณจะได้รับโอเวอร์โฟลว์ด้วยจำนวนเต็มแม้กระทั่ง 64- บิต ยานอวกาศโคจรรอบพลูโต พยายามคำนวณระยะทางจากยานอวกาศไปยังดวงอาทิตย์ กู้หน้า ความเจริญ
Laurent Couvidou

3
ฉันไม่เห็นด้วยอย่างยิ่งกับการยืนยันในย่อหน้าสุดท้าย - คำถามของ OP มีเหตุผลอย่างสมบูรณ์แบบและไม่จำเป็นต้องคาดหวังว่าจะมีรายการในทุก ๆ (ลูกบาศก์) เซนติเมตรเพื่อดูแลเกี่ยวกับความถูกต้อง 1 ซม. ในตำแหน่ง
Steven Stadnicki

1
@StevenStadnicki ยุติธรรมเพียงพอ แต่แม้ในระดับกิโลเมตรมันก็ยังคง 164,029,188 กิกะไบต์สำหรับ 1 บิตต่อลูกบาศก์กิโลเมตร มันคล้ายกับการขอความแม่นยำของอะตอมในมาตรวัดความเร็วรถของคุณ นั่นเป็นวิธีที่แม่นยำยิ่งกว่าที่ควรจะเป็น
MichaelHouse

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

2

คุณสามารถใช้BigIntegerสิ่งที่ภาษาการเขียนโปรแกรมเรียกมัน มันเป็นจำนวนเต็มไม่ จำกัด ขนาด เครื่องชั่งน้ำหนักมันอย่างดี - โดยทั่วไปใช้จัดเก็บข้อมูลสำหรับจำนวนเต็มของขนาดlog(n)n

Java และ C # มีมัน; ฉันแน่ใจว่าภาษาอื่นทำ หากไม่เป็นเช่นนั้นคุณสามารถถอดรหัสและนำกลับมาใช้ใหม่ได้โดยไม่ต้องลำบากมากเกินไป

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