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)

4 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…)

Leave a Reply

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