tech spec 1.0, first working understanding of pos bytes encoding able to write world coords of all voxels
This commit is contained in:
parent
11279d162b
commit
7d37f4d994
324
README.md
324
README.md
@ -62,58 +62,103 @@ root
|
|||||||
└── snapshots (array)
|
└── snapshots (array)
|
||||||
└── Each snapshot (dictionary)
|
└── Each snapshot (dictionary)
|
||||||
├── s (dictionary) - Snapshot data
|
├── s (dictionary) - Snapshot data
|
||||||
│ ├── lc (binary data) - Location table
|
│ ├── id (dictionary) - Identifiers
|
||||||
|
│ │ ├── c (int64) - Chunk ID
|
||||||
|
│ │ ├── s (int64) - Session ID
|
||||||
|
│ │ └── t (int64) - Type ID
|
||||||
|
│ ├── lc (binary data) - Layer Color Usage
|
||||||
│ ├── ds (binary data) - Voxel data stream
|
│ ├── ds (binary data) - Voxel data stream
|
||||||
│ ├── dlc (binary data) - Default layer colors
|
│ ├── dlc (binary data) - Deselected Layer Color Usage
|
||||||
│ └── st (dictionary) - Statistics/metadata
|
│ └── st (dictionary) - Statistics/metadata
|
||||||
└── Other metadata fields:
|
│ ├── c (int64) - Count of voxels in the chunk
|
||||||
├── cid (chunk id)
|
│ ├── sc (int64) - Selected Count (number of selected voxels)
|
||||||
├── sid (edit session id)
|
│ ├── smin (array) - Selected Minimum coordinates [x,y,z,w]
|
||||||
└── t (type - VXVolumeSnapshotType)
|
│ ├── smax (array) - Selected Maximum coordinates [x,y,z,w]
|
||||||
|
│ ├── min (array) - Minimum coordinates of all voxels [x,y,z]
|
||||||
|
│ ├── max (array) - Maximum coordinates of all voxels [x,y,z]
|
||||||
|
│ └── e (dictionary) - Extent
|
||||||
|
│ ├── o (array) - Origin/reference point [x,y,z]
|
||||||
|
│ └── s (array) - Size/dimensions [width,height,depth]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Chunking System
|
## Chunking System
|
||||||
### Volume Organization
|
### Volume Organization
|
||||||
- The total volume is divided into chunks for efficient storage and manipulation
|
- The total volume is divided into chunks for efficient storage and manipulation
|
||||||
- Standard chunk size: 8×8×8 voxels
|
- Standard chunk size: 32×32×32 voxels
|
||||||
- Total addressable space: 256×256×256 voxels (32×32×32 chunks)
|
- Total addressable space: 256×256×256 voxels (8×8×8 chunks)
|
||||||
|
|
||||||
|
### Morton Encoding for Chunks
|
||||||
|
- Chunk IDs are encoded using 24 bits (8 bits per dimension)
|
||||||
|
- This allows addressing up to 256 chunks in each dimension , although only 8x8x8 are used in practice
|
||||||
|
- The decodeMortonChunkID function extracts x, y, z coordinates from a Morton-encoded chunk ID
|
||||||
|
- The resulting chunk coordinates are then multiplied by 32 to get the world position of the chunk
|
||||||
|
|
||||||
### Chunk Addressing
|
### Chunk Addressing
|
||||||
- Each chunk has 3D coordinates (chunk_x, chunk_y, chunk_z)
|
- Each chunk has 3D coordinates (chunk_x, chunk_y, chunk_z)
|
||||||
- ie a 16×16×16 volume with 8×8×8 chunks, there would be 2×2×2 chunks total
|
- For a 128×128×128 volume with 32×32×32 chunks, there would be 4×4×4 chunks total (64 chunks)
|
||||||
- Chunks are only stored if they contain at least one non-empty voxel
|
- Chunks are only stored if they contain at least one non-empty voxel
|
||||||
|
- Each snapshot contains data for a specific chunk, identified by the 'c' value in the 's.id' dictionary
|
||||||
|
|
||||||
## Data Fields
|
## Data Fields
|
||||||
### Location Table (lc)
|
|
||||||
- Fixed-size binary array (256 bytes)
|
|
||||||
- Each byte represents a position in a 3D volume
|
|
||||||
- Non-zero values (typically 1) indicate occupied positions
|
|
||||||
- The index of each byte is interpreted as a Morton code for the position
|
|
||||||
- Size of 256 bytes limits addressable chunks to 256
|
|
||||||
- ie a 16×16×16 volume would get 16÷8 = 2 chunks, Total chunks = 2×2×2 = 8 chunks total
|
|
||||||
### Voxel Data Stream (ds)
|
### Voxel Data Stream (ds)
|
||||||
- Variable-length binary data
|
- Variable-length binary data
|
||||||
- Contains pairs of bytes for each voxel: [position_byte, color_byte]
|
- Contains pairs of bytes for each voxel: [position_byte, color_byte]
|
||||||
|
- Each chunk can contain up to 32,768 voxels (32×32×32)
|
||||||
- *Position Byte:*
|
- *Position Byte:*
|
||||||
- Usually 0 (meaning position at origin of chunk)
|
- The format uses a encoding approach that combines sequential and Morton encoding for optimal storage efficiency:
|
||||||
- Can encode a local position within a chunk using Morton encoding
|
- Uses a mix of position=0 bytes (for sequential implicit positions) and Morton-encoded position bytes
|
||||||
|
- The decoder maintains an internal position counter that advances through the chunk in a predefined order (x, then y, then z)
|
||||||
|
- Color byte 0 indicates "no voxel at this position" (empty space)
|
||||||
|
- If a chunk uses the entire 256x256x256 addressable space, then it uses exactly 65,536 bytes (32,768 voxel pairs)
|
||||||
|
- This is the dense case and it not memory efficient
|
||||||
|
- When we introduce morton encoding we can jump to a specific position in the chunk
|
||||||
|
- Data stream can terminate at any point, avoiding the need to store all 32,768 voxel pairs
|
||||||
|
### Morton Encoding Process
|
||||||
|
- A space-filling curve that interleaves the bits of the x, y, and z coordinates
|
||||||
|
- Used to convert 3D coordinates to a 1D index and vice versa
|
||||||
|
- Creates a coherent ordering of voxels that preserves spatial locality
|
||||||
|
1. Take the binary representation of x, y, and z coordinates
|
||||||
|
2. Interleave the bits in the order: z₀, y₀, x₀, z₁, y₁, x₁, z₂, y₂, x₂, ...
|
||||||
|
3. The resulting binary number is the Morton code
|
||||||
|
|
||||||
|
|
||||||
- *Color Byte:*
|
- *Color Byte:*
|
||||||
- Stores the color value + 1 (offset of +1 from actual color)
|
- Stores the color value + 1 (offset of +1 from actual color)
|
||||||
- Value 0 would represent -1 (typically not used)
|
- Value 0 indicates no voxel at this position
|
||||||
|
- A fully populated chunk will have 32,768 voxel pairs (65,536 bytes total in ds)
|
||||||
|
|
||||||
### Default Layer Colors (dlc)
|
### Snapshot Accumulation
|
||||||
- Optional 256-byte array
|
- Each snapshot contains data for a specific chunk (identified by the chunk ID)
|
||||||
- May contain default color information for specific layers
|
- Multiple snapshots together build up the complete voxel model
|
||||||
|
- Later snapshots for the same chunk ID overwrite earlier ones, allowing for edits over time
|
||||||
|
|
||||||
|
### Layer Color Usagw (lc)
|
||||||
|
- s.lc is a summary table (256 bytes) that tracks which colors are used anywhere in the chunk
|
||||||
|
- Each byte position (0-255) corresponds to a color palette ID
|
||||||
|
- [TODO] understand why the word layer color is used, what is a layer color
|
||||||
|
|
||||||
|
### Deselected Layer Color Usage (dlc)
|
||||||
|
- Optional 256-byte array
|
||||||
|
- Used during editing to track which color layers the user has deselected
|
||||||
|
- Primarily for UI state preservation rather than 3D model representation
|
||||||
|
|
||||||
### Statistics Data (st)
|
### Statistics Data (st)
|
||||||
- Dictionary containing metadata like:
|
- Dictionary containing metadata about the voxels in a chunk:
|
||||||
|
- c (count): Total number of voxels in the chunk
|
||||||
|
- sc (selectedCount): Number of currently selected voxels
|
||||||
|
- sMin (selectedMin): Array defining minimum coordinates of current selection [x,y,z,w]
|
||||||
|
- sMax (selectedMax): Array defining maximum coordinates of current selection [x,y,z,w]
|
||||||
|
- min: Array defining minimum coordinates of all voxels [x,y,z]
|
||||||
|
- max: Array defining maximum coordinates of all voxels [x,y,z]
|
||||||
- e (extent): Array defining the bounding box [min_x, min_y, min_z, max_x, max_y, max_z]
|
- e (extent): Array defining the bounding box [min_x, min_y, min_z, max_x, max_y, max_z]
|
||||||
- Other statistics fields may include count, max, min, etc.
|
- e.o (extent.origin): Reference point or offset for extent calculations
|
||||||
|
|
||||||
## Coordinate Systems
|
## Coordinate Systems
|
||||||
### Primary Coordinate System
|
### Primary Coordinate System
|
||||||
- Y-up coordinate system: Y is the vertical axis
|
- Y-up coordinate system: Y is the vertical axis
|
||||||
- Origin (0,0,0) is at the bottom-left-front corner
|
- Origin (0,0,0) is at the bottom-left-front corner
|
||||||
- Coordinates increase toward right (X+), up (Y+), and backward (Z+)
|
- Coordinates increase toward right (X+), up (Y+), and backward (Z+)
|
||||||
|
|
||||||
### Addressing Scheme
|
### Addressing Scheme
|
||||||
1. World Space: Absolute coordinates in the full volume
|
1. World Space: Absolute coordinates in the full volume
|
||||||
2. Chunk Space: Which chunk contains a voxel (chunk_x, chunk_y, chunk_z)
|
2. Chunk Space: Which chunk contains a voxel (chunk_x, chunk_y, chunk_z)
|
||||||
@ -121,32 +166,20 @@ root
|
|||||||
|
|
||||||
## Coordinate Conversion
|
## Coordinate Conversion
|
||||||
- *World to Chunk:*
|
- *World to Chunk:*
|
||||||
- chunk_x = floor(world_x / 8)
|
- chunk_x = floor(world_x / 32)
|
||||||
- chunk_y = floor(world_y / 8)
|
- chunk_y = floor(world_y / 32)
|
||||||
- chunk_z = floor(world_z / 8)
|
- chunk_z = floor(world_z / 32)
|
||||||
- *World to Local:*
|
- *World to Local:*
|
||||||
- local_x = world_x % 8
|
- local_x = world_x % 32
|
||||||
- local_y = world_y % 8
|
- local_y = world_y % 32
|
||||||
- local_z = world_z % 8
|
- local_z = world_z % 32
|
||||||
- *Chunk+Local to World:*
|
- *Chunk+Local to World:*
|
||||||
- world_x = chunk_x * 8 + local_x
|
- world_x = chunk_x * 32 + local_x
|
||||||
- world_y = chunk_y * 8 + local_y
|
- world_y = chunk_y * 32 + local_y
|
||||||
- world_z = chunk_z * 8 + local_z
|
- world_z = chunk_z * 32 + local_z
|
||||||
|
|
||||||
## Morton Encoding
|
|
||||||
### Morton Code (Z-order curve)
|
|
||||||
- A space-filling curve that interleaves the bits of the x, y, and z coordinates
|
|
||||||
- Used to convert 3D coordinates to a 1D index and vice versa
|
|
||||||
- Creates a coherent ordering of voxels that preserves spatial locality
|
|
||||||
### Encoding Process
|
|
||||||
1. Take the binary representation of x, y, and z coordinates
|
|
||||||
2. Interleave the bits in the order: z₀, y₀, x₀, z₁, y₁, x₁, z₂, y₂, x₂, ...
|
|
||||||
3. The resulting binary number is the Morton code
|
|
||||||
### For Chunk Indexing
|
|
||||||
- Morton code is used to map the 3D chunk coordinates to a 1D index in the lc array
|
|
||||||
Formula: index = interleave_bits(chunk_x, chunk_y, chunk_z)
|
|
||||||
|
|
||||||
### Detailed Example
|
|
||||||
|
### Detailed Morton Encoding Example
|
||||||
To clarify the bit interleaving process, here's a step-by-step example:
|
To clarify the bit interleaving process, here's a step-by-step example:
|
||||||
|
|
||||||
For position (3,1,2):
|
For position (3,1,2):
|
||||||
@ -165,185 +198,36 @@ For position (3,1,2):
|
|||||||
|
|
||||||
Therefore, position (3,1,2) has Morton index 134.
|
Therefore, position (3,1,2) has Morton index 134.
|
||||||
|
|
||||||
An 8×8×8 chunk contains 512 voxels total, with Morton indices ranging from 0 to 511:
|
|
||||||
Morton index 0 corresponds to position (0,0,0)
|
|
||||||
Morton index 511 corresponds to position (7,7,7)
|
|
||||||
The Morton indices are organized by z-layer:
|
|
||||||
Z=0 layer: indices 0-63
|
|
||||||
Z=1 layer: indices 64-127
|
|
||||||
Z=2 layer: indices 128-191
|
|
||||||
Z=3 layer: indices 192-255
|
|
||||||
Z=4 layer: indices 256-319
|
|
||||||
Z=5 layer: indices 320-383
|
|
||||||
Z=6 layer: indices 384-447
|
|
||||||
Z=7 layer: indices 448-511
|
|
||||||
Each z-layer contains 64 positions (8×8), and with 8 layers, we get the full 512 positions for the chunk.
|
|
||||||
|
|
||||||
### For Local Positions
|
|
||||||
The position byte in the voxel data can contain a Morton-encoded local position
|
|
||||||
- Typically 0 (representing the origin of the chunk)
|
|
||||||
- When non-zero, it encodes a specific position within the chunk
|
|
||||||
|
|
||||||
## Color Representation
|
|
||||||
### Color Values
|
|
||||||
- Stored as a single byte (8-bit)
|
|
||||||
- Range: 0-255
|
|
||||||
- Important: Stored with an offset of +1 from actual color
|
|
||||||
|
|
||||||
### Color Interpretation
|
|
||||||
Format doesn't specify a specific color model (RGB, palette, etc.)
|
|
||||||
- Interpretation depends on the implementation
|
|
||||||
## Snapshots and Edit History
|
|
||||||
###Snapshots
|
|
||||||
- Each snapshot represents a single edit operation
|
|
||||||
- Multiple snapshots build up the complete voxel model over time
|
|
||||||
- Later snapshots override earlier ones for the same positions
|
|
||||||
|
|
||||||
### Snapshot Metadata
|
|
||||||
- cid (Chunk ID): Which chunk was modified
|
|
||||||
- sid (Session ID): Identifies the editing session
|
|
||||||
- t (Type): Type of snapshot (VXVolumeSnapshotType)
|
|
||||||
|
|
||||||
## Special Considerations
|
|
||||||
### Sparse Representation
|
|
||||||
- Only non-empty chunks and voxels are stored
|
|
||||||
- This creates an efficient representation for mostly empty volumes
|
|
||||||
### Position Encoding
|
|
||||||
- When all voxels in a chunk are at the origin (0,0,0), the position byte is always 0
|
|
||||||
- For more complex structures, the position byte encodes local positions within the chunk
|
|
||||||
### Color Offset
|
|
||||||
- The +1 offset for colors must be accounted for when reading and writing
|
|
||||||
- This might be to reserve 0 as a special value (e.g., for "no color")
|
|
||||||
### Field Sizes
|
|
||||||
- The location table (lc) is fixed at 256 bytes
|
|
||||||
- The voxel data stream (ds) varies based on the number of voxels
|
|
||||||
- For a simple 16×16×16 volume with 8×8×8 chunks, only 64 chunks can be addressed (2×2×2 chunks = 8 chunks total)
|
|
||||||
## Implementation Guidance
|
## Implementation Guidance
|
||||||
### Reading Algorithm
|
### Reading Algorithm
|
||||||
1. Parse the plist file to access the snapshot array
|
1. Parse the plist file to access the snapshot array
|
||||||
2. For each snapshot, extract the lc and ds data
|
2. For each snapshot:
|
||||||
3. Scan the lc data for non-zero entries to identify occupied positions
|
a. Extract the chunk ID from s > id > c
|
||||||
4. For each non-zero entry, decode the Morton index to get the chunk coordinates
|
b. Extract the lc and ds data
|
||||||
5. Process the ds data in pairs of bytes (position, color)
|
c. Process the ds data in pairs of bytes (position, color)
|
||||||
6. For each voxel, calculate its absolute position and store with the corrected color (subtract 1)
|
d. Calculate the world origin by decoding the Morton chunk ID and multiplying by 32
|
||||||
7. Combine all snapshots to build the complete voxel model
|
e. Store the voxels for this chunk ID
|
||||||
|
3. Combine all snapshots to build the complete voxel model, using the chunk IDs as keys
|
||||||
|
|
||||||
### Writing Algorithm
|
### Writing Algorithm
|
||||||
1. Organize voxels by chunk
|
1. Organize voxels by chunk (32×32×32 voxels per chunk)
|
||||||
2. For each non-empty chunk:
|
2. For each non-empty chunk:
|
||||||
3. Create a snapshot entry
|
a. Create a snapshot entry
|
||||||
4. Set up a 256-byte lc array (all zeros)
|
b. Set up the id dictionary with the appropriate chunk ID
|
||||||
5. Set the appropriate byte in lc to 1 based on the chunk's Morton code
|
c. Set up a 256-byte lc array (all zeros)
|
||||||
6. Create the ds data by encoding each voxel as a (position, color+1) pair
|
d. Create the ds data by encoding each voxel as a (position, color+1) pair
|
||||||
7. Add metadata as needed
|
e. Set the appropriate byte in lc to 1 if the color is used in ds
|
||||||
8. Add all snapshots to the array
|
3. Add all snapshots to the array
|
||||||
9. Write the complete structure to a plist file
|
4. Write the complete structure to a plist file
|
||||||
10. Compress with LZFSE
|
|
||||||
12. [hand wabving] Package up in a MacOS style package directory with some other files
|
|
||||||
## Practical Limits
|
|
||||||
- 256-byte location table can address up to 256 distinct positions
|
|
||||||
- 8-bit color values allow 256 different colors (including the offset)
|
|
||||||
- For a 256×256×256 volume with 8×8×8 chunks, there would be 32×32×32 = 32,768 chunks total
|
|
||||||
- The format could efficiently represent volumes with millions of voxels
|
|
||||||
|
|
||||||
|
- [?] Models typically use SessionIDs to group related edits (observed values include 10 and 18)
|
||||||
|
|
||||||
-----
|
## Snapshot Types
|
||||||
|
The 't' field in the snapshot's 's.id' dictionary indicates the type of snapshot:
|
||||||
|
- 0: underRestore - Snapshot being restored from a previous state
|
||||||
|
- 1: redoRestore - Snapshot being restored during a redo operation
|
||||||
|
- 2: undo - Snapshot created for an undo operation
|
||||||
|
- 3: redo - Snapshot created for a redo operation
|
||||||
|
- 4: checkpoint - Snapshot created as a regular checkpoint during editing (most common)
|
||||||
|
- 5: selection - Snapshot representing a selection operation
|
||||||
|
|
||||||
# Scratch notes
|
|
||||||
|
|
||||||
```
|
|
||||||
Morton Binary Coords Visual (Z-layers)
|
|
||||||
Index (zyx bits) (x,y,z)
|
|
||||||
|
|
||||||
0 000 (000) (0,0,0) Z=0 layer: Z=1 layer:
|
|
||||||
1 001 (001) (1,0,0) +---+---+ +---+---+
|
|
||||||
2 010 (010) (0,1,0) | 0 | 1 | | 4 | 5 |
|
|
||||||
3 011 (011) (1,1,0) +---+---+ +---+---+
|
|
||||||
4 100 (100) (0,0,1) | 2 | 3 | | 6 | 7 |
|
|
||||||
5 101 (101) (1,0,1) +---+---+ +---+---+
|
|
||||||
6 110 (110) (0,1,1)
|
|
||||||
7 111 (111) (1,1,1)
|
|
||||||
```
|
|
||||||
|
|
||||||
In memory, this would be stored linearly:
|
|
||||||
|
|
||||||
```
|
|
||||||
Memory: [0][1][2][3][4][5][6][7]
|
|
||||||
| | | | | | | |
|
|
||||||
v v v v v v v v
|
|
||||||
Coords: (0,0,0)(1,0,0)(0,1,0)(1,1,0)(0,0,1)(1,0,1)(0,1,1)(1,1,1)
|
|
||||||
```
|
|
||||||
|
|
||||||
All voxels with z=0 (Morton indices 0-3 in our 2×2×2 example) are stored contiguously
|
|
||||||
Then all voxels with z=1 (Morton indices 4-7) are stored contiguously
|
|
||||||
This pattern scales to larger volumes too:
|
|
||||||
In a 4×4×4 cube, indices 0-15 would be the entire z=0 layer
|
|
||||||
Indices 16-31 would be the z=1 layer
|
|
||||||
And so on
|
|
||||||
|
|
||||||
## Morton encoding
|
|
||||||
|
|
||||||
Morton encoding completes an entire z-layer before moving to the next one. This happens because the highest-order bit in the Morton code (the z bit in the most significant position) changes less frequently than the lower-order bits, creating this layered organization.
|
|
||||||
This property makes operations like rendering slice-by-slice more efficient, as entire z-layers are stored together.
|
|
||||||
|
|
||||||
|
|
||||||
The Morton encoding is applied at the chunk level (8×8×8)
|
|
||||||
It processes the entire front z-layer (z=0) first, traversing in a zig-zag pattern
|
|
||||||
The zig-zag pattern creates a space-filling curve that maintains spatial locality
|
|
||||||
After completing one z-layer, it moves to the next (z=1)
|
|
||||||
This continues through all 8 possible z-layers in the chunk
|
|
||||||
The location table (lc) uses this Morton ordering to efficiently address all possible chunks, and within each chunk, the data follows this same pattern when decoding positions.
|
|
||||||
This approach is particularly efficient for this voxel format because:
|
|
||||||
It groups related voxels together in memory
|
|
||||||
It enables quick access to entire z-layers
|
|
||||||
It maintains spatial locality which improves cache performance
|
|
||||||
|
|
||||||
## Location table chunks
|
|
||||||
|
|
||||||
The 256 bytes in the lc table doesn't represent voxels within a chunk, but rather which chunks exist in the entire volume:
|
|
||||||
Each byte in the 256-byte lc array corresponds to a potential chunk position
|
|
||||||
For a full 256×256×256 voxel world, you'd have 32×32×32 = 32,768 possible chunks
|
|
||||||
The 256-byte limit means each snapshot can only reference up to 256 distinct chunks
|
|
||||||
This is why the format uses multiple snapshots - it allows the format to build complex models by combining multiple snapshots, each referencing up to 256 chunks.
|
|
||||||
So while 256 bytes is small for individual storage, it's actually a limitation on how many chunks can be referenced in a single snapshot. For most practical voxel models, this is adequate since they typically use far fewer than 256 chunks.
|
|
||||||
|
|
||||||
|
|
||||||
In each snapshot:
|
|
||||||
The cid (Chunk ID) field identifies which specific 8×8×8 chunk was modified
|
|
||||||
The s dictionary contains the actual edit data:
|
|
||||||
lc (Location Table): Shows which voxels in the chunk were edited
|
|
||||||
ds (Data Stream): Contains the color values for those edited voxels
|
|
||||||
Each snapshot represents a single edit operation affecting one 8×8×8 chunk. The format builds up complex models by combining multiple snapshots, each modifying different chunks or the same chunks at different times.
|
|
||||||
Later snapshots override earlier ones when they modify the same voxel positions, allowing for an edit history that reflects the model's evolution.
|
|
||||||
|
|
||||||
## chunk ID
|
|
||||||
|
|
||||||
The cid (Chunk ID) has a range of 0-255 to match the addressing capacity of the lc table.
|
|
||||||
This means:
|
|
||||||
- Each snapshot can identify one specific chunk via its cid
|
|
||||||
- Can reference up to 256 unique chunks across all snapshots
|
|
||||||
- This 0-255 range aligns with the Morton encoding scheme for chunk coordinates and provides a clean 8-bit identifier for each chunk.
|
|
||||||
|
|
||||||
|
|
||||||
## Morton encoding on the chunks
|
|
||||||
|
|
||||||
The chunk indices use Morton encoding (Z-order curve), just like the voxel positions within chunks.
|
|
||||||
To convert from a cid in range 0-255 to chunk coordinates in an 8×8×8 chunk volume:
|
|
||||||
Convert the index to binary (8 bits)
|
|
||||||
|
|
||||||
### Deinterleave the bits:
|
|
||||||
Extract bits 0, 3, 6 for the x coordinate
|
|
||||||
Extract bits 1, 4, 7 for the y coordinate
|
|
||||||
Extract bits 2, 5 for the z coordinate (note: z only needs 2 bits for 0-3 range)
|
|
||||||
For example, to convert chunk ID 73 to 3D chunk coordinates:
|
|
||||||
73 in binary: 01001001
|
|
||||||
|
|
||||||
### Deinterleaving:
|
|
||||||
```
|
|
||||||
x = bits 0,3,6 = 101 = 5
|
|
||||||
y = bits 1,4,7 = 001 = 1
|
|
||||||
z = bits 2,5 = 00 = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
So chunk ID 73 corresponds to chunk position (5,1,0).
|
|
||||||
The Morton encoding ensures that spatially close chunks are also close in memory.
|
|
||||||
36
makefile
36
makefile
@ -10,10 +10,14 @@ ifeq ($(UNAME), Darwin)
|
|||||||
LZFSELIBNAME = liblzfse.dylib
|
LZFSELIBNAME = liblzfse.dylib
|
||||||
INCLUDEDIRS = -I$(SDKBASE)/src
|
INCLUDEDIRS = -I$(SDKBASE)/src
|
||||||
INCLUDEDIRS2 = -I../lzfse/src
|
INCLUDEDIRS2 = -I../lzfse/src
|
||||||
|
INCLUDEDIRS3 = -I../PlistCpp/include
|
||||||
|
INCLUDEDIRS4 = -I../PlistCpp/src
|
||||||
LIBDIR = $(SDKBASE)/lib
|
LIBDIR = $(SDKBASE)/lib
|
||||||
LIBDIRS = -L$(LIBDIR)
|
LIBDIRS = -L$(LIBDIR)
|
||||||
LZFSEBUILDDIR = ../lzfse/build
|
LZFSEBUILDDIR = ../lzfse/build
|
||||||
LZFSELIBDIR = -L$(LZFSEBUILDDIR)
|
LZFSELIBDIR = -L$(LZFSEBUILDDIR)
|
||||||
|
PLISTDIR = ../PlistCpp/build
|
||||||
|
PLISTLIBDIR = -L$(PLISTDIR)
|
||||||
OBJDIR = obj/$(UNAME)
|
OBJDIR = obj/$(UNAME)
|
||||||
BINDIR = bin/$(UNAME)
|
BINDIR = bin/$(UNAME)
|
||||||
OUTPUT = $(BINDIR)/$(OUTNAME)
|
OUTPUT = $(BINDIR)/$(OUTNAME)
|
||||||
@ -30,13 +34,16 @@ ifeq ($(UNAME), Darwin)
|
|||||||
-fvisibility=hidden\
|
-fvisibility=hidden\
|
||||||
-O3\
|
-O3\
|
||||||
$(INCLUDEDIRS)\
|
$(INCLUDEDIRS)\
|
||||||
$(INCLUDEDIRS2)
|
$(INCLUDEDIRS2)\
|
||||||
|
$(INCLUDEDIRS3)\
|
||||||
|
$(INCLUDEDIRS4)
|
||||||
|
|
||||||
CFLAGS = $(CCFLAGS)\
|
CFLAGS = $(CCFLAGS)\
|
||||||
-std=c17
|
-std=c17
|
||||||
|
|
||||||
CXXFLAGS = $(CCFLAGS)\
|
CXXFLAGS = $(CCFLAGS)\
|
||||||
-std=c++17
|
-std=c++17\
|
||||||
|
-Wno-deprecated-declarations
|
||||||
|
|
||||||
CPPDEFINES = -DNDEBUG=1\
|
CPPDEFINES = -DNDEBUG=1\
|
||||||
-DDL_USE_SHARED
|
-DDL_USE_SHARED
|
||||||
@ -44,7 +51,8 @@ ifeq ($(UNAME), Darwin)
|
|||||||
LIBS = -l$(SDKNAME)\
|
LIBS = -l$(SDKNAME)\
|
||||||
-lm\
|
-lm\
|
||||||
-ldl\
|
-ldl\
|
||||||
-llzfse
|
-llzfse\
|
||||||
|
$(PLISTDIR)/libplist.a
|
||||||
|
|
||||||
LINKFLAGS = -mmacosx-version-min=11.0\
|
LINKFLAGS = -mmacosx-version-min=11.0\
|
||||||
-isysroot $(ISYSROOT)\
|
-isysroot $(ISYSROOT)\
|
||||||
@ -61,8 +69,14 @@ else
|
|||||||
SDKFNAME2 = liblzfse.so
|
SDKFNAME2 = liblzfse.so
|
||||||
INCLUDEDIRS = -I$(SDKBASE)/src
|
INCLUDEDIRS = -I$(SDKBASE)/src
|
||||||
INCLUDEDIRS2 = -I../lzfse/src
|
INCLUDEDIRS2 = -I../lzfse/src
|
||||||
|
INCLUDEDIRS3 = -I../PlistCpp/include
|
||||||
|
INCLUDEDIRS4 = -I../PlistCpp/src
|
||||||
LIBDIR = $(SDKBASE)/lib
|
LIBDIR = $(SDKBASE)/lib
|
||||||
LIBDIRS = -L$(LIBDIR)
|
LIBDIRS = -L$(LIBDIR)
|
||||||
|
LZFSEBUILDDIR = ../lzfse/build
|
||||||
|
LZFSELIBDIR = -L$(LZFSEBUILDDIR)
|
||||||
|
PLISTDIR = ../PlistCpp/build
|
||||||
|
PLISTLIBDIR = -L$(PLISTDIR)
|
||||||
OBJDIR = obj/$(UNAME)
|
OBJDIR = obj/$(UNAME)
|
||||||
BINDIR = bin/$(UNAME)
|
BINDIR = bin/$(UNAME)
|
||||||
OUTPUT = $(BINDIR)/$(OUTNAME)
|
OUTPUT = $(BINDIR)/$(OUTNAME)
|
||||||
@ -76,7 +90,9 @@ else
|
|||||||
-D_FILE_OFFSET_BITS=64\
|
-D_FILE_OFFSET_BITS=64\
|
||||||
-O3\
|
-O3\
|
||||||
$(INCLUDEDIRS)\
|
$(INCLUDEDIRS)\
|
||||||
$(INCLUDEDIRS2)
|
$(INCLUDEDIRS2)\
|
||||||
|
$(INCLUDEDIRS3)\
|
||||||
|
$(INCLUDEDIRS4)
|
||||||
|
|
||||||
|
|
||||||
CFLAGS = $(CCFLAGS)\
|
CFLAGS = $(CCFLAGS)\
|
||||||
@ -93,7 +109,8 @@ else
|
|||||||
-ldl\
|
-ldl\
|
||||||
-lrt\
|
-lrt\
|
||||||
-lpthread\
|
-lpthread\
|
||||||
-llzfse
|
-llzfse\
|
||||||
|
$(PLISTDIR)/libplist.a
|
||||||
|
|
||||||
LINKFLAGS = -m64\
|
LINKFLAGS = -m64\
|
||||||
-fvisibility=hidden\
|
-fvisibility=hidden\
|
||||||
@ -102,16 +119,19 @@ else
|
|||||||
-Wl,-rpath,'$$ORIGIN/lib'
|
-Wl,-rpath,'$$ORIGIN/lib'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
OBJS = vmax2bella.o
|
OBJS = vmax2bella.o
|
||||||
OBJ = $(patsubst %,$(OBJDIR)/%,$(OBJS))
|
OBJ = $(patsubst %,$(OBJDIR)/%,$(OBJS))
|
||||||
|
|
||||||
|
# Define the path to the precompiled pugixml.o
|
||||||
|
PUGIXML_OBJ = pugixml/bin/$(UNAME)/pugixml.o
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.cpp
|
$(OBJDIR)/%.o: %.cpp
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CXX) -c -o $@ $< $(CXXFLAGS) $(CPPDEFINES)
|
$(CXX) -c -o $@ $< $(CXXFLAGS) $(CPPDEFINES)
|
||||||
|
|
||||||
$(OUTPUT): $(OBJ)
|
$(OUTPUT): $(OBJ) $(PUGIXML_OBJ)
|
||||||
@mkdir -p $(@D)
|
@mkdir -p $(@D)
|
||||||
$(CXX) -o $@ $^ $(LINKFLAGS) $(LIBDIRS) $(LZFSELIBDIR) $(LIBS)
|
$(CXX) -o $@ $(OBJ) $(PUGIXML_OBJ) $(LINKFLAGS) $(LIBDIRS) $(LZFSELIBDIR) $(LIBS)
|
||||||
@cp $(LIBDIR)/$(SDKFNAME) $(BINDIR)/$(SDKFNAME)
|
@cp $(LIBDIR)/$(SDKFNAME) $(BINDIR)/$(SDKFNAME)
|
||||||
@cp $(LZFSEBUILDDIR)/$(LZFSELIBNAME) $(BINDIR)/$(LZFSELIBNAME)
|
@cp $(LZFSEBUILDDIR)/$(LZFSELIBNAME) $(BINDIR)/$(LZFSELIBNAME)
|
||||||
|
|
||||||
|
|||||||
2185
vmax2bella.cpp
2185
vmax2bella.cpp
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user