Jump to content
moth0027

Help with a cmiVFX tutorial - Houdini XML Based Procedural Cities

Recommended Posts

Hello ODFORCE community!

I've started one of the cmiVFX tutorials and I've run into an error I can't figure out! I should mention that I am fairly new to Python scripting which is why I wanted to try out this amazing looking tutorial.

Essentially the tutorial is guiding you through the process of taking XML map data and creating a cityscape. Using Python, coordinates are extracted from the XML file to create the map and then variables such as 'highway' and 'building' are extracted to be used to customise how the data is translated into geometry.

Everything worked fine until I had to create a local variable to group all the roads together to apply a polywire to them without effecting the other geometry (buildings etc...).

The code I used to do this was:

if geo.findGlobalAttrib("varmap") is None:

geo.addAttrib(hou.attribType.Global,"varmap","")

followed by:

type_attrib = geo.addAttrib(hou.attribType.Prim,"Type",0)

map_attrib = type_attrib.name()+' -> ' +type_attrib.name().upper()

geo.setGlobalAttribValue("varmap",map_attrib)

The error I'm getting is this:

Error: Python error: Traceback (most recent call last):

File "<stdin>", line 155, in <module>

File "<stdin>", line 152, in createCity

File "<stdin>", line 63, in handleWays

File "/Library/Frameworks/Houdini.framework/Versions/12.1.33/Resources/houdini/python2.6libs/hou.py", line 16371, in setGlobalAttribValue

return_hou.Geometry_setGlobalAttribValue(*args)

OperationFailed: The attempted operation failed.

No attribute with this name, type, and size 1 exists

I originally thought I must have typed something wrong and searched for any mistakes. Eventually I decided the best thing to do was try comparing the completed project files that came with the tutorial however when I loaded the OTL and .hip file I had the same error.

I have no idea if the tutorial was created on an older version of Houdini. Is it possible that the code in the tutorial is out of date? If so how would I need to change it to make this work?

If anyone could shed some light on this it would be amazing!

Thank you all in advance,

Best,

Moth

post-8290-0-09635800-1354227008_thumb.pn

Share this post


Link to post
Share on other sites

Houdini 12 now longer allows you to set varmap attributes like you once could. SESI also made hou.Geometry.addAttrib properly create the local variable for an attribute, which is what this code that is erroring is attempting to do. Most likely you can now omit anything that has to do with creating/setting the varmap global attribute.

  • Like 1

Share this post


Link to post
Share on other sites

Thank you Graham for your really quick response!

Oh dear... that's good news... sort of. At least I haven't done anything wrong. I shall attempt to do what you recommend by omitting the creating and setting the global attribute 'varmap' and tell you how it goes.

Thanks again!

Share this post


Link to post
Share on other sites

Hello again Graham,

I just wanted to thank you again. I did what you recommended and it has worked. I didn't have to create the Global Variable - one was created for me allowing me to use it in the polywire node.

I shall post an image of the city tomorrow when I complete the tutorial.

Thanks again and all the best!

Share this post


Link to post
Share on other sites

if you manage to get it working please share the updated code,

I'm sure many people would appreciate this (also maybe send it to the CMIVFX guys)

Share this post


Link to post
Share on other sites

like graham says, you only need to put the # sign befor the lines with the geo.xxx:

# if geo.findGlobalAttrib("varmap") is None:

# geo.addAttrib(hou.attribType.Global,"varmap","")

# geo.setGlobalAttribValue("varmap",map_attrib)

Share this post


Link to post
Share on other sites

It works with the following code:



----------------------------------------------------------------------------------------------

# This code is called when instances of this SOP cook.
geo = hou.pwd().geometry()

# Add code to modify the contents of geo.

