Procedural Terrain Reconstruction, Part II: Rebuilding POI, Stamp, Vegetation, and Rock Layouts Using the Original Algorithms

Part I, Rebuilding the Heightmap at Its Original Scale covered region heights, rasterization, and filtering. This article describes POI and Stamp placement, Location support, and the expansion and grounding of vegetation and rock assets. It then examines block-based Scatter and its zone, density, and material filters.

By September 21, we could independently generate 1,253 parent instances using the ordinary grid-based Stamp branch that runs for this fixed tundra request. Location support, natural Stamp drawing, Location height textures, and this branch’s Vista blend are also connected. Within the central 2048² region covered by the actual capture, the maximum error in floating-point height before encoding is about 0.803 mm, with an RMS of 0.0186 mm. Those heights aren’t bitwise identical. The comparison conditions also differ from Part I’s older R16 test, so we’ll keep the two results separate in the final section.

[D] marks configuration or rule evidence, [R] implementation and comparison results, and [E] teaching examples. Captions distinguish actual layouts from diagrams. The vegetation and rock validation dates to September 16, 2026; the block-based Scatter replay to September 17; and the height chain to September 21. These batches used different inputs; we haven’t yet run them together as one end-to-end test.

From configuration to instance layout

Instance layouts result from candidate generation, resource selection, collision retries, and acceptance checks. The drawing program then uses those layouts to generate terrain. Validation compares the resources, coordinates, and orientations of all 1,253 instances as well as their total count.

Location support needs updating whenever base height changes. That means querying helper heights and expansion envelopes again, then rebuilding the drawing parameters. An old target can still produce a flat patch, even if the support calculation never reads the new ground.

Validation covers placement records, support queries, drawing parameters, and final height output. Part I’s interpolation, filtering, and encoding still apply; this article describes the data passed between those stages.

Two placement paths: resource composition and block-based Scatter. The left shows independently generated vegetation and rock markers; the right replays captured query maps. These are not two sides of the same validation experiment.

Figure 1: Two placement paths: resource composition and block-based Scatter. The left shows independently generated vegetation and rock markers; the right replays captured query maps. These are not two sides of the same validation experiment.

POI selection and spatial layout

Here, POI covers mission sites, outposts, and exploration sites that a player can visit. The program records them as Locations, but one Location does not necessarily mean one mission. A main site can have satellite sites, and each site can expand into several support shapes and resource children.

[R] The September 20 follow-up tests independently generated all 54 Locations for this request, including 23 satellites, from the original request and complete static configuration. Generation does not read reference positions, orientations, or selected-resource lists. The reference instance records are used only after output for comparison. Site layout supplies later region, height, and collision queries, so site generation precedes Stamp placement in this explanation.

Mission tags and category filtering

The request contains six mission-tag slots: [128,128,104,99,99,96]. Duplicates matter: the same mission type can appear twice. Part I traced the internal resource names to shutting down a grinder (128), extracting organic soup (104), destroying a detector tower (99), and destroying communication facilities (96). These descriptions follow resource names; they are not claimed as official localized names.

For each slot, the program follows static task associations in resource, group, and member order. Disabled flags, tag associations, and environment conditions also filter the pool. This step consumes no random numbers and has not selected a site yet.

Tag slots Tags Initial candidates Candidates in later effective weight tables
1, 2 128, 128 8 each 4 each
3 104 2 2
4, 5 99, 99 11 each 5 each
6 96 1 1

The initial pools contain 41 candidate references, not 41 unique resources or final sites. The last column also reflects later conditions and usage checks, so category filtering alone does not explain the reduction.

The request’s categories=[1,2,6] is a separate condition. A nonempty candidate allow-list must intersect it; an empty list passes this check. [E] [2,5] passes, [4,5] fails, and an empty list passes. We do not yet have reliable names that identify 1, 2, and 6 as main missions, side missions, or outposts, so we retain the numbers. The mission-tag array is also separate from a 64-bit tag-condition field. That field is zero here; the six mission tags still affect selection.

Slot categories, draw weights, and usage limits

The program collects allowed categories for each slot, then assigns target categories according to configured quotas. All six slots allow category 1 in this request. Assignment produces [1,0,0,0,0,0]: zero means no additional category restriction, not selection of a category called zero. Request categories, slot targets, and a candidate’s selected category belong to different steps.

Only then does the program build a draw table. Disabled candidates and candidates at their usage limit are skipped. A nonzero slot target adds a category check. Usage is tracked by resource, group, and member identifiers; different candidates sharing a resource must not be merged. Accepted selections enter the implementation’s own history and affect subsequent draws.

The draw accumulates weights in their original order and locates a random value in that total. A selected entry temporarily receives zero current weight. When the remaining total falls below the threshold, current weights reset to their originals. This is not permanent sampling without replacement; configured usage caps still need separate checks. Failed attempts do not roll back consumed random numbers.

Repeated mission slots remain separate; filtering, quotas, draws, and placement history have different roles.

Figure 2: Repeated mission slots remain separate; filtering, quotas, draws, and placement history have different roles.

Candidate position search and clearance checks

The proposal’s initial XY is not its final position. A search-point pool supplies further positions for spatial and clearance checks. This request uses a 16 m minimum spacing. Candidates are generated around an active point; those passing bounds and neighbor checks are added. After 30 unsuccessful attempts, that active point is removed. A grid with cell width 16/√2 m accelerates neighbor lookup; it does not fix site coordinates to grid centers.

This search generates 4,575 points, with 1,168 remaining after circular filtering. Those are search opportunities, not 1,168 POIs. Generation order, later sorting, and attempt order must also remain distinct.

Each placement attempt computes orientation, checks regional boundary conditions, then compares support clearance with existing sites in the required order. If required clearance exceeds actual distance, it tries another position. An accepted site becomes an obstacle for later searches. The first batch of 11 sites takes 947 attempts; coordinates, orientations, decisions, and random states have been compared. That count belongs to this batch, not to Stamp’s four-attempt local retry rule.

Exploration and outpost stages extend the layout: it first reaches 22 sites, adds five more outposts to reach 27, then accepts four optional exploration sites for a total of 31. Optional exploration reuses an earlier initialized quota state while maintaining its own spatial sampling state. Reinitializing the shared state changed this request’s result by adding an extra site; the corrected implementation preserves both streams.

Radial placement of satellite sites

Satellites come from static candidate groups bound to the parent resource. This request produces 17 effective tables containing 186 ordered candidate references. A candidate may appear in more than one parent’s table. Each parent gets at most 256 attempts and stops when its configured count is reached. The 256-attempt limit is per parent, not per map.

An attempt draws a resource by weight, then consumes gap, category, and bearing random values in order. With parent center P, parent and child support radii Rp and Rc, sampled gap g, and bearing unit vector d, the geometry can be written as:

Q = P + Rp × d + (Rc + g) × d

[E] A parent at (100,100) with radius 20 m, a child radius of 8 m, a 12 m gap, and a positive-X bearing gives (140,100). These are teaching circles, not measured site dimensions. The implementation retains the two additions and original direction calculation rather than rearranging floating-point operations.

The candidate first checks clearance against existing sites. That query also rotates the resource bounding circle’s local offset. The parent and child circles in the diagram explain the radial proposal; they do not replace the actual bounding circles. A parent–child reduction factor adjusts the required clearance, rather than subtracting a fixed number of meters.

