any way to export points to .prt file

   3426   8   2
User Avatar
Member
10 posts
Joined: Jan. 2017
Offline
I need a way to get particles from Houdini to pFlow in 3ds Max.
And found that tyFlow can read .prt files. So I need to get out .prt from Houdini.
I searched the whole internet and only found this old repo:
https://github.com/flipswitchingmonkey/houdini_PRTROP [github.com]

I even tried to build this for Houdini 19 but no luck...

Any other way?
User Avatar
Member
10 posts
Joined: Jan. 2017
Offline
I found this python code:
https://forums.thinkboxsoftware.com/t/houdini-exporter/12527/8 [forums.thinkboxsoftware.com]

after some changes i get rid of errors and script produce some files.
This is a code:


import sys, struct, zlib

node = hou.pwd()
geo = node.geometry()

frameNum = str(hou.intFrame()).zfill(4)
OutFilename = 'H:/Particles_%s.prt' %frameNum

particleCount = len(geo.points())

out = open(OutFilename, 'wb')

out.write(struct.pack("B", 0xc0)) # Magic numbers
out.write(struct.pack("B", 0x50))
out.write(struct.pack("B", 0x52))
out.write(struct.pack("B", 0x54))
out.write(struct.pack("B", 0x0d))
out.write(struct.pack("B", 0x0a))
out.write(struct.pack("B", 0x1a))
out.write(struct.pack("B", 0x0a))

out.write(struct.pack("<I", 56)) # Header Length
out.write(struct.pack("@32s", b"Extensible Particle Format" )) #Format Name
out.write(struct.pack("<I", 1)) # Version Number
out.write(struct.pack("<Q", particleCount)) # Particle Count
out.write(struct.pack("<I", 4)) # Reserved 4 bytes
out.write(struct.pack("<I", 6)) # Number of Channels
out.write(struct.pack("<I", 44)) # Channel definition entry length

# Write Channel Definitions

out.write(struct.pack("@32s", b"Position" )) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 3)) # number of values per particle for this channel
out.write(struct.pack("<I", 0)) # Data offset of this channel

out.write(struct.pack("@32s", b"Orientation" )) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 4)) # number of values per particle for this channel
out.write(struct.pack("<I", 12)) # Data offset of this channel

out.write(struct.pack("@32s", b"Scale" )) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 3)) # number of values per particle for this channel
out.write(struct.pack("<I", 28)) # Data offset of this channel

out.write(struct.pack("@32s", b"ShapeIndex" )) #Name of Channel
out.write(struct.pack("<I", 1)) # Data type
out.write(struct.pack("<I", 1)) # number of values per particle for this channel
out.write(struct.pack("<I", 40)) # Data offset of this channel

out.write(struct.pack("@32s", b"MtlIndex" )) #Name of Channel
out.write(struct.pack("<I", 1)) # Data type
out.write(struct.pack("<I", 1)) # number of values per particle for this channel
out.write(struct.pack("<I", 44)) # Data offset of this channel

out.write(struct.pack("@32s", b"Color" )) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 3)) # number of values per particle for this channel
out.write(struct.pack("<I", 48)) # Data offset of this channel

data = []

m = hou.Matrix4((   1, 0, 0, 0,     0, 0, 1, 0,      0, -1, 0, 0,     0, 0, 0, 1   ))  # Transform matrix to transform into 3DSMax space

for point in geo.points():

    #Transform Position
    pos = point.position()
    pos = pos*m
    data.append(pos)
    
    #Transform Orientation
    ov = point.attribValue('orient')
    x = ov[0]
    y = ov[1]
    z = ov[2]
    w = ov[3]
    orient = hou.Quaternion(x, y, z, w)
    
    orientM = hou.Matrix4(orient.extractRotationMatrix3())
    newMatrix = orientM*m
    
    orient = hou.Quaternion(newMatrix)    
    
    data.append(orient)
    
    data.append(point.attribValue('pscale'))
    data.append(point.attribValue('meshID'))
    data.append(point.attribValue('MtlIndex'))

z = zlib.compressobj()

for p in data:
    if type(p) is int:
        x = (struct.pack("<i", p))
        compressedData = z.compress(x)
        out.write(compressedData)
    else:
        for v in p:
            x = (struct.pack("<f", v))
            compressedData = z.compress(x)
            out.write(compressedData)

compressedData = z.flush()
out.write(compressedData)
out.close()

I can read this .prt files in max but data is incomplete. KrakatoaPRTLoader gives error "zlib_reader::read() Unexpected EOF"...
Any thoughts?
Edited by POLPPMnietek - Jan. 23, 2023 21:18:03
User Avatar
Member
249 posts
Joined: March 2013
Offline
I compiled that plugin for H18 a while ago, it should compile in H19, what errors did you get?
I could take a look at compiling it again, see if it's borked

L
I'm not lying, I'm writing fiction with my mouth.
User Avatar
Member
10 posts
Joined: March 2017
Offline
刘易斯_T
I compiled that plugin for H18 a while ago, it should compile in H19, what errors did you get?
I could take a look at compiling it again, see if it's borked