def createCity():
    import xml.dom.minidom

    sizeMultiplier = hou.pwd().parm('sizeMultiplier').evalAsFloat()
    MapFile = hou.pwd().parm('MapFile').evalAsString()
    if(MapFile==''):
        print('Please specify a file name')
        return
    if not(MapFile.endswith('.osm')) and not(MapFile.endswith('.xml')):
        print('Bad file type, please use only .osm or .xml data')
        return
    map = xml.dom.minidom.parse(MapFile)

    if(map.documentElement.tagName != "osm"):
        print ('Bad File Type')
        return
   
    pointsIDs = []
    points = []

    def handleNodes(xmlData):
        bounds = xmlData.getElementsByTagName("bounds")[0]
        minlat = float(bounds.getAttribute('minlat'))
        maxlat = float(bounds.getAttribute('maxlat'))
        minlon = float(bounds.getAttribute('minlon'))
        maxlon = float(bounds.getAttribute('maxlon'))

        normalizingFactor = sizeMultiplier / max((maxlon-minlon),(maxlat-minlat))

        nodes = xmlData.getElementsByTagName('node')
        for node in nodes:
            lat = float(node.getAttribute('lat'))
            lon = float(node.getAttribute('lon'))

            if lat<minlat or lat>maxlat or lon<minlon or lon>maxlon :
                continue

            normalizedLat = (lat-minlat) * normalizingFactor
            normalizedLon = (lon-minlon) * normalizingFactor

            centeredLat = normalizedLat - (maxlat-minlat)*normalizingFactor/2
            centeredLon = normalizedLon - (maxlon-minlon)*normalizingFactor/2

            point = geo.createPoint()
            point.setPosition((centeredLon,0,-centeredLat))

            pointsIDs.append(int(node.getAttribute('id')))
            points.append(point)

    def handleWays(xmlData):

#        if geo.findGlobalAttrib("varmap") is None:
#            geo.addAttrib(hou.attribType.Global,"varmap","")

        color_attrib = geo.addAttrib(hou.attribType.Prim,"Cd",(1.0,1.0,1.0))
        type_attrib = geo.addAttrib(hou.attribType.Prim,"Type",0)
        map_attrib = type_attrib.name()+' -> ' +type_attrib.name().upper()
#        geo.setGlobalAttribValue("varmap",map_attrib)

        width_attrib = geo.addAttrib(hou.attribType.Point,"width",0.02)
        map_attrib = width_attrib.name()+' -> ' +width_attrib.name().upper()
#        geo.setGlobalAttribValue("varmap",map_attrib)

        ways = xmlData.getElementsByTagName('way')
        for way in ways:
            wayPoints = []
            nodes = way.getElementsByTagName('nd')
            tags = way.getElementsByTagName('tag')

            isACarRoad = 0
            isABuilding = 0
            isAPark = 0
            isACoastline = 0
            width = 0.02
            layer = 0

            for tag in tags:
                tagType = str(tag.getAttribute('k'))
                if tagType == 'highway':
                    subType = str(tag.getAttribute('v'))
                    if not(subType =='pedestrian') and not(subType =='steps') and not(subType =='footway') and not(subType =='cycleway'):
                        isACarRoad = 1
                elif tagType == 'building':
                    temp = str(tag.getAttribute('v'))
                    if temp=='yes':
                        isABuilding = 1
                elif tagType == 'leisure':
                    temp = str(tag.getAttribute('v'))
                    if temp == 'park':
                        isAPark = 1
                elif tagType == 'natural':
                    temp = str(tag.getAttribute('v'))
                    if temp == 'coastline':
                        isACoastline = 1
                elif tagType == 'layer':
                    layer = int(tag.getAttribute('v'))

            for node in nodes:
                ref = int(node.getAttribute('ref'))
                try:
                    index = pointsIDs.index(ref)
                except ValueError:
                    index = -1

                if (index != -1):
                    wayPoints.append(points[index])
            if (isACarRoad == 1 or isABuilding ==1 or isAPark ==1 or isACoastline ==1):
                poly = geo.createPolygon()
   
                if(isABuilding == 1):
                    poly.setIsClosed(1)
                    poly.setAttribValue(color_attrib,(0.9,0.9,0.9))
                    poly.setAttribValue(type_attrib,1)
                elif(isAPark ==1):
                    poly.setIsClosed(1)
                    poly.setAttribValue(color_attrib,(0.3,1.0,0.3))
                    poly.setAttribValue(type_attrib,2)
                elif(isACoastline ==1):
                    poly.setIsClosed(1)
                    poly.setAttribValue(color_attrib,(0.6,0.6,0.6))
                    poly.setAttribValue(type_attrib,3)
                elif(isACarRoad ==1):
                    poly.setIsClosed(0)
                    poly.setAttribValue(type_attrib,4)
                    if(subType=='motorway' or subType =='motorway_link'):
                        poly.setAttribValue(color_attrib,(0.5,0.75,0.85))
                        width = 0.035
                    elif(subType=='primary' or subType =='primary_link'):
                        poly.setAttribValue(color_attrib,(1.0,0.5,0.5))
                        width = 0.035
                    elif(subType=='secondary' or subType =='secondary_link'):
                        poly.setAttribValue(color_attrib,(1.0,0.8,0.65))
                        width = 0.025
                    elif(subType=='trunk' or subType =='trunk_link'):
                        poly.setAttribValue(color_attrib,(0.7,0.85,0.7))
                        width = 0.025
                    else:
                        width = 0.03
       
                for point in wayPoints:
                    poly.addVertex(point)
                    point.setAttribValue(width_attrib,width)
