@@ -1319,17 +1319,44 @@ public boolean render(MapChunkCache cache, HDMapTile tile, String mapname) {
13191319
13201320 final int tilePixelSize = tileSize * sizescale ;
13211321 final double invSizescale = 1.0 / sizescale ;
1322+
1323+ /* Precompute ray direction — constant for all pixels in this tile.
1324+ * direction = map_to_world * (0, 0, (miny-0.5) - (height+0.5)) */
1325+ ps .direction .x = 0.0 ; ps .direction .y = 0.0 ;
1326+ ps .direction .z = (miny - 0.5 ) - (height + 0.5 );
1327+ map_to_world .transform (ps .direction );
1328+
1329+ /* Decompose map_to_world into per-axis step vectors so we can compute
1330+ * ps.top incrementally (3 muls + 9 adds/pixel) rather than doing two
1331+ * full 3x3 matrix transforms (18 muls + 12 adds) + a subtract/pixel. */
1332+ /* xstep = map_to_world * (1,0,0) — how top shifts per unit of px (map-x) */
1333+ Vector3D xstep = new Vector3D (1.0 , 0.0 , 0.0 );
1334+ map_to_world .transform (xstep );
1335+ /* ystep = map_to_world * (0,1,0) — how top shifts per unit of py (map-y) */
1336+ Vector3D ystep = new Vector3D (0.0 , 1.0 , 0.0 );
1337+ map_to_world .transform (ystep );
1338+ /* zbase = map_to_world * (0,0,height+0.5) — constant z contribution */
1339+ Vector3D zbase = new Vector3D (0.0 , 0.0 , height + 0.5 );
1340+ map_to_world .transform (zbase );
1341+
13221342 for (int x = 0 ; x < tilePixelSize ; x ++) {
13231343 ps .px = x ;
13241344 final double px_center = xbase + (x + 0.5 ) * invSizescale ;
1345+ /* Column-constant portion: zbase + xstep * px_center */
1346+ final double colx = zbase .x + xstep .x * px_center ;
1347+ final double coly = zbase .y + xstep .y * px_center ;
1348+ final double colz = zbase .z + xstep .z * px_center ;
1349+ double py_center = ybase + 0.5 * invSizescale ;
13251350 for (int y = 0 ; y < tilePixelSize ; y ++) {
1326- ps .top .x = ps .bottom .x = px_center ;
1327- ps .top .y = ps .bottom .y = ybase + (y + 0.5 ) * invSizescale ;
1328- ps .top .z = height + 0.5 ; ps .bottom .z = miny - 0.5 ;
1329- map_to_world .transform (ps .top ); /* Transform to world coordinates */
1330- map_to_world .transform (ps .bottom );
1331- ps .direction .set (ps .bottom );
1332- ps .direction .subtract (ps .top );
1351+ /* top = column-contribution + ystep * py_center */
1352+ ps .top .x = colx + ystep .x * py_center ;
1353+ ps .top .y = coly + ystep .y * py_center ;
1354+ ps .top .z = colz + ystep .z * py_center ;
1355+ /* bottom = top + direction (avoids second matrix transform) */
1356+ ps .bottom .x = ps .top .x + ps .direction .x ;
1357+ ps .bottom .y = ps .top .y + ps .direction .y ;
1358+ ps .bottom .z = ps .top .z + ps .direction .z ;
1359+ py_center += invSizescale ;
13331360 ps .py = y / sizescale ;
13341361 for (int i = 0 ; i < numshaders ; i ++) {
13351362 shaderstate [i ].reset (ps );
0 commit comments