XYZ data to point cloud

This script was initially created by Michael Auerswald and 908video.
I sligthly edited the script so it works with the latest version of C4D, which happen to be 2023.
Because the website which hosted the script before seems to be down and people were asking for it you are here now.

Edit 26/04/2023
– I found some failures in the color processing, which lead to errors. Fixed it.
– no more double backslashes in the pts_file path. before it lead to a unicode escape error.
Now you can use filepaths like C:\users\….

Download the python file here

What the script does
The script makes it possibe to import 3D point data into Cinema4d. If you try to import a pointdata only .obj file into c4d you will realize that this is not possible. C4D seems to not understand obj’s which only hold pointdata and ends up importing nothing nor giving the user a error message.

That is where the script comes into play. It reads out every line/point and stores it’s point position and color into an array which will be written into a polygon object inside Cinema4D.

Important
To make this process work the obj file has to be in a specific format otherwise the script will crash. If the file is not in the right format, you can edit it with a text editor to make it work. A photogrammertry software like Agisoft Photoscan should give you the option to directly export your point data as a .txt file to have it as plain position and color data.

The right format for of your color data
Color data is usually handled in two formats. Either you have float RGB values ranging from 0 to 1 like 0.1468, or you get integer RGB values from 0 to 255 i.e..
It is important that choose the right processing of these values, otherwise your color data looks wrong. The code two sections were it deals with these two workflows. You have to choose the right one and comment out the other one. Cinema4D uses float RGB values, thus if your file looks like the OBJ example below you can use the first section of code. If your the values in you OBJ are in integer type, you have to use the second block of code, and comment out the first block.

choose your weapon – convert from int to float or keep float values
Format of the OBJ file
import c4d
from c4d import gui

# This path should point to your .OBJ file you want to read in.
pts_file = r"C:\Users\Christoph\OneDrive\Desktop\test3.obj"

# Main function
def main():
    doc = c4d.documents.GetActiveDocument()
    num_points = sum(1 for line in open(pts_file))
    print("Lines: " + str(num_points))
    new_obj = c4d.PolygonObject(num_points,0)
    vtx_color_tag = c4d.VertexColorTag(num_points)
    vtx_color_tag.SetPerPointMode(True)
    data = vtx_color_tag.GetDataAddressW()
    print (vtx_color_tag)
    print (data)
    points = new_obj.GetAllPoints()
    normals = new_obj.GetAllPoints()
    colors = new_obj.GetAllPoints()

    with open(pts_file,"r") as pts:
        idx = 0
        for line in pts:
            values = line.split(" ")
            points[idx] = c4d.Vector(float(values[0]),float(values[1]),float(values[2]))
            
            # Use this code line to convert RGB float values to integer RGB values - like 0.354 to 255.
            # colors[idx] = c4d.Vector(float(values[3]),float(values[4]),float(values[5]))
            
            # Use this code line to convert integer RGB values to float values - like 255 to 0.354.
            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])
            idx += 1
        new_obj.SetAllPoints(points)
        vtx_color_tag[c4d.ID_VERTEXCOLOR_DRAWPOINTS] = True
        new_obj.InsertTag(vtx_color_tag)
        doc.InsertObject(new_obj)
        c4d.EventAdd()

# Execute main()
if __name__=='__main__':
    main()