L
How to compile can you make a tutorial
User Avatar
Member
185 posts
Joined: Feb. 2017
Offline
Does anyone know what to do?
User Avatar
Member
249 posts
Joined: March 2013
Offline
Seems it's still somewhat useful, let me compile it, I'll try to do it tonight.


L
I'm not lying, I'm writing fiction with my mouth.
User Avatar
Member
1 posts
Joined: Feb. 2020
Offline
It's seems working if comment out some channels:

import sys, struct, zlib

node = hou.pwd()
geo = node.geometry()

frameNum = str(hou.intFrame()).zfill(4)
OutFilename = 'D://Projects//Particles_%s.prt' %frameNum

particleCount = len(geo.points())

out = open(OutFilename, 'wb')

out.write(struct.pack("B", 0xc0)) # Magic numbers
out.write(struct.pack("B", 0x50))
out.write(struct.pack("B", 0x52))
out.write(struct.pack("B", 0x54))
out.write(struct.pack("B", 0x0d))
out.write(struct.pack("B", 0x0a))
out.write(struct.pack("B", 0x1a))
out.write(struct.pack("B", 0x0a))

out.write(struct.pack("<I", 56)) # Header Length
out.write(struct.pack("@32s", bytes("Extensible Particle Format", 'ascii'))) #Format Name
out.write(struct.pack("<I", 1)) # Version Number
out.write(struct.pack("<Q", particleCount)) # Particle Count
out.write(struct.pack("<I", 4)) # Reserved 4 bytes
out.write(struct.pack("<I", 4)) # Number of Channels
out.write(struct.pack("<I", 44)) # Channel definition entry length

# Write Channel Definitions

out.write(struct.pack("@32s", bytes("Position", 'ascii'))) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 3)) # number of values per particle for this channel
out.write(struct.pack("<I", 0)) # Data offset of this channel

out.write(struct.pack("@32s", bytes("Orientation", 'ascii'))) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 4)) # number of values per particle for this channel
out.write(struct.pack("<I", 12)) # Data offset of this channel

out.write(struct.pack("@32s", bytes("Scale", 'ascii'))) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 3)) # number of values per particle for this channel
out.write(struct.pack("<I", 28)) # Data offset of this channel

#out.write(struct.pack("@32s", bytes("ShapeIndex", 'ascii'))) #Name of Channel
#out.write(struct.pack("<I", 1)) # Data type
#out.write(struct.pack("<I", 1)) # number of values per particle for this channel
#out.write(struct.pack("<I", 40)) # Data offset of this channel

#out.write(struct.pack("@32s", bytes("MtlIndex", 'ascii'))) #Name of Channel
#out.write(struct.pack("<I", 1)) # Data type
#out.write(struct.pack("<I", 1)) # number of values per particle for this channel
#out.write(struct.pack("<I", 44)) # Data offset of this channel

out.write(struct.pack("@32s", bytes("Color", 'ascii'))) #Name of Channel
out.write(struct.pack("<I", 4)) # Data type
out.write(struct.pack("<I", 3)) # number of values per particle for this channel
out.write(struct.pack("<I", 40)) # Data offset of this channel

data = []

m = hou.Matrix4((   1, 0, 0, 0,     0, 0, 1, 0,      0, -1, 0, 0,     0, 0, 0, 1   ))  # Transform matrix to transform into 3DSMax space

for point in geo.points():

    #Transform Position
    pos = point.position()
    pos = pos*m
    data.append(pos)
    
    #Transform Orientation
    ov = point.attribValue('orient')
    x = ov[0]
    y = ov[1]
    z = ov[2]
    w = ov[3]
    orient = hou.Quaternion(x, y, z, w)
    
    orientM = hou.Matrix4(orient.extractRotationMatrix3())
    newMatrix = orientM*m
    
    orient = hou.Quaternion(newMatrix)    
    
    data.append(orient)
    
    data.append(point.attribValue('pscale'))
#    data.append(point.attribValue('meshID'))
#    data.append(point.attribValue('MtlIndex'))
    data.append(point.attribValue('Cd'))

z = zlib.compressobj()

for p in data:
    if type(p) is int:
        x = (struct.pack("<i", p))
        compressedData = z.compress(x)
        out.write(compressedData)
    else:
        for v in p:
            x = (struct.pack("<f", v))
            compressedData = z.compress(x)
            out.write(compressedData)

compressedData = z.flush()
out.write(compressedData)
out.close()
Edited by _rainman_ - May 27, 2023 12:14:51
User Avatar
Member
10 posts
Joined: March 2017
Offline
There is already a compiled version here

https://github.com/CycloneRing/HoudiniPlugins/releases/tag/h19 [github.com]
User Avatar
Member
10 posts
Joined: May 2016
Offline
zuoyuanle
There is already a compiled version here

https://github.com/CycloneRing/HoudiniPlugins/releases/tag/h19 [github.com]

I tried using this with 19.5.534 and have not had any luck getting it to show up in Houdini. I'm copying the .dll file to the houdini DSO folder. Should I be putting it somewhere else? Not seeing a PRT rop node in either the OUT context or in a ropnet.
  • Quick Links