#                    pointPos = point.position()
#                    point.setPosition((pointPos[0],layer,pointPos[2]))

    handleNodes(map)
    handleWays(map)
    map.unlink()

createCity()

Edited by lubitel

Share this post


Link to post
Share on other sites

Thanks for full code. Was getting weird syntax errors along the tutorial. Now all works!

Edited by ilionic

Share this post


Link to post
Share on other sites


Posting in Code Block for Easier Reading


# This code is called when instances of this SOP cook.

geo = hou.pwd().geometry()

# Add code to modify the contents of geo.

def createCity():

    import xml.dom.minidom

    sizeMultiplier = hou.pwd().parm('sizeMultiplier').evalAsFloat()

    MapFile = hou.pwd().parm('MapFile').evalAsString()

    if(MapFile==''):

        print('Please specify a file name')

        return

    if not(MapFile.endswith('.osm')) and not(MapFile.endswith('.xml')):

        print('Bad file type, please use only .osm or .xml data')

        return

    map = xml.dom.minidom.parse(MapFile)

    if(map.documentElement.tagName != "osm"):

        print ('Bad File Type')

        return

   

    pointsIDs = []

    points = []

    def handleNodes(xmlData):

        bounds = xmlData.getElementsByTagName("bounds")[0]

        minlat = float(bounds.getAttribute('minlat'))

        maxlat = float(bounds.getAttribute('maxlat'))

        minlon = float(bounds.getAttribute('minlon'))

        maxlon = float(bounds.getAttribute('maxlon'))

        normalizingFactor = sizeMultiplier / max((maxlon-minlon),(maxlat-minlat))

        nodes = xmlData.getElementsByTagName('node')

        for node in nodes:

            lat = float(node.getAttribute('lat'))

            lon = float(node.getAttribute('lon'))

            if lat<minlat or lat>maxlat or lon<minlon or lon>maxlon :

                continue

            normalizedLat = (lat-minlat) * normalizingFactor

            normalizedLon = (lon-minlon) * normalizingFactor

            centeredLat = normalizedLat - (maxlat-minlat)*normalizingFactor/2

            centeredLon = normalizedLon - (maxlon-minlon)*normalizingFactor/2

            point = geo.createPoint()

            point.setPosition((centeredLon,0,-centeredLat))

            pointsIDs.append(int(node.getAttribute('id')))

            points.append(point)

    def handleWays(xmlData):

#        if geo.findGlobalAttrib("varmap") is None:

#            geo.addAttrib(hou.attribType.Global,"varmap","")

        color_attrib = geo.addAttrib(hou.attribType.Prim,"Cd",(1.0,1.0,1.0))

        type_attrib = geo.addAttrib(hou.attribType.Prim,"Type",0)

        map_attrib = type_attrib.name()+' -> ' +type_attrib.name().upper()

