การคำนวณแรงโน้มถ่วงที่เหมาะสมที่สุด


23

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

มันรู้สึกเหมือนฉันควรจะสามารถที่จะปรับปรุงประสิทธิภาพการทำงาน เมื่อถึงเวลาใดก็ตาม 99% ของวัตถุในระบบอาจมีอิทธิพลเพียงเล็กน้อยต่อวัตถุ แน่นอนว่าฉันไม่สามารถจัดเรียงวัตถุตามมวลและพิจารณาวัตถุที่ใหญ่ที่สุด 10 อันดับแรกหรือบางสิ่งบางอย่างเท่านั้นเนื่องจากแรงแตกต่างกันไปตามระยะทางมากกว่ามวล (สมการนี้อยู่ในแนวของforce = mass1 * mass2 / distance^2) ฉันคิดว่าการประมาณที่ดีคือการพิจารณาวัตถุที่ใหญ่ที่สุดและวัตถุที่อยู่ใกล้ที่สุดโดยไม่สนใจเศษหินเล็ก ๆ หลายร้อยชิ้นที่อยู่อีกด้านหนึ่งของโลกซึ่งอาจไม่ส่งผลกระทบใด ๆ ต่อวัตถุ แต่เพื่อค้นหาว่าวัตถุใดเป็นวัตถุ ที่ใกล้เคียงที่สุดฉันต้องย้ำไปที่วัตถุทั้งหมดและตำแหน่งของพวกเขาจะเปลี่ยนแปลงตลอดเวลาดังนั้นฉันจึงไม่สามารถทำได้เพียงครั้งเดียว

ขณะนี้ฉันกำลังทำสิ่งนี้:

private void UpdateBodies(List<GravitatingObject> bodies, GameTime gameTime)
{
    for (int i = 0; i < bodies.Count; i++)
    {
        bodies[i].Update(i);
    }
}

//...

public virtual void Update(int systemIndex)
{
    for (int i = systemIndex + 1; i < system.MassiveBodies.Count; i++)
    {
        GravitatingObject body = system.MassiveBodies[i];

        Vector2 force = Gravity.ForceUnderGravity(body, this);
        ForceOfGravity += force;
        body.ForceOfGravity += -force;
    }

    Vector2 acceleration = Motion.Acceleration(ForceOfGravity, Mass);
    ForceOfGravity = Vector2.Zero;

    Velocity += Motion.Velocity(acceleration, elapsedTime);
    Position += Motion.Position(Velocity, elapsedTime);
}

(โปรดทราบว่าฉันได้ลบรหัสจำนวนมาก - ตัวอย่างเช่นการทดสอบการชนฉันจะไม่วนซ้ำวัตถุในครั้งที่สองเพื่อตรวจจับการชนกัน)

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

Gravity.ForceUnderGravity(...)และMotion.Velocity(...)ฟังก์ชั่นอื่น ๆ เพียงแค่ใช้บิตของ XNA ที่สร้างขึ้นในคณิตศาสตร์เวกเตอร์

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

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

มีความคิดเกี่ยวกับว่าฉันจะปรับปรุงสิ่งนี้ได้อย่างไร ฮิวริสติกบางอย่างที่ฉันสามารถใช้เพื่อโกนความยาวของลูปจากหลายร้อยไปจนถึงเพียงไม่กี่ รหัสบางอย่างที่ฉันสามารถเรียกใช้งานได้บ่อยกว่าการอัพเดททุกครั้ง? ฉันควร multithread มันจนกว่ามันจะเร็วพอที่จะทำให้โลกมีขนาดพอเหมาะ ฉันควรลองลดการคำนวณความเร็วลงสู่ GPU หรือไม่ ถ้าเป็นเช่นนั้นฉันจะออกแบบได้อย่างไร ฉันสามารถเก็บข้อมูลคงที่และใช้ร่วมกันบน GPU ได้หรือไม่? ฉันสามารถสร้างฟังก์ชั่น HLSL บน GPU และเรียกพวกมันตามอำเภอใจ (ใช้ XNA) หรือว่าพวกเขาจะต้องเป็นส่วนหนึ่งของกระบวนการวาด


