Cinema 4D – convert XYZ data to Point Cloud

Here’s a simple little script to turn your XYZ data (that you could get out of Photogrammetry software, for example) into point geometry within Cinema 4D.

Since XYZ is a very, very simple format to store data, there’s little in terms of error checking or whatever. It’s just a long list of numbers with one row per point. If your data contains color information as well as position data (like in the case of Photoscan), this is the kind of result you can expect:

Here’s the script:

# XYZ to PolygonObject
# 908video / Michael Auerswald
# 908video.de / 908lab.de

import c4d
from c4d import gui

INVERT_Z = True
SCALE = 100.0

def main():
    
    # Get input file
    pts_file = c4d.storage.LoadDialog(title="Open XYZ file for processing", flags=c4d.FILESELECT_LOAD, def_path="d:\\")
    if pts_file is None:
        return  # cancelled

    doc = c4d.documents.GetActiveDocument()

    with open(pts_file,"r") as pts:

        num_points = sum(1 for line in pts)
        print("XYZ point count: " + str(num_points))
        
        new_obj = c4d.PolygonObject(num_points,0)
        
        vtx_color_tag = c4d.VertexColorTag(num_points)
        vtx_color_tag.SetPerPointMode(True)
        vtx_color_tag[c4d.ID_VERTEXCOLOR_DRAWPOINTS] = True
        
        data = vtx_color_tag.GetDataAddressW()
    
        points = new_obj.GetAllPoints()
        normals = new_obj.GetAllPoints()
        colors = new_obj.GetAllPoints()

        pts.seek(0)
    
        mult_z = 1.0
        if INVERT_Z is True:
            mult_z = -1.0
        
        idx = 0        
        for line in pts:
            values = line.strip().replace("\\n","").split(" ")
            print values
            # read position values
            points[idx] = c4d.Vector(float(values[0]),float(values[1]),float(values[2])*mult_z) * SCALE
            
            # since XYZ has no defined order of these columns, these columns may or may not exist and can contain normals, color or whatever
            # read second column of values
            if len(values) > 3:
                colors[idx] = c4d.Vector(float(values[3])/255.0,float(values[4])/255.0,float(values[5])/255.0)
                c4d.VertexColorTag.SetColor(data, None, None, idx, colors[idx])
                #normals[idx] = c4d.Vector(float(values[3]),float(values[4]),float(values[5]))
            
            # read third column of values
            if len(values) > 6:
                normals[idx] = c4d.Vector(float(values[6]),float(values[7]),float(values[8]))
            
            # increase index
            idx += 1
            
        new_obj.SetAllPoints(points)
        
        new_obj.InsertTag(vtx_color_tag)
        doc.InsertObject(new_obj)
        c4d.EventAdd()

if __name__=='__main__':
    main()

It really is quite straight forward. You may need to change the order in which data is being read from each row depending on how your software stores the data in the XYZ file.

For testing, you can just look for the Stanford dragon or bunny as XYZ files or really anything else.

(Note that this script is primarily simple, not fast. Large files take a bit to process)

12 thoughts to “Cinema 4D – convert XYZ data to Point Cloud”

  1. hallo,
    ich versuche gerade, dein skript auszuführen. es wird auch der dialog geöffnet, um das xyz-file auszuwählen, aber danach geschieht nichts mehr und c4d ist normal zu benutzen. keine fortschrittsanzeige. ist das beabsichtigt?

    1. Nein, da sollte er eigentlich die XYZ Werte aus der Datei auslesen. Evtl stimmt was mit der Datei nicht? Steht denn was wie “XYZ point count: xxx” in der Konsole? Wenn nicht, dann kann er die Datei nicht lesen…

  2. This is awesome, thank you! But, does anyone know how best to get these vertex colours to render? I can’t seem to get the vertex colour map tag to work without creating a cloner and instancing.

    1. I’d like to know too please !
      And BTW thank you so much Michael for sharing this script !
      Would it be easy to use it in blender ? (sorry I’m totally new to this…)

  3. Okay – I’m a total newbie to scripts so although you state this is ‘quite straightforward’… i’m completely lost. Am i copy and pasting the ‘here’s the script’ portion? I assume not as there are directions written there. Also your screengrab of script is quite different. Is there a download of a script? Basically I don’t get it… I have a Metashape xyz point cloud file exported… just need help getting it in!! Any help is appreciated!

    1. I should clarify. The script is successful in loading the points into C4D, but they don’t have any of the colour information. This is under C4D R21

    2. Hey, I checked your file and your .xyz file is not in the right structure.
      You can read .xyz files by changing its extension to .txt. You can get huge files what notepad (windows) cant handle so i recomment just open it in [http://www.readfileonline.com/]. After you opened you see 1 line = 1 point. Point information stored like this:

      Xcord Ycord Zcord Red Green Blue VTXcolor1 VTXcolor2 VTXcolor3
      29.251 -59.096 -97.707 45 43 32 -0.999717 0.000000 0.023803
      In your file:
      95.68713379 -40.85255814 100.00000000 0.596078 0.596078 0.298039 0.000978 0.000978 0.999999

      So it contains some other color information format. You should try to export .xyz from MeshLab/Metashape or what you are using in the right format.
      I havent checked your final object but maybe this was the issue.

      Anyways thanks Michael sharing this. I was surprised it was working for me for the first try. Coding in C4D is new for me, something I always wanted to start so I do now 🙂

  4. Hallo Michael
    machst du eine Anpassung an die R23? Python3? Schein da nicht mehr zu funktionieren..Konsole sagt was von Zeile 47 “print” Da fehlen ()

    hm, danach funzt es bis Konsole sagt:

    XYZ point count: 4000001
    [‘X’, ‘Y’, ‘Z’]
    Traceback (most recent call last):
    File “C:\Users\User\AppData\Roaming\MAXON\Maxon Cinema 4D R23_DBA5903C\library\scripts\xyz_importer.py”, line 71, in
    main()
    File “C:\Users\User\AppData\Roaming\MAXON\Maxon Cinema 4D R23_DBA5903C\library\scripts\xyz_importer.py”, line 48, in main
    points[idx] = c4d.Vector(float(values[0]),float(values[1]),float(values[2])*mult_z) * SCALE
    ValueError: could not convert string to float: ‘X’

Leave a Reply

Your email address will not be published. Required fields are marked *