The map check must leave room for the whole child. With map center C, half-span H, range fraction f, child radius Rc, and inset factor k, this branch requires:

distance(Q, C) + Rc ≤ H × f − Rc × k

Checking only Q would allow part of the child outside the boundary. After clearance and map checks, the resource mode determines final orientation. This request exercises a fresh random orientation and a correction based on a static entrance direction. The program then checks parent–child support, writes the accepted record, and updates ownership and counts. A candidate reaching its instance cap is removed by replacing it with the last table entry. That order change affects later draws too.

The radial proposal uses teaching circles; rejection and acceptance counts come from this request.

Figure 3: The radial proposal uses teaching circles; rejection and acceptance counts come from this request.

[R] The satellite loop makes 2,976 attempts: 1,685 clearance rejections, 1,268 map-boundary rejections, and 23 acceptances. Parents need not fill their configured quotas. Those 23 satellites join the previous 31 sites to make 54. All non-address record fields match the reference instance records; parent–child links and counts are verified separately. Later regional association and orientation processing can still update state, so proposal bearings must not all be treated as final orientations.

The interface between site layout and height generation

Selection and placement provide resource identifiers, XY, orientation, parent–child relationships, and support configuration. Base height later feeds support queries to calculate helper heights, targets, and expansion bounds. Those values are not building-final Z. The following support section explains this step and retains the 54-site layout comparison.

These tests cover the branches executed by this fixed request. The independent implementation preloads static tables; it does not validate the asynchronous loading lifecycle. Other seeds and biomes, inactive regional restrictions, rectangular overlap, and positive-penetration handling need separate checks. Validating 54-site generation also does not combine it, the latest height chain, vegetation, rocks, and runtime Scatter into one end-to-end test.

Stamp candidate generation and filtering

[R] By September 21, 2026, the complete selection and placement loop for ordinary grid candidates had been ported to C++. Starting from the request, static configuration, and independently generated regions, Locations, paths, and height geometry, this case produces 1,253 natural Stamp parent instances. The reference acceptance trace is used only for comparison after generation. It supplies no candidate positions, random states, or acceptance list to the loop.

Failed attempts are part of that loop. It visits root regions, groups, and members in order. At the start of each root region, it sets the corresponding scheduling random state; groups and members within that root continue from the same state. After the member’s range and count conditions pass, the loop tests a probability check, advances the grid cursor, applies two XY jitters, queries corners and local conditions, and selects a resource by weight. The selected resource depends on both the configured pool and the position just generated.

After selection, the program checks whether the support bounds fit inside the map, samples the local terrain, and determines orientation from configuration. Collision checks involve three kinds of objects: this request’s Locations, internal path collision objects, and Stamps already accepted under the same root. Where allowed, the candidate is moved and tried again. This branch allows at most four attempts, including the first.

After collision passes, the program still checks map bounds, region acceptance, distance from the mission circle, clearing segments, and corner occupancy. If all pass, it writes the acceptance record and adds the shape to the root’s accepted list. Later candidates encounter that new obstacle. A candidate that exhausts its attempts is discarded, and the loop continues.

The ordinary grid-candidate branch. The diagram groups position generation and resource selection into one step. Execution still generates XY and queries corners before weighted resource selection and orientation. Retry and post-acceptance feedback remain separate.

Figure 4: The ordinary grid-candidate branch. The diagram groups position generation and resource selection into one step. Execution still generates XY and queries corners before weighted resource selection and orientation. Retry and post-acceptance feedback remain separate.

We compared resource keys and order, float32 bit patterns for XY and orientation, and the random states before the probability check and after rotation for all 1,253 accepted candidates. Every one matched the reference. We also compared the complete acceptance records. For cross-process comparison, only two address slots and one completion flag sampled at different times were normalized; height, bounds, corner, and region fields were retained.

All group flags were zero across this request’s 3,672 structural member visits. Edge-based generation and special member occupancy didn’t run in this case. The independent interface reports an error if an unconnected branch becomes active. The 1,253 matching instances therefore validate the ordinary grid loop that ran here.

The grid supplies positions; positions change resource weights

[D][R] The first step in Figure 4 contains three calculations: the probability check, a jittered grid position, and position-dependent resource selection. Each advances the random state and must run in order.

The probability check draws a random value and compares it with the current group’s probability parameter. Failure advances the candidate index and returns to the loop. A passing candidate proceeds to grid placement. Grid counts come from member bounds and group spacing: floor the width divided by spacing, add one where required by the configured mode, and keep the count at least one. One axis convention is easy to reverse: the integer quotient row = index / countX advances X, while the remainder col advances Y. Swapping them changes the candidate positions.

For spacing s, jitter width j, base grid coordinate G, and random values ux, uy, the candidate is:

X = Gx + (ux × j − j / 2)
Y = Gy + (uy × j − j / 2)

The grid is centered on the member. An axis with an even grid count receives a half-spacing adjustment so its points sit around that center. [E] With four points on each axis, 20 m spacing, and center (100,100), the first base point is (70,70). A jitter width of 8 m and ux=0.75, uy=0.25 produce (72,68). In this example, spacing controls grid density; jitter controls displacement from each grid point.

Slope, height, and distance outside the region are queried at this position before effective resource weights are calculated. Candidates also have category limits; an ineligible category gets zero weight. Eligible candidates start with their static weights and apply the enabled conditions. A four-parameter range (a,b,c,d) acts as follows:

Condition value v Effect on the current weight
v < a or v > d Set to zero
a ≤ v < b Multiply by (v−a)/(b−a), ramping from zero to full weight
b ≤ v ≤ c Keep the current weight
c < v ≤ d Multiply by 1−(v−c)/(d−c), ramping down to zero

Move the candidate from a hill’s foot to a slope or higher ground, and the same resource can get a different weight. Configuration flags decide which checks apply: slope, height, or outside distance.

[E] Suppose resource A has static weight 2 and height range (0,10,20,30). At 5 m, with only height attenuation enabled, its effective weight is 2 × 0.5 = 1. Resource B currently has weight 3, for a total of 4. A draw of u=0.6 gives 2.4. Subtracting A’s weight leaves 1.4; subtracting B’s weight makes the remainder nonpositive, so B is selected.

Before the random draw, the code checks that total weight exceeds “candidate count × 2⁻²³.” If it doesn’t, no resource is selected. The example uses convenient numbers; the implementation keeps the original accumulation order and random-state progression.

A teaching example of grid jitter and range-based weight. Resource A has static weight 2; at the candidate height of 5 m, its effective weight is 1.

Figure 5: A teaching example of grid jitter and range-based weight. Resource A has static weight 2; at the candidate height of 5 m, its effective weight is 1.

What a collision retry actually changes

Once a resource is selected, the program derives bounds from its static support shape, checks the map boundary, and queries local terrain. It then enters the loop of up to four attempts. Each attempt computes orientation according to the resource’s mode. The connected random-orientation mode consumes one random value to form an angle of about 2πu; the direction mode computes an angle from the supplied direction and continues to use that direction on retries.

A collision query returns contact depth, a correction amount, and a direction. Depth decides whether the collision passes: nonpositive passes, positive fails. If it fails and the group flag allows correction, the position changes as follows:

P_next = P_current − correction × normal

correction is the amount returned by the query; it is a separate quantity from contact depth. If position correction is disabled, the candidate remains where it is but still proceeds to another attempt. That attempt keeps the selected resource and recomputes orientation and collision at the current position.