1
เพียงแค่ทราบว่าคุณพูดว่า "วัตถุขนาดใหญ่ไม่ได้ย้ำซากเศษเล็กเศษน้อยซึ่งเป็นส่วนหนึ่งของการคำนวณความเร็วของพวกเขา แต่เศษชิ้นส่วนแต่ละชิ้นจะต้องวนซ้ำไปตามอนุภาคขนาดใหญ่" ฉันได้รับความประทับใจจากสิ่งนั้นว่าคุณคิดว่ามันมีประสิทธิภาพมากกว่า อย่างไรก็ตามการวนซ้ำวัตถุ 100 ชิ้นแต่ละครั้งยังคงเหมือนเดิม 10 วัตถุขนาดใหญ่ 100 ครั้ง อาจเป็นความคิดที่ดีที่จะย้ำวัตถุแต่ละชิ้นในวงวัตถุขนาดใหญ่เพื่อให้คุณไม่ต้องทำมันเป็นครั้งที่สอง
Richard Marskell - Drackir

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

@Drackir ฉันคิดว่าคุณพูดถูก เหตุผลส่วนหนึ่งที่พวกเขาแยกกันคือเพราะคณิตศาสตร์นั้นแตกต่างจากวัตถุที่ไม่มีมวลและส่วนหนึ่งเป็นเพราะในตอนแรกพวกเขาไม่เชื่อฟังแรงโน้มถ่วงเลยมันมีประสิทธิภาพมากกว่าที่จะไม่รวมพวกมัน ดังนั้นมันจึงร่องรอย
Carson Myers

@chaosTechnician ไม่ต้องแม่นยำมาก - อันที่จริงถ้ามันเป็นเพียงการบัญชีสำหรับกองกำลังที่โดดเด่นที่สุดไม่กี่ระบบจะมีเสถียรภาพมากขึ้นซึ่งเหมาะ แต่มันเป็นการค้นหาว่ากองกำลังใดโดดเด่นที่สุดในวิธีที่มีประสิทธิภาพที่ฉันมีปัญหา นอกจากนี้การคำนวณความโน้มถ่วงได้ประมาณไว้แล้วซึ่งเป็นเพียงแค่G * m1 * m2 / r^2ที่ G เป็นเพียงการปรับแต่งพฤติกรรม (แม้ว่าฉันไม่สามารถเพียงแค่มีพวกเขาไปตามเส้นทางเพราะผู้ใช้สามารถรบกวนระบบ)
คาร์สันไมเออร์

ทำไมเศษของแต่ละชิ้นจึงต้องวนซ้ำในอนุภาคขนาดใหญ่ถ้ามันไม่มีมวล? ชน?
sam hocevar

คำตอบ:


26

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

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

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

หากโลกของเกมมีขนาดใหญ่มากคุณสามารถใช้กริดลำดับขั้นเช่น quadtree (2D) หรือ octree (3D) และใช้หลักการที่คล้ายกันได้ การสื่อสารทางไกลจะสอดคล้องกับลำดับชั้นที่สูงขึ้น


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

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

8
นี่คืออัลกอริทึม Barnes-Hut: en.wikipedia.org/wiki/Barnes –Hut_simulation
Russell Borogove

มันฟังดูคล้ายกับว่าแรงโน้มถ่วงควรทำงานในวิชาฟิสิกส์หรือไม่คือการดัดงอของเวลาอวกาศ
Zan Lynx

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

16

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

เยี่ยมชมhttp://mathandcode.com/programs/javagrav/และกด "start" และ "show quadtree"

ในแท็บตัวเลือกคุณจะเห็นว่าการนับอนุภาคสามารถไปได้ถึง 200,000 บนคอมพิวเตอร์ของฉันการคำนวณเสร็จสิ้นในเวลาประมาณ 2 วินาที (ภาพวาด 200,000 จุดใช้เวลาประมาณ 1 วินาที แต่การคำนวณจะทำงานบนเธรดแยกต่างหาก)

