FyroxEngine/Fyrox · error

Invalid Terrain quad tree node position

Error message

Invalid Terrain quad tree node position

What it means

Fyrox terrain quadtree nodes must have an integer position >= 1 on each axis; a node positioned below that is invalid and its AABB cannot be computed. The library logs this error and returns a default empty AABB instead of computing geometry.

Solutions

  1. Check the terrain data in the scene file for nodes with position < 1 and fix or rebuild the terrain.
  2. Rebuild the terrain from its height map so the quadtree is regenerated with valid positions.
  3. Avoid directly editing quadtree node positions; use the terrain API.
  4. Report or investigate if the corruption appears after upgrading Fyrox versions (serialization format change).
Defensive patterns

Strategy: validation

Validate before calling

// before relying on terrain.aabb(), re-generate terrain from its height map
terrain.refresh(); // ensure quadtree is rebuilt from valid data

Prevention

When it happens

Trigger: Calling Terrain::aabb (via debug_draw or select) when a quadtree node's position.x or position.y is less than 1 — typically from corrupted terrain data or a bad split during quadtree build.

Common situations: Loading a scene file whose terrain quadtree was serialized with bad node positions; custom code mutating terrain chunk layout; version changes in terrain serialization format.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/d84e4fbb384b971a. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-impl/src/scene/terrain/quadtree.rs:243

    /// * physical_size: The size of the whole of the height map data in world units.
    /// Note that the sizes of these arguments are only for the chunk of this [QuadTree].
    /// Other chunks are not included since they have entirely separate height data.
    pub fn aabb(
        &self,
        transform: &Matrix4<f32>,
        height_map_size: Vector2<u32>,
        physical_size: Vector2<f32>,
    ) -> AxisAlignedBoundingBox {
        if self.size.x < 1 || self.size.y < 1 {
            Log::err("Invalid Terrain quad tree node size");
            return Default::default();
        }
        if height_map_size.x < 3 || height_map_size.y < 3 {
            Log::err("Invalid Terrain height texture size");
            return Default::default();
        }
        if self.position.x < 1 || self.position.y < 1 {
            Log::err("Invalid Terrain quad tree node position");
            return Default::default();
        }
        // Convert sizes from pixel sizes to mesh sizes.
        // For calculating AABB, we do not care about the number of vertices;
        // we care about the number of edges between vertices, which is one fewer.
        let real_map_size = height_map_size.map(|x| x - 3);
        // Nodes have no margins, but we still need to subtract one so we are measuring length, not counting vertices.
        let real_node_size = self.size.map(|x| x - 1);
        // Exclude the one-pixel margin when calculating the real position of this node.
        let pos = self.position.map(|x| x - 1);
        let min_x = (pos.x as f32 / real_map_size.x as f32) * physical_size.x;
        let min_y = (pos.y as f32 / real_map_size.y as f32) * physical_size.y;

        let max_x = ((pos.x + real_node_size.x) as f32 / real_map_size.x as f32) * physical_size.x;
        let max_y = ((pos.y + real_node_size.y) as f32 / real_map_size.y as f32) * physical_size.y;

        let min = Vector3::new(min_x, self.min_height, min_y);
        let max = Vector3::new(max_x, self.max_height, max_y);

View on GitHub (pinned to 76c91aad8e)