[E] Suppose a candidate at (72,68) receives positive depth, correction 2 m, and direction (1,0), with correction enabled. The next attempt starts at (70,68). Even if collision passes on the second attempt, region, mission-circle, clearing-segment, and corner-occupancy checks still follow. Failure there also returns to the attempt loop. Only a fully accepted shape enters the root’s accepted list.

The next attempt picks up where the previous one stopped. It keeps the resource and terrain data already queried, then updates position, orientation, and checks within the attempt loop. Starting over at the grid, choosing another resource, or re-querying terrain each time would change the candidate record and random sequence.

Collision retry mechanics, using illustrative obstacle shapes and coordinates. The returned correction amount must not be replaced with contact depth without checking the query's meaning.

Figure 6: Collision retry mechanics, using illustrative obstacle shapes and coordinates. The returned correction amount must not be replaced with contact depth without checking the query’s meaning.

Why failed paths and execution order matter

A seed reproduces instances only with the same candidate set, visit order, and random-number consumption. A failed collision may add no visible terrain while still advancing the random state. Removing that attempt, or resetting the state on every retry, changes later selections.

An accepted candidate immediately becomes an obstacle for later candidates under the same root. Generating all positions first and removing overlaps afterward changes which obstacles each candidate encounters. Attempt counts and random states can change with them.

That’s why we check random states alongside resource order, coordinates, and orientation. Some mistakes move the current candidate; others only show up farther down the list.

[E] Think of the root’s accepted list as an obstacle table that grows during the loop. Suppose A is accepted, then B intersects it. The active branch decides whether B can move and retry. If B is ultimately discarded, C sees only A in the accepted list. If B is accepted, C must check both A and B. This is a made-up sequence to show the dependency, not a recorded trace from this request.

Discarding B leaves the obstacle table unchanged, but the random state may already have advanced. The next selection continues from that state. Failed attempts therefore have to execute in their original order too.

The retry arrow in Figure 4 stays within checking. It continues with the selected resource. Selecting a new resource after every collision failure would change the shape and random consumption as well.

Location support from base height

The layout comparison below shows the same 54 Locations on both sides. Numbers identify each Location, arrows show local +X, and circles show configured extents. These positions tell support queries where to sample. The circles show neither building outlines nor target support heights.

Layout comparison for 54 Locations: independent generation on the left, Target Reference on the right. The screenshot shows XY, orientation, and configured circles. The September 21 support result in the footer comes from a same-input numerical comparison and is not depicted by this older screenshot.

Figure 7: Layout comparison for 54 Locations: independent generation on the left, Target Reference on the right. The screenshot shows XY, orientation, and configured circles. The September 21 support result in the footer comes from a same-input numerical comparison and is not depicted by this older screenshot.

After base height is complete, Location support adjusts the local ground. Natural Stamps then add terrain detail, followed by Location height textures for the internal shapes of each site. Support therefore reads the base terrain, before any natural height textures have been drawn.

[R] The September 21 implementation starts with the newly generated 4096² base height, rebuilds eight CPU query levels from 1024² down to 8², and recalculates Location support. It preserves the validated single-precision operation order and converts input row direction once. Old helper heights and expansion bounds are no longer inputs to this step.

For a circular query, first move the asset’s local circle into world space: rotate its center offset with the Location, then add the Location’s XY. The circle’s offset inside the asset matters just as much as the Location position. Next, place samples around the circumference, with the count based on perimeter.

Local circles can overlap. A circumference point inside another circle of the same asset is discarded; the retained points describe the union’s effective outer boundary. Circles belonging to other Locations do not participate in this rejection. At each retained point, the algorithm queries a height envelope with a 0.5 m radius, accumulates its lower and upper bounds separately, and computes a helper height:

L_mean = sum of lower envelope bounds / valid sample count
U_mean = sum of upper envelope bounds / valid sample count
H_helper = 0.625 × L_mean + 0.375 × U_mean

[D] The coefficients 0.625 and 0.375 belong to this circular branch. The implementation keeps the original float32 accumulation order as well. The formula summarizes those operations. The averaged quantities are lower and upper height-envelope bounds queried with a 0.5 m radius, rather than single-point heights around the asset boundary. Only when no valid boundary samples remain does the algorithm query at the instance center with zero radius and average the two bounds.

Circular support-query order. Circles and sample points illustrate the mechanism rather than a measured site outline. Green points enter envelope queries; orange points are rejected because they fall inside another circle.

Figure 8: Circular support-query order. Circles and sample points illustrate the mechanism rather than a measured site outline. Green points enter envelope queries; orange points are rejected because they fall inside another circle.

Helper height is followed by parent–child weighting, region overrides and offsets, satellite transitions, and regional lower limits. Expansion envelopes are queried again too. Helper height is an intermediate query result. The support target adjusts the ground; a building’s final Z is determined later during scene placement.

[R] For all 54 Locations, helper heights, valid-sample counts, rejection counts, and fallback states match the original function on the same new height input. Support is active for 53 Locations; index 28 is inactive. Those 53 targets and expansion results, the 84 support circles, and their drawing inputs also pass comparison. So the counts describe different things: 54 Locations, 53 active support targets, and 84 circles. This test covers circular topology; the rectangular helper path hasn’t passed it yet.

Two sampling layers: the asset boundary and the ground envelope

[D][R] There are two kinds of circle in Figure 8. The large circles define the asset’s support shape. Around each retained boundary point, a small 0.5 m query circle samples the nearby ground. Both sampling layers contribute to helper height.

The asset center first moves into world space. In conventional 2D rotation notation, C_world = P_location + R(θ) × C_local, with radius unchanged. Here θ has already been converted to the support coordinate convention. The current entry uses the recorded angle minus π/2; the recorded value cannot be used directly as a conventional +X rotation angle.

A resource circle of radius R gets max(1, floor(2πR + 0.5)) evenly spaced boundary samples, approximately one per meter of circumference. Each point is checked against the asset’s other circles. It is rejected only when squared distance is strictly less than the other radius squared. A point exactly on that boundary is retained by this test. The trigonometric notation below explains the geometry; implementation still preserves the original direction approximation and single-precision order.

Each retained boundary point Q receives an envelope query of radius r:

n = floor(r / 4 + 4)
Qi = Q + r × (cos(2πi/n), sin(2πi/n)), i = 0…n−1
L(Q) = min(h(Qi))
U(Q) = max(h(Qi))

Samples outside the query map’s UV range are skipped. For the helper query’s r=0.5 m, n is 4. The query reads interpolated heights in four directions; it does not search every pixel inside the small circle for exact extrema. “Envelope” here means the bounds obtained from those samples.

The query also selects a height level using r/n. Starting at level 0, it compares the span with thresholds of 4, 8, 16 m, and so on, moving to lower resolution as the span grows. With r=0.5, r/n=0.125, so it stays at level 0. This is the CPU pyramid’s 1024² map, not the original 4096² height or Vista mip 0.

World coordinates are mapped into this example’s 2048 m domain and then into pixel coordinates at the selected level. Four adjacent floating-point heights provide bilinear interpolation, with row direction handled according to the query-map convention. Changing level, using nearest-point sampling, or flipping Y twice changes the resulting bounds.