แอปเพล็ตของฉันทำงานอย่างไร:

  1. สร้างรายการของอนุภาคสุ่มด้วยมวลสุ่มตำแหน่งและความเร็วในการเริ่มต้น
  2. สร้างควอดทรีจากอนุภาคเหล่านี้ แต่ละโหนด quadtree มีศูนย์กลางของมวลของแต่ละโหนดย่อย โดยทั่วไปสำหรับแต่ละโหนดคุณมีสามค่า: massx, massy และ mass ทุกครั้งที่คุณเพิ่มอนุภาคลงในโหนดที่กำหนดคุณจะเพิ่ม massx และ massy โดย particle.x * particle.mass และ particle.y * particle.mass ตามลำดับ ตำแหน่ง (massx / mass, massy / mass) จะจบลงที่จุดศูนย์กลางของโหนด
  3. สำหรับแต่ละอนุภาคให้คำนวณแรง (อธิบายทั้งหมดที่นี่ ) สิ่งนี้ทำโดยเริ่มต้นที่โหนดด้านบนและเรียกใช้ซ้ำผ่านแต่ละโหนดย่อยของ quadtree จนกว่าโหนดย่อยที่กำหนดนั้นมีขนาดเล็กพอ เมื่อคุณหยุดการเรียกซ้ำคุณสามารถคำนวณระยะทางจากอนุภาคไปยังจุดศูนย์กลางมวลของโหนดและจากนั้นคุณสามารถคำนวณแรงโดยใช้มวลของโหนดและมวลของอนุภาค

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

ดูเพิ่มเติมที่: http://www.youtube.com/watch?v=XAlzniN6L94สำหรับการแสดงผลขนาดใหญ่นี้


ลิงค์แรกเสียชีวิต แอปเพล็ตโฮสต์ที่อื่นหรือไม่
Anko

1
หนี้! ขออภัยลืมที่จะจ่ายค่าเช่าในโดเมนนั้นและมีคนซื้อโดยอัตโนมัติ: \ นอกจากนี้ 3 นาทีเป็นเวลาตอบสนองที่ดีงามในโพสต์เก่า 1.3 ปี 8D

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

3

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

อย่างไรก็ตามการดำเนินการต่อจากนั้นมีความเป็นไปได้อีกอย่างหนึ่งคือการอัปเดตวัตถุเป็นระยะ โดยทั่วไปในแต่ละขั้นตอน (เฟรม) จะอัพเดทเพียงเศษเสี้ยวของวัตถุทั้งหมดและปล่อยให้ความเร็ว (หรือการเร่งความเร็วขึ้นอยู่กับความชอบของคุณ) เหมือนกันกับวัตถุอื่น ผู้ใช้ไม่น่าจะสังเกตเห็นความล่าช้าในการอัปเดตจากนี้ตราบใดที่ช่วงเวลาไม่นานเกินไป สิ่งนี้จะทำให้คุณได้อัลกอริธึมเชิงเส้นเร็วขึ้นดังนั้นลองดูเทคนิค Broadphase อย่างที่ Nathan แนะนำเช่นกัน แม้ว่าจะไม่ได้จำลองแบบเดียวกันเลยแม้แต่น้อยนี่เป็นเหมือนการมี "คลื่นแรงโน้มถ่วง" :)

นอกจากนี้คุณยังสามารถสร้างสนามแรงโน้มถ่วงในหนึ่งผ่านแล้วอัปเดตวัตถุในรอบที่สอง ผ่านครั้งแรกที่คุณกรอกตาราง (หรือโครงสร้างข้อมูลเชิงพื้นที่ที่ซับซ้อนมากขึ้น) โดยมีอิทธิพลต่อแรงโน้มถ่วงของแต่ละวัตถุ ผลที่ได้คือฟิลด์แรงโน้มถ่วงที่คุณสามารถแสดงผล (ดูเจ๋งมาก) เพื่อดูว่าการเร่งความเร็วใดที่จะนำไปใช้กับวัตถุในตำแหน่งใด ๆ จากนั้นคุณวนซ้ำวัตถุและใช้เอฟเฟกต์สนามแรงโน้มถ่วงกับวัตถุนั้น แม้แต่ตัวที่เย็นกว่าคุณสามารถทำได้บน GPU โดยการแสดงวัตถุเป็นวงกลม / ทรงกลมกับพื้นผิวจากนั้นอ่านพื้นผิว (หรือใช้การส่งผ่านข้อเสนอแนะการเปลี่ยนแปลงอื่นบน GPU) เพื่อปรับเปลี่ยนความเร็วของวัตถุ


การแยกกระบวนการออกเป็นความคิดที่ยอดเยี่ยมเนื่องจากช่วงเวลาการอัพเดทคือเท่าที่ฉันรู้ส่วนที่เล็กมากของวินาที พื้นผิวสนามแรงโน้มถ่วงน่ากลัว แต่อาจจะไกลเกินเอื้อม
Carson Myers

