octreeãšã¯äœã§ããïŒ ãã®æŠå¿µããŸã£ããç¥ããªãå Žåã¯ã ãŠã£ãããã£ã¢ã®èšäºãèªãããšããå§ãããŸã ïŒããã«ã¯çŽ5åããããŸãïŒã ããã¯ååãªã¢ã€ãã¢ãäžããŸããããããããªã䜿çšãããã©ã®ããã«ããããå®è£ ããã®ããç解ããã®ã«ååã§ã¯ãããŸããã
ãã®èšäºã§ã¯ãæŠå¿µãå³ãããã³ã³ãŒãã説æããäŸã䜿çšããŠãoctreeããªãŒã®ããŒã¿æ§é ãäœæããããã«å¿ èŠãªãã¹ãŠã®æé ã«ã€ããŠèª¬æããŸãã ãŸããå段éã§äžãã決å®ã«ã€ããŠã説æããŸãã ãã®èšäºããªã¯ã¿ãŒãã®å®è£ ã«é¢ããå¯äžã®çã®ã¬ã€ãã«ãªããšã¯æããªãããããã¯ããªãã«è¯ãåºç€ãäžããã¯ãã§ãããåç §ã®ããã«äœ¿çšããããšãã§ããã
å¿ èŠãªç¥è
ãã®èšäºãæžããšããèªè ã¯æ¬¡ã®ããšãåæãšããŠããŸãã
- Cã¹ã¿ã€ã«ã®æ§æãæã€èšèªã®ããã°ã©ãã³ã°ã«ç²ŸéããŠããïŒXNAã§CïŒã䜿çšããïŒã
- ãã€ããªæ€çŽ¢ããªãŒ ãªã©ã®ããŒã¿æ§é ã®ãã㪠ãããçš®ã®ããªãŒã¯ãã§ã«ããã°ã©ãã³ã°ãããŠãããååž°ããã®é·æãšçæã«ç²ŸéããŠããŸãã
- å¢çé·æ¹åœ¢ãçäœãããã³è§éå°ã§è¡çªèªèãã©ã®ããã«å®çŸãããããç¥ã£ãŠããŸãã
- 圌ã¯æšæºã®ããŒã¿æ§é ïŒé åããªã¹ããªã©ïŒãç解ãã 倧ããªãOããäœã§ããããç解ããŠããŸãïŒ ãã®GDnetã®èšäºã§èªãããšãã§ãã倧ããªãOã ã«ã€ã㊠ïŒã
- 圌ã¯ãè¡çªããã§ãã¯ããå¿ èŠãããæ©èœããããããžã§ã¯ãã«åãçµãã§ããŸãã
ã·ãŒã³ã®æºå
éåžžã«å€§èŠæš¡ãªã²ãŒã ãäœæããããŸããŸãªçš®é¡ã圢ç¶ããµã€ãºã®äœåãã®ç©çãªããžã§ã¯ããå«ããããšãã§ãããããã®ããã€ãã¯äºãã«è¡çªããå¿ èŠããããšããŸãã åãã¬ãŒã ã§ãã©ã®ãªããžã§ã¯ããäºãã«äº€å·®ããããå€æãããããã®äº€å·®ãäœããã®æ¹æ³ã§åŠçããå¿ èŠããããŸãã ã²ãŒã ã®é床ãèœã¡ãªãããã«ãããè¡ãæ¹æ³ã¯ïŒ
åçŽãªãã«ãŒããã©ãŒã¹ã«ããè¡çªæ€åº
æãç°¡åãªè§£æ±ºçã¯ãåãªããžã§ã¯ããäžçã®ãã¹ãŠã®ãªããžã§ã¯ããšæ¯èŒããããšã§ãã ããã¯éåžžã2ã€ã®forã«ãŒãã§å®è¡ã§ããŸãã ã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
foreach(gameObject myObject in ObjList) { foreach(gameObject otherObject in ObjList) { if(myObject == otherObject) continue; // if(myObject.CollidesWith(otherObject)) { // } } }
ã°ã©ãã£ã«ã«ã«ã¯ã次ã®ããã«è¡šãããšãã§ããŸãã
èµ€ãç·ã¯ãããããCPUã®äº€å·®ç¹ã®ã³ã¹ãã®é«ããã§ãã¯ã§ãã
åœç¶ããã®ãããªã³ãŒãã¯OïŒN 2 ïŒåå®è¡ããããããæãããã¯ãã§ãã 10,000åã®ãªããžã§ã¯ããããå Žåã1ååã®è¡çªãã§ãã¯ïŒ1ååïŒãå®è¡ããå¿ èŠããããŸãã ããã»ããµã®é床ãæ°åŠã³ãŒããã©ãã ãæ¹åãããã¯é¢ä¿ãããŸããããã®ãããªããã°ã©ã ã¯ã³ã³ãã¥ãŒã¿ã®é床ãäœäžãããŸãã ã²ãŒã ãæ¯ç§60ãã¬ãŒã ã§åäœããå Žåãæ¯ç§60 * 1åã®èšç®ãå®è¡ãããŸãïŒ ããã¯å®å šãªçæ°ã§ãã
ãããåé¿ã§ããå Žåã¯ãå°ãªããšã倧èŠæš¡ãªãªããžã§ã¯ãã®ã»ããã«ã€ããŠã¯ããããè¡ããªãã§ãã ããã ããã¯ãããšãã°ããã§ãã¯ã10åã®ãªããžã§ã¯ãïŒ100åã®ãã§ãã¯ïŒã«å¯ŸããŠã®ã¿å®è¡ãããå Žåã«ã®ã¿åãå ¥ããããŸãã ã²ãŒã å ã«ãªããžã§ã¯ãïŒããšãã°å°ææïŒãã»ãšãã©ãªãããšãäºåã«ç¥ã£ãŠããå Žåã¯ãåçŽãªæ¯æžãé©åã§ãããå «åæšãå®å šã«æŸæ£ããããšãã§ããŸãã ãã¬ãŒã ããšã®è¡çªãã§ãã¯ãå€ãããããã«ããã©ãŒãã³ã¹ã®åé¡ã«æ°ä»ãå§ããå Žåãéåžžã«ç°¡åãªæé©åã䜿çšã§ããŸãã
1.è¡çªèšç®æé ã«ã¯ããã€ã®èšç®ãå¿ èŠã§ããïŒ ãã¶ããã®äžã®ã©ããã«å¹³æ¹æ ¹ã®èšç®ãé ãããŠãããããããŸããïŒããšãã°ãè·é¢ããã§ãã¯ãããšãïŒïŒ 詳现ãªè¡çªãã§ãã¯ïŒãã¯ã»ã«ãäžè§åœ¢ãªã©ã®äº€å·®ïŒãå®è¡ããŠããŸããïŒ æšæºçãªææ³ããããŸããæåã«è¡çªã®å€§ãŸããªãã§ãã¯ãå®è¡ããŠããããã詳现ãªãã®ã«é²ã¿ãŸãã é·æ¹åœ¢ãŸãã¯ç圢ã®å¢çç·ãèšè¿°ãããªããžã§ã¯ããè¿œå ããå¢çç·ã®äº€å·®ã確èªããŠãããããå€ãã®æ°åŠçèšç®ãšãªãœãŒã¹ãå¿ èŠãšãã詳现ãªãã§ãã¯ãå®è¡ã§ããŸãã
ãªããžã§ã¯ãéã®è·é¢ãæ¯èŒããã«ã¯ããªããžã§ã¯ãéã®å¹³æ¹å¹³æ¹è·é¢ã䜿çšããŠãå¹³æ¹æ ¹ã®èšç®ãé¿ããŸãã å¹³æ¹æ ¹ãèšç®ããã«ã¯ãéåžžãã¥ãŒãã³è¿äŒŒã䜿çšãããéåžžã«é«äŸ¡ã«ãªãå¯èœæ§ããããŸãã
2.ããå°ãªãè¡çªãã§ãã¯ãèšç®ããããšã§ååŸã§ããŸããïŒ ã²ãŒã ãæ¯ç§60ãã¬ãŒã ã§å®è¡ãããå Žåãããã€ãã®ãã¬ãŒã ãã¹ãããã§ããŸããïŒ äžéšã®ãªããžã§ã¯ãã®åäœã決å®çã§ããå Žåããããã®è¡çªã¯äºåã«èšç®ã§ããŸãïŒããšãã°ãããªã€ãŒãããŒã«ãšããŒãã«ã®åŽé¢ã®éïŒã ã¹ãã£ã³ããããªããžã§ã¯ãã®æ°ãæžããããšã¯å¯èœã§ããïŒ ãªããžã§ã¯ããç°ãªããªã¹ãã«åå²ããŠã¿ãŠãã ããã 1ã€ã®ãªã¹ãã«ã¯ããéæ¢ããªããžã§ã¯ããå«ããããšãã§ããŸãã äºãã®ç«¶åããã§ãã¯ããããšã¯ã§ããŸããã å¥ã®ãªã¹ãã«ã¯ãã移åããããªããžã§ã¯ããå«ãŸããå ŽåããããŸãããã®ãªããžã§ã¯ãã«ã€ããŠã¯ãä»ã®ãã¹ãŠã®ç§»åãªããžã§ã¯ãããã³ãã¹ãŠã®éæ¢ãªããžã§ã¯ããšã®è¡çªããã§ãã¯ããå¿ èŠããããŸãã ããã«ãããå¿ èŠãªè¡çªãã§ãã¯ã®æ°ã蚱容å¯èœãªããã©ãŒãã³ã¹ã¬ãã«ãŸã§æžããããšãã§ããŸãã
3.ããã©ãŒãã³ã¹ã®åé¡ãããå Žåãäžéšã®ãªããžã§ã¯ãã®è¡çªã®ãã§ãã¯ãæåŠããããšã¯å¯èœã§ããïŒ ããšãã°ãç ã®ç²åã¯è¡šé¢ãªããžã§ã¯ããšçžäºäœçšãããã®èŒªéããã©ã£ãŠçŸããå¹æãçã¿åºãããšãã§ããŸãããããã¯ã²ãŒã ãã¬ã€ã劚ããã¹ãã§ã¯ãããŸããã ãã§ãã¯ã®æ°ãç¹å®ã®å¶éãè¶ ããå Žåãç ç²åã®è¡çªã®èšç®ãåæ¢ã§ããŸãã ãã ãã éèŠãªã²ãŒã ãªããžã§ã¯ãã®åããç¡èŠãããšãã²ãŒã ãã¬ã€ãç Žå£ãããŸãïŒããšãã°ããã¬ã€ã€ãŒã®åŒŸäžžãã¢ã³ã¹ã¿ãŒãšçžäºäœçšããªããªããŸãïŒã ã€ãŸããè¡çªã®åªå 床ãã§ãã¯ã®ãªã¹ããä¿æããŠãããšäŸ¿å©ã§ãã ãŸããåªå 床ã®é«ãã³ãªãžã§ã³ãåŠçãããå¶éãè¶ ããªãå Žåãåªå 床ã®äœãã³ãªãžã§ã³ãåŠçãããŸãã å¶éã«éãããšãã²ãŒã ã¯åªå é äœãªã¹ãã«æ®ã£ãŠãããã¹ãŠã®èŠçŽ ãç Žæ£ããããå°æ¥ã®æ€èšŒãé ãããå¿ èŠããããŸãã
4.å®è¡æã«OïŒN 2 ïŒãåãé€ãããã«ãè¡çªãæ€åºããããã®ããé«éã§ãããªããç°¡åãªæ¹æ³ã䜿çšããããšã¯å¯èœã§ããïŒ è¡çªããã§ã«ãã§ãã¯ãããŠãããªããžã§ã¯ããåé€ãããšãã©ã³ã¿ã€ã ã¯OïŒNïŒN + 1ïŒ/ 2ïŒã«ççž®ãããŸããããã¯ã¯ããã«é«éã§ãããå®è£ ã¯éåžžã«ç°¡åã§ãïŒæè¡çã«ã¯ãããã¯ãŸã OïŒN 2 ïŒã§ãïŒ ïŒ ãœãããŠã§ã¢éçºã®èŠ³ç¹ããèŠããšãçµæãšããŠã貧匱ãªã¢ã«ãŽãªãºã ãšäžæ£ç¢ºãªããŒã¿æ§é ã®æ¹åã«ããããã©ãŒãã³ã¹äœäžãæããããã«ãããè²»çšãããå€ãã®æéãè²»ããããšãã§ããŸãã è²»çšäŸ¿çæ¯ã¯çã äžæ¡ç®ã«ãªãã€ã€ãããè¡çªèªèã®åŠçã«ããé©åãªããŒã¿æ§é ãéžæããæãæ¥ãŸããã
å®è¡æã®è¡çªã®èªèã®åé¡ã®è§£æ±ºçãšããŠãã¹ããŒã¹ãåå²ããã¢ã«ãŽãªãºã ãç©æ¥µçã«äœ¿çšãããŠããŸãã é床ã®äžéšãäºåã«éžæããŸããã察æ°çã«è¡çªãã§ãã¯ã®åæ°ãæžãããŸãã éçºæéãšCPUã®åæè²»çšã¯ãã¹ã±ãŒã©ããªãã£ãšé«éåã®å©ç¹ã«ãã£ãŠç°¡åã«çžæ®ºãããŸãã
ã¹ããŒã¹ãã¬ã€ã¯ã®ã³ã³ã»ãã
äžæ©åŸéããŠãå «åæšã«ç§»ãåã«ãäžè¬ã«ç©ºéãšæšãåå²ããèããèããŠã¿ãŸãããã ãã®æŠå¿µãç解ããŠããªãå Žåãã³ãŒãã§å®è£ ããããšã¯ã§ããŸããã
äžèšã®åçŽãªæ€çŽ¢ã®å®è£ ã§ã¯ãã²ãŒã å ã®åãªããžã§ã¯ããååŸãããã®äœçœ®ãä»ã®ãã¹ãŠã®ãªããžã§ã¯ãã®äœçœ®ãšæ¯èŒããŠãé¢é£ãããã©ããã確èªããŸããã ãããã®ãªããžã§ã¯ãã¯ãã¹ãŠãã²ãŒã ã®äžçã«ç©ºéçã«é 眮ãããŠããŸãã ã²ãŒã ã®äžçãå¶éããå³ãäœæãããã®å³ã«å«ãŸãããªããžã§ã¯ããèŠã€ãããšãããã«å«ãŸãããªããžã§ã¯ãã®ãªã¹ããå«ãã¹ããŒã¹é åãã§ããŸãã ãã®å Žåãã²ãŒã ã®ãã¹ãŠã®ãªããžã§ã¯ããå«ãŸããŸãã
1ã€ã®ãªããžã§ã¯ããäžçã®äžç«¯ã«ããããã1ã€ã®ãªããžã§ã¯ããå察åŽã«ããããšãããããŸãããããã£ãŠãåãã¬ãŒã ã§ãªããžã§ã¯ãéã®è¡çªãã§ãã¯ãèšç®ããå¿ èŠã¯ãããŸããã ããã¯è²Žéãªããã»ããµæéã®ç¡é§ã«ãªããŸãã ãããããããšããããïŒ äžçãæ£ç¢ºã«ååã«åå²ãããšããªããžã§ã¯ãã®3ã€ã®åå¥ã®ãªã¹ããäœæã§ããŸãã
æåã®ãªã¹ãããªã¹ãAã«ã¯ãã¯ãŒã«ãã®å·ŠåŽã«ãããã¹ãŠã®ãªããžã§ã¯ããå«ãŸããŸãã
2çªç®ã®ãªã¹ãList Bã«ã¯ãäžçã®å³åŽã«ãªããžã§ã¯ããå«ãŸããŠããŸãã
äžéšã®ãªããžã§ã¯ãã¯ãããŒãéã®å¢çç·ãã€ãŸããã®äž¡åŽã«ããå¢çç·ã«è§Šããå ŽåããããŸãã ãã®ãããªãªããžã§ã¯ãã«å¯ŸããŠã3çªç®ã®ãªã¹ãããªã¹ãCãäœæããŸãã
ååºåã§ãäžçãååã«ç©ºéçã«çž®å°ããçµæã®ååã«ãããªããžã§ã¯ãã®ãªã¹ããåéããããšã«æ°ä»ããããããŸããã ãããã®ãªã¹ããä¿åããããã«ããã€ããªæ€çŽ¢ããªãŒãäœæã§ããŸãã ãã®ãããªããªãŒã®æŠå¿µã¯æ¬¡ã®ããã«ãªããŸãã
æ¬äŒŒã³ãŒãã®ããªãŒã®ããŒã¿æ§é ã¯æ¬¡ã®ããã«ãªããŸãã
public class BinaryTree { // , private List m_objectList; // private BinaryTree m_left, m_right; // ( ). private BinaryTree m_parent; }
ãªã¹ãAã®ãã¹ãŠã®ãªããžã§ã¯ãããªã¹ãBã®ãªããžã§ã¯ããšäº€å·®ããããšã¯ãªããããè¡çªãã§ãã¯ã®ã»ãŒååãæŸæ£ã§ããŸãã ãªã¹ãCã«ã¯ããªã¹ãAããã³Bã®ãªããžã§ã¯ãã«è§Šããããšãã§ãããªããžã§ã¯ããæ®ã£ãŠããããããªã¹ãAãBãCã®ãã¹ãŠã®ãªããžã§ã¯ããšã®è¡çªããªããããªã¹ãCã®ãã¹ãŠã®ãªããžã§ã¯ãã確èªããå¿ èŠããããŸã
äžçããŸããŸãå°ããªéšåã«åå²ãç¶ãããªããæ¯åååãã€ãã§ãã¯ã®æ°ãæžããç¶ããŸãã ããããã¹ããŒã¹ãåå²ããäž»ãªã¢ã€ãã¢ã§ãã äžçãããªãŒã®ãããªããŒã¿æ§é ã«åå²ããæ¹æ³ã¯å€æ°ãããŸãïŒ ãã€ããªã¹ããŒã¹ããŒãã£ã·ã§ã³ïŒBSPïŒ ã ååæš ã K次å æš ãå «åæšãªã©ïŒã
ããã§ãããã©ã«ãã§ã¯ããã¹ãŠã®ãªããžã§ã¯ããäžçå šäœã«ã»ãŒåäžã«ååžããŠãããšèããŠãããããæè¯ã®åå²ã¯çãäžã®ã¡ããã©ååã®åå²ã§ãããšåçŽã«ä»®å®ããŸãã ããã¯è¯ãä»®å®ã§ãããäžéšã®ããŒãã£ã·ã§ã³ã¢ã«ãŽãªãºã ã§ã¯ãåååã«çããæ°ã®ãªããžã§ã¯ããååšããããã«ããŒãã£ã·ã§ã³ãå®è¡ããïŒéã¿ä»ãããŒãã£ã·ã§ã³ïŒãçµæã®ããªãŒã®ãã©ã³ã¹ãããè¯ããªããŸãã ããããããããã¹ãŠã®ãªããžã§ã¯ããåãå§ãããšã©ããªããŸããïŒ ã»ãŒåçãªåå²ãç¶æããã«ã¯ãå²ç·é¢ã移åããããåãã¬ãŒã ã§ããªãŒãå®å šã«åæ§ç¯ããå¿ èŠããããŸãã ããã¯ããªãè€éã§è€éã§ãã
ãããã£ãŠãã¹ããŒã¹ããŒãã£ã·ã§ã³ããªãŒãå®è£ ããããã«ãæ¯åãããååã«åå²ããããšã«ããŸããã ãã®çµæãäžéšã®ããªãŒã¯ãããŸã°ãã«ãªããŸãããããã¯æ£åžžã§ããã倧ããªã³ã¹ãã«ã¯ã€ãªãããŸããã
å ±æãããå ±æããªããïŒ ãããåé¡ã§ãã
ã»ãã®æ°åã®ãªããžã§ã¯ãã ãã§ããªããŸã°ããªé åããããšããŸãã æåŸã®ãªããžã§ã¯ãã®å¯èœãªéãå°ããå¢çã¹ããŒã¹ãèŠã€ãããŸã§ãããŒãã£ã·ã§ã³ã®å®è¡ãç¶è¡ã§ããŸãã ããããããã¯å¿ èŠã§ããïŒ ããªãŒãäœæããçç±ã¯ ãåãã¬ãŒã ã§å®è¡ãããè¡çªãã§ãã¯ã®åæ°ã®æžå°ã§ããããã¹ãŠã®ãªããžã§ã¯ããçæ³çã«åºåã空éé åã®äœæã§ã¯ãªãããšãæãåºããŠãã ããã åå²ãããã©ããã決å®ããããã«éžæããã«ãŒã«ã¯æ¬¡ã®ãšããã§ãã
- ãªããžã§ã¯ãã1ã€ãããªãåé¢ãäœæããå Žåãã¹ããŒã¹ãããã«åå²ã§ãããšããäºå®ã«ãããããããåå²ãåæ¢ããŸãã ãã®ã«ãŒã«ã¯ãoctreeã§ããªãŒãããŒãããå®çŸ©ããåºæºã®éèŠãªéšåã«ãªããŸãã
- ãã1ã€ã®éèŠãªåºæºã¯ãé åã®æå°ãµã€ãºãèšå®ããããšã§ãã ãµã€ãºãæ°ããã¡ãŒãã«ã®éåžžã«å°ããªãªããžã§ã¯ããããå ŽåïŒãŸãã¯ã³ãŒãã«ãã°ãããããªããžã§ã¯ãã®ãµã€ãºãåæåããã®ãå¿ããå ŽåïŒïŒãåé¢ãç¶è¡ãããåŒã³åºãã¹ã¿ãã¯ããªãŒããŒãããŒããå¯èœæ§ããããŸãã ç§ã®å®è£ ã§ã¯ãæå°é¢ç©ã§ãã1x1x1ãµã€ãºã®ãã¥ãŒããéžæããŸããã ãã®ãã¥ãŒãå ã®ãã¹ãŠã®ãªããžã§ã¯ãã«ã€ããŠãåçŽãªåæïŒOïŒN 2 ïŒïŒã«ããè¡çªãã§ãã¯ãå®è¡ããå¿ èŠããããŸãïŒãã以äžãªããžã§ã¯ããæåŸ ããªãïŒïŒã
- é åã«ãªããžã§ã¯ããå«ãŸããŠããªãå ŽåãããªãŒã«è¿œå ããŸããã
ååã«åå²ããäžçã®2次å 空éãåååã«åå²ããããšã§ããã1ã€ã®æé ãå®è¡ã§ããŸãã ããžãã¯ã¯åºæ¬çã«åãã§ããã2ã€ã®é·æ¹åœ¢ã§ã¯ãªãã4ã€ã®æ£æ¹åœ¢éã®è¡çªããã§ãã¯ããŸãã å®äºæ¡ä»¶ãæºãããããŸã§ããŒãã£ã·ã§ã³ãç¶ç¶ã§ããŸãã äžçã®ç©ºéãšè±¡éæšã«å¯Ÿå¿ããããŒã¿æ§é ã¯æ¬¡ã®ããã«ãªããŸãã
ã¯ã¢ãã©ã³ãããªãŒãžã®åå²ãšããŒã¿æ§é ãè«ççã«èŠããå Žåãoctreeãæ確ã«ãªããŸãã 3çªç®ã®æ¬¡å ãè¿œå ããæ£æ¹åœ¢ã§ã¯ãªãå¢çãã¥ãŒãã䜿çšããŸããã€ãŸãã4ã€ã®åããŒãã§ã¯ãªãã8ã€ã®åããŒãããããŸãã ã²ãŒã ã¯ãŒã«ãã®ãµã€ãºã200x300x400ãªã©ã®éç«æ¹äœã®å Žåãã©ããªãã®ãçåã«æããããããããŸããã ãšã«ãããç«æ¹äœã®å¯žæ³ãæã€å «åæšã䜿çšããããšãã§ããŸã-ããã€ãã®åããŒãã¯ãäžçã®ç©ºéã«äœããªãå Žåãåã«ç©ºã«ãªããŸãã æããã«ãoctreeã®æ¬¡å ã¯ãå°ãªããšãã²ãŒã ã¯ãŒã«ãã®æ¬¡å ã®å€§ããæ¹ã«çããããšãå¿ èŠã§ãã
ãªã¯ããªãŒã®äœæ
ãããã£ãŠããã§ã«ãèªã¿ããã ããããã«ãoctreeã¯ç¹å¥ãªã¿ã€ãã®åå²ããªãŒã§ãããéåžžã¯3次å 空éïŒãŸãã¯3次å ã®ãªããžã§ã¯ãïŒã§äœ¿çšãããŸãã å¢çé åã¯3次å ã®é·æ¹åœ¢ïŒããã¯ã¹ïŒïŒéåžžã¯ç«æ¹äœïŒã§ãã 次ã«ãäžèšã®ããžãã¯ãé©çšããå¢çé åã8ã€ã®å°ããªå¹³è¡å é¢äœã«åå²ããŸãã ã²ãŒã ãªããžã§ã¯ãããããã®ãµããã£ããžã§ã³ã®1ã€ã«å®å šã«é 眮ãããŠããå ŽåãããªãŒãäžã£ãŠãšãªã¢ãå«ãããŒããŸã§äžããŸãã 次ã«ãå®äºæ¡ä»¶ã®1ã€ãæºãããããŸã§ãçµæã®åé åãååž°çã«åé¢ãç¶ããŸãã ãã®çµæãçŸããããªãŒã®ãããªããŒã¿æ§é ãååŸããå¿ èŠããããŸãã
ç§ã®octreeã®å®è£ ã§ã¯ãå¢ççããã³/ãŸãã¯å¢çããã¯ã¹ãæã€ãªããžã§ã¯ããå«ãŸããŸãã 䜿çšããå¢ç圢ç¶ã決å®ããããã«å€§éã®ã³ãŒãã䜿çšããããšãããããŸãã
Octreeã¯ã©ã¹ã®ããŒã¿æ§é ã§ã¯ãåããªãŒã«æ¬¡ã®ã«ãŒã«ãéžæããŸããã
- åããŒãã«ã¯ããã®é åãå®çŸ©ããå¢çé åããããŸã
- åããŒãã«ã¯èŠªããŒããžã®ãªã³ã¯ããããŸã
- 8ã€ã®åããŒãã®é åãå«ãŸããŸãïŒé åã¯ã³ãŒãã®ç°¡çŽ åãšãã£ãã·ã¥é床ã®ããã«äœ¿çšãããŸãïŒ
- çŸåšã®é åã®ãªããžã§ã¯ãããªã¹ãããŸãã
- ãã€ããµã€ãºã®ããããã¹ã¯ã䜿çšããŠãã©ã®åããŒããã¢ã¯ãã£ãã«äœ¿çšãããŠããããå€æããŸã ïŒ è€éããå¢ããšããæé©åã®å©ç¹ã¯ããªãéèŠãªãã€ã³ãã§ã ïŒ
- ããã€ãã®éçå€æ°ã䜿çšããŠãããªãŒã®ç¶æ ã瀺ããŸãã
次ã«ã Octreeã¯ã©ã¹ã®ã¢ãŠãã©ã€ã³ã³ãŒãã瀺ããŸãã
public class OctTree { BoundingBox m_region; List m_objects; /// /// , . /// , . . /// static Queue m_pendingInsertion = new Queue(); /// /// . /// OctTree[] m_childNode = new OctTree[8]; /// /// , , . /// , , . /// byte m_activeNodes = 0; /// /// - 1x1x1. /// const int MIN_SIZE = 1; /// /// , . , . /// , "" (64) /// int m_maxLifespan = 8; // int m_curLife = -1; // , /// /// . . /// OctTree _parent; static bool m_treeReady = false; // , , static bool m_treeBuilt = false; // }
å¢çã®åæå
octreeãäœæããæåã®ã¹ãããã¯ãããªãŒå šäœã®å¢çé åãå®çŸ©ããããšã§ãã ããã¯ãããªãŒã®ã«ãŒãããŒãã®ããŠã³ãã£ã³ã°ããã¯ã¹ã«ãªããæåã¯ã²ãŒã ã¯ãŒã«ãå ã®ãã¹ãŠã®ãªããžã§ã¯ããå«ãŸããŸãã å¢çããªã¥ãŒã ãåæåããåã«ãèšèšã«é¢ãã決å®ãè¡ãå¿ èŠããããŸãã
1.ã«ãŒãããŒãã®å¢çããªã¥ãŒã ãè¶ ããŠãªããžã§ã¯ãã移åãããšã©ããªããŸããïŒ ãã¹ãŠã®ãªããžã§ã¯ããå¶éãããããã«ããªãŒå šäœã®ãµã€ãºãå€æŽããŸããïŒ ãã®å Žåã¯ãoctreeãæåããå®å šã«åæ§ç¯ããå¿ èŠããããŸãã ããã§ãªãå Žåã¯ãå¢çå€ã®ãªããžã§ã¯ããåŠçããæ¹æ³ãèŠã€ãããããªããžã§ã¯ãã決ããŠå¢çãè¶ããªãããã«ããå¿ èŠããããŸãã
2. octreeã®å¢çããã¯ã¹ãã©ã®ããã«äœæããŸããïŒ ããšãã°ãå¹³è¡å é¢äœã®200x400x200ïŒXãYãZïŒãªã©ã®æå®ã®ãµã€ãºã䜿çšããŸããïŒ ãŸãã¯ãç«æ¹äœã®æ¬¡å ã䜿çšããŸãã 2ã®ã¹ãä¹ã§ããïŒ æå°èš±å®¹å¢çé åãåå²ã§ããªãå Žåã¯ã©ããªããŸããïŒ ç§ã¯ãå šäžçãå®å šã«å¶éããã®ã«ååãªå€§ããã®2ã®çŽ¯ä¹ã«çãã次å ãæã€ç«æ¹äœã®å¢çé åã䜿çšããããšã«ããŸããã æå°ã®èš±å®¹é åã¯1x1x1ãŠããããã¥ãŒãã§ãã ããã«ãããäžçãæ確ã«åå²ããæŽæ°ãååŸããŸãïŒ Vector3ã«ã¯æµ®åå°æ°ç¹åœ¢åŒããããŸãïŒã ãŸããå¢çé åãå šäžçãå¶éããããšã決å®ããããããªããžã§ã¯ãããã®é åãé¢ãããšç Žå£ãããŸãã æå°éã®ãªã¯ã¿ã³ãã§ã¯ãåçŽãªåæã§è¡çªãã§ãã¯ãå®è¡ããŸãã ãã ãããã®ãããªå°ããªé åãåæã«å æãããªããžã§ã¯ãã¯3ã€ãŸã§ã§ãããããOïŒN 2 ïŒã®ããã©ãŒãã³ã¹ã³ã¹ãã¯çµ¶å¯Ÿã«èš±å®¹ã§ããŸãã ãªãŒãžã§ã³ã®ãµã€ãºãšããªãŒã«æ¿å ¥ããããªããžã§ã¯ãã®ãªã¹ããååŸããã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããŠãoctreeãæšæºçã«åæåããŸãã ã³ãŒãã®ãã®éšåã¯åºæ¬çãªãã®ã§ããããã衚瀺ããã¹ãã§ã¯ãªãããã«æããŸããããå®å šãæãããã«è¿œå ããŸããã
ç§ã®ã³ã³ã¹ãã©ã¯ã¿ã¯æ¬¡ã®ãšããã§ãã
/*: , .*/ /// /// , . /// /// . /// , private OctTree(BoundingBox region, List objList) { m_region = region; m_objects = objList; m_curLife = -1; } public OctTree() { m_objects = new List(); m_region = new BoundingBox(Vector3.Zero, Vector3.Zero); m_curLife = -1; } /// /// , . /// /// . /// : , . public OctTree(BoundingBox region) { m_region = region; m_objects = new List(); m_curLife = -1; }
å ã®octreeã®äœæ
ç§ã¯åæåã®é 延ã倧奜ãã§ãã 絶察ã«å¿ èŠã«ãªããŸã§ãã¡ã¢ãªã®å²ãåœãŠãšäœæ¥ãé¿ããããšããŸãã octreeã®å Žåãå¯èœãªéãããŒã¿æ§é ãäœæããªãããã«ããŸãã ããŒã¿æ§é ã«ãªããžã§ã¯ããæ¿å ¥ãããšãããŠãŒã¶ãŒã®ãªã¯ãšã¹ããåãåããŸãããå®éã«ã¯ã誰ãããã®ãã¥ãŒãéå§ãããŸã§ããªãŒãäœæããå¿ èŠã¯ãããŸããã
ããã«ããäœãåŸãããŸããïŒ ããŠãããªãŒã®äœæãšãã©ããŒã¹ã®ããã»ã¹ã¯ãããªãã®ãªãœãŒã¹ãæ¶è²»ãããšèããŠãã ããã ãŠãŒã¶ãŒãããªãŒã«1000åã®ãªããžã§ã¯ããæ¿å ¥ãããå ŽåãåŸç¶ã®åããŠã³ãã£ã³ã°ãšãªã¢ã1,000åã«ãŠã³ãããã®ã¯çã«ããªã£ãŠããŸããïŒãŸãã¯ãæéãç¯çŽããŠäžæ¬åŠçã§ããŸããïŒ
èŠçŽ ã®ãåŸ æ©ããã¥ãŒãšãããªãŒã®æ§ç¯ç¶æ ã瀺ãããã€ãã®ãã©ã°ãäœæããŸãããæ¿å ¥ããããã¹ãŠã®èŠçŽ ã¯ä¿çäžã®ãã¥ãŒã«ç§»åãããã¥ãŒã®æºåãå®äºãããšããããã®ä¿çäžã®èŠæ±ã¯ãã¹ãŠè»¢éãããŠããªãŒã«æ¿å ¥ãããŸããããã¯ã²ãŒã ãããŒããããšãã«ç¹ã«äŸ¿å©ã§ããäœåãã®ãªããžã§ã¯ããåæã«æ¿å ¥ããå¯èœæ§ãé«ãããã§ããã²ãŒã ã¯ãŒã«ããèªã¿èŸŒãã åŸãããªãŒã«æ¿å ¥ããããªããžã§ã¯ãã®æ°ã¯ãæ¡éãã«å°ãããªããŸããé 延åæåã«ãŒãã³ã¯ãUpdateTreeïŒïŒã¡ãœããã«å«ãŸããŠããŸããããªãŒãæ§ç¯ãããŠãããã©ããã確èªããããŒã¿æ§é ãååšããä¿çäžã®ãªããžã§ã¯ããããå Žåã¯æ§ç¯ããŸãã
/// /// . /// /// ? private void UpdateTree() // { if (!m_treeBuilt) { while (m_pendingInsertion.Count != 0) m_objects.Add(m_pendingInsertion.Dequeue()); BuildTree(); } else { while (m_pendingInsertion.Count != 0) Insert(m_pendingInsertion.Dequeue()); } m_treeReady = true; }
ããªãŒèªäœãæ§ç¯ããã«ã¯ããããååž°çã«äœ¿çšã§ããŸãã
ã€ãŸããååž°å埩ããšã«ãå¢çé åã«å«ãŸãããªããžã§ã¯ãã®ãªã¹ãããå§ããŸããå®äºæ¡ä»¶ãæºããããŠãããã©ããã確èªããããã§ãªãå Žåã¯ãå¢çé åã«å®å šã«åãŸã8ã€ã®åå²ãããå¢ç空éãäœæããŸãã次ã«ãæå®ããããªã¹ãå ã®åãªããžã§ã¯ãã調ã¹ãŠãããããªã¯ã¿ã³ãã®1ã€ã«å®å šã«åãŸããã©ããã確èªããŸããåãŸãå Žåã¯ããã®ãªã¯ã¿ã³ãã®å¯Ÿå¿ãããªã¹ãã«æ¿å ¥ããŸããæåŸã«ã察å¿ãããªã¯ã¿ã³ãã®ãªã¹ãã§æ°éã確èªããæ°ãããªã¯ã¿ãŒããäœæããŠçŸåšã®ããŒãã«ã¢ã¿ããããã¢ã¯ãã£ãã«äœ¿çšãããŠããåãªã¯ã¿ã³ããããããã¹ã¯ã§ããŒã¯ããŸãã
æ®ãã®ãã¹ãŠã®ãªããžã§ã¯ãã¯èŠªããŒãããæž¡ãããŸãããåããŒãã®ããããã«åçŽã«äžããããšã¯ã§ããŸããããããã£ãŠãããã¯ããã®ãªããžã§ã¯ãã«å«ããããšãã§ããæå°ã®ãªã¯ã¿ã³ãã§ããããšãè«ççã§ãã
/// /// . /// private void BuildTree() // { // , if (m_objects.Count <= 1) return; Vector3 dimensions = m_region.Max - m_region.Min; if (dimensions == Vector3.Zero) { FindEnclosingCube(); dimensions = m_region.Max - m_region.Min; } //, if (dimensions.X <= MIN_SIZE && dimensions.Y <= MIN_SIZE && dimensions.Z <= MIN_SIZE) { return; } Vector3 half = dimensions / 2.0f; Vector3 center = m_region.Min + half; // BoundingBox[] octant = new BoundingBox[8]; octant[0] = new BoundingBox(m_region.Min, center); octant[1] = new BoundingBox(new Vector3(center.X, m_region.Min.Y, m_region.Min.Z), new Vector3(m_region.Max.X, center.Y, center.Z)); octant[2] = new BoundingBox(new Vector3(center.X, m_region.Min.Y, center.Z), new Vector3(m_region.Max.X, center.Y, m_region.Max.Z)); octant[3] = new BoundingBox(new Vector3(m_region.Min.X, m_region.Min.Y, center.Z), new Vector3(center.X, center.Y, m_region.Max.Z)); octant[4] = new BoundingBox(new Vector3(m_region.Min.X, center.Y, m_region.Min.Z), new Vector3(center.X, m_region.Max.Y, center.Z)); octant[5] = new BoundingBox(new Vector3(center.X, center.Y, m_region.Min.Z), new Vector3(m_region.Max.X, m_region.Max.Y, center.Z)); octant[6] = new BoundingBox(center, m_region.Max); octant[7] = new BoundingBox(new Vector3(m_region.Min.X, center.Y, center.Z), new Vector3(center.X, m_region.Max.Y, m_region.Max.Z)); // , . List[] octList = new List[8]; for (int i = 0; i < 8; i++) octList = new List(); // , . . List delist = new List(); foreach (Physical obj in m_objects) { if (obj.BoundingBox.Min != obj.BoundingBox.Max) { for (int a = 0; a < 8; a++) { if (octant[a].Contains(obj.BoundingBox) == ContainmentType.Contains) { octList[a].Add(obj); delist.Add(obj); break; } } } else if (obj.BoundingSphere.Radius != 0) { for (int a = 0; a < 8; a++) { if (octant[a].Contains(obj.BoundingSphere) == ContainmentType.Contains) { octList[a].Add(obj); delist.Add(obj); break; } } } } // . foreach (Physical obj in delist) m_objects.Remove(obj); // , , for (int a = 0; a < 8; a++) { if (octList[a].Count != 0) { m_childNode[a] = CreateNode(octant[a], octList[a]); m_activeNodes |= (byte)(1 << a); m_childNode[a].BuildTree(); } } m_treeBuilt = true; m_treeReady = true; } private OctTree CreateNode(BoundingBox region, List objList) // { if (objList.Count == 0) return null; OctTree ret = new OctTree(region, objList); ret._parent = this; return ret; } private OctTree CreateNode(BoundingBox region, Physical Item) { List objList = new List(1); // objList.Add(Item); OctTree ret = new OctTree(region, objList); ret._parent = this; return ret; }
ããªãŒæŽæ°
ç§ãã¡ã®æšã«ã¯å€ãã®åãç©äœããããšæ³åããŠãã ããããªããžã§ã¯ãã移åããå Žåããã®ãªããžã§ã¯ããå²ããªã¯ã¿ã³ãã®å¢çãè¶ ããå¯èœæ§ãé«ããªããŸããããªãŒæ§é ã®æŽåæ§ãç¶æããªããããªããžã§ã¯ãã®äœçœ®ã®å€æŽãåŠçããæ¹æ³ã¯ïŒ
ãã¯ããã¯1ïŒéåžžã«åçŽã«ããã¹ãŠãåé€ããŠåæ§ç¯ããŸãã
octreeããªãŒã®äžéšã®å®è£ ã§ã¯ãåãã¬ãŒã ã«æ°ããããªãŒãäœæãããå€ãããªãŒãåé€ãããŸããããã¯éåžžã«åçŽã§ããã®ææ³ã¯æ©èœããŸããèªåã«åã£ãŠããå Žåã¯ãéžæããå¿ èŠããããŸããäžè¬ã«ãåãã¬ãŒã ã§ããªãŒãåæ§ç¯ããããã«ããã»ããµã«è²»ããããäºåæéã¯ãåçŽãªç¶²çŸ çæ€çŽ¢ã«ããè¡çªãã§ãã¯ãå®è¡ãããããã¯ããã«å®äŸ¡ã§ãããããã°ã©ãã®æéã¯ãªãã·ã§ã³ã®æé©åã«è²»ããã«ã¯è²ŽéããããšèããããŠããŸããå°é£ãå䜵çãæããç§ãã¡ã«ãšã£ãŠããé€å»ãšåæ§ç¯ãæè¡ã¯å°ããªåé¡ãåŒãèµ·ãããŸãã
- ããªãŒãåæ§ç¯ãããã³ã«ãåžžã«ã¡ã¢ãªãå²ãåœãŠãŠè§£æŸããŸããæ°ããã¡ã¢ãªãå²ãåœãŠãã«ã¯å°ãã®ãªãœãŒã¹ãå¿ èŠã§ããå¯èœãªéããæ¢åã®ã¡ã¢ãªãåå©çšããŠãå²ãåœãŠãããã¡ã¢ãªãšè§£æŸãããã¡ã¢ãªã®éãæå°éã«æããããšããŸãã
- ããªãŒã®ã»ãšãã©ã¯å€æŽãããªããããåããã©ã³ããç¶ç¶çã«åæ§ç¯ããããšã¯ãããã»ããµæéã®ç¡é§ã§ãã
ãã¯ããã¯2ïŒæ¢åã®ããªãŒãä¿åããå€æŽããããã©ã³ããæŽæ°ããŸãã
ããªãŒã®ã»ãšãã©ã®ãã©ã³ãã«ã¯æŽæ°ãå¿ èŠãªãããšã«æ°ä»ããŸãããéæ¢ãããªããžã§ã¯ãã®ã¿ãå«ãŸããŸãã
åãã¬ãŒã ã§ããªãŒå šäœãåæ§ç¯ãã代ããã«ãæŽæ°ãå¿ èŠãªããªãŒã®éšåãæŽæ°ããã ãã§ããã®ã§ã¯ãªãã§ããããïŒãã®ææ³ã¯ãæ¢åã®ããªãŒãä¿åãã移åãªããžã§ã¯ããå«ããã©ã³ãã®ã¿ãæŽæ°ããŸãããã®å®è£ ã¯ããå°ãé£ããã§ãããããèå³æ·±ãã®ã§ããããå®äºãããŸãããïŒ
æåã®å®éšã§ãåããŒãã®ãªããžã§ã¯ãã¯ããªãŒã®1ã€ã®é·ç§»ã®ã¿ãäžäžãããããšãã§ãããšèª€ã£ãŠä¿¡ããŠããŸãããããã¯çå®ã§ã¯ãããŸãããåããŒãã®ãªããžã§ã¯ããããŒãã®ç«¯ã«å°éãããã®ç«¯ãå¢çã®èŠªããŒãã®ç«¯ã§ãããå Žåããªããžã§ã¯ãã¯ãã®èŠªã®äžã«ãå Žåã«ãã£ãŠã¯ãã以äžã«æ¿å ¥ããå¿ èŠããããŸããã€ãŸããçµæãšããŠããªããžã§ã¯ããããªãŒå ã§ã©ãã ãé«ããªããã¯ããããŸãããããã«ããªããžã§ã¯ãã¯åããŒããŸãã¯åããŒãã®åããŒãã«éœåããåãŸãããšãã§ããŸããç§ãã¡ã¯ãã©ããŸã§ç¥ããŸããããŠã³ãããã¯æšãäžãããšãã§ããŸãã
幞ããªããšã«ãåããŒãã®èŠªãžã®åç §ãä¿æããŠãããããæå°éã®èšç®ã䜿çšããååž°ã«ãã£ãŠãã®åé¡ãç°¡åã«è§£æ±ºã§ããŸãã
æŽæ°ã¢ã«ãŽãªãºã ã®äž»ãªã¢ã€ãã¢ã¯ãããªãŒå ã®ãã¹ãŠã®ãªããžã§ã¯ããæåã«èªåèªèº«ãæŽæ°ã§ããããã«ããããšã§ãããããã®äžéšã¯ç§»åãŸãã¯ãµã€ãºå€æŽãããŸãã移åããããã¹ãŠã®ãªããžã§ã¯ãã®ãªã¹ããååŸããŠããªããžã§ã¯ãæŽæ°ã¡ãœãããããªããžã§ã¯ãã®å¢çãå€æŽãããã©ããã決å®ããããŒã«å€ãè¿ãããã«ããŸãã
ãã¹ãŠã®ãªããžã§ã¯ããåãã®ãªã¹ããåãåã£ãåŸãç§ãã¡ã¯çŸåšã®ãµã€ãã§éå§ããããªãŒãååŸããããšãããŸã§ãæã ã¯å®å šã«åããªããžã§ã¯ããïŒã»ãšãã©ã®å Žåããªããžã§ã¯ãããŸã çŸåšã®ããŒãã«ãªããŸãïŒãå容ãããŒããèŠã€ãããŸã§ããªããžã§ã¯ããçŸåšã®ããŒãã«å®å šã«ååšããªãå Žåã次ã®èŠªããŒãã«ç§»åãç¶ããŸããææªã®å Žåããªããžã§ã¯ãã¯ã«ãŒãããŒãã«ããããšãä¿èšŒãããŸãã
ããªãŒå ã§ãªããžã§ã¯ããã§ããã ãé«ã移åããåŸãããªãŒå ã§ãªããžã§ã¯ããã§ããã ãäœãããããšããŸããã»ãšãã©ã®å Žåããªããžã§ã¯ããäžã«ç§»åã§ããå Žåããªããžã§ã¯ããäžããããšã¯ã§ããŸãããããããçŸåšã®ããŒãã®åããŒãããªããžã§ã¯ããå«ãããšãã§ããããã«ãªããžã§ã¯ãã移åããå ŽåãããªãŒã®äžã«ãããäžããæ©äŒããããŸããããªãŒå ã§ãªããžã§ã¯ããäžäžã«ç§»åã§ããããšãéèŠã§ããããããªããšããã¹ãŠã®ç§»åãªããžã§ã¯ããåŸã ã«äžã«ç§»åããè¡çªèªèæé ã®é床ã«åé¡ãçããŸãã
ãã©ã³ãã®åé€
å Žåã«ãã£ãŠã¯ããªããžã§ã¯ããããŒããã移åã§ãããã®ããŒãã«ã¯ãã¹ãŠã®åå«ã®ããã«ãªããžã§ã¯ããå«ãŸããªããªããŸãããã®å Žåã空ã®ãã©ã³ãã圢æãããŸããã次ã«ãããŒã¯ãä»ããŠããã®æ¯ããæãæšããåãåããŸãã
ããã§èå³æ·±ãçåãçããŸãããã€æ¯ããæãæšããåãèœãšãå¿ èŠãããã®ã§ããããïŒæ°ããã¡ã¢ãªã®å²ãåœãŠã«ã¯æéããããã®ã§ãåãé åãæ°ãµã€ã¯ã«ã«ããã£ãŠåå©çšããå Žåãããã«åé€ããã®ã¯ãªãã§ããïŒããããã©ã³ããç¶æããã®ã«è²»çšãããããŸã§ãã©ããããã®æéä¿åã§ããŸããïŒ
ãã©ã³ããåæ¢ãããšãã«ã¢ã¯ãã£ãã«ãªãã«ãŠã³ãããŠã³ã¿ã€ããŒãåããŒãã«äžããããšã«ããŸããããã¹ã¿ã€ããŒãã¢ã¯ãã£ããªãšãã«ãªããžã§ã¯ãããã®ããŒãã®ãªã¯ã¿ã³ãã«ç§»åããå Žåã寿åœã2åã«ããŠã¿ã€ããŒããªã»ããããŸããããã«ãããé »ç¹ã«äœ¿çšããããªã¯ã¿ã³ããã¢ã¯ãã£ãã®ãŸãŸã«ãªããåé€ãããªããªããŸãããŸãã䜿çšé »åºŠã®äœãããŒãã¯ãã¹ãã¬ãŒãžãé«ããªããããåã«åé€ãããŸãã
ãã®æè¡ã®æçšæ§ã¯ãæ©é¢éã匟䞞ã®æµããçºå°ããå®éã®äŸããæããã§ãããããã®åŒŸäžžã¯äºãã«éåžžã«è¿ãã«é£ãã§ããã®ã§ãæåã®åŒŸäžžãé£ã³åºããçŽåŸã«ããŒããåé€ãã2çªç®ã®åŒŸäžžããããããç¬éã«ããŒããå埩ããã®ã¯äžäŸ¿ã§ããç®æ¡æžããããããããã®ã§ããããã®ãªã¯ã¿ã³ãããã°ããä¿æããæ¹ãè¯ãã§ããããåãã©ã³ãã空ã§ãé·æé䜿çšãããŠããªãå ŽåãããªãŒããç°¡åã«åãé¢ãããšãã§ããŸãã
ãã®ãã¹ãŠã®éæ³ãå®è¡ããã³ãŒããèŠãŠã¿ãŸãããã
ãŸããUpdateïŒïŒã¡ãœããããããŸãããã¹ãŠã®åããªãŒã¯ããã®äžã§ååž°çã«åŒã³åºãããŸãããã¹ãŠã®ãªããžã§ã¯ãã移åããããŒã¿æ§é ã®é åºã埩å ããŠãããã·ãããããåãªããžã§ã¯ãã察å¿ããããŒãïŒèŠªãŸãã¯åïŒã«ç§»åããŸãã
public void Update(GameTime gameTime) { if (m_treeBuilt == true) { // , . // , . , . // if (m_objects.Count == 0) { if (HasChildren == false) { if (m_curLife == -1) m_curLife = m_maxLifespan; else if (m_curLife > 0) { m_curLife--; } } } else { if (m_curLife != -1) { if(m_maxLifespan <= 64) m_maxLifespan *= 2; m_curLife = -1; } } List movedObjects = new List(m_objects.Count); // foreach (Physical gameObj in m_objects) { // , , . if (gameObj.Update(gameTime)) { movedObjects.Add(gameObj); } } // . int listSize = m_objects.Count; for (int a = 0; a < listSize; a++) { if (!m_objects[a].Alive) { if (movedObjects.Contains(m_objects[a])) movedObjects.Remove(m_objects[a]); m_objects.RemoveAt(a--); listSize--; } } // . for( int flags = m_activeNodes, index = 0; flags > 0; flags >>=1, index++) if ((flags & 1) == 1) m_childNode[index].Update(gameTime); // , , . //, , . foreach (Physical movedObj in movedObjects) { OctTree current = this; //, , // // , if (movedObj.BoundingBox.Max != movedObj.BoundingBox.Min) { while (current.m_region.Contains(movedObj.BoundingBox) != ContainmentType.Contains) if (current._parent != null) current = current._parent; else break; // , } else { while (current.m_region.Contains(movedObj.BoundingSphere) != ContainmentType.Contains)//, , . if (current._parent != null) current = current._parent; else break; } // . m_objects.Remove(movedObj); current.Insert(movedObj); // , . } // for (int flags = m_activeNodes, index = 0; flags > 0; flags >>= 1, index++) if ((flags & 1) == 1 && m_childNode[index].m_curLife == 0) { m_childNode[index] = null; m_activeNodes ^= (byte)(1 << index); // } //, , . if (IsRoot == true) { // . // . //: , . // 2: , . . List irList = GetIntersection(new List()); foreach (IntersectionRecord ir in irList) { if (ir.PhysicalObject != null) ir.PhysicalObject.HandleIntersection(ir); if (ir.OtherPhysicalObject != null) ir.OtherPhysicalObject.HandleIntersection(ir); } } } else { } }
移åãããªããžã§ã¯ãã«å¯ŸããŠãInsertïŒïŒã¡ãœãããåŒã³åºããŠããããšã«æ³šæããŠãã ãããããªãŒãžã®ãªããžã§ã¯ãã®æ¿å ¥ã¯ãå ã®ããªãŒãäœæããããã«äœ¿çšãããæ¹æ³ã«éåžžã«äŒŒãŠããŸããInsertïŒïŒã¯ããªããžã§ã¯ããããªãŒã®ã§ããã ãäžã«äžããããšããŸãããŸããåããŒãã§æ¢åã®ã¹ããŒã¹ã䜿çšã§ããå Žåã¯ãæ°ããå¢çã¹ããŒã¹ãäœæããªãããã«ããŸãã
/// /// , , /// /// /// private void Insert(T Item) where T : Physical { /*, , - , .*/ if (m_objects.Count <= 1 && m_activeNodes == 0) { m_objects.Add(Item); return; } Vector3 dimensions = m_region.Max - m_region.Min; //, if (dimensions.X <= MIN_SIZE && dimensions.Y <= MIN_SIZE && dimensions.Z <= MIN_SIZE) { m_objects.Add(Item); return; } Vector3 half = dimensions / 2.0f; Vector3 center = m_region.Min + half; // BoundingBox[] childOctant = new BoundingBox[8]; childOctant[0] = (m_childNode[0] != null) ? m_childNode[0].m_region : new BoundingBox(m_region.Min, center); childOctant[1] = (m_childNode[1] != null) ? m_childNode[1].m_region : new BoundingBox(new Vector3(center.X, m_region.Min.Y, m_region.Min.Z), new Vector3(m_region.Max.X, center.Y, center.Z)); childOctant[2] = (m_childNode[2] != null) ? m_childNode[2].m_region : new BoundingBox(new Vector3(center.X, m_region.Min.Y, center.Z), new Vector3(m_region.Max.X, center.Y, m_region.Max.Z)); childOctant[3] = (m_childNode[3] != null) ? m_childNode[3].m_region : new BoundingBox(new Vector3(m_region.Min.X, m_region.Min.Y, center.Z), new Vector3(center.X, center.Y, m_region.Max.Z)); childOctant[4] = (m_childNode[4] != null) ? m_childNode[4].m_region : new BoundingBox(new Vector3(m_region.Min.X, center.Y, m_region.Min.Z), new Vector3(center.X, m_region.Max.Y, center.Z)); childOctant[5] = (m_childNode[5] != null) ? m_childNode[5].m_region : new BoundingBox(new Vector3(center.X, center.Y, m_region.Min.Z), new Vector3(m_region.Max.X, m_region.Max.Y, center.Z)); childOctant[6] = (m_childNode[6] != null) ? m_childNode[6].m_region : new BoundingBox(center, m_region.Max); childOctant[7] = (m_childNode[7] != null) ? m_childNode[7].m_region : new BoundingBox(new Vector3(m_region.Min.X, center.Y, center.Z), new Vector3(center.X, m_region.Max.Y, m_region.Max.Z)); //-, ? // 2: . , /. // . . . // : 256x256x256. . if (Item.BoundingBox.Max != Item.BoundingBox.Min && m_region.Contains(Item.BoundingBox) == ContainmentType.Contains) { bool found = false; // . , . for(int a=0;a<8;a++) { // ? if (childOctant[a].Contains(Item.BoundingBox) == ContainmentType.Contains) { if (m_childNode[a] != null) m_childNode[a].Insert(Item); // , else { m_childNode[a] = CreateNode(childOctant[a], Item); // m_activeNodes |= (byte)(1 << a); } found = true; } } if(!found) m_objects.Add(Item); } else if (Item.BoundingSphere.Radius != 0 && m_region.Contains(Item.BoundingSphere) == ContainmentType.Contains) { bool found = false; // . , . for (int a = 0; a < 8; a++) { // ? if (childOctant[a].Contains(Item.BoundingSphere) == ContainmentType.Contains) { if (m_childNode[a] != null) m_childNode[a].Insert(Item); //A , else { m_childNode[a] = CreateNode(childOctant[a], Item); // m_activeNodes |= (byte)(1 << a); } found = true; } } if (!found) m_objects.Add(Item); } else { // , . , // , //BoundingBox enclosingArea = FindBox(); BuildTree(); } }
è¡çªèªè
æåŸã«ãoctreeãæ§ç¯ããå¿ èŠãªãã¹ãŠã®èšåãæŽã£ãŠããŸããè¡çªèªèã®å®è¡æ¹æ³ã¯ïŒå§ããããã«ãè¡çªãèªèãããããŸããŸãªæ¹æ³ããªã¹ãããŸãããïŒ
octreeã®ååž°è¡çªèªèåŠçã®äž»ãªã¢ã€ãã¢ã¯ãã«ãŒã/çŸåšã®ããŒãããéå§ãããã®ããŒãå ã®ãã¹ãŠã®ãªããžã§ã¯ããšäº€å·®ããå³åœ¢ãšã®äº€å·®ããã§ãã¯ããããšã§ãã
次ã«ã亀差ãã圢ç¶ãæã€ãã¹ãŠã®ã¢ã¯ãã£ããªåããŒãã«å¯ŸããŠãå¢çããã¯ã¹ã䜿çšãã亀差ãã§ãã¯ãå®è¡ãããŸããåããŒãã®äº€å·®ãã§ãã¯ã«å€±æããå Žåããã®åããŒãã®æ®ãã®ããªãŒã¯å®å šã«ç¡èŠãããŸããåããŒãã亀差ã®ãã§ãã¯ã«åæ Œããå ŽåãããªãŒãååž°çã«ãã©ã£ãŠããã»ã¹ãç¹°ãè¿ããŸããåããŒãã¯ãåŒã³åºãå ã®ããã·ãŒãžã£ã«ãªã¹ããæž¡ãå¿ èŠããããŸãã亀差ç¹ã¬ã³ãŒãããã®ããã·ãŒãžã£ã¯ããããã®äº€å·®ç¹ãç¬èªã®äº€å·®ç¹ãªã¹ãã«æ·»ä»ããŸããååž°ãå®äºãããšãå ã®åŒã³åºãããã·ãŒãžã£ã¯ãæå®ããã亀差å³åœ¢ã®ãã¹ãŠã®äº€å·®ç¹ã®ãªã¹ããååŸããŸãã
ãã®ã¢ãããŒãã®å©ç¹ã¯ãå®è£ ã«å¿ èŠãªã³ãŒããéåžžã«å°ãªããããã©ãŒãã³ã¹ãéåžžã«é«ãããšã§ãããããã®è¡çªã®å€ãã§ã¯ãå€ãã®çµæãåŸãããå¯èœæ§ããããŸãããŸããè¡çªãããªããžã§ã¯ãã«å¿ããŠãåè¡çªã«å¯Ÿå¿ããäœããã®æ¹æ³ãå¿ èŠã§ããããšãã°ããã¬ã€ã€ãŒã®ãã£ã©ã¯ã¿ãŒã¯ç©ºäžã«ã¶ãäžãã£ãŠããããŒãã¹ãç²åŸããå¿ èŠããããŸãïŒ4åã®ãã¡ãŒãžïŒïŒããããããã±ããã¯ãã®ããŒãã¹ã«åœãããšççºããŸããã
å亀差ç¹ã«é¢ããæ å ±ãæ ŒçŽããæ°ããã¯ã©ã¹ãäœæããŸããããã®ã¯ã©ã¹ã«ã¯ã亀差ãããªããžã§ã¯ãã亀差ç¹ã亀差ç¹ã§ã®æ³ç·ãªã©ãžã®åç §ãå«ãŸããŸãããã®ãããªäº€å·®ã¬ã³ãŒãã¯ããªããžã§ã¯ãã«æž¡ããŠåŠçãããšãã«éåžžã«åœ¹ç«ã¡ãŸãã
å®å šæ§ãšæ確æ§ã®ããã«ã亀差ç¹ãšã³ããªã³ãŒãã以äžã«ç€ºããŸããã
public class IntersectionRecord { Vector3 m_position; /// /// 3D-, . /// public Vector3 Position { get { return m_position; } } Vector3 m_normal; /// /// /// public Vector3 Normal { get { return m_normal; } } Ray m_ray; /// /// , /// public Ray Ray { get { return m_ray; } } Physical m_intersectedObject1; /// /// , /// public Physical PhysicalObject { get { return m_intersectedObject1; } set { m_intersectedObject1 = value; } } Physical m_intersectedObject2; /// /// ( null, , -) /// public Physical OtherPhysicalObject { get { return m_intersectedObject2; } set { m_intersectedObject2 = value; } } /// /// , . /// . - , /// , . /// OctTree m_treeNode; /// /// . , . /// /// , /// , - , . public override bool Equals(object otherRecord) { IntersectionRecord o = (IntersectionRecord)otherRecord; // // (m_intersectedObject1 != null && m_intersectedObject2 != null && m_intersectedObject1.ID == m_intersectedObject2.ID); if (otherRecord == null) return false; if (o.m_intersectedObject1.ID == m_intersectedObject1.ID && o.m_intersectedObject2.ID == m_intersectedObject2.ID) return true; if (o.m_intersectedObject1.ID == m_intersectedObject2.ID && o.m_intersectedObject2.ID == m_intersectedObject1.ID) return true; return false; } double m_distance; /// /// . /// , . /// public double Distance { get { return m_distance; } } private bool m_hasHit = false; public bool HasHit { get { return m_hasHit; } } public IntersectionRecord() { m_position = Vector3.Zero; m_normal = Vector3.Zero; m_ray = new Ray(); m_distance = float.MaxValue; m_intersectedObject1 = null; } public IntersectionRecord(Vector3 hitPos, Vector3 hitNormal, Ray ray, double distance) { m_position = hitPos; m_normal = hitNormal; m_ray = ray; m_distance = distance; // m_hitObject = hitGeom; m_hasHit = true; } /// /// , , , . /// /// : , . null. public IntersectionRecord(Physical hitObject = null) { m_hasHit = hitObject != null; m_intersectedObject1 = hitObject; m_position = Vector3.Zero; m_normal = Vector3.Zero; m_ray = new Ray(); m_distance = 0.0f; } }
å¢çãåãåã£ããã©ããããšã®äº€å·®ç¹
/// /// , /// /// / /// private List GetIntersection(BoundingFrustum frustum, Physical.PhysicalType type = Physical.PhysicalType.ALL) { if (m_objects.Count == 0 && HasChildren == false) // return null; List ret = new List(); // foreach (Physical obj in m_objects) { // , if ((int)((int)type & (int)obj.Type) == 0) continue; // IntersectionRecord ir = obj.Intersects(frustum); if (ir != null) ret.Add(ir); } // for (int a = 0; a < 8; a++) { if (m_childNode[a] != null && (frustum.Contains(m_childNode[a].m_region) == ContainmentType.Intersects || frustum.Contains(m_childNode[a].m_region) == ContainmentType.Contains)) { List hitList = m_childNode[a].GetIntersection(frustum); if (hitList != null) { foreach (IntersectionRecord ir in hitList) ret.Add(ir); } } } return ret; }
å¢çã®åãæšãŠããããã©ãããã®äº€ç¹ã®ãªã¹ãã䜿çšããŠãçŸåšã®ã«ã¡ã©ã®å¯èŠé åã«è¡šç€ºããããªããžã§ã¯ããã¬ã³ããªã³ã°ã§ããŸããã·ãŒã³ããŒã¿ããŒã¹ã䜿çšããŠãã²ãŒã ã¯ãŒã«ãå ã®ãã¹ãŠã®ãªããžã§ã¯ããã¬ã³ããªã³ã°ããæ¹æ³ãèŠã€ããŸããããã¯ãã¢ã¯ãã£ãã«ã¡ã©ã®å¢çã®åãæšãŠããããã©ãããã䜿çšããã¬ã³ããªã³ã°é¢æ°ã®ã³ãŒãã¹ããããã§ãã
/// /// /// /// public int Render() { int triangles = 0; // , // foreach (IntersectionRecord ir in m_octTree.AllIntersections(m_cameras[m_activeCamera].Frustum)) { ir.PhysicalObject.SetDirectionalLight(m_globalLight[0].Direction, m_globalLight[0].Color); ir.PhysicalObject.View = m_cameras[m_activeCamera].View; ir.PhysicalObject.Projection = m_cameras[m_activeCamera].Projection; ir.PhysicalObject.UpdateLOD(m_cameras[m_activeCamera]); triangles += ir.PhysicalObject.Render(m_cameras[m_activeCamera]); } return triangles; }
ããŒã 亀差ç¹
/// /// , /// /// , /// private List GetIntersection(Ray intersectRay, Physical.PhysicalType type = Physical.PhysicalType.ALL) { if (m_objects.Count == 0 && HasChildren == false) // return null; List ret = new List(); // , . // foreach (Physical obj in m_objects) { // , if ((int)((int)type & (int)obj.Type) == 0) continue; if (obj.BoundingBox.Intersects(intersectRay) != null) { IntersectionRecord ir = obj.Intersects(intersectRay); if (ir.HasHit) ret.Add(ir); } } // for (int a = 0; a < 8; a++) { if (m_childNode[a] != null && m_childNode[a].m_region.Intersects(intersectRay) != null) { List hits = m_childNode[a].GetIntersection(intersectRay, type); if (hits != null) { foreach (IntersectionRecord ir in hits) ret.Add(ir); } } } return ret; }
ãªããžã§ã¯ãã®ãªã¹ããšã®äº€å·®ç¹
ããã¯ãçŸåšã®ããŒãã®ãªããžã§ã¯ãã®ãªã¹ããšãã¹ãŠã®åããŒãã®ãªããžã§ã¯ãã®å ±ééšåã決å®ããããã®ç¹ã«äŸ¿å©ãªååž°çæ¹æ³ã§ãïŒã¢ããªã±ãŒã·ã§ã³ã®UpdateïŒïŒã¡ãœãããåç §ïŒããã®ã¡ãœããã¯æãé »ç¹ã«åŒã³åºãããã®ã§ãæ£ç¢ºã§å¹ççãªæ¹æ³ã«ãããšããã§ãããã
ããªãŒã®ã«ãŒãããŒãããå§ããŸããããçŸåšã®ããŒãã®ãã¹ãŠã®ãªããžã§ã¯ããšçŸåšã®ããŒãã®ä»ã®ãã¹ãŠã®ãªããžã§ã¯ããšã®è¡çªãæ¯èŒããŸãããã¹ãŠã®è¡çªã亀差ç¹ã®èšé²ãšããŠä¿®æ£ãããããããªã¹ãã«æ¿å ¥ããŸãã次ã«ãã¹ãã£ã³ãããªããžã§ã¯ãã®ãªã¹ããåããŒãã«æž¡ããŸããåããŒãã¯ããªããžã§ã¯ããšãããã®äº€ç¹ããã§ãã¯ãã次ã«æž¡ãããªããžã§ã¯ããšã®äº€ç¹ããã§ãã¯ããŸããåããŒãã¯ãã¹ãŠã®è¡çªããªã¹ãã«ä¿åãããã®ãªã¹ãã芪ã«æž¡ããŸãã次ã«ã芪ã¯åããŒãããååŸããè¡çªã®ãªã¹ããååŸãããããç¬èªã®è¡çªã®ãªã¹ãã«è¿œå ããåŒã³åºãå ã®ããã·ãŒãžã£ã«æž¡ããŸãã
å³ã§è¡çªãã§ãã¯ã®åæ°ãæ°ãããšã29ã®è¡çªã®å¯èœæ§ããã§ãã¯ããã4ãèŠã€ãã£ãããšãããããŸã[11 * 11 = 121]è¡çªãã§ãã¯ãããã¯ããã«åªããŠããŸãã
private List GetIntersection(List parentObjs, Physical.PhysicalType type = Physical.PhysicalType.ALL) { List intersections = new List(); // , . // foreach (Physical pObj in parentObjs) { foreach (Physical lObj in m_objects) { // . , . // , . IntersectionRecord ir = pObj.Intersects(lObj); if (ir != null) { intersections.Add(ir); } } } // if (m_objects.Count > 1) { #region self-congratulation /* * . foreach, : * foreach(Physical lObj1 in m_objects) * { * foreach(Physical lObj2 in m_objects) * { * // * } * } * * , O(N*N) , . * , : {1,2,3,4} * {1} {1,2,3,4} * {2} {1,2,3,4}, * {1} {2}, {2} {1} . , {1}? * 4+3+2+1 , O(N(N+1)/2). N = 10, . * for, foreach, * for(int i=0;i tmp = new List(m_objects.Count); tmp.AddRange(m_objects); while (tmp.Count > 0) { foreach (Physical lObj2 in tmp) { if (tmp[tmp.Count - 1] == lObj2 || (tmp[tmp.Count - 1].IsStatic && lObj2.IsStatic)) continue; IntersectionRecord ir = tmp[tmp.Count - 1].Intersects(lObj2); if (ir != null) intersections.Add(ir); } // , O(N(N+1)/2) O(N*N) tmp.RemoveAt(tmp.Count-1); } } // , . foreach (Physical lObj in m_objects) if (lObj.IsStatic == false) parentObjs.Add(lObj); //parentObjs.AddRange(m_objects); // , . for (int flags = m_activeNodes, index = 0; flags > 0; flags >>= 1, index++) if ((flags & 1) == 1) intersections.AddRange(m_childNode[index].GetIntersection(parentObjs, type)); return intersections; } ;i++)>
ãã¢ã®ã¹ã¯ãªãŒã³ã·ã§ãã
, .
, . , .