[E] Suppose four queries around one retained boundary point return 10,12,11,13 m. That point contributes lower bound 10 and upper bound 13. Another point returns 14,16,15,17 m and contributes 14 and 17. With only those two points, the lower mean is 12, the upper mean is 15, and helper height is 0.625×12 + 0.375×15 = 13.125 m. Averaging all eight samples directly gives 13.5 m—a different calculation.

The two layers of asset-boundary sampling and local height envelopes. The example produces helper height 13.125 m. Averaging all individual samples would give 13.5 m.

Figure 9: The two layers of asset-boundary sampling and local height envelopes. The example produces helper height 13.125 m. Averaging all individual samples would give 13.5 m.

Helper-height calculation example

[E] Suppose retained boundary queries have a mean lower bound of 12 m and mean upper bound of 20 m. Helper height is 0.625 × 12 + 0.375 × 20 = 15 m. It sits closer to the lower bound, rather than at the upper bound of 20 m or the equal-weight mean of 16 m. These values explain the formula; they are not measured records for a Location in this request.

Lower and upper bounds accumulate separately and are combined at the end. Boundary samples reflect ground near the asset’s edges; the center query handles cases with no valid boundary samples.

A circle can be active even when some of its samples are rejected. Configuration decides whether the circle is active; overlap checks decide which boundary points remain. Figure 8’s orange points mark rejected samples. They don’t mean the whole circle is disabled.

From queried height to a support target

Boundary queries produce helper height first. Where parent–child relationships exist, eligible children contribute to a weighted average. Region overrides, configured offsets, and satellite coordination follow. Expansion is calculated separately after the ground target; building height remains part of later object placement.

Putting helper height straight into building Z skips target calculation and the object’s local transform. Keeping an old expansion envelope alongside a new target also mixes two versions of the ground. We now calculate both target and expansion from the new query map.

Parent–child support target coordination

[D][R] Helper height starts with the ground around one Location. Related Locations can then affect its target. The weight calculation begins with the gap between their edges: take the center distance and subtract both envelope radii.

g = distance(P_parent, P_child) − R_parent − R_child
t = clamp((g − near) / (far − near), 0, 1)
u = 1 − t
w = coefficient × u² × (3 − 2u)

near, far, and coefficient come from configuration. At gaps no greater than near, weight stays at coefficient. At far it reaches zero, with smooth attenuation between them. Larger radii bring the edges closer without moving either center. That’s why the function uses the edge gap.

The parent’s average assigns weight 1 to its own helper height and adds eligible children: H_mean = (H_self + Σ wiHi) / (1 + Σ wi). [E] With self height 15 m, child height 19 m, a gap halfway between near and far, and coefficient 1, the child weight is 0.5. The result is (15+0.5×19)/1.5 ≈ 16.333 m. The parent’s own height remains in the calculation.

Region height overrides and offsets follow. An override, where present, replaces this average before the offset is added. A satellite Location may also transition toward the recorded target read by this branch as a function of distance from its parent. The current transition width is ln(R_parent+1) × rangeCoefficient, followed by normalized distance and smooth attenuation. The value read here is an intermediate recorded target, distinct from parent helper height. With distance weight s and family weight w, first compute H_intermediate=(1−s)H_current+sH_record, then H_transition=(1−w)H_intermediate+wH_record. Both blends belong to the calculation.

Finally, the algorithm queries lower limits for the regions covered by the Location, takes the maximum accepted lower limit plus margin, and constrains the target: H_target = max(H_current, regionalLowerLimit + margin). The resulting platform height depends on the sampled ground, family relationships, and regional settings.

Edge gap, smooth weight, and weighted height. Halfway between near and far, with coefficient 1, the child contributes weight 0.5.

Figure 10: Edge gap, smooth weight, and weighted height. Halfway between near and far, with coefficient 1, the child contributes weight 0.5.

Height envelopes and support expansion

[D][R] When a support target sits above or below the surrounding ground, the transition needs some room. The expansion function uses the new ground’s envelope to calculate that room:

t = min(ln(kR × R_location + 1), 1)
relief = min((max(U_expansion, H_target) − L_expansion) / reliefScale, 1)
factor = relief × t + (1 − t)
R_outer = R_circle + ln(R_circle + 1) × rangeCoefficient × factor

R_location is the envelope radius of the whole Location; R_circle is the radius of one drawing circle. kR, reliefScale, and rangeCoefficient are configuration parameters. The formula applies within the current valid parameter range; no extra clamp to zero is inserted. L_expansion and U_expansion come from this stage’s expansion query, not the earlier mean bounds across all boundary samples.

[E] To isolate this function, let t=0.5, lower bound 10 m, upper bound 14 m, target 16 m, and reliefScale 12. Then relief is 0.5 and factor is 0.75. For a drawing-circle radius of 9 m and range coefficient 2, R_outer ≈ 9 + ln(10)×2×0.75 ≈ 12.454 m. That outer radius defines the transition band for support drawing; 12.454 m is a radius, not a building height.

A numerical example of support expansion. The expansion factor reads both the target and ground envelope before determining each drawing circle's outer radius.

Figure 11: A numerical example of support expansion. The expansion factor reads both the target and ground envelope before determining each drawing circle’s outer radius.

From placement records to height-drawing parameters

We’ll use these asset names throughout the next sections:

Term Meaning in this article
Stamp parent instance One natural-resource placement, supplying overall position and orientation
Level A static resource container that may contain terrain Units, vegetation groups, and Prefabs
Unit A terrain or object record within a Level or Prefab hierarchy
Prefab A nestable resource subtree; main, parent, and child describe its role in the current hierarchy
Location An instance of a site in this request, referencing its selected resource
Cell in Figure 12 The tool’s name for a Level scene unit
Scatter Cell A map-block cache in block-based Scatter, distinct from Figure 12’s Cell

A placement record gives us a resource key, XY, and orientation. To draw it, we build the parent Level transform, find terrain Units in the static Level’s terrain group, and read their pose nodes, terrain joint indices, and local transforms. Terrain and texture dimensions come from the static assets too.

Each of the 24 natural resource types in this case has one nonempty terrain group and one main terrain Unit. Their main Units have identity local TRS and orientation flag zero. That avoids some transform branches in this case; other assets still need their own local transforms. Parent XY is shifted by −1,024 m into centered coordinates, with initial Z zero. The acceptance record’s support target must not simply be added to parent Z. The parent matrix is multiplied by the static terrain-node matrix, then transposed to the Shader constant convention to form drawing input.

[R] The resulting 1,253 parameter blocks, each 160 bytes, match the corresponding reference drawing-constant files in the natural Stamp replay cases byte for byte. Early bridge tests used an existing supported heightmap and Location parameters. Later full-chain work switched to the new base height, recalculated support, and new Location parameters. The early test checked that records reached the draw correctly. The later test repeated the chain with regenerated inputs.

The Location/Cell resource hierarchy. Direct instances and Prefab children can both contain vegetation or rocks. This illustrates structure, not an actual object list for one Location in this request.

Figure 12: The Location/Cell resource hierarchy. Direct instances and Prefab children can both contain vegetation or rocks. This illustrates structure, not an actual object list for one Location in this request.

The Cell in Figure 12 is the tool’s name for a Level scene unit. Active Scatter Cells later in the article are map-block caches. The purple box is a Prefab subtree: changing its transform moves only its descendants, while changing the Location’s parent transform moves everything. Trees and rocks illustrate that hierarchy. All 1,474 validated vegetation instances in this case belong to the natural-resource chain; the diagram adds no measured claim about POI vegetation.