#        geo.setGlobalAttribValue("varmap",map_attrib)

        width_attrib = geo.addAttrib(hou.attribType.Point,"width",0.02)

        map_attrib = width_attrib.name()+' -> ' +width_attrib.name().upper()

#        geo.setGlobalAttribValue("varmap",map_attrib)

        ways = xmlData.getElementsByTagName('way')

        for way in ways:

            wayPoints = []

            nodes = way.getElementsByTagName('nd')

            tags = way.getElementsByTagName('tag')

            isACarRoad = 0

            isABuilding = 0

            isAPark = 0

            isACoastline = 0

            width = 0.02

            layer = 0

            for tag in tags:

                tagType = str(tag.getAttribute('k'))

                if tagType == 'highway':

                    subType = str(tag.getAttribute('v'))

                    if not(subType =='pedestrian') and not(subType =='steps') and not(subType =='footway') and not(subType =='cycleway'):

                        isACarRoad = 1

                elif tagType == 'building':

                    temp = str(tag.getAttribute('v'))

                    if temp=='yes':

                        isABuilding = 1

                elif tagType == 'leisure':

                    temp = str(tag.getAttribute('v'))

                    if temp == 'park':

                        isAPark = 1

                elif tagType == 'natural':

                    temp = str(tag.getAttribute('v'))

                    if temp == 'coastline':

                        isACoastline = 1

                elif tagType == 'layer':

                    layer = int(tag.getAttribute('v'))

            for node in nodes:

                ref = int(node.getAttribute('ref'))

                try:

                    index = pointsIDs.index(ref)

                except ValueError:

                    index = -1

                if (index != -1):

                    wayPoints.append(points[index])

            if (isACarRoad == 1 or isABuilding ==1 or isAPark ==1 or isACoastline ==1):

                poly = geo.createPolygon()

   

                if(isABuilding == 1):

                    poly.setIsClosed(1)

                    poly.setAttribValue(color_attrib,(0.9,0.9,0.9))

                    poly.setAttribValue(type_attrib,1)

                elif(isAPark ==1):

                    poly.setIsClosed(1)

                    poly.setAttribValue(color_attrib,(0.3,1.0,0.3))

                    poly.setAttribValue(type_attrib,2)

                elif(isACoastline ==1):

                    poly.setIsClosed(1)

                    poly.setAttribValue(color_attrib,(0.6,0.6,0.6))

                    poly.setAttribValue(type_attrib,3)

                elif(isACarRoad ==1):

                    poly.setIsClosed(0)

                    poly.setAttribValue(type_attrib,4)

                    if(subType=='motorway' or subType =='motorway_link'):

                        poly.setAttribValue(color_attrib,(0.5,0.75,0.85))

                        width = 0.035

                    elif(subType=='primary' or subType =='primary_link'):

                        poly.setAttribValue(color_attrib,(1.0,0.5,0.5))

                        width = 0.035

                    elif(subType=='secondary' or subType =='secondary_link'):

                        poly.setAttribValue(color_attrib,(1.0,0.8,0.65))

                        width = 0.025

                    elif(subType=='trunk' or subType =='trunk_link'):

                        poly.setAttribValue(color_attrib,(0.7,0.85,0.7))

                        width = 0.025

                    else:

                        width = 0.03

       

                for point in wayPoints:

                    poly.addVertex(point)

                    point.setAttribValue(width_attrib,width)

#                    pointPos = point.position()

#                    point.setPosition((pointPos[0],layer,pointPos[2]))

    handleNodes(map)

    handleWays(map)

    map.unlink()

createCity()

Edited by paxsonsa
  • Like 1

Share this post


Link to post
Share on other sites

Hey guys. I am trying to get this working in Houdini 15. I get a few errors after pasting this code above.

 

The node errors out and when I middle click to check info I get this.

 

 

Error: python error: Traceback ( most recent call last):

File "<stdin>", line 132 in <module>

File "<stdin>", line 6, in createCity

AttributeError: 'NoneType' object has no attribute 'EvalAsFloat'

 

anyone know whats going wrong?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×