1
อย่าลืมที่จะคูณแรงที่ใช้ด้วยจำนวนเวลาที่ถูกข้ามไปนับตั้งแต่การอัพเดทครั้งล่าสุด
Zan Lynx

@ seanmiddlemitch: คุณช่วยเพิ่มรายละเอียดเกี่ยวกับพื้นผิวแรงโน้มถ่วงอีกหน่อยได้ไหม? ฉันขอโทษฉันไม่ใช่โปรแกรมเมอร์กราฟิก แต่นี่ฟังดูน่าสนใจจริงๆ ฉันไม่เข้าใจว่ามันควรจะทำงานอย่างไร และ / หรือคุณอาจมีลิงค์ไปยังคำอธิบายของเทคนิคหรือไม่?
เฟลิกซ์ Dombek

@ FelixDombek: แสดงวัตถุของคุณเป็นวงกลมแทนพื้นที่ที่มีอิทธิพล แฟรกเมนต์ shader เขียนเวกเตอร์ที่ชี้ไปที่ศูนย์กลางของวัตถุและมีขนาดที่เหมาะสม (ขึ้นอยู่กับระยะทางจากจุดศูนย์กลางและมวลของวัตถุ) การผสมฮาร์ดแวร์สามารถจัดการกับการรวมเวกเตอร์เหล่านี้ในโหมดเสริม ผลลัพธ์จะไม่เป็นฟิลด์แรงโน้มถ่วงที่แม่นยำ แต่เกือบจะดีพอสำหรับความต้องการของเกม เป็นอีกแนวทางหนึ่งในการใช้ GPU โปรดดูเทคนิคการจำลองแรงโน้มถ่วง N-body ตาม CUDA นี้: http.developer.nvidia.com/GPUGems3/gpugems3_ch31.html
Sean Middleditch

3

ฉันอยากจะแนะนำให้ใช้ Quad Tree พวกมันช่วยให้คุณค้นหาวัตถุทั้งหมดในพื้นที่สี่เหลี่ยมโดยพลการอย่างรวดเร็วและมีประสิทธิภาพ นี่คือบทความ wiki เกี่ยวกับพวกเขา: http://en.wikipedia.org/wiki/Quadtree

และลิงก์ที่ไร้ยางอายกับโครงการ XNA Quad Tree ของฉันบน SourceForge: http://sourceforge.net/projects/quadtree/

ฉันจะรักษารายการของวัตถุขนาดใหญ่ทั้งหมดเพื่อให้พวกเขาสามารถโต้ตอบกับทุกสิ่งโดยไม่คำนึงถึงระยะทาง


0

เพียงเล็กน้อยของอินพุต (อาจไร้เดียงสา) ฉันไม่ได้เขียนโปรแกรมเกม แต่สิ่งที่ฉันรู้สึกคือคอขวดพื้นฐานของคุณคือการคำนวณแรงโน้มถ่วงเนื่องจากแรงโน้มถ่วง แทนที่จะวนซ้ำวัตถุแต่ละชิ้น X จากนั้นหาเอฟเฟกต์แรงโน้มถ่วงจากแต่ละวัตถุ Y และเพิ่มเข้าไปคุณสามารถใช้แต่ละคู่ X, Y และหาแรงระหว่างกัน นั่นควรลดจำนวนการคำนวณแรงโน้มถ่วงจาก O (n ^ 2) จากนั้นคุณจะทำการเพิ่มจำนวนมาก (O (n ^ 2)) แต่โดยปกติแล้วจะมีราคาไม่แพง

ณ จุดนี้คุณสามารถใช้กฎเช่น "ถ้าแรงโน้มถ่วงจะน้อยกว่า \ epsilon เพราะร่างกายเหล่านี้มีขนาดเล็กเกินไปตั้งแรงเป็นศูนย์" มันอาจเป็นประโยชน์ที่จะมีโครงสร้างนี้เพื่อวัตถุประสงค์อื่นด้วย (รวมถึงการตรวจจับการชนกันของข้อมูล)