The 54 Location texture draws

[R] The later chain starts from the request’s 54 generated aggregate Location instances. It finds Units through the selected Levels’ terrain marker groups, reads local joint matrices and terrain bounds, and rebuilds complete drawing constants. They reference 44 distinct Levels, and all 54 parameter sets match the existing reference. This round no longer reuses old Location drawing constants.

We can now follow the height all the way through: recalculate support from the new base, draw 1,253 natural Stamps on that ground, then draw the 54 Location textures. With identical stage inputs, the independent source implementation and corresponding original Shader replay produce bitwise-identical 4096² floating-point results after support, after natural Stamps, and after Locations. This compares two implementations on the same input. The final section separately compares with the actual captured height, where floating-point differences remain.

We also checked how support drawing gets its 512² flattening field. The relevant flags filter out all 412 region-type records in this request, so there are no triangles and the field is all zero. That’s the result of running the configuration filters, not an empty map substituted for missing work. Nonempty flattening topology still needs its own implementation and test.

One Unit in the Location resources uses a different orientation flag. Its height-drawing constants match here. We still need to check how the complete asset loader handles that flag.

Height changes across drawing stages

Supported terrain retains broad relief while adjusting the areas around Locations. It uses the new base height and recalculated support parameters, before natural Stamp ridges and internal Location outlines are added.

Natural Stamps then map static shapes to their positions and orientations. Their height programs and blend states can raise or lower the ground, so the effect includes depressions as well as hills.

Location height textures add internal site shapes over the ground already modified by natural Stamps. Although Locations participated earlier in layout and geometric support, this step still needs their own asset transforms and drawing constants. Natural Stamps have changed the ground between the two Location operations, so support and texture drawing retain their separate stages and order.

Vista connects the outer terrain last. Keeping camera, color scale, and height scale fixed across stage comparisons makes the changes visible. Normalizing each image’s colors separately can hide them.

Drawing-parameter and height-output validation

Matching drawing parameters tells us that resources, transforms, and constant packing agree. Running both Shaders on the same input checks the drawing calculation itself. Neither test catches differences already present in that input. For those, we compare final height with the actual capture.

Keeping heightmaps after support, natural Stamps, and Locations helps locate the earliest stage with a difference, then examine that stage’s inputs and arithmetic.

Vista: outer-height encoding and blending

After Location textures, the outer region still needs processing. This request’s main domain is 2,048×2,048 m at 4096² pixels. The outer blend uses radial distance from map center, beginning at 620 m and ending at 680 m. The image is square, while the blend is radial. Even the corners of a central crop can enter the outer transition.

[D][R] This request’s default admission branch reads vista_water_height from the static tundra configuration: −39 m here. The branch draws no height geometry. It initializes a 2048² R16 UNORM outer map with that value, builds seven mip levels, and blends it into the 4096² main height. Other biomes or admission branches must read their own configuration rather than inherit −39 m.

Vista has its own R16 convention. The normalized initial value is −39 × 0.00005 + 0.5. During blending, a stored sample s is decoded as (s − 0.5) × 20000 − 5. After R16 quantization and the decoding offset, this case’s outer height is about −43.914 m, rather than −39 m. The roughly 4.9 m difference comes from the original R16 UNORM write, quantization, and Vista-specific decoder. The −5 belongs to that decoder; no extra height correction was added to match the reference. Part I’s final height uses a −500 to 500 m encoding range. Vista must be read with its own formula.

The blend preserves cubic interpolation built from nine linear samples and the original floating-point order. The resource has seven mips, but this Shader invocation reads only mip 0. Inside 620 m it keeps main height; from 620 to 680 m it transitions with smoothstep; beyond 680 m it uses the outer input.

Adding Vista fixed the missing outer contribution beyond 620 m in the earlier captured-region comparison. The implementation remains limited to the default-admission branch with zero height-geometry draws. Nonzero Vista geometry, complete surface-layer set construction, and the historical scheduler are outside this round’s validation.

The upper row follows the outer texture into decoded height. The lower row shows the blend weight between 620 and 680 m. The curve is a weight function, not a terrain cross-section.

Figure 13: The upper row follows the outer texture into decoded height. The lower row shows the blend weight between 620 and 680 m. The curve is a weight function, not a terrain cross-section.

Vista encoding and decoding conventions

Even without geometry draws, the initial value still passes through texture-format conversion and sample decoding. Blending a floating-point constant of −39 m directly would omit that path. Reading Vista with the final-height R16 decoder would also produce the wrong result.

The resource contains seven mip levels, but this Shader reads mip 0. We’ll need to check geometry and sampling again when we add other configurations.

Radial blend-weight example

[E] Radius 650 m lies halfway between 620 and 680 m. Its normalized parameter is (650 − 620) / 60 = 0.5, and smoothstep also gives 0.5. Main height and decoded outer height each contribute half. The outer weight is zero inside 620 m and one beyond 680 m.

The usual 625 m disk preview extends only 5 m into the band, far short of its 680 m endpoint. Showing the full blend requires a view extending beyond 680 m with both boundaries marked. The preview disk’s own edge appearance should also be distinguished from this height processing.

Vegetation: from natural resource groups to trees and shrubs

Where do the trees, shrubs, and rocks come from? The vegetation checked here is stored in natural terrain Levels, either in vegetation groups or in nested Prefabs. A Level is the asset container: it can hold terrain Units, vegetation, and other objects. A Location is a site instance in the current request.

Once a natural Stamp parent is placed, its terrain and objects share an overall position and orientation. Authored tree layouts move and rotate with the parent resource, then receive their own height and orientation processing. Figure 14 follows one of those groups.

Resource composition in Stamp #710

Take this example from the September 17 records. Natural Stamp #710 references resource 33f7668a83d94500, associated with 11 Heather shrubs and 2 validated rocks. In the common parent coordinate system, the whole group moves with the recorded translation and rotation of about 33.11°.

An actual association for Stamp #710: 11 shrubs and 2 rocks share a parent resource. Points and the parent transform come from records; the green terrain outline is illustrative. Rock coordinates in the local view were obtained by applying the inverse parent transform to final world XY.

Figure 14: An actual association for Stamp #710: 11 shrubs and 2 rocks share a parent resource. Points and the parent transform come from records; the green terrain outline is illustrative. Rock coordinates in the local view were obtained by applying the inverse parent transform to final world XY.

Each tree and rock keeps its own layout under the shared parent. For this view, rocks are projected back into parent coordinates. Some may have reached world space through a Prefab subtree, so appearing in this view doesn’t mean they’re stored directly under the Level.

The common parent transform moves the group. Processing then separates: terrain Units write height, vegetation and rocks follow their respective grounding branches, and rocks may also be culled. One natural resource can supply both terrain shape and object layout.

Two resource paths produce 1,474 vegetation instances

[R] The 1,474 uniquely matched SpeedTree instances in this request follow two paths. Of these, 851 Heather shrubs come directly from Level vegetation groups. The other 623 come from subtree Prefabs within the Level’s main Prefab composition: 354 pine trees and 269 other shrubs. SpeedTree is the resource and instance type here; it does not mean all 1,474 are large trees.

