How to read files in Godot

Part 2 of my Godot journey covers reading a text file, drawing the contained vertices, and how to handle drag & drop.

Reading a file

My go-to tool for visualizing point clouds is CloudCompare. The easiest way to load line geometry in CloudCompare is via the .poly format, a simple text format with one vertex per line in the file (space separated) and empty lines in the file for starting a new line.

Godot has a FileAccess class for file input/output that has a handy get_csv_line() method for dealing with delimited data.

func read_line_poly(filename:String,offset:Vector3) -> Array[Vector3]:
    var file = FileAccess.open(filename, FileAccess.READ)
    var points : Array[Vector3]
    
    while !file.eof_reached():
        var line=file.get_csv_line(" ")
        if len(line)>=3:
            points.append(Vector3(float(line[0]),float(line[2]),float(line[1]))-offset)	
    return points

Some things to consider:

  1. I’ve used an Array as data structure. Godot also has a data structure called a PackedArray that is recommended only for large data sets as it is slower, but it prevents memory fragmentation.
  2. Godot uses a typical computer 3D coordinate system where X and Y align with the screen and Z is the view direction, whereas geographic data is usually in an east-north-up coordinate system. That’s why I’ve flipped around the Y and Z coordinates (which is not entirely correct, as I would find out later).
  3. Unless compiled for using double-precision coordinates, Godot does not like large coordinates like encountered with typical geographic coordinate systems. That’s why I subtract an offset.
  4. This code does not properly deal with multiple lines in one file.

You can then run the resulting array through the drawing function from the previous post.

Drag & drop

Godot has a FileDialog class for picking files, but I’m a big fan of dragging & dropping files from the Explorer instead. Luckily this is super-easy to do. All you need is to connect to the files_dropped signal:

func _ready() -> void:
    get_viewport().files_dropped.connect(on_files_dropped)

func on_files_dropped(files):
        print(files)
    for file in files:
        _lineplotter.draw_line(file)

_lineplotter is an instance of a class that inherits from Marker3D and contains the reading and drawing code. You might of course want to add functionality that handles different file types/extensions.

Two lines loaded from two .poly files

Performance

You might notice in above screenshot that Godot runs at only 19 frames per second. This is with approx. 25,000 objects and in Debug mode. An exported project runs faster. There are other factors with which you can improve performance:

  1. Drawing distance: you can set the maximum drawing distance for an object and set this e.g. to 100m.
  2. By default the Physics engine runs on the same thread, this can be configured to run on a separate thread in the project settings.
  3. For an application that shows only static objects and requires no Physics, you can set the Physics tick frequency to a lower value. 10 works fine and is quicker than the default 60.
  4. Godot also support occlusion culling, i.e. not drawing objects that are hidden behind others. This however will have little to no effect when working with small objects like I did here.

Een reactie plaatsen

Je e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

2 gedachten over “How to read files in Godot”