@@ -17,20 +17,19 @@ public class PCROOT : IWriter
17
17
BufferedStream bsPoints = null ;
18
18
BinaryWriter writerPoints = null ;
19
19
20
- static List < PointCloudTile > nodeBounds = new List < PointCloudTile > ( ) ;
20
+ static List < PointCloudTile > nodeBounds = new List < PointCloudTile > ( ) ; // for all tiles
21
21
22
22
// our nodes (=tiles, =grid cells), string is tileID and float are X,Y,Z,R,G,B values
23
- Dictionary < string , List < float > > nodeX = new Dictionary < string , List < float > > ( ) ;
24
- Dictionary < string , List < float > > nodeY = new Dictionary < string , List < float > > ( ) ;
25
- Dictionary < string , List < float > > nodeZ = new Dictionary < string , List < float > > ( ) ;
23
+ Dictionary < int , List < float > > nodeX = new Dictionary < int , List < float > > ( ) ;
24
+ Dictionary < int , List < float > > nodeY = new Dictionary < int , List < float > > ( ) ;
25
+ Dictionary < int , List < float > > nodeZ = new Dictionary < int , List < float > > ( ) ;
26
26
27
- Dictionary < string , List < float > > nodeR = new Dictionary < string , List < float > > ( ) ;
28
- Dictionary < string , List < float > > nodeG = new Dictionary < string , List < float > > ( ) ;
29
- Dictionary < string , List < float > > nodeB = new Dictionary < string , List < float > > ( ) ;
30
-
31
- Dictionary < string , List < float > > nodeIntensity = new Dictionary < string , List < float > > ( ) ;
32
- Dictionary < string , List < double > > nodeTime = new Dictionary < string , List < double > > ( ) ;
27
+ Dictionary < int , List < float > > nodeR = new Dictionary < int , List < float > > ( ) ;
28
+ Dictionary < int , List < float > > nodeG = new Dictionary < int , List < float > > ( ) ;
29
+ Dictionary < int , List < float > > nodeB = new Dictionary < int , List < float > > ( ) ;
33
30
31
+ Dictionary < int , List < float > > nodeIntensity = new Dictionary < int , List < float > > ( ) ;
32
+ Dictionary < int , List < double > > nodeTime = new Dictionary < int , List < double > > ( ) ;
34
33
35
34
static float cloudMinX = float . PositiveInfinity ;
36
35
static float cloudMinY = float . PositiveInfinity ;
@@ -90,24 +89,69 @@ void IWriter.Randomize()
90
89
91
90
}
92
91
92
+ int Hash ( int x , int y , int z )
93
+ {
94
+ unchecked
95
+ {
96
+ // Apply offset to ensure all values are positive
97
+ x += OFFSET ;
98
+ y += OFFSET ;
99
+ z += OFFSET ;
100
+
101
+ // Combine the values into a single hash using a method that can handle larger ranges
102
+ long combined = ( ( long ) x << 40 ) | ( ( long ) y << 20 ) | ( long ) z ;
103
+ return combined . GetHashCode ( ) ;
104
+ }
105
+ }
106
+
107
+ const int OFFSET = 12345678 ;
108
+
109
+ ( int x , int y , int z ) Unhash ( int hash )
110
+ {
111
+ // Restore the original x, y, z values
112
+ long combined = hash ;
113
+
114
+ int z = ( int ) ( combined & ( ( 1L << 20 ) - 1 ) ) ;
115
+ combined >>= 20 ;
116
+ int y = ( int ) ( combined & ( ( 1L << 20 ) - 1 ) ) ;
117
+ combined >>= 20 ;
118
+ int x = ( int ) combined ;
119
+
120
+ // Remove the offset to get original values
121
+ x -= OFFSET ;
122
+ y -= OFFSET ;
123
+ z -= OFFSET ;
124
+
125
+ return ( x , y , z ) ;
126
+ }
127
+
93
128
void IWriter . AddPoint ( int index , float x , float y , float z , float r , float g , float b , bool hasIntensity , float i , bool hasTime , double time )
94
129
{
95
130
// get global all clouds bounds
96
- if ( x < cloudMinX ) cloudMinX = x ;
97
- if ( x > cloudMaxX ) cloudMaxX = x ;
98
- if ( y < cloudMinY ) cloudMinY = y ;
99
- if ( y > cloudMaxY ) cloudMaxY = y ;
100
- if ( z < cloudMinZ ) cloudMinZ = z ;
101
- if ( z > cloudMaxZ ) cloudMaxZ = z ;
131
+ //if (x < cloudMinX) cloudMinX = x;
132
+ //if (x > cloudMaxX) cloudMaxX = x;
133
+ //if (y < cloudMinY) cloudMinY = y;
134
+ //if (y > cloudMaxY) cloudMaxY = y;
135
+ //if (z < cloudMinZ) cloudMinZ = z;
136
+ //if (z > cloudMaxZ) cloudMaxZ = z;
137
+ cloudMinX = Math . Min ( cloudMinX , x ) ;
138
+ cloudMaxX = Math . Max ( cloudMaxX , x ) ;
139
+ cloudMinY = Math . Min ( cloudMinY , y ) ;
140
+ cloudMaxY = Math . Max ( cloudMaxY , y ) ;
141
+ cloudMinZ = Math . Min ( cloudMinZ , z ) ;
142
+ cloudMaxZ = Math . Max ( cloudMaxZ , z ) ;
143
+
144
+ float gridSize = importSettings . gridSize ;
102
145
103
146
// add to correct cell, MOVE to writer
104
147
// TODO handle bytepacked gridsize here
105
- int cellX = ( int ) ( x / importSettings . gridSize ) ;
106
- int cellY = ( int ) ( y / importSettings . gridSize ) ;
107
- int cellZ = ( int ) ( z / importSettings . gridSize ) ;
148
+ int cellX = ( int ) ( x / gridSize ) ;
149
+ int cellY = ( int ) ( y / gridSize ) ;
150
+ int cellZ = ( int ) ( z / gridSize ) ;
108
151
109
- // collect point to its cell node
110
- string key = cellX + "_" + cellY + "_" + cellZ ;
152
+ // collect point to its cell node, TODO optimize this is ~23% of total time?
153
+ //string key = cellX + "_" + cellY + "_" + cellZ;
154
+ int key = Hash ( cellX , cellY , cellZ ) ;
111
155
112
156
if ( nodeX . ContainsKey ( key ) )
113
157
{
@@ -125,29 +169,21 @@ void IWriter.AddPoint(int index, float x, float y, float z, float r, float g, fl
125
169
else // create new list for this key
126
170
{
127
171
// NOTE if memory error here, use smaller gridsize (single array maxsize is ~2gb)
128
- nodeX [ key ] = new List < float > ( ) ;
129
- nodeX [ key ] . Add ( x ) ;
130
- nodeY [ key ] = new List < float > ( ) ;
131
- nodeY [ key ] . Add ( y ) ;
132
- nodeZ [ key ] = new List < float > ( ) ;
133
- nodeZ [ key ] . Add ( z ) ;
134
- nodeR [ key ] = new List < float > ( ) ;
135
- nodeR [ key ] . Add ( r ) ;
136
- nodeG [ key ] = new List < float > ( ) ;
137
- nodeG [ key ] . Add ( g ) ;
138
- nodeB [ key ] = new List < float > ( ) ;
139
- nodeB [ key ] . Add ( b ) ;
172
+ nodeX [ key ] = new List < float > { x } ;
173
+ nodeY [ key ] = new List < float > { y } ;
174
+ nodeZ [ key ] = new List < float > { z } ;
175
+ nodeR [ key ] = new List < float > { r } ;
176
+ nodeG [ key ] = new List < float > { g } ;
177
+ nodeB [ key ] = new List < float > { b } ;
140
178
141
179
if ( hasIntensity == true )
142
180
{
143
- nodeIntensity [ key ] = new List < float > ( ) ;
144
- nodeIntensity [ key ] . Add ( i ) ;
181
+ nodeIntensity [ key ] = new List < float > { i } ;
145
182
}
146
183
147
184
if ( hasTime == true )
148
185
{
149
- nodeTime [ key ] = new List < double > ( ) ;
150
- nodeTime [ key ] . Add ( time ) ;
186
+ nodeTime [ key ] = new List < double > { time } ;
151
187
}
152
188
}
153
189
}
@@ -196,7 +232,7 @@ void IWriter.Save(int fileIndex)
196
232
List < double > nodeTempTime = null ;
197
233
198
234
// process all tiles
199
- foreach ( KeyValuePair < string , List < float > > nodeData in nodeX )
235
+ foreach ( KeyValuePair < int , List < float > > nodeData in nodeX )
200
236
{
201
237
if ( nodeData . Value . Count < importSettings . minimumPointCount )
202
238
{
@@ -206,7 +242,8 @@ void IWriter.Save(int fileIndex)
206
242
207
243
nodeTempX = nodeData . Value ;
208
244
209
- string key = nodeData . Key ;
245
+ //string key = nodeData.Key;
246
+ int key = nodeData . Key ;
210
247
211
248
nodeTempY = nodeY [ key ] ;
212
249
nodeTempZ = nodeZ [ key ] ;
@@ -323,12 +360,16 @@ void IWriter.Save(int fileIndex)
323
360
if ( importSettings . packColors == true )
324
361
{
325
362
// get local coords within tile
326
- var keys = nodeData . Key . Split ( '_' ) ;
363
+ //var keys = nodeData.Key.Split('_');
364
+ ( int restoredX , int restoredY , int restoredZ ) = Unhash ( nodeData . Key ) ;
365
+ cellX = restoredX ;
366
+ cellY = restoredY ;
367
+ cellZ = restoredZ ;
327
368
328
369
// TODO no need to parse, we should know these values?
329
- cellX = int . Parse ( keys [ 0 ] ) ;
330
- cellY = int . Parse ( keys [ 1 ] ) ;
331
- cellZ = int . Parse ( keys [ 2 ] ) ;
370
+ // cellX = int.Parse(keys[0]);
371
+ // cellY = int.Parse(keys[1]);
372
+ // cellZ = int.Parse(keys[2]);
332
373
// offset to local coords (within tile)
333
374
px -= ( cellX * importSettings . gridSize ) ;
334
375
py -= ( cellY * importSettings . gridSize ) ;
@@ -370,13 +411,17 @@ void IWriter.Save(int fileIndex)
370
411
else if ( useLossyFiltering == true ) // test lossy, not regular packed
371
412
{
372
413
// get local coords within tile
373
- var keys = nodeData . Key . Split ( '_' ) ;
414
+ // var keys = nodeData.Key.Split('_');
374
415
// TODO no need to parse, we should know these values? these are world cell grid coors
375
416
// TODO take reserved grid cells earlier, when reading points! not here on 2nd pass..
376
- cellX = int . Parse ( keys [ 0 ] ) ;
377
- cellY = int . Parse ( keys [ 1 ] ) ;
378
- cellZ = int . Parse ( keys [ 2 ] ) ;
417
+ // cellX = int.Parse(keys[0]);
418
+ // cellY = int.Parse(keys[1]);
419
+ // cellZ = int.Parse(keys[2]);
379
420
// offset point inside local tile
421
+ ( int restoredX , int restoredY , int restoredZ ) = Unhash ( nodeData . Key ) ;
422
+ cellX = restoredX ;
423
+ cellY = restoredY ;
424
+ cellZ = restoredZ ;
380
425
px -= ( cellX * fixedGridSize ) ;
381
426
py -= ( cellY * fixedGridSize ) ;
382
427
pz -= ( cellZ * fixedGridSize ) ;
0 commit comments