Static resource Instance count Resource path in this case
moor_pinetree_01 / 02 / 03 100 / 84 / 170 Nested Prefabs in a Level
moor_pinetree_shrub01 / 02 172 / 97 Nested Prefabs in a Level
moor_heather_bush_01 / 02 488 / 363 Created directly by Level vegetation groups

Level and Prefab tell us where an instance came from. Pine, Heather, and other shrubs tell us what it is. The counts come from seven instance lists for this fixed request, rather than density settings for every biome. A parent resource may contain many local instances, and Prefabs may nest further. Parent Stamp, Prefab, and vegetation counts therefore do not correspond one to one.

Placement comparison for 1,474 vegetation instances: independent generation on the left, Target Reference on the right, with the same camera and ground. Markers show XY. Final Z, rotation, and scale are validated numerically, not by comparing screenshot pixels.

Figure 15: Placement comparison for 1,474 vegetation instances: independent generation on the left, Target Reference on the right, with the same camera and ground. Markers show XY. Final Z, rotation, and scale are validated numerically, not by comparing screenshot pixels.

Resource selection also depends on draw order

Static tables contain several available compositions. Which ones load depends on group conditions, enabled Prefabs, planet resource aliases, and random branches. We need to expand both external and embedded Prefabs. Skip either path and some objects may be missing.

Before natural Levels begin selecting resources, two random Prefabs in the Vista resource have already advanced the World random state. Locations and natural Levels continue from that state. This occurs during Vista resource loading, a separate operation from the final outer-height blend described earlier.

Special Location groups also read their owning Location’s tags to match group conditions. That changes subsequent resource expansion and random consumption. So even when we’re only checking natural vegetation, we still have to run the earlier Location loading. The checked progression in this request includes 2 embedded Vista draws, 132 embedded Location draws, 49 external Location draws, and 2,577 embedded natural-Level draws: 2,760 in total. This count checks the execution path; it is not a number to hard-code into generation.

Vegetation expansion has its own entry and random state. The upstream Stamp candidate loop uses another state. Each must advance according to its actual consumption. Combining them, or adding draws at the end merely to reach a matching state, would change the process.

Height input for vegetation grounding

[D][R] Vegetation grounding reads R32 floating-point height after Location geometric support, before natural Stamp and Location height textures are drawn. Object queries branch off partway through height generation. They do not wait for the final terrain. We’ve confirmed that input stage. The full transform test for 1,474 instances, though, still comes from September 16. It hasn’t yet been rerun with the September 21 chain.

Trees first compose local and parent transforms, then query ground through the appropriate branch. The ordinary branch adds sampled height in single precision. Heather also has orientation handling: it reads three-component grounding parameters from the static asset and uses ground queries to compute an orientation adjustment.

Each resource has its own grounding branch and parameters. Simply aligning every object with the final terrain normal would change those rules. The Web markers sit on the preview surface so XY is easy to see; we check actual Z and rotation in the instance records.

Parent resources expand through direct vegetation groups or nested Prefabs, then read supported height for grounding. This query branch runs before natural and Location height-texture drawing.

Figure 16: Parent resources expand through direct vegetation groups or nested Prefabs, then read supported height for grounding. This query branch runs before natural and Location height-texture drawing.

From a local vegetation point to the ground

[D][R] We compose the transforms before querying the ground. In column-vector notation, a local point passes through its scale, rotation, and translation, then through Prefab and parent-Level transforms: p_world = M_parent × M_child × p_local. File or interface storage conventions may differ. This formula states transform order; whether constants are transposed depends on the interface.

[E] Take a child at (2,1,0.3) and a parent at (100,200,0), rotated 90° around Z with no extra scale. Composition gives (99,202,0.3). If the ordinary grounding branch reads 12 m there, final Z is 0.3+12=12.3 m. The local 0.3 m offset remains: this branch adds ground height to existing Z.

This ordinary grounding entry uses R32 point sampling. For an in-map coordinate, it derives UV from the map origin and world extent, multiplies by texture dimensions, truncates to integer indices, and reads that pixel. Row direction follows the descriptor. It does not bilinearly combine four pixels. Support envelopes and Scatter R16 use different samplers. Before connecting a heightmap, check which query function will read it.

Vegetation that adjusts orientation reads a neighborhood too. The checked entry forms a triangle from three points, rather than using a four-direction central difference. For world-space texel dimensions dx, dy, the queries are:

A = (x+dx, y−dy, hA)
B = (x−dx, y−dy, hB)
C = (x,    y+dy, hC)
n = normalize((A−B) × (C−A))

The resulting direction n is then combined with the asset’s three-component parameter a. The code forms (nx+ax, ny+ay, nz×az), normalizes it, constructs a rotation correction using that result and a, and composes the correction with the existing rotation in the original order. Original scale is restored afterward. Since resource parameters modify the direction, final orientation need not align the model’s upright axis with the ground normal.

[E] With neutral teaching parameters (0,0,1) and a plane h(x,y)=7+0.125x, the triangle direction is parallel to (-0.125,0,1). Normalized, it is approximately (-0.1240,0,0.9923), with tilt about 7.125°. This explains the three-point query on a plane; it is not an actual Heather parameter set. Real instances retain their authored parameters, existing rotation and scale, and float32 operation order.

Three-point height queries and ground direction. Neutral teaching parameters yield about 7.125° of tilt; actual resources retain their own orientation parameters.

Figure 17: Three-point height queries and ground direction. Neutral teaching parameters yield about 7.125° of tilt; actual resources retain their own orientation parameters.

Updating base height and support parameters together

In an early test, we replaced the base height but kept the old support parameters. Seventeen rotations still failed the agreed tolerance. We then re-queried support from the new ground, recalculated weights, limits, expansion, and adjacency, and drew the 84 support circles again. All vegetation transforms passed. Replacing the sampler’s input had only fixed part of the problem; support parameters derived from that ground needed updating too.

[R] The final September 16 validation covered position, rotation, and scale for all 1,474 instances. Maximum Z error was about 0.00190735 mm, maximum rotation error 0.000197253°, and maximum absolute scale difference 2.18839×10⁻⁷. All passed the original tolerances, without adding reference-based height or rotation corrections.

Those are the September 16 results. We still need to connect vegetation to the September 21 height chain and rerun the full transform test.

Rocks: expand asset layouts, then cull the outer region

Rock layouts are stored in Level Unit records or Prefab subtrees. Once the resources and parent transforms are chosen, we can move those local records into world space, ground them, and run culling.

Placement comparison for 3,107 rocks: independent generation on the left, Target Reference on the right. The 625 m display radius shows 3,105; all 3,107 take part in validation. Display clipping does not alter the source list.

Figure 18: Placement comparison for 3,107 rocks: independent generation on the left, Target Reference on the right. The 625 m display radius shows 3,105; all 3,107 take part in validation. Display clipping does not alter the source list.

Placing a local layout in world space

For a rock directly owned by a Level, the static record supplies model, local position, rotation, and scale. It follows the parent Level’s movement and rotation. Composing this Unit does not require drawing a new global random XY.

[E] One transform test uses the real static local coordinate (5.3592305, 0.1481066, −2.3655095) with a deliberately chosen parent at (100, 200, 30), rotated 90° around Z. Composition gives approximately (99.85189, 205.35924, 27.63449). Sampling a constant 7.5 m field in the test branch then produces Z ≈ 35.13449 m. The parent position and constant field are test inputs, not measured positions in this request. The example separates local offset, parent transform, and grounding contribution.

