├── Cells.py ├── Floor.py ├── Main.py ├── README.txt ├── Roof.py ├── Shaders.py ├── UI.py ├── Utilities.py └── projectFiles.zip /Cells.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | import random 3 | 4 | 5 | 6 | def startCell(cellSize): 7 | ''' 8 | Input: cell Size 9 | 10 | - Create the first cell 11 | 12 | Output: cell name, centerPosition 13 | ''' 14 | 15 | print('cellSize: {}'.format(cellSize)) 16 | 17 | # create object: startCell 18 | cell = cmds.polyPlane(n='cell', w=cellSize, h=cellSize, sx=1, sy=1) 19 | 20 | # get objectCenter 21 | XYZ = cmds.objectCenter(cell[0], gl=True) 22 | x = str(int(XYZ[0])) 23 | z = str(int(XYZ[2])) 24 | xz = x +' ' +z 25 | print('startCell position: {}'.format(xz)) 26 | 27 | output = (cell[0], xz) 28 | return output 29 | 30 | 31 | def addCell(cellSize, cellList, setList): 32 | ''' 33 | Input: cellSize, list of cells and list of cell positions 34 | 35 | - selects a random cell and checks for neigbours 36 | - a neighbours cell is created 37 | ''' 38 | 39 | con = True 40 | while con: 41 | 42 | # shuffle list 43 | random.shuffle(cellList) 44 | 45 | cell = cellList[0] 46 | XYZ = cmds.objectCenter(cell, gl=True) 47 | posX = XYZ[0] 48 | posZ = XYZ[2] 49 | print('\ncheck neighbouers') 50 | print('list size: {}'.format(len(cellList))) 51 | print('random index: {}'.format(0)) 52 | print('selected cell: {}'.format(cell)) 53 | print('cell posX: {}'.format(posX)) 54 | print('cell posZ: {}'.format(posZ)) 55 | 56 | 57 | # Calculate neighbours position 58 | topCellX = str(int(posX)) 59 | topCellZ = str(int(posZ + cellSize)) 60 | bottomCellX = str(int(posX)) 61 | bottomCellZ = str(int(posZ - cellSize)) 62 | leftCellX = str(int(posX + cellSize)) 63 | leftCellZ = str(int(posZ)) 64 | rightCellX = str(int(posX - cellSize)) 65 | rightCellZ = str(int(posZ)) 66 | print('topCell X: {} Z: {}'.format(topCellX, topCellZ)) 67 | print('bottomCell X: {} Z: {}'.format(bottomCellX, bottomCellZ)) 68 | print('leftCell X: {} Z: {}'.format(leftCellX, leftCellZ)) 69 | print('rightCell X: {} Z: {}'.format(rightCellX, rightCellZ)) 70 | 71 | # Concatenate values 72 | topxz = topCellX +' ' +topCellZ 73 | bottomxz = bottomCellX +' ' + bottomCellZ 74 | leftxz = leftCellX +' ' +leftCellZ 75 | rightxz = rightCellX +' ' +rightCellZ 76 | print(topxz) 77 | print(bottomxz) 78 | print(leftxz) 79 | print(rightxz) 80 | 81 | # Set neighbours position 82 | neighbours = {topxz, bottomxz, leftxz, rightxz} 83 | newNeighours = list(neighbours.difference(setList)) 84 | print('set newnewNeighours: {}'.format(newNeighours)) 85 | 86 | 87 | if len(newNeighours) != 0: 88 | 89 | # Select random neihgours position 90 | rand = random.randint(0, len(newNeighours)-1) 91 | neighbour = newNeighours[0].split() 92 | 93 | con = False 94 | 95 | 96 | neighbourX = neighbour[0] 97 | neighbourZ = neighbour[1] 98 | print('neighbourX: {}'.format(neighbourX)) 99 | print('neighbourZ: {}'.format(neighbourZ)) 100 | 101 | # Generate new cell 102 | cell = cmds.polyPlane(n='cell', w=cellSize, h=cellSize, sx=1, sy=1) 103 | cmds.move(neighbourX, 0, neighbourZ) 104 | 105 | # Concatenate Position 106 | xz = neighbourX +' ' +neighbourZ 107 | 108 | output = (cell[0], xz) 109 | return output -------------------------------------------------------------------------------- /Floor.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | import sys 3 | import random 4 | 5 | 6 | import Utilities 7 | 8 | sys.path.append('C:/Users\12213119/Documents/maya/2020/scripts/Lab/genHouse') 9 | reload(Utilities) 10 | 11 | 12 | 13 | def genFloors(numFloors, floorHeight, cellList, setList): 14 | ''' 15 | if (number of floors > 0) 16 | 17 | z = 1 18 | for x in range(numFloors) 19 | 20 | step 2: Create a number of floors 21 | 22 | - floorList = setList 23 | - rooflist = setLIst 24 | - remove a RANDOM number of items from lists 25 | - create polyPlanes using position from floorList +z 26 | 27 | - combine copy cells 28 | - merge points 29 | - extrude copy cells 30 | - delete top/bottom faces 31 | 32 | - z=z+1 33 | ''' 34 | 35 | floorList = setList 36 | rooflist = cellList 37 | 38 | print('floorList: {}'.format(floorList)) 39 | print('rooflist: {}'.format(rooflist)) 40 | 41 | # generate ground floor 42 | if (numFloors != 0): 43 | 44 | print('Ground Foor') 45 | 46 | # move Roofs 1 level 47 | sel = cmds.select( 'Roof_:*' ) 48 | objects = cmds.ls(sl=True, g=True) 49 | cmds.move(floorHeight, y=True) 50 | cmds.select( clear=True ) 51 | 52 | # copy cells 53 | sel = cmds.select( 'Cell_:*' ) 54 | objects = cmds.ls(sl=True, g=True) 55 | cmds.duplicate(n='cell') 56 | cmds.select( clear=True ) 57 | 58 | # create ground floor 59 | sel = cmds.select( 'Floor_:*' ) 60 | objects = cmds.ls(sl=True, g=True) 61 | cmds.polyUnite(ch=False, n='GroundFloor' ) 62 | cmds.polyMergeVertex( d=0.15 ) 63 | cmds.polyExtrudeFacet(ty=floorHeight) 64 | cmds.select( clear=True ) 65 | 66 | # delete top/down faces 67 | sel = cmds.select( 'Floor_:*' ) 68 | objects = cmds.ls(sl=True, g=True) 69 | Utilities.facesDel(objects[0]) 70 | #cmds.select( clear=True ) 71 | 72 | # layout UV 73 | Utilities.layoutUV(objects[0],3) 74 | cmds.select( clear=True ) 75 | 76 | 77 | # generate upper floors 78 | if (numFloors > 0): 79 | 80 | for x in range(numFloors): 81 | 82 | print('Floor_{}'.format(x+1)) 83 | 84 | 85 | 86 | def genWindow(h=8): 87 | 88 | # create: Glass Mesh 89 | #base = cmds.polyPlane(n='base', w=h/2, h=h, sx=1, sy=1) 90 | 91 | # create: Frame Mesh 92 | frame = cmds.polyPlane(n='frame', w=h/2, h=h, sx=1, sy=1) 93 | cmds.polyExtrudeEdge(kft=True,lty=h/h) 94 | cmds.delete(frame[0]+'.f[0]') 95 | cmds.polyExtrudeFacet(kft=True,ltz=float(h)/10.0/4.0) 96 | sel = cmds.select(frame[0]+'.f[9]',frame[0]+'.f[11]',frame[0]+'.f[13]',frame[0]+'.f[15]') 97 | cmds.polyExtrudeFacet(kft=True, ltz=float(h)/20.0) 98 | sel = cmds.select(frame[0]+'.f[17]',frame[0]+'.f[19]',frame[0]+'.f[21]',frame[0]+'.f[23]') 99 | cmds.polyExtrudeFacet(kft=True, ltz=float(h)/40.0) 100 | cmds.polyBevel3(frame[0]+'.f[0:63]', offset= float(h)/1000.0 ) 101 | 102 | # create: Deco Mesh 103 | deco = cmds.polyPlane(n='deco', w=h/2, h=h, sx=2, sy=h/(h/4)) 104 | cmds.polyBevel3(deco[0]+'.e[*]', offset= float(h)/100.0 ) 105 | 106 | # list: big faces 107 | selList = [] 108 | for x in range(cmds.polyEvaluate(deco[0], face=True)-1): 109 | faceSize = Utilities.getFaceSqr(deco[0],x) 110 | if (faceSize > float(h)/4.0): # delete big face size 111 | selList.append(deco[0]+'.f[{}]'.format(x)) 112 | print('faceSize: {}'.format(faceSize)) 113 | 114 | # delete faces 115 | cmds.polyDelFacet( selList ) 116 | 117 | # exrude: deco Mesh 118 | cmds.polyExtrudeFacet(deco[0], kft=True, ltz=float(h)/40.0) 119 | numFaces= cmds.polyEvaluate(deco[0], face=True) 120 | 121 | window = cmds.polyUnite(frame[0], deco[0], name='window', ch=0, mergeUVSets=1) 122 | cmds.xform( p=True, ro=[90,0,0] ) 123 | cmds.makeIdentity(apply=True, rotate=True ) # freeTransformation 124 | 125 | 126 | def genDoor(h, floorH=15): 127 | base = cmds.polyPlane(sx=1, sy=1, h=h, w=h/2, n='tempdoor') 128 | cmds.polyExtrudeFacet(base[0]+'.f[*]', ltz= float(h/h)/4.0 ) 129 | 130 | frame = cmds.polyPlane(sx=1, sy=1, h=h, w=h/2, n='frame') 131 | sel = cmds.select(frame[0]+'.e[1:3]') 132 | cmds.polyExtrudeEdge( kft=True, lty=float(h)/20.0) 133 | 134 | getVertex4 = cmds.xform( frame[0]+'.vtx[4]', q=True, objectSpace=True, t=True) 135 | getVertex5 = cmds.xform( frame[0]+'.vtx[5]', q=True, objectSpace=True, t=True) 136 | cmds.polyMoveVertex( frame[0]+'.vtx[4]', tx=-getVertex4[0]+getVertex5[0] ) 137 | getVertex6 = cmds.xform( frame[0]+'.vtx[6]', q=True, objectSpace=True, t=True) 138 | getVertex7 = cmds.xform( frame[0]+'.vtx[7]', q=True, objectSpace=True, t=True) 139 | cmds.polyMoveVertex( frame[0]+'.vtx[6]', tx=-getVertex6[0]+getVertex7[0] ) 140 | cmds.delete(frame[0]+'.f[0]') 141 | cmds.polyExtrudeFacet(frame[0]+'.f[*]', ltz=float(h/h)/2.0 ) 142 | 143 | door = cmds.polyUnite(frame[0], base[0], name='door', ch=0, mergeUVSets=1) 144 | cmds.xform( p=True, ro=[90,0,0] ) 145 | cmds.makeIdentity(apply=True, rotate=True ) # freeTransformation 146 | cmds.move(0,h/2,0) 147 | 148 | 149 | def addWindows(obj, doorHeight, maxDoors): 150 | 151 | # get number of faces 152 | faceNum = cmds.polyEvaluate(obj, face=True) 153 | 154 | for x in range(faceNum): 155 | 156 | setwindow = [0,1,1,1] 157 | random.shuffle(setwindow) 158 | #print('random value: {}'.format(setwindow[0])) 159 | 160 | # get face center position 161 | face = Utilities.faceCenter(obj,x) 162 | print(face) 163 | 164 | # get face Normal Direction 165 | normals = Utilities.getFaceNormal(obj,x) 166 | 167 | # get rot, besed on face normal direction 168 | if (int(float(normals[0])) == 1): 169 | rotY = 90 170 | print('rot: {}'.format(90)) 171 | elif (int(float(normals[0])) == -1): 172 | rotY = -90 173 | print('rot: {}'.format(-90)) 174 | elif (int(float(normals[2])) == -1): 175 | rotY = 180 176 | print('rot: {}'.format(-90)) 177 | else: 178 | rotY = 0 179 | 180 | 181 | if (setwindow[0] == 1): 182 | # gen instance: window 183 | instWindow = cmds.instance('Window_:window', n='instWindow' ) 184 | cmds.xform(instWindow[0], t=[face[0], face[1], face[2]], ro=[0 ,rotY, 0]) 185 | else: 186 | if (maxDoors > 0): 187 | Door = cmds.instance('Window_:door', n='door' ) 188 | cmds.xform(Door[0], t=[face[0], 0+(doorHeight/2), face[2]], ro=[0 ,rotY, 0]) 189 | print('create door') 190 | maxDoors = maxDoors-1 191 | 192 | -------------------------------------------------------------------------------- /Main.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | import pymel.core as pm 3 | import sys 4 | import random 5 | 6 | import UI 7 | import Cells 8 | import Roof 9 | import Floor 10 | import Shaders 11 | import Utilities 12 | 13 | 14 | # ========================================================================= Execute 15 | 16 | ''' 17 | Maya/Script Editor/Python Execute Scrip: 18 | 19 | import sys 20 | 21 | #add folder to PythonPath 22 | sys.path.append('c:/Users/12213119/Documents/maya/2020/scripts/Lab/genHouse') 23 | 24 | # print PythonPaths 25 | from pprint import pprint 26 | sys.path 27 | pprint(sys.path) 28 | 29 | # import file 30 | import Main 31 | 32 | # refresh file 33 | reload(Main) 34 | 35 | # call script 36 | Main.Main() 37 | ''' 38 | 39 | # ========================================================================= Cleanup 40 | 41 | sys.path.append('C:/Users\12213119/Documents/maya/2020/scripts/Lab/genHouse') 42 | reload(UI) 43 | reload(Cells) 44 | reload(Roof) 45 | reload(Floor) 46 | reload(Shaders) 47 | reload(Utilities) 48 | 49 | # remove existing namespaces 50 | defaults = ['UI', 'shared'] 51 | namespaces = (ns for ns in pm.namespaceInfo(lon=True) if ns not in defaults) 52 | namespaces = (pm.Namespace(ns) for ns in namespaces) 53 | for ns in namespaces: 54 | ns.remove() 55 | 56 | # delete empyt groups 57 | transforms = cmds.ls(type='transform') 58 | deleteList = [] 59 | for tran in transforms: 60 | if cmds.nodeType(tran) == 'transform': 61 | children = cmds.listRelatives(tran, c=True) 62 | if children == None: 63 | print '%s, has no childred' %(tran) 64 | deleteList.append(tran) 65 | 66 | cmds.delete(deleteList) 67 | 68 | # ========================================================================= Settings 69 | 70 | # Input 71 | cellSize = 20 72 | numbercell = int(random.uniform(3, 9)) 73 | numFloors = 3 74 | floorHeight = 15 75 | repeatUV = 3 76 | windowHeight = 8 77 | doorHeight = 10 78 | maxDoors = 2 79 | 80 | # Directory 81 | meshDir = 'C:/Users/12213119/Documents/maya/2020/scripts/Lab/genHouse/mesh/' 82 | colorFile = 'C:/Users/12213119/Documents/maya/2020/scripts/Lab/genHouse/tex/brick09_low.jpg' 83 | normalFile = 'C:/Users/12213119/Documents/maya/2020/scripts/Lab/genHouse/tex/brick09_low_d.jpg' 84 | 85 | # Lists 86 | cellList = [] 87 | setList = [] 88 | 89 | # Namespaces 90 | cmds.namespace( add='Import_' ) 91 | cmds.namespace( add='Cell_' ) 92 | cmds.namespace( add='Roof_' ) 93 | cmds.namespace( add='Floor_' ) 94 | cmds.namespace( add='Window_' ) 95 | 96 | 97 | # ========================================================================= Class 98 | 99 | class Main: 100 | 101 | print('\n------------------------------------------------------------- Create UI') 102 | 103 | # Create UI 104 | #UI.showUI() 105 | 106 | 107 | 108 | print('\n------------------------------------------------------------- startCell') 109 | 110 | #set Namespace: CELL 111 | cmds.namespace( set='Cell_' ) 112 | 113 | # Create object: START CELL 114 | startCell = Cells.startCell(cellSize) 115 | print('startCell output: {}'.format(startCell)) 116 | 117 | cellList.append(startCell[0]) 118 | print('cellList: {}'.format(cellList)) 119 | 120 | setList.append(startCell[1]) 121 | print('setList: {}'.format(setList)) 122 | 123 | 124 | # Create objects: Cells 125 | for x in range(numbercell): 126 | 127 | print('\n------------------------------------------------------------- addCell_{}'.format(x)) 128 | 129 | addCell = Cells.addCell(cellSize, cellList, setList) 130 | print('addCell outtput {}'.format(addCell)) 131 | 132 | cellList.append(addCell[0]) 133 | print('cellList: {}'.format(cellList)) 134 | 135 | setList.append(addCell[1]) 136 | print('setList: {}'.format(setList)) 137 | 138 | # set Namaespace: ROOT 139 | cmds.namespace( set=':' ) 140 | 141 | # group: Cells 142 | sel = cmds.select( 'Cell_:*' ) 143 | objects = cmds.ls(sl=True, g=True) 144 | cmds.group( objects, n='Cell_Grp' ) 145 | cmds.select( clear=True ) 146 | 147 | 148 | 149 | print('\n------------------------------------------------------------- Roof') 150 | 151 | cmds.namespace( set='Import_' ) 152 | 153 | # import: Base Roof Objects 154 | Roof.roofObjs(meshDir) 155 | 156 | sel = cmds.select( 'Import_:*' ) 157 | cmds.xform(sel, r=True, s=(cellSize,cellSize,cellSize) ) 158 | cmds.select( clear=True ) 159 | 160 | cmds.namespace( set=':' ) 161 | 162 | # set namaespace 163 | cmds.namespace( set='Roof_') 164 | 165 | # generate: Roof 166 | Roof.roofPattern(cellSize, cellList, setList) 167 | 168 | # set Namaespace: ROOT 169 | cmds.namespace( set=':' ) 170 | 171 | # group: ROOF 172 | sel = cmds.select( 'Roof_:*' ) 173 | objects = cmds.ls(sl=True, g=True) 174 | cmds.group( objects, n='Roof_Grp' ) 175 | cmds.select( clear=True ) 176 | 177 | # group: IMPORT 178 | sel = cmds.select( 'Import_:*' ) 179 | objects = cmds.ls(sl=True, g=True) 180 | cmds.group( objects, n='Import_Grp' ) 181 | cmds.hide( cmds.ls(sl=True)) 182 | cmds.select( clear=True ) 183 | 184 | 185 | 186 | print('\n------------------------------------------------------------- Floor') 187 | 188 | cmds.namespace( set='Floor_' ) 189 | 190 | # Create object: Ground Floor 191 | Floor.genFloors(numFloors, floorHeight, cellList, setList) 192 | 193 | # set Namaespace: ROOT 194 | cmds.namespace( set=':' ) 195 | 196 | # group: Floor 197 | sel = cmds.select( 'Floor_:*' ) 198 | objects = cmds.ls(sl=True, g=True) 199 | cmds.group( objects, n='Floor_Grp' ) 200 | cmds.select( clear=True ) 201 | 202 | # Assign Shader 203 | sel = cmds.select( 'Floor_:*' ) 204 | objects = cmds.ls(sl=True, g=True) 205 | Shaders.wallShader( objects[0], colorFile, normalFile, repeatUV ) 206 | 207 | 208 | print('\n------------------------------------------------------------- Window') 209 | 210 | ''' 211 | - select walls 212 | - get pos & normal direction: wall faces 213 | - add data: nested wall tuple 214 | - select a pattern of faces 215 | - generate window instaces and position 216 | ''' 217 | # set NameSpace: Window 218 | cmds.namespace( set='Window_' ) 219 | 220 | Floor.genWindow(8) 221 | Floor.genDoor(10) 222 | 223 | # create: Windows 224 | Floor.addWindows('Floor_:GroundFloor', doorHeight, maxDoors) 225 | 226 | # set Namaespace: ROOT 227 | cmds.namespace( set=':' ) 228 | 229 | # group: WINDOW 230 | sel = cmds.select( 'Window_:*' ) 231 | 232 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Execute this code: 2 | 0. Install numpy for Python 2.7 insde Maya 3 | 1. Open Maya 4 | 2. Go to: Top Menu > Windows > Gneral Editors > Script Editor 5 | 3. Create a Python Tab 6 | 4. copy/paste this code 7 | 5. press 'ExecuteAll' button 8 | 9 | #-------------------------------------------------------------------------------------------- 10 | 11 | import sys 12 | 13 | #add folder to PythonPath 14 | sys.path.append('c:/root/to/directory') 15 | 16 | # print PythonPaths 17 | from pprint import pprint 18 | sys.path 19 | pprint(sys.path) 20 | 21 | # import file 22 | import Main 23 | 24 | # refresh file 25 | reload(Main) 26 | 27 | # call script 28 | Main.Main() 29 | -------------------------------------------------------------------------------- /Roof.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | import os 3 | 4 | def roofPattern(cellSize, cellList, setList): 5 | """ 6 | Input: cellSize, list of cells and list of cell positions 7 | 8 | - A cell is selected 9 | - base of its positions it checks for neighboring cells 10 | - based on the number of neighbors and the neighbors position, 11 | the right roof-object is selected, with the polyRoof Function 12 | """ 13 | 14 | # get cellListst 15 | print('cellList: {}\n'.format(cellList)) 16 | 17 | # convert: List to Set 18 | setList = set(setList) 19 | 20 | 21 | # create xz pos 22 | xzList = [] 23 | for i in cellList: 24 | print('\n------------------------------------------------------------- createRoof_{}'.format(i.replace('Cell_:',''))) 25 | 26 | name = 'roof{}'.format(i.replace('Cell_:cell','')) 27 | 28 | # get position 29 | XYZ = cmds.objectCenter(i, gl=True) 30 | x = XYZ[0] 31 | z = XYZ[2] 32 | xzItem = str(int(x)) +' ' +str(int(z)) 33 | xzList.append(xzItem) 34 | print('{}.tx: {} \n{}.tz: {}'.format(i,x,i,z)) 35 | 36 | # calculate neigbours pos 37 | topZ = str(int(z + cellSize)) 38 | bottomZ = str(int(z - cellSize)) 39 | leftX = str(int(x + cellSize)) 40 | rightX = str(int(x - cellSize)) 41 | print('\ntopZ: {}\nbottomZ: {}\nleftX: {}\nrightX: {}'.format(topZ,bottomZ,leftX,rightX)) 42 | 43 | # concatenate 44 | top = str(int(x)) +' ' +topZ 45 | bottom = str(int(x)) +' ' +bottomZ 46 | left = leftX +' ' +str(int(z)) 47 | right = rightX +' ' +str(int(z)) 48 | 49 | # find actual neighbours 50 | setNeighbours = {top, bottom, left, right} 51 | foundNeighbours = list( setList.intersection(setNeighbours)) 52 | print('\nsim neighbours: {}'.format(setNeighbours)) 53 | print('all cell pos: {}'.format(setList)) 54 | print('found neighbours: {}\n'.format(foundNeighbours)) 55 | 56 | 57 | # get names of the neighbours 58 | c = 0 59 | for a in xzList: 60 | for b in foundNeighbours: 61 | if a == b: 62 | print('{} neigbour: {}'.format(i, cellList[c])) 63 | c = c+1 64 | 65 | # get right roof type 66 | non = len(foundNeighbours) 67 | neighbourOrder = {99} 68 | print('') 69 | for i in foundNeighbours: 70 | pos = i.split() 71 | nx = int(pos[0]) 72 | nz = int(pos[1]) 73 | 74 | # top 75 | if nz > z: 76 | a = 1 77 | neighbourOrder.add(a) 78 | print('found top neighbour') 79 | # left 80 | if nx > x: 81 | b = 2 82 | neighbourOrder.add(b) 83 | print('found left neighbour') 84 | # bottom 85 | if nz < z: 86 | c = 3 87 | neighbourOrder.add(c) 88 | print('found bottom neighbour') 89 | # right 90 | if nx < x: 91 | d = 4 92 | neighbourOrder.add(d) 93 | print('found right neighbour') 94 | 95 | # find roof patterns 96 | print('') 97 | 98 | if non == 1: 99 | t = {1} 100 | l = {2} 101 | b = {3} 102 | r = {4} 103 | if t.issubset(neighbourOrder): 104 | print('generate top roof') 105 | polyRoof(name,1, x,z,0) 106 | if l.issubset(neighbourOrder): 107 | print('generate left roof') 108 | polyRoof(name,1, x,z,90) 109 | if b.issubset(neighbourOrder): 110 | print('generate bottom roof') 111 | polyRoof(name,1, x,z,0) 112 | if r.issubset(neighbourOrder): 113 | print('generate right roof') 114 | polyRoof(name,1, x,z,90) 115 | if non == 2: 116 | tl = {1,2} # top/left 117 | lb = {2,3} # left/bottom 118 | br = {3,4} # bottom/right 119 | rt = {1,4} # top/right 120 | rl = {2,4} # right/left 121 | tb = {1,3} # top/bottom 122 | if tl.issubset(neighbourOrder): 123 | print('generate top/left roof') 124 | polyRoof(name,2, x,z,0) 125 | if lb.issubset(neighbourOrder): 126 | print('generate left/bottom roof') 127 | polyRoof(name,2, x,z,90) 128 | if br.issubset(neighbourOrder): 129 | print('generate bottom/right roof') 130 | polyRoof(name,2, x,z,180) 131 | if rt.issubset(neighbourOrder): 132 | print('generate top/right roof') 133 | polyRoof(name,2, x,z,270) 134 | if rl.issubset(neighbourOrder): 135 | print('generate left/right roof') 136 | polyRoof(name,1, x,z,90) 137 | if tb.issubset(neighbourOrder): 138 | print('generate top/bottom roof') 139 | polyRoof(name,1, x,z,0) 140 | 141 | if non == 3: 142 | tlb = {1,2,3} 143 | lbr = {2,3,4} 144 | brt = {3,4,1} 145 | rtl = {4,1,2} 146 | if tlb.issubset(neighbourOrder): 147 | print('generate top/left/bottom roof') 148 | polyRoof(name,3, x,z, 0) 149 | if lbr.issubset(neighbourOrder): 150 | print('generate left/bottom/right roof') 151 | polyRoof(name,3, x,z, 90) 152 | if brt.issubset(neighbourOrder): 153 | print('generate bottom/right/top roof') 154 | polyRoof(name,3, x,z, 180) 155 | if rtl.issubset(neighbourOrder): 156 | print('generate top/right/ roof') 157 | polyRoof(name,3, x,z,270) 158 | 159 | if non == 4: 160 | tlbr = {1,2,3,4} 161 | if tlbr.issubset(neighbourOrder): 162 | print('generate top/left/bottom/right roof') 163 | polyRoof(name, 4, x,z, 0) 164 | 165 | 166 | def polyRoof(name, type, x, z, r): 167 | """ 168 | Input: RoofType, position, rotation 169 | 170 | - Each rooftype has a value, 171 | base on the value a roof-Object is selected 172 | and placed correclty in the scene 173 | """ 174 | 175 | if type == 1: 176 | roof = cmds.duplicate( 'Import_:roof_F_001', n=name ) 177 | if r == 90: 178 | cmds.xform(roof[0], r=True,t=(x,0,z), ro=(0, 90, 0)) 179 | else: 180 | cmds.xform(roof[0], r=True,t=(x,0,z), ro=(0, 0, 0) ) 181 | if type == 2: 182 | roof = cmds.duplicate( 'Import_:roof_FL_001', n=name ) 183 | if r == 0: 184 | cmds.xform(roof[0], r=True, t=(x,0,z)) 185 | if r == 90: 186 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 90, 0)) 187 | if r == 180: 188 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 180, 0)) 189 | if r == 270: 190 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 270, 0)) 191 | if type == 3: 192 | roof = cmds.duplicate( 'Import_:roof_FLR_001', n=name ) 193 | if r == 0: 194 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 90, 0)) 195 | if r == 90: 196 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 180, 0)) 197 | if r == 180: 198 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 270, 0)) 199 | if r == 270: 200 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 0, 0)) 201 | if type == 4: 202 | roof = cmds.duplicate( 'Import_:roof_FLBR_001', n=name ) 203 | cmds.xform(roof[0], r=True, t=(x,0,z), ro=(0, 0, 0)) 204 | 205 | 206 | 207 | def roofObjs(meshDir): 208 | ''' 209 | input: dircortory of the base Roof Obj-files 210 | 211 | - Import obj-files 212 | ''' 213 | fileType = 'OBJ' 214 | 215 | 216 | objFiles = cmds.getFileList(folder = meshDir, filespec = '*.%s' % fileType) 217 | 218 | for item in objFiles: 219 | fname = os.path.join(meshDir, item) 220 | objName, ext = os.path.splitext(os.path.basename(fname)) 221 | # import each file 222 | imported_objects = cmds.file(fname, i=True, rnn=True) 223 | transforms = cmds.ls(imported_objects, type='transform') 224 | 225 | for i, object in enumerate(transforms): 226 | # rename it 227 | goodName = '%s_%s' % (objName, str(i+1).zfill(3)) 228 | cmds.rename(object, goodName) 229 | -------------------------------------------------------------------------------- /Shaders.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | def wallShader( obj, colorFile, normalFile, repeatUV=3 ): 4 | # create Nodes 5 | placeTexture = cmds.shadingNode('place2dTexture', asUtility=True) 6 | imageTexture = cmds.shadingNode('file', asTexture=True) # input image 7 | 8 | imageNormal = cmds.shadingNode('file', asTexture=True) # input image 9 | bump = cmds.shadingNode('aiBump2d', asTexture=True) # Bump 10 | normal = cmds.shadingNode('aiNormalMap', asTexture=True) # Normal 11 | shaderNode = cmds.shadingNode('aiStandardSurface', asShader=True) # shader 12 | 13 | # connect nodes 14 | cmds.connectAttr(placeTexture + '.outUV', imageTexture + '.uvCoord') 15 | cmds.connectAttr(imageTexture + '.outColor', shaderNode + '.baseColor') 16 | cmds.connectAttr(placeTexture + '.outUV', imageNormal + '.uvCoord') 17 | cmds.connectAttr(imageNormal + '.outAlpha', bump + '.bumpMap') 18 | cmds.connectAttr(bump + '.outValue', normal + '.input') 19 | cmds.connectAttr(normal + '.outValue', shaderNode + '.normalCamera') 20 | 21 | # import file 22 | #colorFile = 'C://Users//12213119//Documents//maya//2020//scripts//Lab//genHouse//tex//brick09_low.jpg' 23 | cmds.setAttr( imageTexture+'.fileTextureName', colorFile, type = "string") 24 | #normalFile = 'C://Users//12213119//Documents//maya//2020//scripts//Lab//genHouse//tex//brick09_low_d.jpg' 25 | cmds.setAttr( imageNormal+'.fileTextureName', normalFile, type = "string") 26 | 27 | # modify attribute 28 | cmds.setAttr(placeTexture + '.repeatU', repeatUV) 29 | cmds.setAttr(placeTexture + '.repeatV', repeatUV) 30 | 31 | # apply shader to object 32 | cmds.select( obj ) 33 | cmds.hyperShade( assign=shaderNode ) 34 | -------------------------------------------------------------------------------- /UI.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | 3 | 4 | def showUI(): 5 | '''UI window''' 6 | myWin = cmds.window(title="Simple Window", widthHeight=(300, 200)) 7 | cmds.columnLayout() 8 | cmds.text(label="Hello, Maya!") 9 | cmds.button(label="Make Cube", command=buttonFunction) 10 | cmds.showWindow(myWin) 11 | 12 | def buttonFunction(args): 13 | ''' showUI button function, create a poly cube''' 14 | cmds.polyCube() 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Utilities.py: -------------------------------------------------------------------------------- 1 | import maya.cmds as cmds 2 | import re #regular expression 3 | import math 4 | 5 | 6 | # OLD VERSION 7 | 8 | def getNormalDirOLD(obj): 9 | # get number of faces 10 | faceNum = cmds.polyEvaluate(obj, face=True) 11 | 12 | for x in range(faceNum): 13 | 14 | # face select 15 | cmds.select( '{}.f[{}:{}]'.format(obj,x,x) ) # select face 0 16 | print('{}.f[0:{}]'.format(obj,x)) 17 | 18 | # get the current selection 19 | selection = cmds.ls(sl=True) 20 | 21 | # trying to get the face normal angles of the current selection 22 | polyInfo = cmds.polyInfo(selection, fn=True) 23 | 24 | # convert the string to array with regular expression 25 | polyInfoArray = re.findall(r"[\w.-]+", polyInfo[0]) 26 | polyInfoX = float(polyInfoArray[2]) 27 | polyInfoY = float(polyInfoArray[3]) 28 | polyInfoZ = float(polyInfoArray[4]) 29 | 30 | # deselect current selection 31 | cmds.select(d=True ) 32 | 33 | print str(polyInfoX) + ', ' + str(polyInfoY) + ', ' + str(polyInfoZ) 34 | 35 | 36 | def facesDel(obj): 37 | """ 38 | delete faces point up or downward 39 | - firt get number of faces 40 | - loop throught all faces 41 | - check for there normal direction 42 | - if normal Y is not 0, a face to list 43 | - delete al faces in list 44 | """ 45 | faces = [] 46 | 47 | # get number of faces 48 | faceNum = cmds.polyEvaluate(obj, face=True) 49 | 50 | for x in range(faceNum): 51 | 52 | # select face number 53 | face = '{}.f[{}]'.format(obj,x) 54 | 55 | # get normal Y value 56 | polyInfo = cmds.polyInfo(face, fn=True) 57 | polyInfoArray = re.findall(r"[\w.-]+", polyInfo[0]) 58 | polyInfoY = float(polyInfoArray[3]) 59 | 60 | # append face 61 | if not polyInfoY == 0.0: 62 | faces.append(face) 63 | 64 | # delete faces in list 65 | cmds.delete(faces) 66 | 67 | 68 | def layoutUV(obj, type=0): 69 | 70 | totalFaces = cmds.polyEvaluate(obj, face=True) 71 | 72 | oneThird = totalFaces/3 73 | 74 | if (type == 0): 75 | startFace = 0 76 | endFace = oneThird - 1 77 | cmds.polyProjection(obj + '.f[' + str(startFace) + ':' + str(endFace) + ']',type="planar") 78 | 79 | if (type == 1): 80 | startFace = oneThird 81 | endFace = (oneThird * 2) - 1 82 | cmds.polyProjection(obj + '.f[' + str(startFace) + ':' + str(endFace) + ']',type="cylindrical") 83 | 84 | if (type == 2): 85 | startFace = (oneThird * 2) 86 | endFace = totalFaces - 1 87 | cmds.polyProjection(obj + '.f[' + str(startFace) + ':' + str(endFace) + ']',type="spherical") 88 | 89 | if (type == 3): 90 | cmds.polyCylindricalProjection(obj + '.f[*]') 91 | cmds.polyMapCut( obj +'.e[17]' ) # WARNING: this does not always select a verticle edge as a cut line 92 | cmds.unfold(obj +'.map[*]', i=5000, ss=0.001, gb=0, gmb=0.5, pub=0, ps=0,oa=2, us=False) 93 | 94 | 95 | def getPolyData(ojb): 96 | ''' 97 | Input: object 98 | - get number of vertecies 99 | - get number of edges 100 | - get number of faces 101 | Output: tuple 102 | ''' 103 | 104 | # get number of vertexes 105 | vertNum = cmds.polyEvaluate(obj, vertex=True) 106 | print('Vertex Number: ',vertNum) 107 | 108 | # get number of edges 109 | edgeNum = cmds.polyEvaluate(obj, edge=True) 110 | print('Edge Number: ', edgeNum) 111 | 112 | # get number of faces 113 | faceNum = cmds.polyEvaluate(obj, face=True) 114 | print('Face Number: ',faceNum) 115 | 116 | polyData = ( vertNum, edgeNum, faceNum ) 117 | return polyData 118 | 119 | 120 | def getFaceVertices(obj, face=0): 121 | info = cmds.polyInfo(fv=True) 122 | info = info[face].replace('FACE','').replace('{}:'.format(face,'' ), '').replace('\n', '').split(' ') 123 | verList = filter(None, info) 124 | print('face vertices: {}'.format(verList)) 125 | return verList 126 | 127 | 128 | def getVertexPos(obj, verNum): 129 | verPos = cmds.xform( obj[0] +'.vtx[{}]'.format(verNum), q=True, objectSpace=True, t=True) 130 | print(verPos) 131 | return verPos # tuple(x, y, z) 132 | 133 | 134 | def pointsDistance(x1, y1, z1, x2, y2, z2): 135 | d = math.sqrt((x2-x1)**2+(y2-y1)**2+(z2-z1)**2) 136 | print('distance between point a and b = {}'.format(d)) 137 | return d 138 | 139 | 140 | # OLD VERSION 141 | def getGreaterFaces(obj, max): 142 | ''' 143 | Input: object, greater face size) 144 | return a list of all the faces of an object, with a greater square root (max) 145 | Output: list 146 | ''' 147 | greaterList = [] 148 | 149 | # get number of faces 150 | faceNum = cmds.polyEvaluate(obj, face=True) 151 | print('Face Number: ',faceNum) 152 | 153 | for i in range(faceNum-1): 154 | # create temp face 155 | temp = cmds.duplicate( obj, n='temp' ) 156 | sel = cmds.select(temp[0] + '.f[*]' ) 157 | cmds.select(temp[0] + '.f[{}]'.format(i), d=True ) 158 | cmds.delete() 159 | cmds.select(temp[0]) 160 | bound = cmds.polyEvaluate(b=True) 161 | print(bound) 162 | cmds.delete() 163 | 164 | # calculate square root 165 | x = bound[0][0] - bound[0][1] 166 | z = bound[2][0] - bound[2][1] 167 | sqr = "{:.2f}".format(x*z) 168 | print(sqr) 169 | 170 | # get greater faces 171 | if (float(sqr) > float(max)): 172 | greaterList.append(i) 173 | 174 | print(greaterList) 175 | return greaterList 176 | 177 | # NEW VERSION 178 | def getFaceSqr(obj, FacNum): 179 | ''' 180 | arg: object, object face number 181 | Calculate the square root of a face 182 | return: square root of selected face 183 | ''' 184 | # print object name 185 | #print('object: ' + obj) 186 | 187 | # get number of faces 188 | faceNum = cmds.polyEvaluate(obj, face=True) 189 | #print('face num: {} '.format(faceNum)) 190 | 191 | # get face vertices 192 | info = cmds.polyInfo(obj+ '.f[{}]'.format(FacNum), fv=True) # get vertecies 193 | info = info[0].replace('FACE','').replace('{}:'.format(FacNum), '').replace('\n', '').split(' ') # edit output 194 | verList = filter(None, info) # face vertices = [ 0, 1, 2, 3 ] 195 | #print('vertex 0: '+ verList[0]) 196 | #print('vertex 1: '+ verList[1]) 197 | #print('vertex 2: '+ verList[2]) 198 | #print('vertex 3: '+ verList[3]) 199 | 200 | # get vertex pos 201 | verPos0 = cmds.xform( obj+'.vtx[{}]'.format(verList[0]), q=True, objectSpace=True, t=True) 202 | verPos1 = cmds.xform( obj+'.vtx[{}]'.format(verList[1]), q=True, objectSpace=True, t=True) 203 | verPos2 = cmds.xform( obj+'.vtx[{}]'.format(verList[2]), q=True, objectSpace=True, t=True) 204 | verPos3 = cmds.xform( obj+'.vtx[{}]'.format(verList[3]), q=True, objectSpace=True, t=True) 205 | #print('vertex 0: {}'.format(verPos0) ) 206 | #print('vertex 1: {}'.format(verPos1) ) 207 | #print('vertex 2: {}'.format(verPos2) ) 208 | 209 | # cal point to point distance 210 | disA = math.sqrt((verPos1[0]-verPos0[0])**2+(verPos1[1]-verPos0[1])**2+(verPos1[2]-verPos0[2])**2) 211 | disB = math.sqrt((verPos2[0]-verPos1[0])**2+(verPos2[1]-verPos1[1])**2+(verPos2[2]-verPos1[2])**2) 212 | disC = math.sqrt((verPos3[0]-verPos2[0])**2+(verPos3[1]-verPos2[1])**2+(verPos3[2]-verPos2[2])**2) 213 | disD = math.sqrt((verPos0[0]-verPos3[0])**2+(verPos0[1]-verPos3[1])**2+(verPos0[2]-verPos3[2])**2) 214 | #print('vertex0 and vertex1: {}'.format(disA)) 215 | #print('vertex1 and vertex2: {}'.format(disB)) 216 | #print('vertex2 and vertex3: {}'.format(disC)) 217 | #print('vertex3 and vertex0: {}'.format(disD)) 218 | 219 | # cal square root 220 | faceSqr = ((disA+disB)/2) * ((disC+disD)/2) 221 | #print( 'face square root: {}'.format(faceSqr)) 222 | 223 | return faceSqr 224 | 225 | 226 | def faceCenter(obj, face): 227 | ''' 228 | arg: object, object face 229 | return: center position of the face 230 | ''' 231 | info = cmds.polyInfo(obj+ '.f[{}]'.format(face), fv=True) # get vertecies 232 | info = info[0].replace('FACE','').replace('{}:'.format(face), '').replace('\n', '').split(' ') # edit output 233 | verList = filter(None, info) # face vertices = [ 0, 1, 2, 3 ] 234 | 235 | # get vertex pos 236 | verPos0 = cmds.xform( obj+'.vtx[{}]'.format(verList[0]), q=True, objectSpace=True, t=True) 237 | verPos1 = cmds.xform( obj+'.vtx[{}]'.format(verList[1]), q=True, objectSpace=True, t=True) 238 | verPos2 = cmds.xform( obj+'.vtx[{}]'.format(verList[2]), q=True, objectSpace=True, t=True) 239 | verPos3 = cmds.xform( obj+'.vtx[{}]'.format(verList[3]), q=True, objectSpace=True, t=True) 240 | 241 | # cal center pos 242 | centerX = (verPos0[0] + verPos1[0] + verPos2[0] + verPos3[0])/4 243 | centerY = (verPos0[1] + verPos1[1] + verPos2[1] + verPos3[1])/4 244 | centerZ = (verPos0[2] + verPos1[2] + verPos2[2] + verPos3[2])/4 245 | centerPos = (centerX, centerY ,centerZ) 246 | #print(centerPos) 247 | 248 | # location marker 249 | #cmds.polySphere() 250 | #cmds.xform(t=[centerX, centerY, centerZ]) 251 | 252 | return centerPos 253 | 254 | # NEW VERSION 255 | def getFaceNormal(obj, face): 256 | ''' 257 | arg: object, object face 258 | return normal direction list 259 | ''' 260 | # get object face, normal dir 261 | faceDir = cmds.polyInfo(obj+ '.f[{}]'.format(face), fn=True) 262 | #print(faceDir) 263 | 264 | # edit String 265 | faceDir = faceDir[0].replace('FACE_NORMAL', '').replace('{}:'.format(face), '').replace('\n', '').split(' ') 266 | faceDir = filter(None, faceDir) 267 | 268 | return faceDir 269 | -------------------------------------------------------------------------------- /projectFiles.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LucasHartman/MayaScript_HouseGenerator/e09cb2be61c2e1b323e1a9c24ab943098007311b/projectFiles.zip --------------------------------------------------------------------------------