นี่คือสิ่งที่ฉันทำ หลังจากที่ฉันได้คู่ทั้งหมดที่เกี่ยวข้องกับ X ฉันจะไม่พูดซ้ำ X ฉันพบแรงระหว่าง X และ Y, X และ Z, และใช้แรงนั้นกับวัตถุทั้งคู่ในคู่ หลังจากลูปเสร็จสมบูรณ์ForceOfGravityเวกเตอร์คือผลรวมของแรงทั้งหมดและนั่นจะถูกแปลงเป็นความเร็วและตำแหน่งใหม่ ฉันไม่แน่ใจว่าการคำนวณแรงโน้มถ่วงมีราคาแพงเป็นพิเศษและการตรวจสอบว่าเกินเกณฑ์แรกหรือไม่จะไม่ช่วยประหยัดเวลาได้อย่างเห็นได้ชัด
Carson Myers

0

ในการขยายคำตอบของ seanmiddleditch ฉันคิดว่าฉันอาจรู้สึกถึงแสง (ประชดประชัน) ในความคิดสนามแรงโน้มถ่วง

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

เมื่อคุณแนะนำวัตถุเข้าสู่สนามศักยภาพของความโน้มถ่วงนั้นสามารถคำนวณได้สำหรับค่าโดยรอบทั้งหมด ดังนั้นการสร้างอ่างล้างจานแรงโน้มถ่วงในสนาม

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

นั่นคือการผ่านครั้งแรกอาจคำนวณแรงโน้มถ่วงของวัตถุที่แสดงในตาราง 4x4 โดยแต่ละค่าเซลล์จะแทนค่าพิกัด 2D ในอวกาศ ให้ความซับซ้อนรวมย่อย O (n * 4 * 4)

รอบที่สองอาจแม่นยำยิ่งขึ้นด้วยสนามแรงโน้มถ่วงความละเอียด 64x64 โดยแต่ละค่าของเซลล์จะแสดงพิกัด 2D ในอวกาศ อย่างไรก็ตามเนื่องจากความซับซ้อนสูงมากคุณสามารถ จำกัด รัศมีของเซลล์รอบข้างที่ได้รับผลกระทบ (อาจจะมีการปรับปรุงเฉพาะเซลล์ 5x5 โดยรอบเท่านั้น)

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

ด้วยวิธีนี้ความซับซ้อนโดยรวมของคุณสำหรับการอัปเดตคือ O (n * (4 * 4 + 5 * 5 + 6 * 6)

ในการคำนวณการเปลี่ยนแปลงความเร็วของวัตถุแต่ละชิ้นของคุณสำหรับแต่ละฟิลด์แรงโน้มถ่วง (4x4, 64x64, 1024x1024) คุณเพียงแมปตำแหน่งมวลมวลของตำแหน่งกับเซลล์กริด ทำซ้ำสำหรับแต่ละ "เลเยอร์" หรือ "ผ่าน"; จากนั้นเพิ่มเข้าด้วยกัน นี่ควรให้เวกเตอร์แรงโน้มถ่วงที่ให้ผลลัพธ์ที่ดีแก่คุณ

ดังนั้นความซับซ้อนโดยรวมคือ: O (n * (4 * 4 + 5 * 5 + 6 * 6) + n) สิ่งที่นับจริง (สำหรับความซับซ้อน) คือจำนวนเซลล์รอบข้างที่คุณอัปเดตเมื่อคำนวณศักยภาพความโน้มถ่วงในรอบที่ผ่านไม่ใช่ความละเอียดโดยรวมของสนามแรงโน้มถ่วง

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

ฉันหวังว่านี่จะเป็นเหตุผล


0

วิธีการเกี่ยวกับวิธีอื่น:

กำหนดพื้นที่ที่มีอิทธิพลต่อวัตถุตามมวลของมัน - มันเล็กเกินไปที่จะมีผลกระทบที่วัดได้เกินขอบเขตนั้น

ตอนนี้แบ่งโลกของคุณออกเป็นกริดและวางวัตถุแต่ละอันในรายการของเซลล์ทั้งหมดที่มันมีอิทธิพล

ทำการคำนวณแรงโน้มถ่วงของคุณเฉพาะกับวัตถุในรายการที่แนบกับเซลล์ที่มีวัตถุอยู่

คุณจะต้องอัปเดตรายการเมื่อวัตถุเคลื่อนที่ไปยังเซลล์กริดใหม่

เซลล์กริดที่เล็กลงการคำนวณที่น้อยกว่าที่คุณจะทำต่อการอัปเดต

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