Prefab processing also depends on which level owns grounding. If an embedded Prefab’s position record requests grounding for the whole group, the parent queries first and passes parameters that disable further grounding to child Units. That prevents adding the same height twice. Grounding both parent and every child could leave a plausible XY layout while changing Z or rotation.

Grounding responsibilities in the Prefab hierarchy

Parent–child transforms and grounding both change position, but they cannot be reordered freely. Suppose a parent Prefab queries 10 m at its anchor and raises the group by that amount. A child rock with local Z 0.4 m already carries that rise after composition. Adding queried ground again at the child would raise it twice.

The verified whole-group branch passes empty height parameters to child Units. Children still execute local-to-world transforms but do not add ground height again. Another path permits children to ground independently at their own XY, so two rocks in one Prefab can receive different corrections. Parent-record flags select the path.

A rock’s Z can include its local asset offset, the displacement already in its parent matrix, and an added ground query. Disabling child grounding removes only that last query. The local offset and parent displacement still apply.

Local-to-world transforms and grounding ownership. Coordinates on the left are teaching inputs. The right separates child grounding from the branch that disables child queries after parent grounding.

Figure 19: Local-to-world transforms and grounding ownership. Coordinates on the left are teaching inputs. The right separates child grounding from the branch that disables child queries after parent grounding.

Rock culling: from 3,305 candidates to 3,107 instances

[R] We first expand all Unit candidates independently, then use the named rock models to count the rock subset: 3,305 candidates. The algorithm removes 198, leaving 3,107. The named-model list is used only for classification and comparison. It does not generate candidates or select reference instances in advance.

Culling combines radial position, static asset bounds, configuration parameters, and mission random state. The current branch keeps inner-region candidates directly. Farther out, it combines radial attenuation, a size term, and an outer-edge penalty, then compares with a random value. Size and randomness affect which outer rocks survive. The Web disk’s display radius has no role in this decision.

Culling visits external Prefabs before embedded Prefabs, in a different order from loading. Change that order and the random values go to different objects. The removal count might still match while the surviving rocks differ. We also need complete static bounds; treating a missing asset as zero-size changes the test.

Rocks move from static Unit/Prefab layouts into world space, follow their grounding branch, and pass through algorithmic culling. The 3,305 candidates are the rock subset, not all Unit candidates.

Figure 20: Rocks move from static Unit/Prefab layouts into world space, follow their grounding branch, and pass through algorithmic culling. The 3,305 candidates are the rock subset, not all Unit candidates.

The 198 removals comprise 162 Level Units and 36 Prefab Units. Of the remaining 3,107 rocks, 1,516 come from Levels and 1,591 from Prefabs. They match the reference uniquely, with zero extras, omissions, or ambiguities. Configuration, independent candidates, and culling rules determine removals. The reference is consulted only after generation for validation.

[R] In the September 16 rock validation, maximum XY error was about 0.030517578 mm, maximum Z error 0.101372600 mm, maximum rotation error 0.000400380°, and maximum absolute scale difference 1.40701×10⁻⁷. All passed the original thresholds. Like the vegetation test, this used its own inputs. The complete output of the September 21 chain still needs another run.

The rock list matched after the first culling pass. The final random state took more work: processing the trailing parent again reproduces it, but we haven’t confirmed why the original scheduler repeats that call. Counts and transforms passed; complete loading, asynchronous scheduling, visibility, and collision still need checking.

Block-based Scatter

The system also has a Scatter path that runs once per resource and map block. It enumerates candidates, queries zone, density, and material conditions, and outputs positions and directions. The dense distribution on the right of Figure 1 is a replay of this path.

Height, zone, and material query maps

The heightmap supplies ground height and neighborhood samples for direction. The zone map provides category and density. The material map provides surface category and allowed intervals. Read their formats carefully. The zone map contains integers. The material map uses R32F storage, but its contents are packed bits, not ordinary floating-point material values.

In the analyzed branch, density comes from a separate density target and is merged into the zone map’s low seven bits. The material path also involves eight weight targets and their merge before producing the CPU material query map. These maps are generated upstream; parts of that production process still need implementation and validation.

Packing density into the zone map

[D] During composition, a sampled density is clamped to 0–1, multiplied by 127, and converted to an unsigned integer. The resulting seven-bit code replaces only the zone map’s low seven bits:

d = uint(clamp(densitySample, 0, 1) × 127)
zone_new = (zone_old & 0xffffff80) | d

The CPU can then read both zone information and the density-gate value d from one pixel. Density is neither height in meters nor a direct count of plants to spawn at that pixel. [E] A sampled density of 0.5 becomes 63.5 before integer conversion, then 63. If the seven-bit random value is uniform, the later density gate passes with probability 64/128=0.5. This is one gate’s probability, before accounting for resource-category and material filtering.

Teaching examples of density quantization and material intervals. Zone and material category selection are prerequisites here; they remain separate gates in the full process.

Figure 21: Teaching examples of density quantization and material intervals. Zone and material category selection are prerequisites here; they remain separate gates in the full process.

Reusing candidate points across blocks

The shared candidate table contains 1,024 records on a 32×32 grid, followed by neighbor-distance adjustment. Block generation reuses this table through periodic indexing and adds the block’s spatial offset. Block coordinates and entry state participate in random generation, giving blocks different filtering outcomes from a shared candidate structure.

Candidates first pass range and random coarse checks, then zone category and density, then material category and interval checks. Eligible planar candidates proceed to output construction. Height and neighborhood queries supply Z and direction, while per-call capacity limits the output. This order affects random state, acceptance counts, and block-cache contents.

Queries and gates in block-based Scatter. Map production, CPU candidate generation, and block budgets have separate roles. The current full-map visualization replays captured inputs.

Figure 22: Queries and gates in block-based Scatter. Map production, CPU candidate generation, and block budgets have separate roles. The current full-map visualization replays captured inputs.

[D] The density gate has an easily missed detail: this branch accepts when random7 ≤ d, with d in 0–127. For uniform random values in that range, its isolated pass probability is (d + 1) / 128. Thus d = 0 does not guarantee zero instances. Other gates still filter candidates, so this probability is not final scene coverage.

The material gate requires an upper bound greater than the lower bound and a random value inside the allowed interval. Height is bilinearly interpolated from four R16 samples and decoded with this branch’s final-height convention. Output also stores a random scalar and two 3D directions. We haven’t traced every consumer of that scalar. Being interpolated between two bounds doesn’t by itself make it model scale.

Scatter candidate queries and output calculation

[D][R] The shared table is initialized once rather than rebuilt for every block. It starts with 32×32 entries and performs ten rounds of distance adjustment using periodic eight-neighbor relationships. Block candidates reuse those entries with a block offset; block coordinates and entry state determine random state. Adjacent blocks share candidate structure and filter independently.

After range and coarse checks, the zone query picks a category and checks whether the resource accepts it. The density gate follows. The material query then selects its category and reads the allowed interval. Both category selections use encoded weights too; reading just one category ID from the pixel won’t reproduce the result.

[E] Suppose range, coarse, and category checks have passed. The zone pixel has density 63 and this candidate draws random7=40, so density passes. The selected material allows [10000,30000]; random16=25000 passes, while 35000 would reject the candidate without output. If upper and lower bounds are equal, even a matching random value fails the prerequisite hi>lo.

