├── .gitignore ├── Assets └── OctoMapSharp │ ├── Bit.cs │ ├── BitExtensions.cs │ ├── BitStream.cs │ ├── Int24.cs │ ├── Int48.cs │ └── OctoMap.cs ├── LICENSE ├── Packages └── manifest.json ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── PresetManager.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | Assets/AssetStoreTools* 7 | 8 | # Visual Studio cache directory 9 | .vs/ 10 | .idea/ 11 | 12 | # Autogenerated VS/MD/Consulo solution and project files 13 | ExportedObj/ 14 | .consulo/ 15 | *.csproj 16 | *.unityproj 17 | *.sln 18 | *.suo 19 | *.tmp 20 | *.user 21 | *.userprefs 22 | *.pidb 23 | *.booproj 24 | *.svd 25 | *.pdb 26 | *.opendb 27 | 28 | # Unity3D generated meta files 29 | *.meta 30 | 31 | # Unity3D Generated File On Crash Reports 32 | sysinfo.txt 33 | 34 | # Builds 35 | *.apk 36 | *.unitypackage 37 | Assets/Plugins/Editor/JetBrains/JetBrains.Rider.Unity.Editor.Plugin.Repacked.dll 38 | -------------------------------------------------------------------------------- /Assets/OctoMapSharp/Bit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OctoMapSharp 4 | { 5 | [Serializable] 6 | public struct Bit 7 | { 8 | private byte value; 9 | 10 | private Bit(int value) 11 | { 12 | this.value = (byte)(value & 1); 13 | } 14 | 15 | public static implicit operator Bit(int value) 16 | { 17 | return new Bit(value); 18 | } 19 | 20 | public static implicit operator Bit(bool value) 21 | { 22 | return new Bit(value ? 1 : 0); 23 | } 24 | 25 | public static implicit operator int (Bit bit) 26 | { 27 | return bit.value; 28 | } 29 | 30 | public static implicit operator byte (Bit bit) 31 | { 32 | return (byte)bit.value; 33 | } 34 | 35 | public static implicit operator bool (Bit bit) 36 | { 37 | return bit.value == 1; 38 | } 39 | 40 | public static Bit operator &(Bit x, Bit y) 41 | { 42 | return x.value & y.value; 43 | } 44 | 45 | public static Bit operator |(Bit x, Bit y) 46 | { 47 | return x.value | y.value; 48 | } 49 | 50 | public static Bit operator ^(Bit x, Bit y) 51 | { 52 | return x.value ^ y.value; 53 | } 54 | 55 | public static Bit operator ~(Bit bit) 56 | { 57 | return (~(bit.value) & 1); 58 | } 59 | 60 | public static implicit operator string (Bit bit) 61 | { 62 | return bit.value.ToString(); 63 | } 64 | 65 | public int AsInt() 66 | { 67 | return this.value; 68 | } 69 | 70 | public bool AsBool() 71 | { 72 | return this.value == 1; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Assets/OctoMapSharp/BitExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace OctoMapSharp 2 | { 3 | public static class BitExtensions 4 | { 5 | 6 | #region GetBit 7 | 8 | public static Bit GetBit(this byte n, int index) 9 | { 10 | return n >> index; 11 | } 12 | 13 | public static Bit GetBit(this sbyte n, int index) 14 | { 15 | return n >> index; 16 | } 17 | 18 | public static Bit GetBit(this short n, int index) 19 | { 20 | return n >> index; 21 | } 22 | 23 | public static Bit GetBit(this ushort n, int index) 24 | { 25 | return n >> index; 26 | } 27 | 28 | public static Bit GetBit(this int n, int index) 29 | { 30 | return n >> index; 31 | } 32 | 33 | public static Bit GetBit(this uint n, int index) 34 | { 35 | return (byte)(n >> index); 36 | } 37 | 38 | public static Bit GetBit(this long n, int index) 39 | { 40 | return (byte)(n >> index); 41 | } 42 | 43 | public static Bit GetBit(this ulong n, int index) 44 | { 45 | return (byte)(n >> index); 46 | } 47 | 48 | #endregion 49 | 50 | #region CircularShift 51 | 52 | public static byte CircularShift(this byte n, int bits, bool leftShift) 53 | { 54 | if (leftShift) 55 | { 56 | n = (byte)(n << bits | n >> (8 - bits)); 57 | } 58 | else 59 | { 60 | n = (byte)(n >> bits | n << (8 - bits)); 61 | } 62 | return n; 63 | } 64 | 65 | public static sbyte CircularShift(this sbyte n, int bits, bool leftShift) 66 | { 67 | if (leftShift) 68 | { 69 | n = (sbyte)(n << bits | n >> (8 - bits)); 70 | } 71 | else 72 | { 73 | n = (sbyte)(n >> bits | n << (8 - bits)); 74 | } 75 | return n; 76 | } 77 | 78 | public static short CircularShift(this short n, int bits, bool leftShift) 79 | { 80 | if (leftShift) 81 | { 82 | n = (short)(n << bits | n >> (16 - bits)); 83 | } 84 | else 85 | { 86 | n = (short)(n >> bits | n << (16 - bits)); 87 | } 88 | return n; 89 | } 90 | 91 | public static ushort CircularShift(this ushort n, int bits, bool leftShift) 92 | { 93 | if (leftShift) 94 | { 95 | n = (ushort)(n << bits | n >> (16 - bits)); 96 | } 97 | else 98 | { 99 | n = (ushort)(n >> bits | n << (16 - bits)); 100 | } 101 | return n; 102 | } 103 | 104 | public static int CircularShift(this int n, int bits, bool leftShift) 105 | { 106 | if (leftShift) 107 | { 108 | n = (n << bits | n >> (32 - bits)); 109 | } 110 | else 111 | { 112 | n = (n >> bits | n << (32 - bits)); 113 | } 114 | return n; 115 | } 116 | 117 | public static uint CircularShift(this uint n, int bits, bool leftShift) 118 | { 119 | if (leftShift) 120 | { 121 | n = (uint)(n << bits | n >> (32 - bits)); 122 | } 123 | else 124 | { 125 | n = (uint)(n >> bits | n << (32 - bits)); 126 | } 127 | return n; 128 | } 129 | 130 | public static long CircularShift(this long n, int bits, bool leftShift) 131 | { 132 | if (leftShift) 133 | { 134 | n = (n << bits | n >> (64 - bits)); 135 | } 136 | else 137 | { 138 | n = (n >> bits | n << (64 - bits)); 139 | } 140 | return n; 141 | } 142 | 143 | public static ulong CircularShift(this ulong n, int bits, bool leftShift) 144 | { 145 | if (leftShift) 146 | { 147 | n = (ulong)(n << bits | n >> (64 - bits)); 148 | } 149 | else 150 | { 151 | n = (ulong)(n >> bits | n << (64 - bits)); 152 | } 153 | return n; 154 | } 155 | 156 | #endregion 157 | 158 | #region Reverse 159 | 160 | public static byte ReverseBits(this byte b) 161 | { 162 | return (byte)(((b & 1) << 7) + ((((b >> 1) & 1) << 6)) + (((b >> 2) & 1) << 5) + (((b >> 3) & 1) << 4) + (((b >> 4) & 1) << 3) +(((b >> 5) & 1) << 2) +(((b >> 6) & 1) << 1) + ((b >> 7)&1)); 163 | } 164 | 165 | #endregion 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Assets/OctoMapSharp/BitStream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | 6 | namespace OctoMapSharp 7 | { 8 | /// 9 | /// Stream wrapper to use bit-level operations 10 | /// 11 | public class BitStream 12 | { 13 | private long offset { get; set; } 14 | private int bit { get; set; } 15 | private bool MSB { get; set; } 16 | private Stream stream; 17 | private Encoding encoding; 18 | 19 | /// 20 | /// Allows the auto increase in size when needed 21 | /// 22 | public bool AutoIncreaseStream { get; set; } 23 | 24 | /// 25 | /// Get the stream length 26 | /// 27 | public long Length 28 | { 29 | get 30 | { 31 | return stream.Length; 32 | } 33 | } 34 | 35 | /// 36 | /// Get the current bit position in the stream 37 | /// 38 | public long BitPosition 39 | { 40 | get 41 | { 42 | return bit; 43 | } 44 | } 45 | 46 | /// 47 | /// Check if offset is inside the stream length 48 | /// 49 | private bool ValidPosition 50 | { 51 | get 52 | { 53 | return offset < Length; 54 | } 55 | } 56 | 57 | #region Constructors 58 | 59 | /// 60 | /// Creates a using a Stream 61 | /// 62 | /// Stream to use 63 | /// true if Most Significant Bit will be used, if false LSB will be used 64 | public BitStream(Stream stream, bool MSB = false) 65 | { 66 | this.stream = new MemoryStream(); 67 | stream.CopyTo(this.stream); 68 | this.MSB = MSB; 69 | offset = 0; 70 | bit = 0; 71 | encoding = Encoding.UTF8; 72 | AutoIncreaseStream = false; 73 | } 74 | 75 | /// 76 | /// Creates a using a Stream 77 | /// 78 | /// Stream to use 79 | /// Encoding to use with chars 80 | /// true if Most Significant Bit will be used, if false LSB will be used 81 | public BitStream(Stream stream, Encoding encoding, bool MSB = false) 82 | { 83 | this.stream = new MemoryStream(); 84 | stream.CopyTo(this.stream); 85 | this.MSB = MSB; 86 | offset = 0; 87 | bit = 0; 88 | this.encoding = encoding; 89 | AutoIncreaseStream = false; 90 | } 91 | 92 | /// 93 | /// Creates a using a byte[] 94 | /// 95 | /// byte[] to use 96 | /// true if Most Significant Bit will be used, if false LSB will be used 97 | public BitStream(byte[] buffer, bool MSB = false) 98 | { 99 | this.stream = new MemoryStream(); 100 | MemoryStream m = new MemoryStream(buffer); 101 | m.CopyTo(this.stream); 102 | this.MSB = MSB; 103 | offset = 0; 104 | bit = 0; 105 | encoding = Encoding.UTF8; 106 | AutoIncreaseStream = false; 107 | } 108 | 109 | /// 110 | /// Creates a using a byte[] 111 | /// 112 | /// byte[] to use 113 | /// Encoding to use with chars 114 | /// true if Most Significant Bit will be used, if false LSB will be used 115 | public BitStream(byte[] buffer, Encoding encoding, bool MSB = false) 116 | { 117 | this.stream = new MemoryStream(); 118 | MemoryStream m = new MemoryStream(buffer); 119 | m.CopyTo(this.stream); 120 | this.MSB = MSB; 121 | offset = 0; 122 | bit = 0; 123 | this.encoding = encoding; 124 | AutoIncreaseStream = false; 125 | } 126 | 127 | /// 128 | /// Creates a using a byte[] 129 | /// 130 | /// byte[] to use 131 | /// true if Most Significant Bit will be used, if false LSB will be used 132 | public static BitStream Create(byte[] buffer, bool MSB = false) 133 | { 134 | return new BitStream(buffer, MSB); 135 | } 136 | 137 | /// 138 | /// Creates a using a byte[] 139 | /// 140 | /// byte[] to use 141 | /// Encoding to use with chars/param> 142 | /// true if Most Significant Bit will be used, if false LSB will be used 143 | public static BitStream Create(byte[] buffer, Encoding encoding, bool MSB = false) 144 | { 145 | return new BitStream(buffer, encoding, MSB); 146 | } 147 | 148 | /// 149 | /// Creates a using a file path, throws IOException if file doesn't exists or path is not a file 150 | /// 151 | /// File path 152 | /// Encoding of the file, if null default will be used 153 | /// 154 | public static BitStream CreateFromFile(string path, Encoding encoding = null) 155 | { 156 | if (!File.Exists(path)) 157 | { 158 | throw new IOException("File doesn't exists!"); 159 | } 160 | if(File.GetAttributes(path) == FileAttributes.Directory) 161 | { 162 | throw new IOException("Path is a directory!"); 163 | } 164 | if (encoding == null) 165 | { 166 | encoding = Encoding.UTF8; 167 | } 168 | return new BitStream(File.ReadAllBytes(path), encoding); 169 | } 170 | 171 | #endregion 172 | 173 | #region Methods 174 | 175 | /// 176 | /// Seek to the specified offset and check if it is a valid position for reading in the stream 177 | /// 178 | /// offset on the stream 179 | /// bit position 180 | /// true if offset is valid to do reading, false otherwise 181 | public bool this[long offset, int bit] 182 | { 183 | get 184 | { 185 | Seek(offset, bit); 186 | return ValidPosition; 187 | } 188 | //set { 189 | // Seek(offset, bit); 190 | //} 191 | private set { } 192 | } 193 | 194 | /// 195 | /// Seek through the stream selecting the offset and bit using 196 | /// 197 | /// offset on the stream 198 | /// bit position 199 | public void Seek(long offset, int bit) 200 | { 201 | if (offset > Length) 202 | { 203 | this.offset = Length; 204 | } 205 | else 206 | { 207 | if (offset >= 0) 208 | { 209 | this.offset = offset; 210 | } 211 | else 212 | { 213 | offset = 0; 214 | } 215 | } 216 | if (bit >= 8) 217 | { 218 | int n = (int)(bit / 8); 219 | this.offset += n; 220 | this.bit = bit % 8; 221 | } 222 | else 223 | { 224 | this.bit = bit; 225 | } 226 | stream.Seek(offset, SeekOrigin.Begin); 227 | } 228 | 229 | /// 230 | /// Advances the stream by one bit 231 | /// 232 | public void AdvanceBit() 233 | { 234 | bit = (bit + 1) % 8; 235 | if (bit == 0) 236 | { 237 | offset++; 238 | } 239 | } 240 | 241 | /// 242 | /// Returns the stream by one bit 243 | /// 244 | public void ReturnBit() 245 | { 246 | bit = ((bit - 1) == -1 ? 7 : bit - 1); 247 | if (bit == 7) 248 | { 249 | offset--; 250 | } 251 | if(offset < 0) 252 | { 253 | offset = 0; 254 | } 255 | } 256 | 257 | /// 258 | /// Get the edited stream 259 | /// 260 | /// Modified stream 261 | public Stream GetStream() 262 | { 263 | return stream; 264 | } 265 | 266 | /// 267 | /// Get the stream data as a byte[] 268 | /// 269 | /// Stream as byte[] 270 | public byte[] GetStreamData() 271 | { 272 | stream.Seek(0, SeekOrigin.Begin); 273 | MemoryStream s = new MemoryStream(); 274 | stream.CopyTo(s); 275 | Seek(offset, bit); 276 | return s.ToArray(); 277 | } 278 | 279 | /// 280 | /// Get the used for chars and strings 281 | /// 282 | /// used 283 | public Encoding GetEncoding() 284 | { 285 | return encoding; 286 | } 287 | 288 | /// 289 | /// Set the that will be used for chars and strings 290 | /// 291 | /// to use 292 | public void SetEncoding(Encoding encoding) 293 | { 294 | this.encoding = encoding; 295 | } 296 | 297 | /// 298 | /// Changes the length of the stream, if new length is less than current length stream data will be truncated 299 | /// 300 | /// New stream length 301 | /// return true if stream changed length, false if it wasn't possible 302 | public bool ChangeLength(long length) 303 | { 304 | if (stream.CanSeek && stream.CanWrite) 305 | { 306 | stream.SetLength(length); 307 | return true; 308 | } 309 | else 310 | { 311 | return false; 312 | } 313 | } 314 | 315 | /// 316 | /// Cuts the from the specified offset and given length, will throw an exception when length + offset is higher than stream's length, offset and bit will be set to 0 317 | /// 318 | /// Offset to start 319 | /// Length of the new 320 | public void CutStream(long offset, long length) 321 | { 322 | byte[] data = GetStreamData(); 323 | byte[] buffer = new byte[length]; 324 | Array.Copy(data, offset, buffer, 0, length); 325 | this.stream = new MemoryStream(); 326 | MemoryStream m = new MemoryStream(buffer); 327 | this.stream = new MemoryStream(); 328 | m.CopyTo(this.stream); 329 | this.offset = 0; 330 | bit = 0; 331 | } 332 | 333 | /// 334 | /// Copies the current buffer to another 335 | /// 336 | /// to copy buffer 337 | public void CopyStreamTo(Stream stream) 338 | { 339 | Seek(0, 0); 340 | stream.SetLength(this.stream.Length); 341 | this.stream.CopyTo(stream); 342 | } 343 | 344 | /// 345 | /// Copies the current buffer to another 346 | /// 347 | /// to copy buffer 348 | public void CopyStreamTo(BitStream stream) 349 | { 350 | Seek(0, 0); 351 | stream.ChangeLength(this.stream.Length); 352 | this.stream.CopyTo(stream.stream); 353 | stream.Seek(0, 0); 354 | } 355 | 356 | /// 357 | /// Saves current buffer into a file 358 | /// 359 | /// File to write data, if it exists it will be overwritten 360 | public void SaveStreamAsFile(string filename) 361 | { 362 | File.WriteAllBytes(filename, GetStreamData()); 363 | } 364 | 365 | /// 366 | /// Returns the current content of the stream as a 367 | /// 368 | /// containing current data 369 | public MemoryStream CloneAsMemoryStream() 370 | { 371 | return new MemoryStream(GetStreamData()); 372 | } 373 | 374 | /// 375 | /// Returns the current content of the stream as a 376 | /// 377 | /// containing current data 378 | public BufferedStream CloneAsBufferedStream() 379 | { 380 | BufferedStream bs = new BufferedStream(stream); 381 | StreamWriter sw = new StreamWriter(bs); 382 | sw.Write(GetStreamData()); 383 | bs.Seek(0, SeekOrigin.Begin); 384 | return bs; 385 | } 386 | 387 | 388 | /// 389 | /// Checks if the will be in a valid position on its last bit read/write 390 | /// 391 | /// Number of bits it will advance 392 | /// true if will be inside the stream length 393 | private bool ValidPositionWhen(int bits) 394 | { 395 | long o = offset; 396 | int b = bit; 397 | b = (b + 1) % 8; 398 | if (b == 0) 399 | { 400 | o++; 401 | } 402 | return o < Length; 403 | } 404 | 405 | 406 | #endregion 407 | 408 | #region BitRead/Write 409 | 410 | /// 411 | /// Read current position bit and advances the position within the stream by one bit 412 | /// 413 | /// Returns the current position bit as 0 or 1 414 | public Bit ReadBit() 415 | { 416 | if (!ValidPosition) 417 | { 418 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 419 | } 420 | stream.Seek(offset, SeekOrigin.Begin); 421 | byte value; 422 | if (!MSB) 423 | { 424 | value = (byte)((stream.ReadByte() >> (bit)) & 1); 425 | } 426 | else 427 | { 428 | value = (byte)((stream.ReadByte() >> (7 - bit)) & 1); 429 | } 430 | AdvanceBit(); 431 | stream.Seek(offset, SeekOrigin.Begin); 432 | return value; 433 | } 434 | 435 | /// 436 | /// Read from current position the specified number of bits 437 | /// 438 | /// Bits to read 439 | /// [] containing read bits 440 | public Bit[] ReadBits(int length) 441 | { 442 | Bit[] bits = new Bit[length]; 443 | for(int i=0;i< length; i++) 444 | { 445 | bits[i] = ReadBit(); 446 | } 447 | return bits; 448 | } 449 | 450 | /// 451 | /// Writes a bit in the current position 452 | /// 453 | /// Bit to write, it data is not 0 or 1 data = data & 1 454 | public void WriteBit(Bit data) 455 | { 456 | stream.Seek(offset, SeekOrigin.Begin); 457 | byte value = (byte)stream.ReadByte(); 458 | stream.Seek(offset, SeekOrigin.Begin); 459 | if (!MSB) 460 | { 461 | value &= (byte)~(1 << bit); 462 | value |= (byte)(data << bit); 463 | } 464 | else 465 | { 466 | value &= (byte)~(1 << (7 - bit)); 467 | value |= (byte)(data << (7 - bit)); 468 | } 469 | if (ValidPosition) 470 | { 471 | stream.WriteByte(value); 472 | } 473 | else 474 | { 475 | if (AutoIncreaseStream) 476 | { 477 | if (ChangeLength(Length + (offset - Length) + 1)) 478 | { 479 | stream.WriteByte(value); 480 | } 481 | else 482 | { 483 | throw new IOException("Cannot write in an offset bigger than the length of the stream"); 484 | } 485 | } 486 | else 487 | { 488 | throw new IOException("Cannot write in an offset bigger than the length of the stream"); 489 | } 490 | } 491 | AdvanceBit(); 492 | stream.Seek(offset, SeekOrigin.Begin); 493 | } 494 | 495 | /// 496 | /// Write a sequence of bits into the stream 497 | /// 498 | /// [] to write 499 | public void WriteBits(ICollection bits) 500 | { 501 | foreach(Bit b in bits) 502 | { 503 | WriteBit(b); 504 | } 505 | } 506 | 507 | /// 508 | /// Write a sequence of bits into the stream 509 | /// 510 | /// [] to write 511 | /// Number of bits to write 512 | public void WriteBits(ICollection bits, int length) 513 | { 514 | Bit[] b = new Bit[bits.Count]; 515 | bits.CopyTo(b, 0); 516 | for (int i=0;i< length;i++) 517 | { 518 | WriteBit(b[i]); 519 | } 520 | } 521 | 522 | /// 523 | /// Write a sequence of bits into the stream 524 | /// 525 | /// [] to write 526 | /// Offset to begin bit writing 527 | /// Number of bits to write 528 | public void WriteBits(Bit[] bits, int offset, int length) 529 | { 530 | for (int i = offset; i < length; i++) 531 | { 532 | WriteBit(bits[i]); 533 | } 534 | } 535 | 536 | #endregion 537 | 538 | #region Read 539 | 540 | /// 541 | /// Read from the current position bit the specified number of bits or bytes and creates a byte[] 542 | /// 543 | /// Number of bits or bytes 544 | /// if true will consider length as byte length, if false it will count the specified length of bits 545 | /// byte[] containing bytes created from current position 546 | public byte[] ReadBytes(long length, bool isBytes = false) 547 | { 548 | if (isBytes) 549 | { 550 | length *= 8; 551 | } 552 | List data = new List(); 553 | for (long i = 0; i < length;) 554 | { 555 | byte value = 0; 556 | for (int p = 0; p < 8 && i < length; i++, p++) 557 | { 558 | if (!MSB) 559 | { 560 | value |= (byte)(ReadBit() << p); 561 | } 562 | else 563 | { 564 | value |= (byte)(ReadBit() << (7 - p)); 565 | } 566 | } 567 | data.Add(value); 568 | } 569 | return data.ToArray(); 570 | } 571 | 572 | /// 573 | /// Read a byte based on the current stream and bit position 574 | /// 575 | public byte ReadByte() 576 | { 577 | return ReadBytes(8)[0]; 578 | } 579 | 580 | /// 581 | /// Read a byte made of specified number of bits (1-8) 582 | /// 583 | public byte ReadByte(int bits) 584 | { 585 | if (bits < 0) 586 | { 587 | bits = 0; 588 | } 589 | if(bits > 8) 590 | { 591 | bits = 8; 592 | } 593 | return ReadBytes(bits)[0]; 594 | } 595 | 596 | /// 597 | /// Read a signed byte based on the current stream and bit position 598 | /// 599 | public sbyte ReadSByte() 600 | { 601 | return (sbyte)ReadBytes(8)[0]; 602 | } 603 | 604 | /// 605 | /// Read a sbyte made of specified number of bits (1-8) 606 | /// 607 | public sbyte ReadSByte(int bits) 608 | { 609 | if (bits < 0) 610 | { 611 | bits = 0; 612 | } 613 | if (bits > 8) 614 | { 615 | bits = 8; 616 | } 617 | return (sbyte)ReadBytes(bits)[0]; 618 | } 619 | 620 | /// 621 | /// Read a byte based on the current stream and bit position and check if it is 0 622 | /// 623 | public bool ReadBool() 624 | { 625 | return ReadBytes(8)[0] == 0 ? false : true; 626 | } 627 | 628 | /// 629 | /// Read a char based on the current stream and bit position and the encoding 630 | /// 631 | public char ReadChar() 632 | { 633 | return encoding.GetChars(ReadBytes(encoding.GetMaxByteCount(1) * 8))[0]; 634 | } 635 | 636 | /// 637 | /// Read a string based on the current stream and bit position and the encoding 638 | /// 639 | /// Length of the string to read 640 | public string ReadString(int length) 641 | { 642 | int bitsPerChar = encoding.GetByteCount(" ") * 8; 643 | return encoding.GetString(ReadBytes(bitsPerChar*length)); 644 | } 645 | 646 | /// 647 | /// Read a short based on the current stream and bit position 648 | /// 649 | public short ReadInt16() 650 | { 651 | short value = BitConverter.ToInt16(ReadBytes(16), 0); 652 | return value; 653 | } 654 | 655 | /// 656 | /// Read a 24bit value based on the current stream and bit position 657 | /// 658 | public Int24 ReadInt24() 659 | { 660 | byte[] bytes = ReadBytes(24); 661 | Array.Resize(ref bytes, 4); 662 | Int24 value = BitConverter.ToInt32(bytes, 0); 663 | return value; 664 | } 665 | 666 | /// 667 | /// Read an int based on the current stream and bit position 668 | /// 669 | public int ReadInt32() 670 | { 671 | int value = BitConverter.ToInt32(ReadBytes(32), 0); 672 | return value; 673 | } 674 | 675 | /// 676 | /// Read a 48bit value based on the current stream and bit position 677 | /// 678 | public Int48 ReadInt48() 679 | { 680 | byte[] bytes = ReadBytes(48); 681 | Array.Resize(ref bytes, 8); 682 | Int48 value = BitConverter.ToInt64(bytes, 0); 683 | return value; 684 | } 685 | 686 | /// 687 | /// Read a long based on the current stream and bit position 688 | /// 689 | public long ReadInt64() 690 | { 691 | long value = BitConverter.ToInt64(ReadBytes(64), 0); 692 | return value; 693 | } 694 | 695 | /// 696 | /// Read a ushort based on the current stream and bit position 697 | /// 698 | public ushort ReadUInt16() 699 | { 700 | ushort value = BitConverter.ToUInt16(ReadBytes(16), 0); 701 | return value; 702 | } 703 | 704 | /// 705 | /// Read an unsigned 24bit value based on the current stream and bit position 706 | /// 707 | public UInt24 ReadUInt24() 708 | { 709 | byte[] bytes = ReadBytes(24); 710 | Array.Resize(ref bytes, 4); 711 | UInt24 value = BitConverter.ToUInt32(bytes, 0); 712 | return value; 713 | } 714 | 715 | /// 716 | /// Read an uint based on the current stream and bit position 717 | /// 718 | public uint ReadUInt32() 719 | { 720 | uint value = BitConverter.ToUInt32(ReadBytes(32), 0); 721 | return value; 722 | } 723 | 724 | /// 725 | /// Read an unsigned 48bit value based on the current stream and bit position 726 | /// 727 | public UInt48 ReadUInt48() 728 | { 729 | byte[] bytes = ReadBytes(48); 730 | Array.Resize(ref bytes, 8); 731 | UInt48 value = BitConverter.ToUInt64(bytes, 0); 732 | return value; 733 | } 734 | 735 | /// 736 | /// Read an ulong based on the current stream and bit position 737 | /// 738 | public ulong ReadUInt64() 739 | { 740 | ulong value = BitConverter.ToUInt64(ReadBytes(64), 0); 741 | return value; 742 | } 743 | 744 | #endregion 745 | 746 | #region Write 747 | 748 | /// 749 | /// Writes as bits a byte[] by a specified number of bits or bytes 750 | /// 751 | /// byte[] to write 752 | /// Number of bits or bytes to use from the array 753 | /// if true will consider length as byte length, if false it will count the specified length of bits 754 | public void WriteBytes(byte[] data, long length, bool isBytes = false) 755 | { 756 | if (isBytes) 757 | { 758 | length *= 8; 759 | } 760 | int position = 0; 761 | for (long i = 0; i < length;) 762 | { 763 | byte value = 0; 764 | for (int p = 0; p < 8 && i < length; i++, p++) 765 | { 766 | if (!MSB) 767 | { 768 | value = (byte)((data[position] >> p) & 1); 769 | } 770 | else 771 | { 772 | value = (byte)((data[position] >> (7 - p)) & 1); 773 | } 774 | WriteBit(value); 775 | } 776 | position++; 777 | } 778 | } 779 | 780 | /// 781 | /// Write a byte value based on the current stream and bit position 782 | /// 783 | public void WriteByte(byte value) 784 | { 785 | WriteBytes(new byte[] { value }, 8); 786 | } 787 | 788 | /// 789 | /// Write a byte value based on the current stream and bit position 790 | /// 791 | public void WriteByte(byte value, int bits) 792 | { 793 | if (bits < 0) 794 | { 795 | bits = 0; 796 | } 797 | if (bits > 8) 798 | { 799 | bits = 8; 800 | } 801 | WriteBytes(new byte[] { value }, bits); 802 | } 803 | 804 | /// 805 | /// Write a byte value based on the current stream and bit position 806 | /// 807 | public void WriteSByte(sbyte value) 808 | { 809 | WriteBytes(new byte[] { (byte)value }, 8); 810 | } 811 | 812 | /// 813 | /// Write a byte value based on the current stream and bit position 814 | /// 815 | public void WriteSByte(sbyte value, int bits) 816 | { 817 | if (bits < 0) 818 | { 819 | bits = 0; 820 | } 821 | if (bits > 8) 822 | { 823 | bits = 8; 824 | } 825 | WriteBytes(new byte[] { (byte)value }, bits); 826 | } 827 | 828 | /// 829 | /// Write a bool value as 0:false, 1:true as byte based on the current stream and bit position 830 | /// 831 | public void WriteBool(bool value) 832 | { 833 | WriteBytes(new byte[] { value ? (byte)1 : (byte)0 }, 8); 834 | } 835 | 836 | /// 837 | /// Write a char value based on the encoding 838 | /// 839 | public void WriteChar(char value) 840 | { 841 | byte[] bytes = encoding.GetBytes(new char[] { value }, 0, 1); 842 | WriteBytes(bytes, bytes.Length*8); 843 | } 844 | 845 | /// 846 | /// Write a string based on the encoding 847 | /// 848 | public void WriteString(string value) 849 | { 850 | byte[] bytes = encoding.GetBytes(value); 851 | WriteBytes(bytes, bytes.Length * 8); 852 | } 853 | 854 | /// 855 | /// Write a short value based on the current stream and bit position 856 | /// 857 | public void WriteInt16(short value) 858 | { 859 | WriteBytes(BitConverter.GetBytes(value), 16); 860 | } 861 | 862 | /// 863 | /// Write a 24bit value based on the current stream and bit position 864 | /// 865 | public void WriteInt24(Int24 value) 866 | { 867 | WriteBytes(BitConverter.GetBytes((int) value), 24); 868 | } 869 | 870 | /// 871 | /// Write an int value based on the current stream and bit position 872 | /// 873 | public void WriteInt32(int value) 874 | { 875 | WriteBytes(BitConverter.GetBytes(value), 32); 876 | } 877 | 878 | /// 879 | /// Write a 48bit value based on the current stream and bit position 880 | /// 881 | public void WriteInt48(Int48 value) 882 | { 883 | WriteBytes(BitConverter.GetBytes((long) value), 48); 884 | } 885 | 886 | /// 887 | /// Write a long value based on the current stream and bit position 888 | /// 889 | public void WriteInt64(long value) 890 | { 891 | WriteBytes(BitConverter.GetBytes(value), 64); 892 | } 893 | 894 | /// 895 | /// Write an ushort value based on the current stream and bit position 896 | /// 897 | public void WriteUInt16(ushort value) 898 | { 899 | WriteBytes(BitConverter.GetBytes(value), 16); 900 | } 901 | 902 | /// 903 | /// Write an unsigned 24bit value based on the current stream and bit position 904 | /// 905 | public void WriteUInt24(UInt24 value) 906 | { 907 | WriteBytes(BitConverter.GetBytes((uint) value), 24); 908 | } 909 | 910 | /// 911 | /// Write an uint value based on the current stream and bit position 912 | /// 913 | public void WriteUInt32(uint value) 914 | { 915 | WriteBytes(BitConverter.GetBytes(value), 32); 916 | } 917 | 918 | /// 919 | /// Write an unsigned 48bit value based on the current stream and bit position 920 | /// 921 | public void WriteUInt48(UInt48 value) 922 | { 923 | WriteBytes(BitConverter.GetBytes((ulong) value), 48); 924 | } 925 | 926 | /// 927 | /// Write an ulong value based on the current stream and bit position 928 | /// 929 | public void WriteUInt64(ulong value) 930 | { 931 | WriteBytes(BitConverter.GetBytes(value), 64); 932 | } 933 | 934 | #endregion 935 | 936 | #region Shifts 937 | 938 | /// 939 | /// Do a bitwise shift on the current position of the stream on bit 0 940 | /// 941 | /// bits to shift 942 | /// true to left shift, false to right shift 943 | public void bitwiseShift(int bits, bool leftShift) 944 | { 945 | if (!ValidPositionWhen(8)) 946 | { 947 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 948 | } 949 | Seek(offset, 0); 950 | if (bits != 0 && bits <= 7) 951 | { 952 | byte value = (byte)stream.ReadByte(); 953 | if (leftShift) 954 | { 955 | value = (byte)(value << bits); 956 | } 957 | else 958 | { 959 | value = (byte)(value >> bits); 960 | } 961 | Seek(offset, 0); 962 | stream.WriteByte(value); 963 | } 964 | bit = 0; 965 | offset++; 966 | } 967 | 968 | /// 969 | /// Do a bitwise shift on the current position of the stream on current bit 970 | /// 971 | /// bits to shift 972 | /// true to left shift, false to right shift 973 | public void bitwiseShiftOnBit(int bits, bool leftShift) 974 | { 975 | if (!ValidPositionWhen(8)) 976 | { 977 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 978 | } 979 | Seek(offset, bit); 980 | if (bits != 0 && bits <= 7) 981 | { 982 | byte value = ReadByte(); 983 | if (leftShift) 984 | { 985 | value = (byte)(value << bits); 986 | } 987 | else 988 | { 989 | value = (byte)(value >> bits); 990 | } 991 | offset--; 992 | Seek(offset, bit); 993 | WriteByte(value); 994 | } 995 | offset++; 996 | } 997 | 998 | /// 999 | /// Do a circular shift on the current position of the stream on bit 0 1000 | /// 1001 | /// bits to shift 1002 | /// true to left shift, false to right shift 1003 | public void circularShift(int bits, bool leftShift) 1004 | { 1005 | if (!ValidPositionWhen(8)) 1006 | { 1007 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1008 | } 1009 | Seek(offset, 0); 1010 | if (bits != 0 && bits <= 7) 1011 | { 1012 | byte value = (byte)stream.ReadByte(); 1013 | if (leftShift) 1014 | { 1015 | value = (byte)(value << bits | value >> (8 - bits)); 1016 | } 1017 | else 1018 | { 1019 | value = (byte)(value >> bits | value << (8 - bits)); 1020 | } 1021 | Seek(offset, 0); 1022 | stream.WriteByte(value); 1023 | } 1024 | bit = 0; 1025 | offset++; 1026 | } 1027 | 1028 | /// 1029 | /// Do a circular shift on the current position of the stream on current bit 1030 | /// 1031 | /// bits to shift 1032 | /// true to left shift, false to right shift 1033 | public void circularShiftOnBit(int bits, bool leftShift) 1034 | { 1035 | if (!ValidPositionWhen(8)) 1036 | { 1037 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1038 | } 1039 | Seek(offset, bit); 1040 | if (bits != 0 && bits <= 7) 1041 | { 1042 | byte value = ReadByte(); 1043 | if (leftShift) 1044 | { 1045 | value = (byte)(value << bits | value >> (8 - bits)); 1046 | } 1047 | else 1048 | { 1049 | value = (byte)(value >> bits | value << (8 - bits)); 1050 | } 1051 | offset--; 1052 | Seek(offset, bit); 1053 | WriteByte(value); 1054 | } 1055 | offset++; 1056 | } 1057 | 1058 | #endregion 1059 | 1060 | #region Bitwise Operators 1061 | 1062 | /// 1063 | /// Apply an and operator on the current stream and bit position byte and advances one byte position 1064 | /// 1065 | /// Byte value to apply and 1066 | public void And(byte x) 1067 | { 1068 | if (!ValidPositionWhen(8)) 1069 | { 1070 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1071 | } 1072 | Seek(offset, bit); 1073 | byte value = ReadByte(); 1074 | offset--; 1075 | Seek(offset, bit); 1076 | WriteByte((byte)(value & x)); 1077 | } 1078 | 1079 | /// 1080 | /// Apply an or operator on the current stream and bit position byte and advances one byte position 1081 | /// 1082 | /// Byte value to apply or 1083 | public void Or(byte x) 1084 | { 1085 | if (!ValidPositionWhen(8)) 1086 | { 1087 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1088 | } 1089 | Seek(offset, bit); 1090 | byte value = ReadByte(); 1091 | offset--; 1092 | Seek(offset, bit); 1093 | WriteByte((byte)(value | x)); 1094 | } 1095 | 1096 | /// 1097 | /// Apply a xor operator on the current stream and bit position byte and advances one byte position 1098 | /// 1099 | /// Byte value to apply xor 1100 | public void Xor(byte x) 1101 | { 1102 | if (!ValidPositionWhen(8)) 1103 | { 1104 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1105 | } 1106 | Seek(offset, bit); 1107 | byte value = ReadByte(); 1108 | offset--; 1109 | Seek(offset, bit); 1110 | WriteByte((byte)(value ^ x)); 1111 | } 1112 | 1113 | /// 1114 | /// Apply a not operator on the current stream and bit position byte and advances one byte position 1115 | /// 1116 | public void Not() 1117 | { 1118 | if (!ValidPositionWhen(8)) 1119 | { 1120 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1121 | } 1122 | Seek(offset, bit); 1123 | byte value = ReadByte(); 1124 | offset--; 1125 | Seek(offset, bit); 1126 | WriteByte((byte)(~value)); 1127 | } 1128 | 1129 | /// 1130 | /// Apply an and operator on the current stream and bit position and advances one bit position 1131 | /// 1132 | /// Bit value to apply and 1133 | public void BitAnd(Bit x) 1134 | { 1135 | if (!ValidPosition) 1136 | { 1137 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1138 | } 1139 | Seek(offset, bit); 1140 | Bit value = ReadBit(); 1141 | ReturnBit(); 1142 | WriteBit(x & value); 1143 | } 1144 | 1145 | /// 1146 | /// Apply an or operator on the current stream and bit position and advances one bit position 1147 | /// 1148 | /// Bit value to apply or 1149 | public void BitOr(Bit x) 1150 | { 1151 | if (!ValidPosition) 1152 | { 1153 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1154 | } 1155 | Seek(offset, bit); 1156 | Bit value = ReadBit(); 1157 | ReturnBit(); 1158 | WriteBit(x | value); 1159 | } 1160 | 1161 | /// 1162 | /// Apply a xor operator on the current stream and bit position and advances one bit position 1163 | /// 1164 | /// Bit value to apply xor 1165 | public void BitXor(Bit x) 1166 | { 1167 | if (!ValidPosition) 1168 | { 1169 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1170 | } 1171 | Seek(offset, bit); 1172 | Bit value = ReadBit(); 1173 | ReturnBit(); 1174 | WriteBit(x ^ value); 1175 | } 1176 | 1177 | /// 1178 | /// Apply a not operator on the current stream and bit position and advances one bit position 1179 | /// 1180 | public void BitNot() 1181 | { 1182 | if (!ValidPosition) 1183 | { 1184 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1185 | } 1186 | Seek(offset, bit); 1187 | Bit value = ReadBit(); 1188 | ReturnBit(); 1189 | WriteBit(~value); 1190 | } 1191 | 1192 | /// 1193 | /// Reverses the bit order on the byte in the current position of the stream 1194 | /// 1195 | public void ReverseBits() 1196 | { 1197 | if (!ValidPosition) 1198 | { 1199 | throw new IOException("Cannot read in an offset bigger than the length of the stream"); 1200 | } 1201 | Seek(offset, 0); 1202 | byte value = ReadByte(); 1203 | offset--; 1204 | Seek(offset, 0); 1205 | WriteByte(value.ReverseBits()); 1206 | } 1207 | 1208 | #endregion 1209 | 1210 | } 1211 | } 1212 | -------------------------------------------------------------------------------- /Assets/OctoMapSharp/Int24.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OctoMapSharp 4 | { 5 | /// 6 | /// Represents a 24-bit signed integer 7 | /// 8 | [Serializable] 9 | public struct Int24 10 | { 11 | private byte b0, b1, b2; 12 | private Bit sign; 13 | 14 | private Int24(int value) 15 | { 16 | this.b0 = (byte)(value & 0xFF); 17 | this.b1 = (byte)((value >> 8) & 0xFF); 18 | this.b2 = (byte)((value >> 16) & 0x7F); 19 | this.sign = (byte)((value >> 23) & 1); 20 | } 21 | 22 | public static implicit operator Int24(int value) 23 | { 24 | return new Int24(value); 25 | } 26 | 27 | public static implicit operator int (Int24 i) 28 | { 29 | int value = (i.b0 | (i.b1 << 8) | (i.b2 << 16)); 30 | return -(i.sign << 23) + value; 31 | } 32 | 33 | public Bit GetBit(int index) 34 | { 35 | return (this >> index); 36 | } 37 | } 38 | 39 | /// 40 | /// Represents a 24-bit unsigned integer 41 | /// 42 | [Serializable] 43 | public struct UInt24 44 | { 45 | private byte b0, b1, b2; 46 | 47 | private UInt24(uint value) 48 | { 49 | this.b0 = (byte)(value & 0xFF); 50 | this.b1 = (byte)((value >> 8) & 0xFF); 51 | this.b2 = (byte)((value >> 16) & 0xFF); 52 | } 53 | 54 | public static implicit operator UInt24(uint value) 55 | { 56 | return new UInt24(value); 57 | } 58 | 59 | public static implicit operator uint (UInt24 i) 60 | { 61 | return (uint)(i.b0 | (i.b1 << 8) | (i.b2 << 16)); 62 | } 63 | 64 | public Bit GetBit(int index) 65 | { 66 | return (byte)(this >> index); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /Assets/OctoMapSharp/Int48.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OctoMapSharp 4 | { 5 | /// 6 | /// Represents a 48-bit signed integer 7 | /// 8 | [Serializable] 9 | public struct Int48 10 | { 11 | private byte b0, b1, b2, b3, b4, b5; 12 | private Bit sign; 13 | 14 | private Int48(long value) 15 | { 16 | this.b0 = (byte)(value & 0xFF); 17 | this.b1 = (byte)((value >> 8) & 0xFF); 18 | this.b2 = (byte)((value >> 16) & 0xFF); 19 | this.b3 = (byte)((value >> 24) & 0xFF); 20 | this.b4 = (byte)((value >> 32) & 0xFF); 21 | this.b5 = (byte)((value >> 40) & 0x7F); 22 | this.sign = (byte)((value >> 47) & 1); 23 | } 24 | 25 | public static implicit operator Int48(long value) 26 | { 27 | return new Int48(value); 28 | } 29 | 30 | public static implicit operator long (Int48 i) 31 | { 32 | long value = i.b0 + (i.b1 << 8) + (i.b2 << 16) + ((long)i.b3 << 24) + ((long)i.b4 << 32) + ((long)i.b5 << 40); 33 | return -((long)i.sign << 47) + value; 34 | } 35 | 36 | public Bit GetBit(int index) 37 | { 38 | return (byte)(this >> index); 39 | } 40 | } 41 | 42 | /// 43 | /// Represents a 48-bit unsigned integer 44 | /// 45 | [Serializable] 46 | public struct UInt48 47 | { 48 | private byte b0, b1, b2, b3, b4, b5; 49 | 50 | private UInt48(ulong value) 51 | { 52 | this.b0 = (byte)(value & 0xFF); 53 | this.b1 = (byte)((value >> 8) & 0xFF); 54 | this.b2 = (byte)((value >> 16) & 0xFF); 55 | this.b3 = (byte)((value >> 24) & 0xFF); 56 | this.b4 = (byte)((value >> 32) & 0xFF); 57 | this.b5 = (byte)((value >> 40) & 0xFF); 58 | } 59 | 60 | public static implicit operator UInt48(ulong value) 61 | { 62 | return new UInt48(value); 63 | } 64 | 65 | public static implicit operator ulong (UInt48 i) 66 | { 67 | ulong value = (i.b0 + ((ulong)i.b1 << 8) + ((ulong)i.b2 << 16) + ((ulong)i.b3 << 24) + ((ulong)i.b4 << 32) + ((ulong)i.b5 << 40)); 68 | return value; 69 | } 70 | 71 | public Bit GetBit(int index) 72 | { 73 | return (byte)(this >> index); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /Assets/OctoMapSharp/OctoMap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | namespace OctoMapSharp 5 | { 6 | public class OctoMapRaw 7 | { 8 | /// 9 | /// An array containing the centre position of every occupied node in the OctoMap 10 | /// 11 | public Vector3[] Positions { get; } 12 | /// 13 | /// An array containing the size of every occupied node in the OctoMap 14 | /// 15 | public float[] Sizes { get; } 16 | 17 | /// 18 | /// Constructor for the OctoMapRaw. Sets the public properties of the instance. 19 | /// 20 | /// The array of node positions 21 | /// The array of node sizes 22 | public OctoMapRaw(Vector3[] positions, float[] sizes) 23 | { 24 | Positions = positions; 25 | Sizes = sizes; 26 | } 27 | } 28 | 29 | public class OctoMapCompact 30 | { 31 | /// 32 | /// The number of occupied voxels within the octomap. 33 | /// 34 | public uint OccupiedVoxelCount { get; set; } 35 | 36 | /// 37 | /// The origin position of the OctoMap. Individual node positions are derived from this root position. 38 | /// 39 | public Vector3 RootNodePosition { get; set; } 40 | 41 | /// 42 | /// The size of the root node. 43 | /// 44 | public float RootNodeSize { get; set; } 45 | 46 | /// 47 | /// The minimum size a node can get when traversing through the OctoMap. 48 | /// 49 | public float MinimumNodeSize { get; set; } 50 | 51 | /// 52 | /// The compact BitStream containing all the parent-child relationships in the OctoMap. 53 | /// 54 | public byte[] BitStream { get; set; } 55 | 56 | /// 57 | /// Constructor for the compact OctoMap. Sets the public properties of the class. 58 | /// 59 | /// The number of occupied voxels within the octomap 60 | /// The position of the root node 61 | /// The size of the root node 62 | /// The minimum node size within the octomap 63 | /// The compact bitstream 64 | public OctoMapCompact(uint occupiedVoxelCount, Vector3 rootNodePosition, float rootNodeSize, float minimumNodeSize, byte[] bitStream) 65 | { 66 | OccupiedVoxelCount = occupiedVoxelCount; 67 | RootNodePosition = rootNodePosition; 68 | RootNodeSize = rootNodeSize; 69 | MinimumNodeSize = minimumNodeSize; 70 | BitStream = bitStream; 71 | } 72 | } 73 | 74 | public class OctoMap 75 | { 76 | /// 77 | /// A node within the OctoMap which can contain a pointer to an array of child nodes. 78 | /// Can also contain additional per-node information. 79 | /// 80 | private struct OctoMapNode 81 | { 82 | /// 83 | /// The index of the dictionary entry in '_nodeChildren' which contains an array of indexes to this nodes children. 84 | /// 85 | public uint? ChildArrayId { get; set; } 86 | 87 | /// 88 | /// The most basic way of representing a nodes occupancy: binary. -1 is unoccupied, 0 is unknown, 1 is occupied. 89 | /// 90 | public int Occupied { get; set; } 91 | } 92 | 93 | /// 94 | /// The number of occupied voxels within the octomap 95 | /// 96 | private uint _occupiedVoxelCount; 97 | 98 | /// 99 | /// Is true if the octomap has changed in some way since the last time 'HasChanged()' was called. 100 | /// 101 | private bool _hasChanged; 102 | 103 | /// 104 | /// The origin position of the OctoMap. Individual node positions are derived from this root position. 105 | /// 106 | private Vector3 _rootNodePosition; 107 | 108 | /// 109 | /// The current size of the root node which can increase if data is added. 110 | /// 111 | private float _rootNodeSize; 112 | 113 | /// 114 | /// The minimum size a node can get when traversing through the OctoMap. 115 | /// 116 | private readonly float _minimumNodeSize; 117 | 118 | /// 119 | /// Each node in the OctoMap along with an unique index accessor. 120 | /// 121 | private readonly Dictionary _nodes; 122 | 123 | /// 124 | /// Nodes with children have an entry in this dictionary with the value containing an array of node IDs. 125 | /// 126 | private readonly Dictionary _nodeChildren; 127 | 128 | /// 129 | /// The accessor index for the root node. 130 | /// 131 | private uint _rootNodeId; 132 | 133 | /// 134 | /// The current highest index in the nodes dictionary, used to keep every index unique. 135 | /// This solution works because potential duplicate indexes will only occur when we get near to 136 | /// the max uint value, but long before this happens the memory consumption will be the big issue. 137 | /// 138 | private uint _nodeHighestIndex; 139 | 140 | /// 141 | /// The current highest index in the node children dictionary, used to keep every index unique. 142 | /// 143 | private uint _nodeChildrenHighestIndex; 144 | 145 | /// 146 | /// Initialise an empty OctoMap. 147 | /// 148 | /// The starting position of the root node of the OctoMap. 149 | /// The starting size of the root node of the OctoMap. 150 | /// The minimum size of a node. 151 | public OctoMap(Vector3 startingRootNodePosition, float startingRootNodeSize, float minimumNodeSize) 152 | { 153 | _nodes = new Dictionary(); 154 | _nodeChildren = new Dictionary(); 155 | 156 | _rootNodePosition = startingRootNodePosition; 157 | _rootNodeSize = startingRootNodeSize; 158 | _minimumNodeSize = minimumNodeSize; 159 | 160 | _rootNodeId = _nodeHighestIndex++; 161 | _nodes[_rootNodeId] = new OctoMapNode(); 162 | } 163 | 164 | /// 165 | /// Initialize an OctoMap from a compact instance. 166 | /// 167 | /// The compact instance that the OctoMap will be created from. 168 | public OctoMap(OctoMapCompact octoMapCompact) 169 | { 170 | _nodes = new Dictionary(); 171 | _nodeChildren = new Dictionary(); 172 | 173 | _rootNodePosition = octoMapCompact.RootNodePosition; 174 | _rootNodeSize = octoMapCompact.RootNodeSize; 175 | _minimumNodeSize = octoMapCompact.MinimumNodeSize; 176 | _occupiedVoxelCount = octoMapCompact.OccupiedVoxelCount; 177 | 178 | BitStream bitStream = new BitStream(octoMapCompact.BitStream); 179 | 180 | OctoMapNode rootNode = new OctoMapNode(); 181 | _rootNodeId = _nodeHighestIndex++; 182 | _nodes.Add(_rootNodeId, rootNode); 183 | 184 | BuildOctoMapFromBitStreamRecursive(bitStream, _rootNodeId); 185 | } 186 | 187 | #region Compact bit stream 188 | 189 | /// 190 | /// Converts the OctoMap in memory to a compact bitstream data structure. 191 | /// 192 | /// The compact bitstream. 193 | public OctoMapCompact ConvertToOctoMapCompact() 194 | { 195 | // Number of bytes will be number of child node arrays multiplied by 2 196 | // (each item in the array is a node with children and each node takes up 2 bytes) 197 | int streamLength = _nodeChildren.Count * 2; 198 | 199 | BitStream bitStream = new BitStream(new byte[streamLength]); 200 | ConvertToBitStreamRecursive(bitStream, _rootNodeId); 201 | return new OctoMapCompact(_occupiedVoxelCount, _rootNodePosition, _rootNodeSize, _minimumNodeSize, bitStream.GetStreamData()); 202 | } 203 | 204 | /// 205 | /// Recursive function that traverses through node children and writes the relationships to a compact bit stream. 206 | /// 207 | /// The bitstream to write to. 208 | /// The node ID the current recursive traversal is on. 209 | private void ConvertToBitStreamRecursive(BitStream bitStream, uint currentNodeId) 210 | { 211 | OctoMapNode currentNode = _nodes[currentNodeId]; 212 | if (currentNode.ChildArrayId != null) 213 | { 214 | // Build up the current nodes bit stream based on status of its children 215 | for (int i = 0; i < 8; i++) 216 | { 217 | OctoMapNode childNode = _nodes[_nodeChildren[currentNode.ChildArrayId.Value][i]]; 218 | if (childNode.ChildArrayId != null) // INNER NODE 219 | { 220 | bitStream.WriteBit(1); 221 | bitStream.WriteBit(1); 222 | } 223 | else if (CheckNodeFree(childNode)) // FREE 224 | { 225 | bitStream.WriteBit(1); 226 | bitStream.WriteBit(0); 227 | } 228 | else if (CheckNodeOccupied(childNode)) // OCCUPIED 229 | { 230 | bitStream.WriteBit(0); 231 | bitStream.WriteBit(1); 232 | } 233 | else // UNKNOWN 234 | { 235 | bitStream.WriteBit(0); 236 | bitStream.WriteBit(0); 237 | } 238 | } 239 | 240 | for (int i = 0; i < 8; i++) 241 | { 242 | uint childId = _nodeChildren[currentNode.ChildArrayId.Value][i]; 243 | ConvertToBitStreamRecursive(bitStream, childId); 244 | } 245 | } 246 | } 247 | 248 | /// 249 | /// Builds the node and child nodes dictionaries by traversing through the compact bitstream. 250 | /// 251 | /// The bitstream to traverse 252 | /// The node ID the current recursive traversal is on. 253 | private void BuildOctoMapFromBitStreamRecursive(BitStream bitStream, uint currentNodeId) 254 | { 255 | // Create child nodes of this current node 256 | uint[] childIdArray = new uint[8]; 257 | for (int i = 0; i < 8; i++) 258 | { 259 | uint childNodeId = _nodeHighestIndex++; 260 | _nodes.Add(childNodeId, new OctoMapNode()); 261 | childIdArray[i] = childNodeId; 262 | } 263 | 264 | // Add child ids to dictionary 265 | uint childArrayId = _nodeChildrenHighestIndex++; 266 | _nodeChildren.Add(childArrayId, childIdArray); 267 | 268 | // Create node and add child array linkage 269 | OctoMapNode currentNode = _nodes[currentNodeId]; 270 | currentNode.ChildArrayId = childArrayId; 271 | _nodes[currentNodeId] = currentNode; 272 | 273 | // Correctly set the state of each of the children created 274 | List innerNodeChildren = new List(); 275 | for (int i = 0; i < 8; i++) 276 | { 277 | int firstBit = bitStream.ReadBit().AsInt(); 278 | int secondBit = bitStream.ReadBit().AsInt(); 279 | 280 | OctoMapNode childNode; 281 | if (firstBit == 1 && secondBit == 1) // INNER NODE 282 | { 283 | innerNodeChildren.Add(childIdArray[i]); 284 | } 285 | else if (firstBit == 0 && secondBit == 1) // OCCUPIED 286 | { 287 | childNode = _nodes[childIdArray[i]]; 288 | _nodes[childIdArray[i]] = IncreaseNodeOccupation(childNode); 289 | } 290 | else if (firstBit == 1 && secondBit == 0) // FREE 291 | { 292 | childNode = _nodes[childIdArray[i]]; 293 | _nodes[childIdArray[i]] = DecreaseNodeOccupation(childNode); 294 | } 295 | 296 | // else UNKNOWN 297 | } 298 | 299 | // Now loop through each child that is an inner node 300 | for (int i = 0; i < innerNodeChildren.Count; i++) 301 | { 302 | BuildOctoMapFromBitStreamRecursive(bitStream, innerNodeChildren[i]); 303 | } 304 | } 305 | 306 | #endregion 307 | 308 | #region Query OctoMap 309 | 310 | /// 311 | /// Check if a Ray intersects any nodes in the OctoMap and returns the smallest node that it intersects. 312 | /// 313 | /// The ray that will be used in the intersection query. 314 | /// A nullable vector3 that is the centre of the node that it hit (if it hit anything). 315 | public Vector3? GetRayIntersection(Ray ray) 316 | { 317 | return GetRayIntersectionRecursive(ref ray, _rootNodeSize, _rootNodePosition, _rootNodeId); 318 | } 319 | 320 | /// 321 | /// Recursive function that traverses through nodes in order to check for a ray intersection. 322 | /// 323 | /// The ray that will be used in the intersection query. 324 | /// The node size the current recursive traversal is on. 325 | /// The node centre the current recursive traversal is on. 326 | /// The node ID the current recursive traversal is on. 327 | /// 328 | private Vector3? GetRayIntersectionRecursive(ref Ray ray, float currentNodeSize, Vector3 currentNodeCentre, 329 | uint currentNodeId) 330 | { 331 | // Check if the ray intersects the current nodes bounds 332 | Bounds bounds = new Bounds(currentNodeCentre, 333 | new Vector3(currentNodeSize, currentNodeSize, currentNodeSize)); 334 | if (!bounds.IntersectRay(ray)) 335 | { 336 | return null; 337 | } 338 | 339 | // If the ray intersects the current node, check if the current node is occupied 340 | OctoMapNode currentNode = _nodes[currentNodeId]; 341 | if (CheckNodeOccupied(currentNode)) 342 | { 343 | return currentNodeCentre; 344 | } 345 | 346 | // If the ray intersects the current node but the node is not occupied, check its children if it has any 347 | if (currentNode.ChildArrayId != null) 348 | { 349 | for (int i = 0; i < 8; i++) 350 | { 351 | uint childId = _nodeChildren[currentNode.ChildArrayId.Value][i]; 352 | float newNodeSize = currentNodeSize / 2; 353 | Vector3 newNodeCentre = GetBestFitChildNodeCentre(i, newNodeSize, currentNodeCentre); 354 | 355 | Vector3? intersectedNodeCentre = 356 | GetRayIntersectionRecursive(ref ray, newNodeSize, newNodeCentre, childId); 357 | if (intersectedNodeCentre != null) 358 | { 359 | return intersectedNodeCentre; 360 | } 361 | } 362 | } 363 | 364 | return null; 365 | } 366 | 367 | #endregion 368 | 369 | #region Contribute To The Octomap 370 | 371 | /// 372 | /// Adds a point to the OctoMap which will mark a specific node as occupied. 373 | /// 374 | /// The 3D point to add to the OctoMap. 375 | public void AddPoint(Vector3 point) 376 | { 377 | int growCount = 0; 378 | while (true) 379 | { 380 | // Check if the root node encompasses this point. If it does, start the recursive adding process 381 | Bounds bounds = new Bounds(_rootNodePosition, new Vector3(_rootNodeSize, _rootNodeSize, _rootNodeSize)); 382 | if (bounds.Contains(point)) 383 | { 384 | AddPointRecursive(ref point, _rootNodeSize, _rootNodePosition, _rootNodeId); 385 | _hasChanged = true; 386 | return; 387 | } 388 | 389 | // If the root node doesn't encompass the point, grow the OctoMap 390 | GrowOctomap(point - _rootNodePosition); 391 | growCount++; 392 | 393 | if (growCount > 20) 394 | { 395 | Debug.Log("Aborted add operation as it seemed to be going on forever (" + (growCount - 1) + 396 | ") attempts at growing the OctoMap."); 397 | return; 398 | } 399 | } 400 | } 401 | 402 | /// 403 | /// The recursive function that adds a new point to the OctoMap. 404 | /// 405 | /// The point to add to the OctoMap. 406 | /// The node size the current recursive traversal is on. 407 | /// The node centre the current recursive traversal is on. 408 | /// The node ID the current recursive traversal is on. 409 | private void AddPointRecursive(ref Vector3 point, float currentNodeSize, Vector3 currentNodeCentre, 410 | uint currentNodeId) 411 | { 412 | OctoMapNode node = _nodes[currentNodeId]; 413 | 414 | // If we're at the deepest level possible, this current node becomes a leaf node. 415 | if (currentNodeSize < _minimumNodeSize) 416 | { 417 | // If not already occupied increment the counter 418 | if (!CheckNodeOccupied(_nodes[currentNodeId])) 419 | { 420 | _occupiedVoxelCount++; 421 | } 422 | _nodes[currentNodeId] = IncreaseNodeOccupation(node); 423 | return; 424 | } 425 | 426 | // If the node doesn't encompass this point, return out early 427 | Bounds bounds = new Bounds(currentNodeCentre, 428 | new Vector3(currentNodeSize, currentNodeSize, currentNodeSize)); 429 | if (!bounds.Contains(point)) 430 | return; 431 | 432 | // If this node doesn't have any children, new children need to be generated 433 | if (node.ChildArrayId == null) 434 | { 435 | node.ChildArrayId = GenerateChildren(); 436 | _nodes[currentNodeId] = node; 437 | } 438 | 439 | Debug.Assert(_nodes[currentNodeId].ChildArrayId != null); 440 | 441 | // Now handle the new object we're adding now 442 | int bestFitChild = BestFitChildIndex(point, currentNodeCentre); 443 | uint childNodeId = _nodeChildren[node.ChildArrayId.Value][bestFitChild]; 444 | 445 | float newNodeSize = currentNodeSize / 2; 446 | Vector3 newNodeCentre = GetBestFitChildNodeCentre(bestFitChild, newNodeSize, currentNodeCentre); 447 | 448 | AddPointRecursive(ref point, newNodeSize, newNodeCentre, childNodeId); 449 | 450 | // Loop through all children and check if they all share the same occupied state 451 | bool childrenOccupancy = false; 452 | for (int i = 0; i < 8; i++) 453 | { 454 | OctoMapNode child = _nodes[_nodeChildren[node.ChildArrayId.Value][i]]; 455 | if (child.ChildArrayId != null) 456 | { 457 | return; 458 | } 459 | 460 | bool occupancy = CheckNodeOccupied(child); 461 | 462 | if (i == 0) 463 | { 464 | childrenOccupancy = occupancy; 465 | } 466 | else 467 | { 468 | if (occupancy != childrenOccupancy) 469 | { 470 | return; 471 | } 472 | } 473 | } 474 | 475 | // If the code reaches here that means all the children share the same state 476 | // Remove all the child nodes 477 | for (int i = 0; i < 8; i++) 478 | { 479 | var childArrayId = _nodes[currentNodeId].ChildArrayId; 480 | if (childArrayId != null) 481 | { 482 | uint childId = _nodeChildren[childArrayId.Value][i]; 483 | _nodes.Remove(childId); 484 | _occupiedVoxelCount--; 485 | } 486 | else 487 | { 488 | Debug.Log("Failed to remove node from node dictionary"); 489 | } 490 | } 491 | 492 | var arrayId = _nodes[currentNodeId].ChildArrayId; 493 | if (arrayId != null) 494 | { 495 | // Remove the node children array 496 | _nodeChildren.Remove(arrayId.Value); 497 | _occupiedVoxelCount++; 498 | } 499 | else 500 | { 501 | Debug.Log("Failed to remove child array from child dictionary."); 502 | } 503 | 504 | // Set the current nodes occupancy state to that of its children 505 | OctoMapNode currentNode = _nodes[currentNodeId]; 506 | currentNode.ChildArrayId = null; 507 | currentNode = childrenOccupancy ? IncreaseNodeOccupation(currentNode) : DecreaseNodeOccupation(currentNode); 508 | 509 | _nodes[currentNodeId] = currentNode; 510 | } 511 | 512 | /// 513 | /// Adds a ray to the OctoMap which will set any nodes along its path to free. 514 | /// 515 | /// The origin of the ray 516 | /// The 3D point that the ray has hit 517 | public void AddRayToOctoMap(Vector3 originPoint, Vector3 recordedPoint) 518 | { 519 | Ray ray = new Ray(originPoint, (recordedPoint - originPoint).normalized); 520 | AddRayToOctoMap(ray, recordedPoint, _rootNodeSize, _rootNodePosition, _rootNodeId); 521 | } 522 | 523 | /// 524 | /// The recursive function that adds any intersecting nodes along this ray to the octomap 525 | /// 526 | /// The ray that will be used to check intersections against 527 | /// The recorded point that the ray hit 528 | /// The node size the current recursive traversal is on. 529 | /// The node centre the current recursive traversal is on. 530 | /// The node ID the current recursive traversal is on. 531 | private void AddRayToOctoMap(Ray ray, Vector3 recordedPoint, float currentNodeSize, Vector3 currentNodeCentre, 532 | uint currentNodeId) 533 | { 534 | OctoMapNode currentNode = _nodes[currentNodeId]; 535 | 536 | // If this node is a leaf node 537 | if (currentNodeSize < _minimumNodeSize) 538 | { 539 | // Do not check this ray against the node that shares the same centre as the registered point 540 | if (recordedPoint == currentNodeCentre) 541 | { 542 | return; 543 | } 544 | 545 | // Mark this leaf node as free 546 | _nodes[currentNodeId] = DecreaseNodeOccupation(currentNode); 547 | return; 548 | } 549 | 550 | // Generate some children if the current node doesn't have any 551 | if (currentNode.ChildArrayId == null) 552 | { 553 | currentNode.ChildArrayId = GenerateChildren(); 554 | _nodes[currentNodeId] = currentNode; 555 | } 556 | 557 | // Recursively call this function on each of this current nodes children 558 | for (int i = 0; i < 8; i++) 559 | { 560 | uint childId = _nodeChildren[currentNode.ChildArrayId.Value][i]; 561 | float newNodeSize = currentNodeSize / 2; 562 | Vector3 newNodeCentre = GetBestFitChildNodeCentre(i, newNodeSize, currentNodeCentre); 563 | 564 | Bounds bounds = new Bounds(newNodeCentre, new Vector3(newNodeSize, newNodeSize, newNodeSize)); 565 | if (bounds.IntersectRay(ray)) 566 | { 567 | AddRayToOctoMap(ray, recordedPoint, newNodeSize, newNodeCentre, childId); 568 | } 569 | } 570 | } 571 | 572 | #endregion 573 | 574 | #region Get Nodes 575 | 576 | /// 577 | /// Returns a list of the octomap leaf nodes with each node having a position and size 578 | /// 579 | /// The list of octomap nodes 580 | public OctoMapRaw GetOctoMapNodes() 581 | { 582 | List positions = new List(); 583 | List sizes = new List(); 584 | GatherOctoMapNodes(positions, sizes, _rootNodeSize, _rootNodePosition, _rootNodeId); 585 | return new OctoMapRaw(positions.ToArray(), sizes.ToArray()); 586 | } 587 | 588 | /// 589 | /// Recursively traverses though the octomap in order to find leaf nodes and then adds them to a list 590 | /// 591 | /// The list of node of node centre positions 592 | /// The list of node sizes 593 | /// The node size the current recursive traversal is on. 594 | /// The node centre the current recursive traversal is on. 595 | /// The node ID the current recursive traversal is on. 596 | private void GatherOctoMapNodes(List positions, List sizes, float currentNodeSize, 597 | Vector3 currentNodeCentre, 598 | uint currentNodeId) 599 | { 600 | OctoMapNode currentNode = _nodes[currentNodeId]; 601 | if (CheckNodeOccupied(currentNode)) 602 | { 603 | positions.Add(currentNodeCentre); 604 | sizes.Add(currentNodeSize); 605 | } 606 | 607 | if (currentNode.ChildArrayId != null) 608 | { 609 | for (int i = 0; i < 8; i++) 610 | { 611 | uint childId = _nodeChildren[currentNode.ChildArrayId.Value][i]; 612 | float newNodeSize = currentNodeSize / 2; 613 | Vector3 newNodeCentre = GetBestFitChildNodeCentre(i, newNodeSize, currentNodeCentre); 614 | GatherOctoMapNodes(positions, sizes, newNodeSize, newNodeCentre, childId); 615 | } 616 | } 617 | } 618 | 619 | #endregion 620 | 621 | #region Node Evaluation 622 | 623 | /// 624 | /// Sets the occupied state of a node to 1. Can be extended further. 625 | /// 626 | /// The node to set the occupied state on 627 | /// The same node but with the occupied state changed 628 | private static OctoMapNode IncreaseNodeOccupation(OctoMapNode octoMapNode) 629 | { 630 | octoMapNode.Occupied = 1; 631 | return octoMapNode; 632 | } 633 | 634 | /// 635 | /// Sets the occupied state of a node to -1. Can be extended further. 636 | /// 637 | /// The node to set the occupied state on 638 | /// The same node but with the occupied state changed 639 | private static OctoMapNode DecreaseNodeOccupation(OctoMapNode octoMapNode) 640 | { 641 | octoMapNode.Occupied = -1; 642 | return octoMapNode; 643 | } 644 | 645 | /// 646 | /// Returns true or false depending on whether a specific node is occupied. Can be extended further. 647 | /// 648 | /// The node that will be checked 649 | /// True or false depending on whether a specific node is occupied. 650 | private static bool CheckNodeOccupied(OctoMapNode octoMapNode) 651 | { 652 | return octoMapNode.Occupied >= 1; 653 | } 654 | 655 | /// 656 | /// Returns true or false depending on whether a specific node is not occupied. Can be extended further. 657 | /// 658 | /// The node that will be checked 659 | /// True or false depending on whether a specific node is not occupied. 660 | private static bool CheckNodeFree(OctoMapNode octoMapNode) 661 | { 662 | return octoMapNode.Occupied <= -1; 663 | } 664 | 665 | #endregion 666 | 667 | #region Helper Functions 668 | 669 | /// 670 | /// Expand the root node to encompass any additional added points by specifying the direction that it needs 671 | /// 672 | /// The direction that the OctoMap needs to grow in 673 | private void GrowOctomap(Vector3 direction) 674 | { 675 | int xDirection = direction.x >= 0 ? 1 : -1; 676 | int yDirection = direction.y >= 0 ? 1 : -1; 677 | int zDirection = direction.z >= 0 ? 1 : -1; 678 | 679 | uint oldRoot = _rootNodeId; 680 | float half = _rootNodeSize / 2; 681 | 682 | _rootNodeSize = _rootNodeSize * 2; 683 | _rootNodePosition = 684 | _rootNodePosition + new Vector3(xDirection * half, yDirection * half, zDirection * half); 685 | 686 | // Create a new, bigger octomap root node 687 | _rootNodeId = _nodeHighestIndex++; 688 | _nodes.Add(_rootNodeId, new OctoMapNode()); 689 | 690 | // Create 7 new octomap children to go with the old root as children of the new root 691 | int rootPos = GetRootPosIndex(xDirection, yDirection, zDirection); 692 | uint[] childIds = new uint[8]; 693 | for (int i = 0; i < 8; i++) 694 | { 695 | if (i == rootPos) 696 | { 697 | childIds[i] = oldRoot; 698 | } 699 | else 700 | { 701 | uint childNodeId = _nodeHighestIndex++; 702 | _nodes.Add(childNodeId, new OctoMapNode()); 703 | childIds[i] = childNodeId; 704 | } 705 | } 706 | 707 | // Add child ids to dict 708 | uint childId = _nodeChildrenHighestIndex++; 709 | _nodeChildren.Add(childId, childIds); 710 | 711 | // Attach the new children to the new root node 712 | OctoMapNode node = _nodes[_rootNodeId]; 713 | node.ChildArrayId = childId; 714 | _nodes[_rootNodeId] = node; 715 | } 716 | 717 | /// 718 | /// This function generates 8 new nodes, adds them to the dictionaries, and returns the accessor index of item 719 | /// 720 | /// The accessor index of the new node child dictionary item 721 | private uint GenerateChildren() 722 | { 723 | uint[] childIdArray = new uint[8]; 724 | for (int i = 0; i < 8; i++) 725 | { 726 | uint childNodeId = _nodeHighestIndex++; 727 | _nodes.Add(childNodeId, new OctoMapNode()); 728 | childIdArray[i] = childNodeId; 729 | } 730 | 731 | uint childArrayId = _nodeChildrenHighestIndex++; 732 | _nodeChildren.Add(childArrayId, childIdArray); // Add child ids 733 | return childArrayId; 734 | } 735 | 736 | /// 737 | /// Used when growing the octomap. Works out where the old root node would fit inside a new, larger root node. 738 | /// 739 | /// The XDir that the child is in 740 | /// The YDir that the child is in 741 | /// The ZDir that the child is in 742 | /// The array index that this child in this direction has 743 | private static int GetRootPosIndex(int xDir, int yDir, int zDir) 744 | { 745 | int result = xDir > 0 ? 1 : 0; 746 | if (yDir < 0) result += 4; 747 | if (zDir > 0) result += 2; 748 | return result; 749 | } 750 | 751 | /// 752 | /// Returns the index of the child that is the best fit for a point within a specific node 753 | /// 754 | /// The point that will be checked 755 | /// The node that the point will be checked against 756 | /// The index that of the child 757 | private static int BestFitChildIndex(Vector3 point, Vector3 currentNodeCentre) 758 | { 759 | return (point.x <= currentNodeCentre.x ? 0 : 1) + (point.y >= currentNodeCentre.y ? 0 : 4) + 760 | (point.z <= currentNodeCentre.z ? 0 : 2); 761 | } 762 | 763 | /// 764 | /// Returns the position of a child of a specific node at a specific index 765 | /// 766 | /// The child index of the node 767 | /// The size of the child node 768 | /// The position of the parent node 769 | /// The position of the child 770 | private static Vector3 GetBestFitChildNodeCentre(int childIndex, float childSize, Vector3 parentPosition) 771 | { 772 | float quarter = childSize / 4f; 773 | 774 | switch (childIndex) 775 | { 776 | case 0: 777 | return parentPosition + new Vector3(-quarter, quarter, -quarter); 778 | case 1: 779 | return parentPosition + new Vector3(quarter, quarter, -quarter); 780 | case 2: 781 | return parentPosition + new Vector3(-quarter, quarter, quarter); 782 | case 3: 783 | return parentPosition + new Vector3(quarter, quarter, quarter); 784 | case 4: 785 | return parentPosition + new Vector3(-quarter, -quarter, -quarter); 786 | case 5: 787 | return parentPosition + new Vector3(quarter, -quarter, -quarter); 788 | case 6: 789 | return parentPosition + new Vector3(-quarter, -quarter, quarter); 790 | case 7: 791 | return parentPosition + new Vector3(quarter, -quarter, quarter); 792 | } 793 | 794 | Debug.Log("Failed to determine best fit child node centre."); 795 | return Vector3.zero; 796 | } 797 | 798 | #endregion 799 | 800 | #region Public Accessors 801 | 802 | /// 803 | /// Returns the number of occupied voxels within the octomap. 804 | /// 805 | /// The number of voxels that are occupied within the octomap. 806 | public uint GetOccupiedVoxelCount() 807 | { 808 | return _occupiedVoxelCount; 809 | } 810 | 811 | /// 812 | /// Returns true if the octomap has changed in some way (one or more new points have been added) since the last time this function was called. 813 | /// 814 | /// 815 | public bool HasChanged() 816 | { 817 | bool hasChanged = _hasChanged; 818 | _hasChanged = false; 819 | return hasChanged; 820 | } 821 | 822 | #endregion 823 | } 824 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alex Scott 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "com.unity.ads": "2.0.8", 4 | "com.unity.analytics": "2.0.16", 5 | "com.unity.package-manager-ui": "1.9.11", 6 | "com.unity.purchasing": "2.0.3", 7 | "com.unity.textmeshpro": "1.2.4", 8 | "com.unity.modules.ai": "1.0.0", 9 | "com.unity.modules.animation": "1.0.0", 10 | "com.unity.modules.assetbundle": "1.0.0", 11 | "com.unity.modules.audio": "1.0.0", 12 | "com.unity.modules.cloth": "1.0.0", 13 | "com.unity.modules.director": "1.0.0", 14 | "com.unity.modules.imageconversion": "1.0.0", 15 | "com.unity.modules.imgui": "1.0.0", 16 | "com.unity.modules.jsonserialize": "1.0.0", 17 | "com.unity.modules.particlesystem": "1.0.0", 18 | "com.unity.modules.physics": "1.0.0", 19 | "com.unity.modules.physics2d": "1.0.0", 20 | "com.unity.modules.screencapture": "1.0.0", 21 | "com.unity.modules.terrain": "1.0.0", 22 | "com.unity.modules.terrainphysics": "1.0.0", 23 | "com.unity.modules.tilemap": "1.0.0", 24 | "com.unity.modules.ui": "1.0.0", 25 | "com.unity.modules.uielements": "1.0.0", 26 | "com.unity.modules.umbra": "1.0.0", 27 | "com.unity.modules.unityanalytics": "1.0.0", 28 | "com.unity.modules.unitywebrequest": "1.0.0", 29 | "com.unity.modules.unitywebrequestassetbundle": "1.0.0", 30 | "com.unity.modules.unitywebrequestaudio": "1.0.0", 31 | "com.unity.modules.unitywebrequesttexture": "1.0.0", 32 | "com.unity.modules.unitywebrequestwww": "1.0.0", 33 | "com.unity.modules.vehicles": "1.0.0", 34 | "com.unity.modules.video": "1.0.0", 35 | "com.unity.modules.vr": "1.0.0", 36 | "com.unity.modules.wind": "1.0.0", 37 | "com.unity.modules.xr": "1.0.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 1024 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 1 23 | m_ClothInterCollisionSettingsToggle: 0 24 | m_ContactPairsMode: 0 25 | m_BroadphaseType: 0 26 | m_WorldBounds: 27 | m_Center: {x: 0, y: 0, z: 0} 28 | m_Extent: {x: 250, y: 250, z: 250} 29 | m_WorldSubdivisions: 8 30 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Scenes/SampleScene.unity 10 | guid: 99c9720ab356a0642a771bea13969a05 11 | m_configObjects: {} 12 | -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 2 10 | m_DefaultBehaviorMode: 0 11 | m_SpritePackerMode: 0 12 | m_SpritePackerPaddingPower: 1 13 | m_EtcTextureCompressorBehavior: 1 14 | m_EtcTextureFastCompressor: 1 15 | m_EtcTextureNormalCompressor: 2 16 | m_EtcTextureBestCompressor: 4 17 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef 18 | m_ProjectGenerationRootNamespace: 19 | m_UserGeneratedProjectSuffix: 20 | m_CollabEditorSettings: 21 | inProgressEnabled: 1 22 | m_EnableTextureStreamingInPlayMode: 1 23 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | m_PreloadedShaders: [] 39 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 40 | type: 0} 41 | m_CustomRenderPipeline: {fileID: 0} 42 | m_TransparencySortMode: 0 43 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 44 | m_DefaultRenderingPath: 1 45 | m_DefaultMobileRenderingPath: 1 46 | m_TierSettings: [] 47 | m_LightmapStripping: 0 48 | m_FogStripping: 0 49 | m_InstancingStripping: 0 50 | m_LightmapKeepPlain: 1 51 | m_LightmapKeepDirCombined: 1 52 | m_LightmapKeepDynamicPlain: 1 53 | m_LightmapKeepDynamicDirCombined: 1 54 | m_LightmapKeepShadowMask: 1 55 | m_LightmapKeepSubtractive: 1 56 | m_FogKeepLinear: 1 57 | m_FogKeepExp: 1 58 | m_FogKeepExp2: 1 59 | m_AlbedoSwatchInfos: [] 60 | m_LightsUseLinearIntensity: 0 61 | m_LightsUseColorTemperature: 0 62 | -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -887442657 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_AutoSimulation: 1 23 | m_QueriesHitTriggers: 1 24 | m_QueriesStartInColliders: 1 25 | m_ChangeStopsCallbacks: 0 26 | m_CallbacksOnDisable: 1 27 | m_AutoSyncTransforms: 1 28 | m_AlwaysShowColliders: 0 29 | m_ShowColliderSleep: 1 30 | m_ShowColliderContacts: 0 31 | m_ShowColliderAABB: 0 32 | m_ContactArrowScale: 0.2 33 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 34 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 35 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 36 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 37 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 38 | -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: 7 | - type: 8 | m_NativeTypeID: 108 9 | m_ManagedTypePPtr: {fileID: 0} 10 | m_ManagedTypeFallback: 11 | defaultPresets: 12 | - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea, 13 | type: 2} 14 | - type: 15 | m_NativeTypeID: 1020 16 | m_ManagedTypePPtr: {fileID: 0} 17 | m_ManagedTypeFallback: 18 | defaultPresets: 19 | - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6, 20 | type: 2} 21 | - type: 22 | m_NativeTypeID: 1006 23 | m_ManagedTypePPtr: {fileID: 0} 24 | m_ManagedTypeFallback: 25 | defaultPresets: 26 | - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9, 27 | type: 2} 28 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 15 7 | productGUID: efefad388870749448829f266eccb6e2 8 | AndroidProfiler: 0 9 | AndroidFilterTouchesWhenObscured: 0 10 | AndroidEnableSustainedPerformanceMode: 0 11 | defaultScreenOrientation: 4 12 | targetDevice: 2 13 | useOnDemandResources: 0 14 | accelerometerFrequency: 60 15 | companyName: DefaultCompany 16 | productName: OctoMapSharpApp 17 | defaultCursor: {fileID: 0} 18 | cursorHotspot: {x: 0, y: 0} 19 | m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} 20 | m_ShowUnitySplashScreen: 1 21 | m_ShowUnitySplashLogo: 1 22 | m_SplashScreenOverlayOpacity: 1 23 | m_SplashScreenAnimation: 1 24 | m_SplashScreenLogoStyle: 1 25 | m_SplashScreenDrawMode: 0 26 | m_SplashScreenBackgroundAnimationZoom: 1 27 | m_SplashScreenLogoAnimationZoom: 1 28 | m_SplashScreenBackgroundLandscapeAspect: 1 29 | m_SplashScreenBackgroundPortraitAspect: 1 30 | m_SplashScreenBackgroundLandscapeUvs: 31 | serializedVersion: 2 32 | x: 0 33 | y: 0 34 | width: 1 35 | height: 1 36 | m_SplashScreenBackgroundPortraitUvs: 37 | serializedVersion: 2 38 | x: 0 39 | y: 0 40 | width: 1 41 | height: 1 42 | m_SplashScreenLogos: [] 43 | m_VirtualRealitySplashScreen: {fileID: 0} 44 | m_HolographicTrackingLossScreen: {fileID: 0} 45 | defaultScreenWidth: 1024 46 | defaultScreenHeight: 768 47 | defaultScreenWidthWeb: 960 48 | defaultScreenHeightWeb: 600 49 | m_StereoRenderingPath: 0 50 | m_ActiveColorSpace: 0 51 | m_MTRendering: 1 52 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 53 | iosShowActivityIndicatorOnLoading: -1 54 | androidShowActivityIndicatorOnLoading: -1 55 | iosAppInBackgroundBehavior: 0 56 | displayResolutionDialog: 1 57 | iosAllowHTTPDownload: 1 58 | allowedAutorotateToPortrait: 1 59 | allowedAutorotateToPortraitUpsideDown: 1 60 | allowedAutorotateToLandscapeRight: 1 61 | allowedAutorotateToLandscapeLeft: 1 62 | useOSAutorotation: 1 63 | use32BitDisplayBuffer: 1 64 | preserveFramebufferAlpha: 0 65 | disableDepthAndStencilBuffers: 0 66 | androidBlitType: 0 67 | defaultIsNativeResolution: 1 68 | macRetinaSupport: 1 69 | runInBackground: 1 70 | captureSingleScreen: 0 71 | muteOtherAudioSources: 0 72 | Prepare IOS For Recording: 0 73 | Force IOS Speakers When Recording: 0 74 | deferSystemGesturesMode: 0 75 | hideHomeButton: 0 76 | submitAnalytics: 1 77 | usePlayerLog: 1 78 | bakeCollisionMeshes: 0 79 | forceSingleInstance: 0 80 | resizableWindow: 0 81 | useMacAppStoreValidation: 0 82 | macAppStoreCategory: public.app-category.games 83 | gpuSkinning: 1 84 | graphicsJobs: 0 85 | xboxPIXTextureCapture: 0 86 | xboxEnableAvatar: 0 87 | xboxEnableKinect: 0 88 | xboxEnableKinectAutoTracking: 0 89 | xboxEnableFitness: 0 90 | visibleInBackground: 1 91 | allowFullscreenSwitch: 1 92 | graphicsJobMode: 0 93 | fullscreenMode: 1 94 | xboxSpeechDB: 0 95 | xboxEnableHeadOrientation: 0 96 | xboxEnableGuest: 0 97 | xboxEnablePIXSampling: 0 98 | metalFramebufferOnly: 0 99 | n3dsDisableStereoscopicView: 0 100 | n3dsEnableSharedListOpt: 1 101 | n3dsEnableVSync: 0 102 | xboxOneResolution: 0 103 | xboxOneSResolution: 0 104 | xboxOneXResolution: 3 105 | xboxOneMonoLoggingLevel: 0 106 | xboxOneLoggingLevel: 1 107 | xboxOneDisableEsram: 0 108 | xboxOnePresentImmediateThreshold: 0 109 | switchQueueCommandMemory: 0 110 | videoMemoryForVertexBuffers: 0 111 | psp2PowerMode: 0 112 | psp2AcquireBGM: 1 113 | vulkanEnableSetSRGBWrite: 0 114 | vulkanUseSWCommandBuffers: 0 115 | m_SupportedAspectRatios: 116 | 4:3: 1 117 | 5:4: 1 118 | 16:10: 1 119 | 16:9: 1 120 | Others: 1 121 | bundleVersion: 0.1 122 | preloadedAssets: [] 123 | metroInputSource: 0 124 | wsaTransparentSwapchain: 0 125 | m_HolographicPauseOnTrackingLoss: 1 126 | xboxOneDisableKinectGpuReservation: 0 127 | xboxOneEnable7thCore: 0 128 | vrSettings: 129 | cardboard: 130 | depthFormat: 0 131 | enableTransitionView: 0 132 | daydream: 133 | depthFormat: 0 134 | useSustainedPerformanceMode: 0 135 | enableVideoLayer: 0 136 | useProtectedVideoMemory: 0 137 | minimumSupportedHeadTracking: 0 138 | maximumSupportedHeadTracking: 1 139 | hololens: 140 | depthFormat: 1 141 | depthBufferSharingEnabled: 0 142 | oculus: 143 | sharedDepthBuffer: 0 144 | dashSupport: 0 145 | enable360StereoCapture: 0 146 | protectGraphicsMemory: 0 147 | useHDRDisplay: 0 148 | m_ColorGamuts: 00000000 149 | targetPixelDensity: 30 150 | resolutionScalingMode: 0 151 | androidSupportedAspectRatio: 1 152 | androidMaxAspectRatio: 2.1 153 | applicationIdentifier: {} 154 | buildNumber: {} 155 | AndroidBundleVersionCode: 1 156 | AndroidMinSdkVersion: 16 157 | AndroidTargetSdkVersion: 0 158 | AndroidPreferredInstallLocation: 1 159 | aotOptions: 160 | stripEngineCode: 1 161 | iPhoneStrippingLevel: 0 162 | iPhoneScriptCallOptimization: 0 163 | ForceInternetPermission: 0 164 | ForceSDCardPermission: 0 165 | CreateWallpaper: 0 166 | APKExpansionFiles: 0 167 | keepLoadedShadersAlive: 0 168 | StripUnusedMeshComponents: 1 169 | VertexChannelCompressionMask: 4054 170 | iPhoneSdkVersion: 988 171 | iOSTargetOSVersionString: 8.0 172 | tvOSSdkVersion: 0 173 | tvOSRequireExtendedGameController: 0 174 | tvOSTargetOSVersionString: 9.0 175 | uIPrerenderedIcon: 0 176 | uIRequiresPersistentWiFi: 0 177 | uIRequiresFullScreen: 1 178 | uIStatusBarHidden: 1 179 | uIExitOnSuspend: 0 180 | uIStatusBarStyle: 0 181 | iPhoneSplashScreen: {fileID: 0} 182 | iPhoneHighResSplashScreen: {fileID: 0} 183 | iPhoneTallHighResSplashScreen: {fileID: 0} 184 | iPhone47inSplashScreen: {fileID: 0} 185 | iPhone55inPortraitSplashScreen: {fileID: 0} 186 | iPhone55inLandscapeSplashScreen: {fileID: 0} 187 | iPhone58inPortraitSplashScreen: {fileID: 0} 188 | iPhone58inLandscapeSplashScreen: {fileID: 0} 189 | iPadPortraitSplashScreen: {fileID: 0} 190 | iPadHighResPortraitSplashScreen: {fileID: 0} 191 | iPadLandscapeSplashScreen: {fileID: 0} 192 | iPadHighResLandscapeSplashScreen: {fileID: 0} 193 | appleTVSplashScreen: {fileID: 0} 194 | appleTVSplashScreen2x: {fileID: 0} 195 | tvOSSmallIconLayers: [] 196 | tvOSSmallIconLayers2x: [] 197 | tvOSLargeIconLayers: [] 198 | tvOSLargeIconLayers2x: [] 199 | tvOSTopShelfImageLayers: [] 200 | tvOSTopShelfImageLayers2x: [] 201 | tvOSTopShelfImageWideLayers: [] 202 | tvOSTopShelfImageWideLayers2x: [] 203 | iOSLaunchScreenType: 0 204 | iOSLaunchScreenPortrait: {fileID: 0} 205 | iOSLaunchScreenLandscape: {fileID: 0} 206 | iOSLaunchScreenBackgroundColor: 207 | serializedVersion: 2 208 | rgba: 0 209 | iOSLaunchScreenFillPct: 100 210 | iOSLaunchScreenSize: 100 211 | iOSLaunchScreenCustomXibPath: 212 | iOSLaunchScreeniPadType: 0 213 | iOSLaunchScreeniPadImage: {fileID: 0} 214 | iOSLaunchScreeniPadBackgroundColor: 215 | serializedVersion: 2 216 | rgba: 0 217 | iOSLaunchScreeniPadFillPct: 100 218 | iOSLaunchScreeniPadSize: 100 219 | iOSLaunchScreeniPadCustomXibPath: 220 | iOSUseLaunchScreenStoryboard: 0 221 | iOSLaunchScreenCustomStoryboardPath: 222 | iOSDeviceRequirements: [] 223 | iOSURLSchemes: [] 224 | iOSBackgroundModes: 0 225 | iOSMetalForceHardShadows: 0 226 | metalEditorSupport: 1 227 | metalAPIValidation: 1 228 | iOSRenderExtraFrameOnPause: 0 229 | appleDeveloperTeamID: 230 | iOSManualSigningProvisioningProfileID: 231 | tvOSManualSigningProvisioningProfileID: 232 | iOSManualSigningProvisioningProfileType: 0 233 | tvOSManualSigningProvisioningProfileType: 0 234 | appleEnableAutomaticSigning: 0 235 | iOSRequireARKit: 0 236 | appleEnableProMotion: 0 237 | vulkanEditorSupport: 0 238 | clonedFromGUID: c0afd0d1d80e3634a9dac47e8a0426ea 239 | templatePackageId: com.unity.3d@1.0.2 240 | templateDefaultScene: Assets/Scenes/SampleScene.unity 241 | AndroidTargetArchitectures: 5 242 | AndroidSplashScreenScale: 0 243 | androidSplashScreen: {fileID: 0} 244 | AndroidKeystoreName: 245 | AndroidKeyaliasName: 246 | AndroidBuildApkPerCpuArchitecture: 0 247 | AndroidTVCompatibility: 1 248 | AndroidIsGame: 1 249 | AndroidEnableTango: 0 250 | androidEnableBanner: 1 251 | androidUseLowAccuracyLocation: 0 252 | m_AndroidBanners: 253 | - width: 320 254 | height: 180 255 | banner: {fileID: 0} 256 | androidGamepadSupportLevel: 0 257 | resolutionDialogBanner: {fileID: 0} 258 | m_BuildTargetIcons: [] 259 | m_BuildTargetPlatformIcons: [] 260 | m_BuildTargetBatching: 261 | - m_BuildTarget: Standalone 262 | m_StaticBatching: 1 263 | m_DynamicBatching: 0 264 | - m_BuildTarget: tvOS 265 | m_StaticBatching: 1 266 | m_DynamicBatching: 0 267 | - m_BuildTarget: Android 268 | m_StaticBatching: 1 269 | m_DynamicBatching: 0 270 | - m_BuildTarget: iPhone 271 | m_StaticBatching: 1 272 | m_DynamicBatching: 0 273 | - m_BuildTarget: WebGL 274 | m_StaticBatching: 0 275 | m_DynamicBatching: 0 276 | m_BuildTargetGraphicsAPIs: 277 | - m_BuildTarget: AndroidPlayer 278 | m_APIs: 0b00000015000000 279 | m_Automatic: 1 280 | - m_BuildTarget: iOSSupport 281 | m_APIs: 10000000 282 | m_Automatic: 1 283 | - m_BuildTarget: AppleTVSupport 284 | m_APIs: 10000000 285 | m_Automatic: 0 286 | - m_BuildTarget: WebGLSupport 287 | m_APIs: 0b000000 288 | m_Automatic: 1 289 | m_BuildTargetVRSettings: 290 | - m_BuildTarget: Standalone 291 | m_Enabled: 0 292 | m_Devices: 293 | - Oculus 294 | - OpenVR 295 | m_BuildTargetEnableVuforiaSettings: [] 296 | openGLRequireES31: 0 297 | openGLRequireES31AEP: 0 298 | m_TemplateCustomTags: {} 299 | mobileMTRendering: 300 | Android: 1 301 | iPhone: 1 302 | tvOS: 1 303 | m_BuildTargetGroupLightmapEncodingQuality: [] 304 | m_BuildTargetGroupLightmapSettings: [] 305 | playModeTestRunnerEnabled: 0 306 | runPlayModeTestAsEditModeTest: 0 307 | actionOnDotNetUnhandledException: 1 308 | enableInternalProfiler: 0 309 | logObjCUncaughtExceptions: 1 310 | enableCrashReportAPI: 0 311 | cameraUsageDescription: 312 | locationUsageDescription: 313 | microphoneUsageDescription: 314 | switchNetLibKey: 315 | switchSocketMemoryPoolSize: 6144 316 | switchSocketAllocatorPoolSize: 128 317 | switchSocketConcurrencyLimit: 14 318 | switchScreenResolutionBehavior: 2 319 | switchUseCPUProfiler: 0 320 | switchApplicationID: 0x01004b9000490000 321 | switchNSODependencies: 322 | switchTitleNames_0: 323 | switchTitleNames_1: 324 | switchTitleNames_2: 325 | switchTitleNames_3: 326 | switchTitleNames_4: 327 | switchTitleNames_5: 328 | switchTitleNames_6: 329 | switchTitleNames_7: 330 | switchTitleNames_8: 331 | switchTitleNames_9: 332 | switchTitleNames_10: 333 | switchTitleNames_11: 334 | switchTitleNames_12: 335 | switchTitleNames_13: 336 | switchTitleNames_14: 337 | switchPublisherNames_0: 338 | switchPublisherNames_1: 339 | switchPublisherNames_2: 340 | switchPublisherNames_3: 341 | switchPublisherNames_4: 342 | switchPublisherNames_5: 343 | switchPublisherNames_6: 344 | switchPublisherNames_7: 345 | switchPublisherNames_8: 346 | switchPublisherNames_9: 347 | switchPublisherNames_10: 348 | switchPublisherNames_11: 349 | switchPublisherNames_12: 350 | switchPublisherNames_13: 351 | switchPublisherNames_14: 352 | switchIcons_0: {fileID: 0} 353 | switchIcons_1: {fileID: 0} 354 | switchIcons_2: {fileID: 0} 355 | switchIcons_3: {fileID: 0} 356 | switchIcons_4: {fileID: 0} 357 | switchIcons_5: {fileID: 0} 358 | switchIcons_6: {fileID: 0} 359 | switchIcons_7: {fileID: 0} 360 | switchIcons_8: {fileID: 0} 361 | switchIcons_9: {fileID: 0} 362 | switchIcons_10: {fileID: 0} 363 | switchIcons_11: {fileID: 0} 364 | switchIcons_12: {fileID: 0} 365 | switchIcons_13: {fileID: 0} 366 | switchIcons_14: {fileID: 0} 367 | switchSmallIcons_0: {fileID: 0} 368 | switchSmallIcons_1: {fileID: 0} 369 | switchSmallIcons_2: {fileID: 0} 370 | switchSmallIcons_3: {fileID: 0} 371 | switchSmallIcons_4: {fileID: 0} 372 | switchSmallIcons_5: {fileID: 0} 373 | switchSmallIcons_6: {fileID: 0} 374 | switchSmallIcons_7: {fileID: 0} 375 | switchSmallIcons_8: {fileID: 0} 376 | switchSmallIcons_9: {fileID: 0} 377 | switchSmallIcons_10: {fileID: 0} 378 | switchSmallIcons_11: {fileID: 0} 379 | switchSmallIcons_12: {fileID: 0} 380 | switchSmallIcons_13: {fileID: 0} 381 | switchSmallIcons_14: {fileID: 0} 382 | switchManualHTML: 383 | switchAccessibleURLs: 384 | switchLegalInformation: 385 | switchMainThreadStackSize: 1048576 386 | switchPresenceGroupId: 387 | switchLogoHandling: 0 388 | switchReleaseVersion: 0 389 | switchDisplayVersion: 1.0.0 390 | switchStartupUserAccount: 0 391 | switchTouchScreenUsage: 0 392 | switchSupportedLanguagesMask: 0 393 | switchLogoType: 0 394 | switchApplicationErrorCodeCategory: 395 | switchUserAccountSaveDataSize: 0 396 | switchUserAccountSaveDataJournalSize: 0 397 | switchApplicationAttribute: 0 398 | switchCardSpecSize: -1 399 | switchCardSpecClock: -1 400 | switchRatingsMask: 0 401 | switchRatingsInt_0: 0 402 | switchRatingsInt_1: 0 403 | switchRatingsInt_2: 0 404 | switchRatingsInt_3: 0 405 | switchRatingsInt_4: 0 406 | switchRatingsInt_5: 0 407 | switchRatingsInt_6: 0 408 | switchRatingsInt_7: 0 409 | switchRatingsInt_8: 0 410 | switchRatingsInt_9: 0 411 | switchRatingsInt_10: 0 412 | switchRatingsInt_11: 0 413 | switchLocalCommunicationIds_0: 414 | switchLocalCommunicationIds_1: 415 | switchLocalCommunicationIds_2: 416 | switchLocalCommunicationIds_3: 417 | switchLocalCommunicationIds_4: 418 | switchLocalCommunicationIds_5: 419 | switchLocalCommunicationIds_6: 420 | switchLocalCommunicationIds_7: 421 | switchParentalControl: 0 422 | switchAllowsScreenshot: 1 423 | switchAllowsVideoCapturing: 1 424 | switchAllowsRuntimeAddOnContentInstall: 0 425 | switchDataLossConfirmation: 0 426 | switchSupportedNpadStyles: 3 427 | switchNativeFsCacheSize: 32 428 | switchIsHoldTypeHorizontal: 0 429 | switchSupportedNpadCount: 8 430 | switchSocketConfigEnabled: 0 431 | switchTcpInitialSendBufferSize: 32 432 | switchTcpInitialReceiveBufferSize: 64 433 | switchTcpAutoSendBufferSizeMax: 256 434 | switchTcpAutoReceiveBufferSizeMax: 256 435 | switchUdpSendBufferSize: 9 436 | switchUdpReceiveBufferSize: 42 437 | switchSocketBufferEfficiency: 4 438 | switchSocketInitializeEnabled: 1 439 | switchNetworkInterfaceManagerInitializeEnabled: 1 440 | switchPlayerConnectionEnabled: 1 441 | ps4NPAgeRating: 12 442 | ps4NPTitleSecret: 443 | ps4NPTrophyPackPath: 444 | ps4ParentalLevel: 11 445 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 446 | ps4Category: 0 447 | ps4MasterVersion: 01.00 448 | ps4AppVersion: 01.00 449 | ps4AppType: 0 450 | ps4ParamSfxPath: 451 | ps4VideoOutPixelFormat: 0 452 | ps4VideoOutInitialWidth: 1920 453 | ps4VideoOutBaseModeInitialWidth: 1920 454 | ps4VideoOutReprojectionRate: 60 455 | ps4PronunciationXMLPath: 456 | ps4PronunciationSIGPath: 457 | ps4BackgroundImagePath: 458 | ps4StartupImagePath: 459 | ps4StartupImagesFolder: 460 | ps4IconImagesFolder: 461 | ps4SaveDataImagePath: 462 | ps4SdkOverride: 463 | ps4BGMPath: 464 | ps4ShareFilePath: 465 | ps4ShareOverlayImagePath: 466 | ps4PrivacyGuardImagePath: 467 | ps4NPtitleDatPath: 468 | ps4RemotePlayKeyAssignment: -1 469 | ps4RemotePlayKeyMappingDir: 470 | ps4PlayTogetherPlayerCount: 0 471 | ps4EnterButtonAssignment: 1 472 | ps4ApplicationParam1: 0 473 | ps4ApplicationParam2: 0 474 | ps4ApplicationParam3: 0 475 | ps4ApplicationParam4: 0 476 | ps4DownloadDataSize: 0 477 | ps4GarlicHeapSize: 2048 478 | ps4ProGarlicHeapSize: 2560 479 | ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ 480 | ps4pnSessions: 1 481 | ps4pnPresence: 1 482 | ps4pnFriends: 1 483 | ps4pnGameCustomData: 1 484 | playerPrefsSupport: 0 485 | enableApplicationExit: 0 486 | restrictedAudioUsageRights: 0 487 | ps4UseResolutionFallback: 0 488 | ps4ReprojectionSupport: 0 489 | ps4UseAudio3dBackend: 0 490 | ps4SocialScreenEnabled: 0 491 | ps4ScriptOptimizationLevel: 0 492 | ps4Audio3dVirtualSpeakerCount: 14 493 | ps4attribCpuUsage: 0 494 | ps4PatchPkgPath: 495 | ps4PatchLatestPkgPath: 496 | ps4PatchChangeinfoPath: 497 | ps4PatchDayOne: 0 498 | ps4attribUserManagement: 0 499 | ps4attribMoveSupport: 0 500 | ps4attrib3DSupport: 0 501 | ps4attribShareSupport: 0 502 | ps4attribExclusiveVR: 0 503 | ps4disableAutoHideSplash: 0 504 | ps4videoRecordingFeaturesUsed: 0 505 | ps4contentSearchFeaturesUsed: 0 506 | ps4attribEyeToEyeDistanceSettingVR: 0 507 | ps4IncludedModules: [] 508 | monoEnv: 509 | psp2Splashimage: {fileID: 0} 510 | psp2NPTrophyPackPath: 511 | psp2NPSupportGBMorGJP: 0 512 | psp2NPAgeRating: 12 513 | psp2NPTitleDatPath: 514 | psp2NPCommsID: 515 | psp2NPCommunicationsID: 516 | psp2NPCommsPassphrase: 517 | psp2NPCommsSig: 518 | psp2ParamSfxPath: 519 | psp2ManualPath: 520 | psp2LiveAreaGatePath: 521 | psp2LiveAreaBackroundPath: 522 | psp2LiveAreaPath: 523 | psp2LiveAreaTrialPath: 524 | psp2PatchChangeInfoPath: 525 | psp2PatchOriginalPackage: 526 | psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui 527 | psp2KeystoneFile: 528 | psp2MemoryExpansionMode: 0 529 | psp2DRMType: 0 530 | psp2StorageType: 0 531 | psp2MediaCapacity: 0 532 | psp2DLCConfigPath: 533 | psp2ThumbnailPath: 534 | psp2BackgroundPath: 535 | psp2SoundPath: 536 | psp2TrophyCommId: 537 | psp2TrophyPackagePath: 538 | psp2PackagedResourcesPath: 539 | psp2SaveDataQuota: 10240 540 | psp2ParentalLevel: 1 541 | psp2ShortTitle: Not Set 542 | psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF 543 | psp2Category: 0 544 | psp2MasterVersion: 01.00 545 | psp2AppVersion: 01.00 546 | psp2TVBootMode: 0 547 | psp2EnterButtonAssignment: 2 548 | psp2TVDisableEmu: 0 549 | psp2AllowTwitterDialog: 1 550 | psp2Upgradable: 0 551 | psp2HealthWarning: 0 552 | psp2UseLibLocation: 0 553 | psp2InfoBarOnStartup: 0 554 | psp2InfoBarColor: 0 555 | psp2ScriptOptimizationLevel: 0 556 | splashScreenBackgroundSourceLandscape: {fileID: 0} 557 | splashScreenBackgroundSourcePortrait: {fileID: 0} 558 | spritePackerPolicy: 559 | webGLMemorySize: 256 560 | webGLExceptionSupport: 1 561 | webGLNameFilesAsHashes: 0 562 | webGLDataCaching: 1 563 | webGLDebugSymbols: 0 564 | webGLEmscriptenArgs: 565 | webGLModulesDirectory: 566 | webGLTemplate: APPLICATION:Default 567 | webGLAnalyzeBuildSize: 0 568 | webGLUseEmbeddedResources: 0 569 | webGLCompressionFormat: 1 570 | webGLLinkerTarget: 1 571 | scriptingDefineSymbols: {} 572 | platformArchitecture: {} 573 | scriptingBackend: {} 574 | il2cppCompilerConfiguration: {} 575 | incrementalIl2cppBuild: {} 576 | allowUnsafeCode: 0 577 | additionalIl2CppArgs: 578 | scriptingRuntimeVersion: 1 579 | apiCompatibilityLevelPerPlatform: {} 580 | m_RenderingPath: 1 581 | m_MobileRenderingPath: 1 582 | metroPackageName: Template_3D 583 | metroPackageVersion: 584 | metroCertificatePath: 585 | metroCertificatePassword: 586 | metroCertificateSubject: 587 | metroCertificateIssuer: 588 | metroCertificateNotAfter: 0000000000000000 589 | metroApplicationDescription: Template_3D 590 | wsaImages: {} 591 | metroTileShortName: 592 | metroTileShowName: 0 593 | metroMediumTileShowName: 0 594 | metroLargeTileShowName: 0 595 | metroWideTileShowName: 0 596 | metroDefaultTileSize: 1 597 | metroTileForegroundText: 2 598 | metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} 599 | metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, 600 | a: 1} 601 | metroSplashScreenUseBackgroundColor: 0 602 | platformCapabilities: {} 603 | metroFTAName: 604 | metroFTAFileTypes: [] 605 | metroProtocolName: 606 | metroCompilationOverrides: 1 607 | n3dsUseExtSaveData: 0 608 | n3dsCompressStaticMem: 1 609 | n3dsExtSaveDataNumber: 0x12345 610 | n3dsStackSize: 131072 611 | n3dsTargetPlatform: 2 612 | n3dsRegion: 7 613 | n3dsMediaSize: 0 614 | n3dsLogoStyle: 3 615 | n3dsTitle: GameName 616 | n3dsProductCode: 617 | n3dsApplicationId: 0xFF3FF 618 | XboxOneProductId: 619 | XboxOneUpdateKey: 620 | XboxOneSandboxId: 621 | XboxOneContentId: 622 | XboxOneTitleId: 623 | XboxOneSCId: 624 | XboxOneGameOsOverridePath: 625 | XboxOnePackagingOverridePath: 626 | XboxOneAppManifestOverridePath: 627 | XboxOneVersion: 1.0.0.0 628 | XboxOnePackageEncryption: 0 629 | XboxOnePackageUpdateGranularity: 2 630 | XboxOneDescription: 631 | XboxOneLanguage: 632 | - enus 633 | XboxOneCapability: [] 634 | XboxOneGameRating: {} 635 | XboxOneIsContentPackage: 0 636 | XboxOneEnableGPUVariability: 0 637 | XboxOneSockets: {} 638 | XboxOneSplashScreen: {fileID: 0} 639 | XboxOneAllowedProductIds: [] 640 | XboxOnePersistentLocalStorageSize: 0 641 | XboxOneXTitleMemory: 8 642 | xboxOneScriptCompiler: 0 643 | vrEditorSettings: 644 | daydream: 645 | daydreamIconForeground: {fileID: 0} 646 | daydreamIconBackground: {fileID: 0} 647 | cloudServicesEnabled: 648 | UNet: 1 649 | facebookSdkVersion: 7.9.4 650 | apiCompatibilityLevel: 3 651 | cloudProjectId: 652 | projectName: 653 | organizationId: 654 | cloudEnabled: 0 655 | enableNativePlatformBackendsForNewInputSystem: 0 656 | disableOldInputManagerSupport: 0 657 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2018.2.6f1 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 4 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 4 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 4 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 1 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 1 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 4 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 2 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 1 108 | antiAliasing: 2 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 1 112 | billboardsFaceCameraPosition: 1 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 4 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 2 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 40 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 1 136 | antiAliasing: 4 137 | softParticles: 1 138 | softVegetation: 1 139 | realtimeReflectionProbes: 1 140 | billboardsFaceCameraPosition: 1 141 | vSyncCount: 1 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 4 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 2 153 | shadowResolution: 2 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 1 164 | antiAliasing: 4 165 | softParticles: 1 166 | softVegetation: 1 167 | realtimeReflectionProbes: 1 168 | billboardsFaceCameraPosition: 1 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 4 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSP2: 2 183 | Standalone: 5 184 | Tizen: 2 185 | WebGL: 3 186 | WiiU: 5 187 | Windows Store Apps: 5 188 | XboxOne: 5 189 | iPhone: 2 190 | tvOS: 2 191 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - PostProcessing 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.02 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 0 7 | m_TestMode: 0 8 | m_TestEventUrl: 9 | m_TestConfigUrl: 10 | m_TestInitMode: 0 11 | CrashReportingSettings: 12 | m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes 13 | m_NativeEventUrl: https://perf-events.cloud.unity3d.com/symbolicate 14 | m_Enabled: 0 15 | m_CaptureEditorExceptions: 1 16 | UnityPurchasingSettings: 17 | m_Enabled: 0 18 | m_TestMode: 0 19 | UnityAnalyticsSettings: 20 | m_Enabled: 0 21 | m_InitializeOnStartup: 1 22 | m_TestMode: 0 23 | m_TestEventUrl: 24 | m_TestConfigUrl: 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OctoMapSharp 2 | An Efficient Probabilistic 3D Mapping Framework Based on Octrees. A Unity C# port of the original C++ implementation. 3 | 4 | # Acknowledgements 5 | - OctoMap white paper and C++ implementation originally developed by Kai M. Wurm and Armin Hornung. [LINK](https://github.com/OctoMap/octomap) 6 | - BitStream stream wrapper to read/write bits and other data types developed by Rubendal. [LINK](https://github.com/rubendal/BitStream) 7 | 8 | # Requirements 9 | - Unity Scripting Runtime Version .NET 4.x Equivalent 10 | 11 | # Features 12 | - Create an OctoMap data structure by defining a starting position and size as well as the minimum node size. 13 | - Add 3D points to the OctoMap and mark nodes as occupied. Recursive subdivision is used to mark the leaf node (as defined by the minimum node size) that encompasses the added point as occupied. 14 | - Mark nodes along a ray as free. Recursive subdivision is used to find leaf nodes that the ray intersects as marks them as free. 15 | - Child nodes are pruned (removed) if they share the same occupancy state and the parent node's occupancy value is set to it. 16 | - Compact bitstream serialization (as first defined in the white paper) that reduces the OctoMap to a small size by only storing parent-child relationships as opposed to individual node positions. --------------------------------------------------------------------------------