#!BPY """ Name: 'Beast' Blender: 232 Group: 'Misc' Tooltip: 'Generate fur with textured card technique' """ # The Beast 0.5 Alpha 3 # by : # Johan Badenhorst (ezual) # Landis # Fweeb # LhonC # ------------------- # Thanks to Theeth for the # vector functions # ------------------- # # ------------------------------------------------------------------------ # # --- Notes --- # Note on code: # ------------- # I've been spitting out this code as # fast as possible to get the basic # beast functionality going as quickly # as possible. There will be a lot of # fixes and improvements once the script # is stable. # # Note on GUI: # ------------ # The gaps in the GUI will be filled up with # functionality as Beast progresses. # # Short to-do list: # ----------------- # 1. Some hair orientation mechansims # 2. Hair lock method (with auto-armatures) # 3. Using more than one alpha # 4. Alpha previews # # ------------------------------------------------------------------------ # # --- Imports --- import math import string from string import * import rgbimg from math import * import random from random import * import Blender from Blender.Draw import * from Blender.BGL import * from time import time # --- Logo --- try: import logo from logo import * imgbuf = logo.Init() except: print "logo.py not found" # ------------------------------------------------------------------------ # # --- Functions to convert between radians and degrees --- def Radians(Degrees): return Degrees * pi / 180 def Degrees(Radians): return Radians / pi * 180 # ------------------------------------------------------------------------ # # --- Functions to get face oreintation --- # --- Thanxs to Theeth --- def vcopy(v): return [v[0], v[1], v[2]] def makeRotMtx3D(rx, ry, rz): A, B = sin(rx), cos(rx) C, D = sin(ry), cos(ry) E, F = sin(rz), cos(rz) AC, BC = A*C, B*C return [[D*F, D*E, -C], [AC*F-B*E, AC*E+B*F, A*D], [BC*F+A*E, BC*E-A*F, B*D]] def makeRotMtx_fromVec(tv): v = vcopy(tv) v[1], v[2] = v[2], v[1] r = v[0]*v[0] + v[1]*v[1] if r>0.0: r = (acos(v[2]) / sqrt(r)) / pi u, v = v[0]*r, v[1]*r theta, phi = atan2(v, u), pi*sqrt(u*u + v*v) mtx = makeRotMtx3D(phi+0.5*pi, 0.5*pi-theta, 0.0) return mtx def mat2euler_rot(mat): mtx = [list(mat[0][:3]), list(mat[1][:3]), list(mat[2][:3])] angle_y = -asin(max(min(mtx[0][2], 1.0), -1.0)) C = cos(angle_y) if C!=0.0: C = 1.0/C angle_x = atan2(mtx[1][2] * C, mtx[2][2] * C) angle_z = atan2(mtx[0][1] * C, mtx[0][0] * C) return [angle_x, angle_y, angle_z] def VDot(v1, v2): # dot product return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] def VNorm(v): # normalize vector d = VDot(v, v) if d>0.0: d = 1./sqrt(d); v[0]*=d; v[1]*=d; v[2]*=d return v def MtxIdentity3x3(): return [[ 1.0, 0.0, 0.0], [ 0.0, 1.0, 0.0], [ 0.0, 0.0, 1.0]] def transp3x3(m): r = MtxIdentity3x3() for i in range(3): for j in range(3): r[i][j] = m[j][i] return r def MtxIdentity4x4(): return [[ 1.0, 0.0, 0.0, 0.0], [ 0.0, 1.0, 0.0, 0.0], [ 0.0, 0.0, 1.0, 0.0], [ 0.0, 0.0, 0.0, 1.0]] def mulmat(m1, m2, d): r = MtxIdentity4x4() #just for initialisation for i in range(d): for j in range(d): rij = 0.0 for k in range(d): rij += m1[i][k] * m2[k][j] r[i][j] = rij return r # ------------------------------------------------------------------------ # # --- Function to get the actual vertice location --- def GetLoc(vertco, obmat): x, y, z = vertco tx = x * obmat[0][0] + y * obmat[1][0] + z * obmat[2][0] ty = x * obmat[0][1] + y * obmat[1][1] + z * obmat[2][1] tz = x * obmat[0][2] + y * obmat[1][2] + z * obmat[2][2] return [tx, ty, tz] # ------------------------------------------------------------------------ # # --- Function to calculate the center of a face --- def GetFaceCenter(obj, face): totalx = 0.0 totaly = 0.0 totalz = 0.0 nverts = 0 for vert in face.v: truevert = GetLoc(vert, obj.getMatrix()) totalx += truevert[0] + obj.loc[0] totaly += truevert[1] + obj.loc[1] totalz += truevert[2] + obj.loc[2] nverts += 1 return totalx / nverts, totaly / nverts, totalz / nverts # ------------------------------------------------------------------------ # # --- Function to get a random location on a face --- def GetRandFacePos(obj, face): i = 0 tvert = [] for vert in face.v: tvert.append(GetLoc(vert.co, obj.getMatrix())) tvert[i][0] += obj.LocX tvert[i][1] += obj.LocY tvert[i][2] += obj.LocZ i += 1 nverts = len(face.v) vertns = [] rone = random() rtwo = random() rthree = random() pone = [0.0, 0.0, 0.0] ptwo = [0.0, 0.0, 0.0] pthree = [0.0, 0.0, 0.0] for i in range(0, 4): rn = int(random() * nverts) j = 0 while vertns.count(rn) > 0 and j < 100: rn = int(random() * nverts) j += 1 vertns.append(rn) pone[0] = ((1 - rone) * tvert[vertns[0]][0]) + (rone * tvert[vertns[1]][0]) pone[1] = ((1 - rone) * tvert[vertns[0]][1]) + (rone * tvert[vertns[1]][1]) pone[2] = ((1 - rone) * tvert[vertns[0]][2]) + (rone * tvert[vertns[1]][2]) ptwo[0] = ((1 - rtwo) * tvert[vertns[2]][0]) + (rtwo * tvert[vertns[3]][0]) ptwo[1] = ((1 - rtwo) * tvert[vertns[2]][1]) + (rtwo * tvert[vertns[3]][1]) ptwo[2] = ((1 - rtwo) * tvert[vertns[2]][2]) + (rtwo * tvert[vertns[3]][2]) pthree[0] = ((1 - rthree) * ptwo[0]) + (rthree * pone[0]) pthree[1] = ((1 - rthree) * ptwo[1]) + (rthree * pone[1]) pthree[2] = ((1 - rthree) * ptwo[2]) + (rthree * pone[2]) return pthree # ------------------------------------------------------------------------ # # --- Use theeth's super cool functions to get face orientation --- def GetFaceOrientation(obj, face): # Get True Direction Vector n = GetLoc(face.normal, obj.getMatrix()) # Normalize Direction Vector VNorm(n) # Invert To Avoid Spawning to inside of Object n[0] = -n[0] n[1] = -n[1] n[2] = -n[2] # Return Face Orientation return mat2euler_rot(makeRotMtx_fromVec(n)) # ------------------------------------------------------------------------ # # --- Make a Copy of An Object --- def MakeCopy(obj): msh = Blender.NMesh.GetRawFromObject(obj.name) newobj = Blender.NMesh.PutRaw(msh) newobj.SizeX = obj.SizeX newobj.SizeY = obj.SizeY newobj.SizeZ = obj.SizeZ newobj.RotX -= obj.RotX newobj.RotY -= obj.RotY newobj.RotZ += obj.RotZ newobj.colbits = 1 return newobj # ------------------------------------------------------------------------ # # --- Make a Copy of An Object --- def MakeCopyNoAdd(obj): newobj = Blender.Object.New("Mesh") msh = Blender.NMesh.GetRawFromObject(obj.name) newobj.SizeX = obj.SizeX newobj.SizeY = obj.SizeY newobj.SizeZ = obj.SizeZ newobj.RotX -= obj.RotX newobj.RotY -= obj.RotY newobj.RotZ += obj.RotZ newobj.colbits = 1 return newobj # ------------------------------------------------------------------------ # # --- Join Objects in an object list --- def GetPos(vertco, obmat): x, y, z = vertco tx = x * obmat[0][0] + y * obmat[1][0] + z * obmat[2][0] + obmat[3][0] ty = x * obmat[0][1] + y * obmat[1][1] + z * obmat[2][1] + obmat[3][1] tz = x * obmat[0][2] + y * obmat[1][2] + z * obmat[2][2] + obmat[3][2] return [tx, ty, tz] def MyJoin(objlist): # New Object To Hold Combined Data newobj = Blender.Object.New("Mesh") newmsh = Blender.NMesh.New() on = 0 count = 0 for obj in objlist: msh = obj.getData() for vert in msh.verts: truevert = GetPos(vert, obj.getMatrix()) newmsh.verts.append(Blender.NMesh.Vert(truevert[0], truevert[1], truevert[2])) toadd = len(objlist[on].getData().verts) for face in msh.faces: newface = Blender.NMesh.Face() for v in face.v: newface.v.append(newmsh.verts[count + v.index]) newmsh.faces.append(newface) toadd = len(objlist[on].getData().verts) count += toadd on += 1 # Link, Update and Return newmsh.update() newobj.link(newmsh) return newobj # ------------------------------------------------------------------------ # # --- Move Object Up So That It's Center is At It's Base --- def MoveUp(obj): # Get Mesh of Object To Move msh = obj.getData() # Get Lowest Vertice lowest = 10000 for vert in msh.verts: truevert = GetLoc(vert, obj.getMatrix()) if vert.loc[2] < lowest: lowest = vert.loc[2] lowest = abs(lowest) # Move Mesh Up for vert in msh.verts: vert.loc[2] += lowest msh.update() # ------------------------------------------------------------------------ # # --- Get Average Intensity of Face --- def GetFaceIntensity(face): # Initialize Varaibles totr = 0.0 totg = 0.0 totb = 0.0 nverts = 0 # Get Total Intensity for col in face.col: totr += col.r totg += col.g totb += col.b nverts += 1 # Check To Avoid Zero Division if nverts < 1: nverts = 1 # Calcualate Average Face Intensity return (((totr + totg + totb) / nverts) / 765) # ------------------------------------------------------------------------ # # --- Determine Density based on Intensity --- def GetFaceDensity(face): i = GetFaceIntensity d = 0 if i > 0.2: d = 1 if i > 0.4: d = 2 if i > 0.6: d = 3 if i > 0.8: d = 4 if i > 0.9: d = 5 return d # ------------------------------------------------------------------------ # # --- Create a Card for Hair Alpha --- def MakePatch(stacks, size, height, rand, material): # Stack Height stackheight = float(height / stacks) # Layer Offset loffset = [0.0, 0.0] # Current Layer Height curheight = 0.0 radius = float(size / 2) # --- Vertices --- pverts = [[0.0, radius] , [0.0, -radius], [radius, 0.0], [-radius, 0.0]] patchobj = Blender.Object.New("Mesh") patchmesh = Blender.NMesh.New() patchmesh.hasVertexUV(1) # --- Create Vertices and Faces--- for i in xrange(0, stacks + 1): if rand > 0.0: loffset[0] = (random() * rand) - rand / 2 loffset[1] = (random() * rand) - rand / 2 # --- Add Vertices --- for vert in pverts: v = Blender.NMesh.Vert(vert[0] + loffset[0], vert[1] + loffset[1], curheight) patchmesh.verts.append(v) curheight += stackheight # --- Create Faces --- j = 0 uvstack = float(height / stacks) / height curheight = 0.0 next = False for i in xrange(0, stacks + stacks): nextheight = curheight + uvstack newface = Blender.NMesh.Face() newface.v.append(patchmesh.verts[j]) newface.uv.append((0.0, curheight)) newface.v.append(patchmesh.verts[j + 1]) newface.uv.append((1.0, curheight)) newface.v.append(patchmesh.verts[j + 5]) newface.uv.append((1.0, nextheight)) newface.v.append(patchmesh.verts[j + 4]) newface.uv.append((0.0, nextheight)) newface.smooth = 1 patchmesh.faces.append(newface) if next == True: curheight += uvstack next = False else: next = True j += 2 # --- Update Patch And Link Mesh--- patchobj.link(patchmesh) patchmesh.update(1) # --- Add Materials --- # --- For Some Reason It Only Works This Way --- newobj = Blender.Object.Get(patchobj.getName()) newobj.setMaterials([material]) newobj.colbits = 1 # --- Return Patch Object --- return patchobj # ------------------------------------------------------------------------ # # --- Spawn Objects on Surface --- def MakeCombedPatch(stacks, size, height, maxheight, rand, material): # Stack Height stackheight = float(height / stacks) bendheight = 0 # Layer Offset loffset = [0.0, 0.0] # Current Layer Height curheight = 0.0 curstack = 0 radius = float(size / 2) # --- Vertices --- pverts = [[0.0, radius] , [0.0, -radius], [radius, 0.0], [-radius, 0.0]] patchobj = Blender.Object.New("Mesh") patchmesh = Blender.NMesh.New() patchmesh.hasVertexUV(1) # --- Create Vertices and Faces--- if height > maxheight: theta = asin(maxheight / height) topx = height * cos(theta) # Radius of side vertices at top sider = radius # Angle of side vertices at top sidea = 90/pi * 180 +theta for i in xrange(0, stacks + 1): if rand > 0.0: loffset[0] = (random() * rand) - rand / 2 loffset[1] = (random() * rand) - rand / 2 # --- Calculate pushdown --- if height > maxheight: if i == 0: x = 0 sideonex = radius sideoney = 0 sidetwox = -radius sidetwoy = 0 else: angle = (90.0 / float(stacks)) * float(curstack) angle = (angle * pi)/180 cr = topx x = topx - abs(cr * cos(angle)) - (topx - cr) curangle = -curstack / stacks * (Radians(90) - theta) sideonex = x + (sider * cos(curangle)) sideoney = bendheight + (sider * sin(curangle)) sidetwox = x - (sider * cos(curangle)) sidetwoy = bendheight - (sider * sin(curangle)) # --- Add Vertices --- vertnr = 0 if sideoney < 0: sideoney = 0 sideonex = size / 2.0 for vert in pverts: if vertnr == 0 or vertnr == 1: v = Blender.NMesh.Vert(vert[0] + loffset[0] + x, vert[1] + loffset[1], bendheight) patchmesh.verts.append(v) elif vertnr == 2: v = Blender.NMesh.Vert(loffset[0] + sideonex, vert[1] + loffset[1], sideoney) patchmesh.verts.append(v) elif vertnr == 3: v = Blender.NMesh.Vert(loffset[0] + sidetwox, vert[1] + loffset[1], sidetwoy) patchmesh.verts.append(v) vertnr += 1 else: # --- Out of range for pushdown --- for vert in pverts: v = Blender.NMesh.Vert(vert[0] + loffset[0], vert[1] + loffset[1], curheight) patchmesh.verts.append(v) bendheight += maxheight / stacks curheight += stackheight curstack += 1 # --- Create Faces --- j = 0 uvstack = float(height / stacks) / height curheight = 0.0 next = False for i in xrange(0, stacks + stacks): nextheight = curheight + uvstack newface = Blender.NMesh.Face() newface.v.append(patchmesh.verts[j]) newface.uv.append((0.0, curheight)) newface.v.append(patchmesh.verts[j + 1]) newface.uv.append((1.0, curheight)) newface.v.append(patchmesh.verts[j + 5]) newface.uv.append((1.0, nextheight)) newface.v.append(patchmesh.verts[j + 4]) newface.uv.append((0.0, nextheight)) newface.smooth = 1 patchmesh.faces.append(newface) if next == True: curheight += uvstack next = False else: next = True j += 2 # --- Update Patch And Link Mesh--- patchobj.link(patchmesh) patchmesh.update(1) # --- Add Materials --- # --- For Some Reason It Only Works This Way --- newobj = Blender.Object.Get(patchobj.getName()) newobj.setMaterials([material]) newobj.colbits = 1 # --- Return Patch Object --- return patchobj # ------------------------------------------------------------------------ # # --- Spawn Objects on Surface --- def Spawn(surface, surffaces, objects, density, colsize, colheight, max, randrot, randsize, share): # Initiate Master for Sharing if share == 1: master = MakeCopy(objects[0]) master.loc = Blender.Window.GetCursorPos() master.RotZ = -180/(180/pi) # Start up the progress bar Blender.Window.DrawProgressBar(0.0, "Starting") nfaces = len(surffaces) # Initialize List of Spawned Objects newobjects = [] # Get surface mesh surfacemesh = surface.getData() # Loop Through Spawn Activated Faces count = 0.0 for face in surffaces: # Place Face Object(s) for i in range (0, density): # Choose Random Object From Selected ro = int(random() * len(objects)) # Set Object Location On Face if density > 1: pos = GetRandFacePos(surface, face) else: pos = GetFaceCenter(surface, face) # Calculate Rotation facerot = GetFaceOrientation(surface, face) # Random Rotation rot = [0.0, 0.0, 0.0] rot[0] += (1 - (2 * random())) * (randrot[0] / 180 * pi) rot[1] += (1 - (2 * random())) * (randrot[1] / 180 * pi) rot[2] += (1 - (2 * random())) * (randrot[2] / 180 * pi) # Copy Object curobj = MakeCopy(objects[ro]) # Place and Rotate Object curobj.LocX += pos[0] curobj.LocY += pos[1] curobj.LocZ += pos[2] curobj.RotX += facerot[0] curobj.RotY += facerot[1] curobj.RotZ += facerot[2] # Rotation Matrixes objrotmat = makeRotMtx3D(curobj.RotX, curobj.RotY, curobj.RotZ) invobjrotmat = transp3x3(objrotmat) randrotmat = makeRotMtx3D(rot[0], rot[1], rot[2]) # Three steps to local axis rotation if randrot[0] <> 0.0 or randrot[1] <> 0.0 or randrot[2] <> 0.0: firstmat = mulmat(objrotmat, invobjrotmat, 3) secmat = mulmat(firstmat, randrotmat, 3) thirdmat = mulmat(secmat, objrotmat, 3) frandrot = mat2euler_rot(thirdmat) curobj.RotX = frandrot[0] curobj.RotY = frandrot[1] curobj.RotZ = frandrot[2] # Apply Random Size curobj.SizeX += curobj.SizeX * (random() * randsize[0]) curobj.SizeY += curobj.SizeY * (random() * randsize[1]) curobj.SizeZ += curobj.SizeZ * (random() * randsize[2]) # Apply Size According to Average Face Colour if colsize == True: if colheight == True: curobj.SizeZ = curobj.SizeZ * (1 + ( max * GetFaceIntensity(face))) else: curobj.SizeX = curobj.SizeX * (1 + ( max * GetFaceIntensity(face))) curobj.SizeY = curobj.SizeY * (1 + ( max * GetFaceIntensity(face))) curobj.SizeZ = curobj.SizeZ * (1 + ( max * GetFaceIntensity(face))) # Move Object Up MoveUp(curobj) curobj.makeDisplayList() surface.makeParent([curobj], 0, 1) newobjects.append(curobj) if share == 1: curobj.getData().update() curobj.shareFrom(master) count += 1.0 # Set the progress bar progress = float(count / nfaces) Blender.Window.DrawProgressBar(progress, "Duplicating: " + str(int(progress * 100)) + "%") return newobjects Blender.Window.DrawProgressBar(1.0, "Done") # ------------------------------------------------------------------------ # # --- GUI and Event Handlers --- # --- Controls --- settings = Create(1) # Toggle For Settings Tab fileman = Create(0) # Toggle For File Management Tab optset = Create(1) # Toggle For Options randset = Create(0) # Toggle For Randomization Options randx = Create(0.0) # Slider For X Rotation randy = Create(0.0) # Slider For Y Rotation randz = Create(0.0) # Slider For Z Rotation randsx = Create(0.0) # Slider For X Size randsy = Create(0.0) # Slider For Y Size randsz = Create(0.0) # Slider For Z Size objfile = Create(0.0) # File in Which Oject is Stored coldens = Create(0.0) # Toggle For Letting Face Colour Affect Density colsize = Create(0.0) # Toggle For Letting Face Colour Affect Object Size colheight = Create(0.0) # Toggle For Constraining Face Colour Effect To Height maxvar = Create(1) # Number For Setting Max Size Variance beastmode = Create(2) # Menu For Selecting Beast Mode colmode = Create(5) # Menu For Selecting Base Colour Mode colset = Create(0) # Toggle For Base Colour Tab colr = Create(0.5) # Slider For Setting Red Value colg = Create(0.3) # Slider For Setting Green Value colb = Create(0.1) # Slider For Setting Blue Value densvar = Create(1) # Number For Density (Objects Per Face) cardset = Create(0) # Toggle For Card Tab alphaset = Create(0) # Toggle For Alpha Tab alphamaps = Create(0) # Menu For Displaying Alpha Maps nstacks = Create(2) # Number For Setting Hair Card Stacks hheight = Create(0.8) # Number For Setting Hair Card Height curl = Create (0.1) # Slider For Setting Hair Card Curliness hsize = Create(0.5) # Slider For Setting Hair Card Width share = Create(0) # Toggle button for setting shrefrom functionlity iscombed = Create(0.0) # Toggle button to comb(flatten hair against scalp maxheight = Create(0.5) # --- Variables --- surfacename = "None" facecount = 0 nobjs = 0 objects = [] faces = [] hassurface = False colone = [0.5, 0.3, 0.1] coltwo = [0.8, 0.5, 0.2] alphastr = "Alpha Maps %t" alphalist = [] baseimg = "" # Stores comlete base image filename baseimgtxt = "None" # Stores formatted base image filename nmats = 0 # --- Button event identifiers --- pexit = 101 tsettings = 102 tfileman = 103 trandset = 104 toptset = 106 pasurf = 107 pafaces = 108 pafacesall= 109 pcreate = 110 paobjs = 113 papobjs = 114 tcoldens = 115 tcolset = 116 modeswitch= 117 pacolone = 118 pacoltwo = 119 tcardset = 120 paddalpha = 121 pclearalpha = 122 pcardpreview = 123 pselbaseimg = 124 talphaset = 125 tcombed = 126 slide = 50 # ------------------------------------------------------------------------ # # --- Add-Alpha Callback Function --- def AddAlpha(filename): global alphalist, alphastr global alphamaps alphalist.append(filename) # Set Cutoff length = len(filename) if length > 20: cutoff = 16 else: cutoff = len(filename) # Append To Alpha Menu String alphastr += "|..." + filename[len(filename) - cutoff:] alphamaps.val = len(alphalist) Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Select Base Image Callback Function --- def SelBaseImg(filename): global baseimg, baseimgtxt baseimg = filename # Set Cutoff length = len(baseimg) if length > 30: cutoff = 26 else: cutoff = len(baseimg) baseimgtxt = "..." + baseimg[len(baseimg) - cutoff:] Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Keyboard and mouse events --- def Event(evt, val): if evt == QKEY: Exit() return # ------------------------------------------------------------------------ # # --- Button Events --- def BEvent(evt): global surfacename, facecount, faces global nobjs, objects, hassurface, alphamaps global alphalist, alphastr, baseimg global iscombed, maxheight # ------------------------------------------------------------------------ # # --- Exit --- if evt == pexit: Exit() return elif evt == pexit: Exit() return # ------------------------------------------------------------------------ # # --- Slide --- elif evt == slide: Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Switch Beast Modes --- elif evt == modeswitch: optset.val = 1 randset.val = 0 colset.val = 0 cardset.val = 0 objects = [] faces = [] surface = "" surfacename = "None" facecount = 0 nobjs = 0 Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Toggle between settings and file management --- elif evt == tsettings: if settings.val == 1: fileman.val = 0 else: settings.val = 1 Register(GUI, Event, BEvent) elif evt == tfileman: if fileman.val == 1: settings.val = 0 else: fileman.val = 1 Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Sub setting tabs togle functionality--- elif evt == trandset: if randset.val == 1: optset.val = 0 colset.val = 0 cardset.val = 0 alphaset.val = 0 else: randset.val = 1 Register(GUI, Event, BEvent) elif evt == toptset: if optset.val == 1: randset.val = 0 colset.val = 0 cardset.val = 0 alphaset.val = 0 else: optset.val = 1 Register(GUI, Event, BEvent) elif evt == tcolset: if colset.val == 1: randset.val = 0 optset.val = 0 cardset.val = 0 alphaset.val = 0 else: colset.val = 1 Register(GUI, Event, BEvent) elif evt == tcardset: if cardset.val == 1: colset.val = 0 randset.val = 0 optset.val = 0 alphaset.val = 0 else: cardset.val = 1 Register(GUI, Event, BEvent) elif evt == talphaset: if alphaset.val == 1: colset.val = 0 randset.val = 0 optset.val = 0 cardset.val = 0 else: alphaset.val = 1 Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Surface Settings --- elif evt == pasurf: if len(Blender.Object.GetSelected()) > 0: facecount = 0 faces = [] surfacename = Blender.Object.GetSelected()[0].name surfaceobj = Blender.Object.Get(surfacename) if surfaceobj.getType() == "Mesh": surfacename = Blender.Object.GetSelected()[0].name hassurface = True else: surfacename = "Not a Mesh" else: surfacename = "Nothing Selected" Register(GUI, Event, BEvent) # Assign Selected Faces elif evt == pafaces: if surfacename <> "None": if surfacename <> "Nothing Selected": if surfacename <> "Not a Mesh": obj = Blender.Object.Get(surfacename) faces = obj.getData().getSelectedFaces(0) facecount = len(faces) else: print "Assign surface first" Register(GUI, Event, BEvent) # Assign All Faces elif evt == pafacesall: if surfacename <> "None": if surfacename <> "Nothing Selected": if surfacename <> "Not a Mesh": obj = Blender.Object.Get(surfacename) faces = obj.getData().faces facecount = len(faces) else: print "Assign surface first" Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Objects Settings --- elif evt == paobjs: nobjs = len(Blender.Object.GetSelected()) if nobjs > 0: objects = Blender.Object.GetSelected() Register(GUI, Event, BEvent) elif evt == papobjs: nobjs = len(objects) + len(Blender.Object.GetSelected()) if nobjs > 0: for obj in Blender.Object.GetSelected(): objects.append(obj) Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Assign Colours --- elif evt == pacolone: colone[0] = colr.val colone[1] = colg.val colone[2] = colb.val Register(GUI, Event, BEvent) elif evt == pacoltwo: coltwo[0] = colr.val coltwo[1] = colg.val coltwo[2] = colb.val Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Add Alpha Map --- elif evt == paddalpha: Blender.Window.FileSelector(AddAlpha, "Select Image") # ------------------------------------------------------------------------ # # --- Clear Alpha Map List --- elif evt == pclearalpha: alphastr = "Alpha Maps %t" alphalist = [] Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # # --- Create Card Preview At Cursor --- elif evt == pcardpreview: if iscombed.val == 1: mat = Blender.Material.New("PrevMat") prevcard = MakeCombedPatch(nstacks.val, hsize.val, hheight.val, maxheight.val, curl.val, mat) prevcard.name = "Preview" prevcard.setLocation(Blender.Window.GetCursorPos()) Blender.Scene.getCurrent().link(prevcard) else: mat = Blender.Material.New("PrevMat") prevcard = MakePatch(nstacks.val, hsize.val, hheight.val, curl.val, mat) prevcard.name = "Preview" prevcard.setLocation(Blender.Window.GetCursorPos()) Blender.Scene.getCurrent().link(prevcard) # ------------------------------------------------------------------------ # # --- Select Base Image Texture --- elif evt == pselbaseimg: Blender.Window.FileSelector(SelBaseImg, "Select Image") # ------------------------------------------------------------------------ # # --- Create --- elif evt == pcreate: starttime = time() # Initiate Variables nmats = 0 matlist = [] if beastmode.val == 2: nobjs = 1 if nobjs > 0: if hassurface == True: # Add Colour And Alpha if Beast is # in Fur/Hair mode if beastmode.val == 2: # --- Create Material --- basemat = Blender.Material.New("HairColour") # --- Create Alpha Textures --- if len(alphalist) > 0: for alpha in alphalist: curmat = Blender.Material.New("HairColour") # Alpha Texture image = Blender.Image.Load(alpha) atx = Blender.Texture.New("AlphaTex") atx.setType("Image") atx.setImage(image) curmat.setTexture(1, atx) curmat.setAlpha(0.0) curmat.setSpecTransp(0.0) curmat.mode |= Blender.Material.Modes.ZTRANSP matx = curmat.getTextures()[1] matx.mapto = 128 matx.texco = 16 matx.tex.extend = 2 matlist.append(curmat) nmats += 1 else: matlist.append(basemat) nmats += 1 # --- Set Base Solid Colour --- if colmode.val == 5: for mat in matlist: mat.setRGBCol(colone) # --- Create Base Texture For Colour Variation --- if colmode.val in (1, 2, 3, 4): # Create Texture tx = Blender.Texture.New("ColourTex") # Set Texture Type if colmode.val in(1, 2, 3): tx.setType("Clouds") for mat in matlist: mat.setRGBCol(colone) else: tx.setType("Image") try: txi = Blender.Image.Load(baseimg) tx.setImage(txi) except: print "Not a valid base image" # Set Noise Depth tx.noiseDepth = 6 # Set Noise Size if colmode.val == 1: tx.noiseSize = 0.100 elif colmode.val == 2: tx.noiseSize = 0.500 elif colmode.val == 3: tx.noiseSize = 1.000 # Setup the Colour Texture tx.rgbCol = [coltwo[0], coltwo[1], coltwo[2]] for mat in matlist: mat.setTexture(0, tx) mtx = mat.getTextures()[0] mtx.mapto = 1 mtx.texco = 32 objects = [] for mat in matlist: if iscombed.val == 1: obj = MakeCombedPatch(nstacks.val, hsize.val, hheight.val, maxheight.val, curl.val, mat) else: obj = MakePatch(nstacks.val, hsize.val, hheight.val, curl.val, mat) objects.append(obj) surface = Blender.Object.Get(surfacename) randomrot = [randx.val, randy.val, randz.val] randomsize = [randsx.val, randsy.val, randsz.val] newobjects = Spawn(surface, faces, objects, densvar.val, colsize.val, colheight.val, maxvar.val, randomrot, randomsize, share.val) # Set colbits if beastmode.val == 2: for ob in newobjects: ob.setMaterials(matlist) randmat = int(random() * nmats) ob.colbits = 1 Blender.Window.RedrawAll() # Print Report print "-------------" print "Beast Report:" print "-------------" print "Surface: " + str(surface.name) print "Number of Objects: " + str(len(faces)) print "Number of Alphas: " + str(len(alphalist)) endtime = time() print "Ellapsed Time: " + str(endtime - starttime) + " seconds" print "-------------\n" # ------------------------------------------------------------------------ # # --- Default --- else: Register(GUI, Event, BEvent) # ------------------------------------------------------------------------ # #def LoadImg(filename): # img = PIL.Image.open(filename) # img.load() # bb = img.getbbox() # imgw = bb[2] + bb[0] # imgh = bb[3] + bb[1] # print str(imgw) + " " + str(imgh) # buf = Buffer(GL_BYTE, (imgh, imgw, 4)) # # for y in xrange(0, imgh): # for x in xrange(0, imgw): # d = img.getpixel((x, imgh - y - 1)) # buf[y][x][0] = d[0] # buf[y][x][1] = d[1] # buf[y][x][2] = d[2] # return imgw, imgh, buf # ------------------------------------------------------------------------ # # --- Draw an image --- def DrawImg(buf, imgw, imgh, px, py): glRasterPos2f(px, py) glDrawPixels(imgw, imgh, GL_RGBA, GL_UNSIGNED_BYTE, buf) # ------------------------------------------------------------------------ # # --- Draw a group box --- def GroupBox(x,y, w, h, r, g, b): glColor3f(0.0, 0.0, 0.0) glRecti(x, y, w, h) glColor3f(r, g, b) glRecti(x + 1, y + 1, w - 1, h - 1) # ------------------------------------------------------------------------ # # --- GUI --- def GUI(): global beastmode, colset, colmode global settings, randset, randx, randy, randz global randsx, randsy, randsz, fileman global optset, surfacename, objass, objfile global coldens, colsize, colheight, maxvar global colr, colg, colb, densvar, cardset global alphamaps, alphastr, nstacks, hheight global curl, hsize, baseimgtxt global logobuf, alphaset, share, maxheight global iscombed # ------------------------------------------------------------------------ # glClearColor(0.4, 0.4, 0.4, 1.0) glClear(GL_COLOR_BUFFER_BIT) top = 390 curpos = top line = 25 longline = 30 verylongline = 35 # ------------------------------------------------------------------------ # beastmode = Menu("Beast Modes %t|General %x1|Hair and Fur %x2", modeswitch, 15, top + 65, 120, 25, beastmode.val) # ------------------------------------------------------------------------ # # --- Assign Options --- # White BG group boxes # GroupBox(10,curpos - 147, 375, curpos + 20, 0.9, 0.9, 0.9) # GroupBox(10, 40, 375, curpos - 150, 0.9, 0.9, 0.9) GroupBox(25, 105, 220, 165, 0.8, 0.8, 0.8) GroupBox(15,curpos - 10, 370, curpos - 140, 0.6, 0.6, 0.6) glColor3f(0.9, 0.9, 0.9) glRasterPos2f(175, curpos) Text("Assign:") curpos -= verylongline glColor3f(0.0, 0.0, 0.0) glRasterPos2i(30, curpos) Text("Surface :") glRasterPos2i(130, curpos) Text(surfacename) Button("Assign", pasurf, 235, curpos - 7, 125, 20, "Make selected object the surface") curpos -= longline glColor3f(0.0, 0.0, 0.0) glRasterPos2f(30, curpos) Text("Faces :") glRasterPos2f(130, curpos) Text(str(facecount)) Button("All", pafacesall, 300, curpos - 7, 60, 20, "Activate all faces for spawning") Button("Assign", pafaces, 235, curpos - 7, 60, 20, "Activate selected faces for spawning") if beastmode.val == 1: curpos -= (line + 20) # GroupBox(25, curpos - 10, 220, curpos + 19, 0.8, 0.8, 0.8) glColor3f(0.0, 0.0, 0.0) glRasterPos2f(30, curpos) Text("Objects :") glRasterPos2f(130, curpos) Text(str(nobjs)) Button("Append", papobjs, 235, curpos - 7, 60, 20, "Append Selected Objects To Be Copied To Surface") Button("Assign", paobjs, 300, curpos - 7, 60, 20, "Assign Selected Objects To Be Copied To Surface") curpos = 210 # ------------------------------------------------------------------------ # GroupBox(15,45, 370, curpos - 5, 0.6, 0.6, 0.6) settings = Toggle("Settings", tsettings, 45, curpos + 2, 135, 20, settings.val, "Beast Settings") fileman = Toggle("File Management", tfileman, 200, curpos + 2, 135, 20, fileman.val, "Manage Beast Files") Button("X", pexit, 350, 11, 20, 20, "Exit") Button("Unleash Beast!", pcreate, 140, 11, 100, 23, "Make selected object the surface") # ------------------------------------------------------------------------ # curpos -= verylongline if settings.val == 1: GroupBox(20,50, 365, curpos -5, 0.9, 0.9, 0.9) optset = Toggle("Options", toptset, 25, curpos, 60, 20, optset.val, "Objects Settings") randset = Toggle("Random", trandset, 90, curpos, 60, 20, randset.val, "Objects Size and Orientation Randomization") if beastmode.val == 2: colset = Toggle("Colour", tcolset, 285, curpos, 60, 20, colset.val, "Texture for Hair Colour Variation") cardset = Toggle("Card", tcardset, 155, curpos, 60, 20, cardset.val, "Card Settings") alphaset = Toggle("Alpha", talphaset, 220, curpos, 60, 20, alphaset.val, "Alpha Settings") # ------------------------------------------------------------------------ # # --- Other Options --- if optset.val == 1: curpos -= verylongline - 3 glColor3f(0.0, 0.0, 0.0) glRasterPos2f(30, curpos + 5) Text("Density :") densvar = Number("Density: ", -1, 110, curpos, 90, 20, densvar.val, 1, 100, "Set Objects Per Face") # Option to share data with master mesh glColor3f(0.0, 0.0, 0.0) glRasterPos2f(220, curpos + 5) Text("Share :") share = Toggle("Share", -1, 270, curpos, 70, 20, share.val, "Share Mesh Data With Master Object Created At Cursor") curpos -= line glColor3f(0.0, 0.0, 0.0) glRasterPos2f(30, curpos) Text("Face Colour :") # Options For Face Colour Effects colsize = Toggle("Size", tcoldens, 110, curpos - 5, 70, 20, colsize.val, "Let Face Colour Affect Size") if colsize.val == 1: colheight = Toggle("Height", tcoldens, 190, curpos - 5, 70, 20, colheight.val, "Limit Size Effect to Height") maxvar = Number("Max: ", -1, 270, curpos - 5, 90, 20, maxvar.val, 1, 5, "Maximum") # ------------------------------------------------------------------------ # # --- Randomization Options --- elif randset.val == 1: # Randomization options curpos -= line glColor3f(0.0, 0.0, 0.0) glRasterPos2f(85, curpos) Text("Rotation") glRasterPos2f(265, curpos) Text("Size") curpos -= longline randx = Slider("x-rot: ", slide, 25, curpos, 160, 20, randx.val, 0.0, 90.0, 0,"Set Maximum Variation") randsx = Slider("x-siz: ", slide, 200, curpos, 160, 20, randsx.val, 0.0, 5.0, 0, "Set Maximum Variation") curpos -= longline randy = Slider("y-rot: ", slide, 25, curpos, 160, 20, randy.val, 0.0, 90.0, 0, "Set Maximum Variation") randsy = Slider("y-siz: ", slide, 200, curpos, 160, 20, randsy.val, 0.0, 5.0, 0, "Set Maximum Variation") curpos -= longline randz = Slider("z-rot: ", slide, 25, curpos, 160, 20, randz.val, 0.0, 180.0, 0, "Set Maximum Variation") randsz = Slider("z-siz: ", slide, 200, curpos, 160, 20, randsz.val, 0.0, 5.0, 0, "Set Maximum Variation") # ------------------------------------------------------------------------ # # --- Colour Options --- elif colset.val == 1: curpos -= longline glColor3f(0.0, 0.0, 0.0) glRasterPos2i(30, curpos) Text("Texture: ") colmode = Menu("Colour Modes %t|Clouds (Sm) %x1|Clouds (Med) %x2|Clouds (Lrg) %x3|Image %x4|Solid %x5", -1, 90, curpos - 5, 100, 20, colmode.val) # --- Solid Base Texture Options --- if colmode.val == 5: glColor3f(0.0, 0.0, 0.0) glRasterPos2i(235, curpos) Text("Colour:") curpos -= longline colr = Slider("Red: ", slide, 30, curpos, 160, 20, colr.val, 0.0, 1.0, 0,"Set Red Component") curpos -= longline colg = Slider("Green: ", slide, 30, curpos, 160, 20, colg.val, 0.0, 1.0, 0,"Set Green Component") curpos -= longline colb = Slider("Blue: ", slide, 30, curpos, 160, 20, colb.val, 0.0, 1.0, 0,"Set Blue Component") GroupBox(200, 55, 220, 135 , colr.val, colg.val, colb.val) GroupBox(230, curpos + longline, 290, 135 , colone[0], colone[1], colone[2]) Button("Assign", pacolone, 230, curpos, 60, 20, "Assign RGB to Colour One") # --- Texture Base Texture Options --- if colmode.val == 4: curpos -= verylongline glColor3f(0.0, 0.0, 0.0) glRasterPos2i(30, curpos + 5) Text("Image: ") glRasterPos2i(90, curpos + 5) Text(baseimgtxt) Button("Select", pselbaseimg, 265, curpos , 90, 20, "Select Base Image") # --- Cloud Base Texture Options --- if colmode.val in (1, 2, 3): glColor3f(0.0, 0.0, 0.0) glRasterPos2i(235, curpos) Text("Colour 1:") glRasterPos2i(305, curpos) Text("Colour 2:") curpos -= longline colr = Slider("Red: ", slide, 30, curpos, 160, 20, colr.val, 0.0, 1.0, 0,"Set Red Component") curpos -= longline colg = Slider("Green: ", slide, 30, curpos, 160, 20, colg.val, 0.0, 1.0, 0,"Set Green Component") curpos -= longline colb = Slider("Blue: ", slide, 30, curpos, 160, 20, colb.val, 0.0, 1.0, 0,"Set Blue Component") GroupBox(200, 55, 220, 135 , colr.val, colg.val, colb.val) GroupBox(230, curpos + longline, 290, 135 , colone[0], colone[1], colone[2]) GroupBox(300, curpos + longline, 360, 135 , coltwo[0], coltwo[1], coltwo[2]) Button("Assign", pacolone, 230, curpos, 60, 20, "Assign RGB to Colour One") Button("Assign", pacoltwo, 300, curpos , 60, 20, "Assign RGB to Colour Two") # ------------------------------------------------------------------------ # # --- Card Management --- elif cardset.val == 1: # Options For Card Generation curpos -= longline glColor3f(0.0, 0.0, 0.0) glRasterPos2f(30, curpos ) Text("Card :") nstacks = Number("Stacks: ", -1, 110, curpos - 5, 75, 20, nstacks.val, 1, 10, "Set Stacks Per Card") hheight = Slider("Height: ", slide, 190, curpos - 5, 170, 20, hheight.val, 0.1, 10.0, 0,"Set Height") curpos -= longline curl = Slider("Curl: ", slide, 110, curpos, 120, 20, curl.val, 0.0, 1.0, 0,"Set Curl") hsize = Slider("Wdt: ", slide, 240, curpos, 120, 20, hsize.val, 0.1, 5.0, 0,"Set Width") curpos -= line Button("Preview", pcardpreview, 110, curpos , 80, 20, "Create Card Preview At 3D Cursor") iscombed = Toggle("Combed", tcombed, 280, curpos, 80, 20, iscombed.val, "Limit Size Effect to Height") curpos -= line maxheight = Slider("Max height: ", slide, 110, curpos, 250, 20, maxheight.val, hsize.val / 2, hheight.val, 0,"Set Height") # ------------------------------------------------------------------------ # # --- Alpha Management --- elif alphaset.val == 1: curpos -= verylongline glColor3f(0.0, 0.0, 0.0) glRasterPos2i(30, curpos + 5) Text("Alpha Maps: ") alphamaps = Menu(alphastr,-1, 110, curpos, 150, 20, alphamaps.val) Button("Add", paddalpha, 265, curpos , 40, 20, "Add Alpha Map") Button("Clear", pclearalpha, 310, curpos , 50, 20, "Clear Alpha Menu") # ------------------------------------------------------------------------ # # --- File Management --- elif fileman.val == 1: glColor3f(0.0, 0.0, 0.0) glRasterPos2f(125, 120) Text("Not Yet Implemented") # ------------------------------------------------------------------------ # # --- Logo --- try: DrawImg(imgbuf, imgwidth, imgheight, 210, 430) except: print "logo.py not found" Register(GUI, Event, BEvent) Blender.Redraw()