Four adjacent R16 heights are then read. Each integer sample is divided by 65535, bilinearly interpolated using the fractional pixel coordinates, and decoded:

s00 = code00 / 65535; likewise for the other three samples
a = s00 × (1−fx) + s10 × fx
b = s01 × (1−fx) + s11 × fx
Z = 1000 × (a × (1−fy) + b × fy) − 500

[E] For integer samples 32768,33423,34078,34733 with fx=0.25, fy=0.5, the equivalent interpolated code is 33586.75, giving approximately 12.501 m. These values support hand calculation. The implementation preserves actual sample coordinates, floating-point order, and the order of integer conversion and interpolation.

After height and neighborhood queries, the output receives two 3D directions and a random scalar of the form a+(b−a)u. We’ll call it a random scalar until its downstream use is confirmed. The current record is 48 bytes, including XYZ, this scalar, two 3D directions, and slots whose purpose is unconfirmed. How those fields drive model placement still needs explanation.

Capacity affects results too. If an active block already holds 250 records, the remaining capacity is 256−250=6, not another 256. The full-grid replay gives each resource in each block a separate capacity of 256. That differs from the runtime’s shared block-cache budget. With different budgets, the two runs can produce different instance sets even from the same query maps.

A teaching example of bilinear R16 height. Corner codes match the text and yield about 12.501 m. Hand calculations do not replace the implementation's floating-point order.

Figure 23: A teaching example of bilinear R16 height. Corner codes match the text and yield about 12.501 m. Hand calculations do not replace the implementation’s floating-point order.

Full-grid replay and runtime validation scope

[R] The current full-grid replay covers 23 registered resources and 128×128 blocks of 16 m. Across 376,832 calls it outputs 900,731 records, with 20 nonempty resources. It uses this request’s captured query maps and gives each resource/block pair capacity 256. It does not replay shared budgets, streaming, or LOD. The result shows what a full-grid run produces from those inputs. It doesn’t reproduce the set visible at that moment, and it still depends on captured query maps.

Six actual active Cells provide another sample of 41 reference records. Replay also returns 41; in original order, 37 have identical floating-point XYZ. Coordinate differences in the remaining 4, along with differences in some other fields, remain unresolved. Passing the 900,731-record export checks does not remove these active-block failures.

The Web point layers are useful for checking where objects are and which resources they came from. Their markers sit on preview ground, though; they don’t test final instance Z, materials, occlusion, or collision. For vegetation and rocks, we use the separate numerical transform tests. For the full-grid Scatter view, we have a replay of captured inputs.

Scatter next needs independent zone and material maps and continued investigation of active-block differences. Vegetation and rocks need a complete rerun with the latest height chain. These are separate validation tasks.

Independent implementation and validation: September 21, 2026

The central capture is square; 620 m and 680 m are radial boundaries. Capture corners enter the outer region, so the central crop is not exclusively main terrain height.

Figure 24: The central capture is square; 620 m and 680 m are radial boundaries. Capture corners enter the outer region, so the central crop is not exclusively main terrain height.

Conditions and results of the three height comparisons

Experiment Inputs and scope Recorded result What it establishes
Older final R16 output Full 4096² map; generated codes versus corresponding reference codes 99.7904% identical codes; remaining pixels differ by one code; decoded RMS about 0.699 mm A historical baseline for the initial final encoded file
Current actual-capture comparison Central 2048² captured region; float32 height before final encoding; 4,194,304 pixels Maximum absolute error about 0.803 mm; RMS about 0.0186 mm; 3,769,876 pixels differ in floating-point bits Floating-point error within actual capture coverage; not bitwise identity
Current Vista implementation comparison Same main and outer inputs; reconstructed source versus original Vista Shader; full 4096² map All 16,777,216 pixels bitwise identical; maximum error and RMS both zero Implementation parity for the executed Vista branch; not agreement with a full-map actual capture

A bit-pattern difference means two float32 values have different representations. It does not mean every differing pixel has a millimeter-scale height error. The captured region’s maximum error remains below 1 mm, with RMS about 0.0186 mm. The mismatch count tells us how many floating-point values differ; height error tells us by how much.

These experiments use different data types, inputs, and regions. We can’t calculate an accuracy improvement by comparing their numbers, or replace the older 99.7904% with the new floating-point RMS. To update that metric, we need to encode the new final R16 map and compare its codes again.

The actual capture covers only the central 2048² region of the full heightmap. Comparison crops [1024:3072, 1024:3072] directly in GPU row order at 0.5 m per pixel, without extra flipping, translation, scaling, or height correction. Generation does not read this captured height; it is used only after output for comparison. Actual final height outside the captured region is not validated by this experiment.

Within that region, the 620–680 m transition band has maximum error about 0.0381 mm and RMS about 0.00645 mm. The 31,760 pixels beyond 680 m are bitwise identical. The full region still has nonzero floating-point differences, with maximum about 0.803 mm; their source has not been isolated to a particular operation. “Zero pixels above 1 mm” is a diagnostic statistic, not a replacement for the agreed acceptance criteria.

Implementation scope and unvalidated branches

Early Stamp-to-height bridge tests used an existing supported heightmap and Location drawing parameters. Later records include their recalculation. The empty flattening field is also confirmed to follow from this request’s configuration. Large outer-region differences seen during full-chain work were resolved by the later Vista integration. Those connections are now in place. The branches that didn’t run in this request still need work.

So far, we’ve validated the branches that ran for this request. Other seeds and biomes, special Stamp generation, rectangular support, nonempty flattening, nonzero Vista height geometry, and complete asset loading and runtime lifecycle each need validation. The chain also takes validated layout, support ownership, parent–child relationships, regional geometry, and static asset packages as stage inputs. A single-seed entry that completes the entire process in one call has not been fully validated.

Vegetation, rock, and Scatter status

Object and batch Validated result Separate work still required
September 16 vegetation Seven types, 1,474 instances; position, rotation, and scale pass original tolerances Reconnect the September 21 chain; other seeds, collision, and complete runtime
September 16 rocks 3,305 candidates culled to 3,107; counts and transforms pass New-chain batch validation; complete scheduling, visibility, and physics
September 17 block-based Scatter 900,731 records from captured-map full-grid replay; 37/41 active-sample XYZ match Independent query-map production; 4 coordinate mismatches and other field differences; shared budgets and streaming

POI selection and placement now have independent validation for this request. Next we’ll cover other configurations and surface Layer generation. We also need to rerun vegetation and rocks on the latest height chain; their current results are the earlier batches listed above.

AI-assisted writing and evidence review

AI helped organize the evidence, draft the article, and draw the diagrams. During editing, we had to keep going back to dates and inputs. Early notes still listed support inputs and outer blending as missing, even though later records had filled them in. The successful vegetation and rock tests had the opposite problem: they were valid, but they predated the latest height chain. We checked each record before describing what was complete.

Validation metrics also require their experimental context. The older full-map R16 test, the newer central floating-point comparison, and the same-input Shader runs measure different things. Grouping them under ‘accuracy’ would hide the different formats and regions, so each keeps its own result in the article.

Further work will complete independent zone and surface Layer inputs, validate POI branches under other configurations, and rerun vegetation and rocks on the latest height chain.

Leave a Reply

Discover more from AI Native Game Development

Subscribe now to keep reading and get access to the full archive.

Continue reading