Skip to content

Instantly share code, notes, and snippets.

@WesleyE
Last active August 29, 2015 14:26
Show Gist options
  • Save WesleyE/050f8ae6b077c02e8fa9 to your computer and use it in GitHub Desktop.
Save WesleyE/050f8ae6b077c02e8fa9 to your computer and use it in GitHub Desktop.
"""Houdini Import Script - Work In Progress
Check http://scripts.wesleyelfring.nl/minecraft-import-script-for-houdini/
"""
import hou,os,sys
# Check for the required modules, we need pyyaml and pymclevel in the $JOB/scripts/ folder.
job = hou.expandString('$JOB')
sys.path.insert(0, os.path.join(job, "scripts", "pymclevel"))
sys.path.insert(0, os.path.join(job, "scripts"))
sys.path.insert(0, os.path.join(job, "scripts", "pyyaml", "lib"))
try:
import yaml
from pymclevel import mclevel,ChunkNotPresent,BoundingBox
except ImportError:
raise ImportError("Could not load the required modules. Please read the documentation about downloading MCLevel and PyYAML")
node = hou.pwd()
geo = node.geometry()
class HoudiniMinecraftImport:
# Block flags
TOP_BLOCKED = 0x01
BOTTOM_BLOCKED = 0x02
LEFT_BLOCKED = 0x04
RIGHT_BLOCKED = 0x08
FRONT_BLOCKED = 0x10
BACK_BLOCKED = 0x20
#Setup full cube
full_point_positions = [(0,0,0), (1,0,0), (1,1,0), (0,1,0), (0,0,1), (1,0,1), (1,1,1), (0,1,1)]
full_poly_point_indices = [(0,1,2), (2,3,0), (1,5,2), (5,6,2), (5,4,6), (4,7,6), (4,0,7), (0,3,7), (7,3,6), (3,2,6), (5,1,4), (1,0,4)]
def __init__(self):
self.geo = hou.pwd().geometry()
self.node = hou.pwd()
#Setup Attributes
self.blockIdAttrib = self.geo.addAttrib(hou.attribType.Prim, "blockId", -1)
self.blockTypeAttrib = self.geo.addAttrib(hou.attribType.Prim, "blockType", -1)
self.blockChunkAttrib = self.geo.addAttrib(hou.attribType.Prim, "blockChunk", -1)
self.loadedEntities = set()
self.LoadChunks()
def LoadChunks(self):
level = mclevel.fromFile(node.evalParm("world_folder"))
print level.playerSpawnPosition()
position = self.node.evalParmTuple("position")
size = self.node.evalParmTuple("size")
#Try to load the first chunk, if it fails, give a hint to the user
with hou.InterruptableOperation(
"Loading chunks", open_interrupt_dialog=True) as operation:
box = BoundingBox(position, size)
print box.origin
#hou.ui.displayMessage("Chunk count: " + str(box.chunkCount))
id = 0
for (chunk, slices, point) in level.getChunkSlices(box):
self.LoadChunk(chunk, point, id)
id = id + 1
percent = float(id) / float(box.chunkCount)
operation.updateProgress(percent)
def LoadChunk(self, chunk, offset, id):
#To be able to cull the bottom and top
cullTopBottom = node.evalParmTuple("cull_top_bottom")
blocks = chunk.Blocks[:,:,cullTopBottom[0]:cullTopBottom[1]] #:,:,0:180
#Loop over all the blocks, take note that the array is indexed x, z, y
x = 0
z = 0
y = 0
for blocksX in blocks:
for blocksZ in blocksX:
for block in blocksZ:
#Check if air
if int(block) == 0:
y += 1
continue
#Calculate the position of this block and check if we already loaded this one
#We need to do this since the slices may contain parts of chunks that are already loaded
newPos = (x + offset[0], y, z + offset[2])
if newPos in self.loadedEntities:
y += 1
continue
#Add the block to the loaded entities
self.loadedEntities.add(newPos)
bitflags = 0x00
bitflags = self.checkNeighbourBlocks(blocks, x, z, y)
prims = self.BuildCube((x,z,y), bitflags)
for prim in prims:
prim.setAttribValue(self.blockTypeAttrib, int(block))
prim.setAttribValue(self.blockChunkAttrib, int(id))
prim.setAttribValue(self.blockIdAttrib, int(x * z * (y + 1)))
#self.geo.transformPrims(prims, hou.hmath.buildTranslate(x + offset[0], y, z + offset[2] + 3))
self.geo.transformPrims(prims, hou.hmath.buildTranslate(x + offset[0], y, z + offset[2]))
y += 1
y = 0
z += 1
z = 0
x += 1
def BuildCube(self, pos, blockedFlags):
#Copy the full box
point_positions = list(self.full_point_positions)
poly_point_indices = list(self.full_poly_point_indices)
if blockedFlags & HoudiniMinecraftImport.LEFT_BLOCKED:
#Draw left
poly_point_indices.remove((0,1,2))
poly_point_indices.remove((2,3,0))
if blockedFlags & HoudiniMinecraftImport.FRONT_BLOCKED:
#Remove front
poly_point_indices.remove((1,5,2))
poly_point_indices.remove((5,6,2))
if blockedFlags & HoudiniMinecraftImport.RIGHT_BLOCKED:
#Remove right
poly_point_indices.remove((5,4,6))
poly_point_indices.remove((4,7,6))
if blockedFlags & HoudiniMinecraftImport.BACK_BLOCKED:
#Remove back
poly_point_indices.remove((4,0,7))
poly_point_indices.remove((0,3,7))
if blockedFlags & HoudiniMinecraftImport.TOP_BLOCKED:
#Remove top
poly_point_indices.remove((7,3,6))
poly_point_indices.remove((3,2,6))
if blockedFlags & HoudiniMinecraftImport.BOTTOM_BLOCKED:
#Remove bottom
poly_point_indices.remove((5,1,4))
poly_point_indices.remove((1,0,4))
#Skip building the block if every side has been blocked
if len(poly_point_indices) == 0:
return []
# Create all the points.
points = []
for position in point_positions:
points.append(self.geo.createPoint())
points[-1].setPosition(position)
#points[-1].setAttribValue("N", (0, 0, 0))
# Create the polygons
cubePolys = []
for point_indices in poly_point_indices:
poly = geo.createPolygon()
for point_index in point_indices:
poly.addVertex(points[point_index])
cubePolys.append(poly)
return cubePolys
def checkNeighbourBlocks(self, blocks, x, z, y):
bitflags = 0b0000
#Check if the top block has air
if y+1 < 255:
if blocks[x][z][y+1] != 0:
bitflags = bitflags | HoudiniMinecraftImport.TOP_BLOCKED
#Check bottom block has air
if y > 0:
if blocks[x][z][y-1] != 0:
bitflags = bitflags | HoudiniMinecraftImport.BOTTOM_BLOCKED
#Check left block has air
if x > 0:
if blocks[x-1][z][y] != 0:
bitflags = bitflags | HoudiniMinecraftImport.BACK_BLOCKED
#Check right block has air
if x < 15:
if blocks[x+1][z][y] != 0:
bitflags = bitflags | HoudiniMinecraftImport.FRONT_BLOCKED
#Check front block has air
if z < 15:
if blocks[x][z+1][y] != 0:
bitflags = bitflags | HoudiniMinecraftImport.RIGHT_BLOCKED
#Check back block has air
if z > 0:
if blocks[x][z-1][y] != 0:
bitflags = bitflags | HoudiniMinecraftImport.LEFT_BLOCKED
return bitflags
HoudiniMinecraftImport()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment