def __updatePrism(self, mesh, o, e, index, p): dir = aljabr.vsub(e, o) # direction vector from o to e len = aljabr.vlen(dir) # distance from o to e scale = 0.5 # the thickness is 10% of the length i = aljabr.vadd(o, aljabr.vmul(dir, 0.25)) # the thickest part is 25% from o n = aljabr.vmul(dir, 1.0 / len) # the normalized direction q = aljabr.axisAngleToQuaternion(n, pi / 2.0) # a quaternion to rotate the point p1 to obtain the other points p1 = p # a random point in the plane defined by 0,0,0 and n p1 = aljabr.vmul(aljabr.vnorm(p1), scale) # the point scaled to the thickness p2 = aljabr.quaternionVectorTransform(q, p1) # the other points p3 = aljabr.quaternionVectorTransform(q, p2) p4 = aljabr.quaternionVectorTransform(q, p3) p1 = aljabr.vadd(i, p1) # translate by i since we were working in the origin p2 = aljabr.vadd(i, p2) p3 = aljabr.vadd(i, p3) p4 = aljabr.vadd(i, p4) # The 6 vertices mesh.verts[index].co = o mesh.verts[index+1].co = p1 mesh.verts[index+2].co = p2 mesh.verts[index+3].co = p3 mesh.verts[index+4].co = p4 mesh.verts[index+5].co = e
def projectLighting(self): mesh = gui3d.app.selectedHuman.mesh mesh.setShadeless(1) dstImg = mh.Image(width=1024, height=1024, bitsPerPixel=24) dstW = dstImg.width dstH = dstImg.height for v in mesh.verts: ld = vnorm(vsub((-10.99, 20.0, 20.0,), v.co)) s = vdot(v.no, ld) s = max(0, min(255, int(s*255))) v.setColor([s, s, s, 255]) for g in mesh.faceGroups: if g.name.startswith("joint") or g.name.startswith("helper"): continue for f in g.faces: co = [(mesh.uvValues[i][0]*dstW, dstH-(mesh.uvValues[i][1]*dstH)) for i in f.uv] c = [v.color for v in f.verts] RasterizeTriangle(dstImg, co[0], co[1], co[2], ColorShader(c[:3])) RasterizeTriangle(dstImg, co[2], co[3], co[0], ColorShader((c[2], c[3], c[0]))) #dstImg.resize(128, 128); dstImg.save(os.path.join(mh.getPath(''), 'data', 'skins', 'lighting.png')) gui3d.app.selectedHuman.setTexture(os.path.join(mh.getPath(''), 'data', 'skins', 'lighting.png')) mesh.setColor([255, 255, 255, 255])
def updatePrism(mesh, o, e, index, p): dir = aljabr.vsub(e, o) # direction vector from o to e if dir == [0.0, 0.0, 0.0]: dir = [0.0, 1.0, 0.0] len = aljabr.vlen(dir) # distance from o to e if len == 0: len = 1 scale = 0.5 # the thickness is 10% of the length i = aljabr.vadd(o, aljabr.vmul(dir, 0.25)) # the thickest part is 25% from o n = aljabr.vmul(dir, 1.0 / len) # the normalized direction q = aljabr.axisAngleToQuaternion( n, pi / 2.0) # a quaternion to rotate the point p1 to obtain the other points p1 = p # a random point in the plane defined by 0,0,0 and n p1 = aljabr.vmul(aljabr.vnorm(p1), scale) # the point scaled to the thickness p2 = aljabr.quaternionVectorTransform(q, p1) # the other points p3 = aljabr.quaternionVectorTransform(q, p2) p4 = aljabr.quaternionVectorTransform(q, p3) p1 = aljabr.vadd(i, p1) # translate by i since we were working in the origin p2 = aljabr.vadd(i, p2) p3 = aljabr.vadd(i, p3) p4 = aljabr.vadd(i, p4) # The 6 vertices mesh.verts[index].co = o mesh.verts[index + 1].co = p1 mesh.verts[index + 2].co = p2 mesh.verts[index + 3].co = p3 mesh.verts[index + 4].co = p4 mesh.verts[index + 5].co = e
def chooseTraslSamples(self): direction = aljabr.vnorm(self.angle) similarity = {} if self.angle != [0.0,0.0,0.0]: for sample in self.examplesTrasl: direction2 = aljabr.vnorm(sample) sampleDistance1 = aljabr.vdist(direction,direction2) sampleDistance2 = math.fabs(aljabr.vlen(aljabr.vsub(self.angle,sample))) similarity[sampleDistance1+sampleDistance2] = sample d = similarity.keys() d.sort() nearestSample1 = similarity[d[0]] nearestSample2 = similarity[d[1]] nearestSample3 = similarity[d[2]] factor1,factor2,factor3 = self.equalize(d[0],d[1],d[2]) return (nearestSample1,nearestSample2,nearestSample3,factor1,factor2,factor3) else: return ([0,0,0],[0,0,0],[0,0,0],0,0,0)
def hairWidthUpdate(scn, obj,res=0.04, widthFactor=1.0): #luckily both normal and vertex index of object remains the same! N=len(obj.verts) origWidth = vdist(obj.verts[1].co,obj.verts[0].co)/res diff= (widthFactor-origWidth)*res/2 for i in xrange(0,N/2): vec=vmul(vnorm(vsub(obj.verts[i*2+1].co,obj.verts[i*2].co)), diff) obj.verts[i*2].co=vsub(obj.verts[i*2].co,vec) obj.verts[i*2+1].co=vadd(obj.verts[i*2+1].co,vec) obj.verts[i*2].update(updateNor=0) obj.verts[i*2+1].update(updateNor=0)
def addPrism(mesh, o=[0.0, 0.0, 0.0], e=[0.0, 1.0, 0.0], name='prism'): fg = mesh.createFaceGroup(name) dir = aljabr.vsub(e, o) # direction vector from o to e if dir == [0.0, 0.0, 0.0]: dir = [0.0, 1.0, 0.0] len = aljabr.vlen(dir) # distance from o to e if len == 0: len = 1 scale = 0.5 # the thickness is 10% of the length i = aljabr.vadd(o, aljabr.vmul(dir, 0.25)) # the thickest part is 25% from o n = aljabr.vmul(dir, 1.0 / len) # the normalized direction q = aljabr.axisAngleToQuaternion( n, pi / 2.0) # a quaternion to rotate the point p1 to obtain the other points p = p1 = aljabr.randomPointFromNormal( n) # a random point in the plane defined by 0,0,0 and n p1 = aljabr.vmul(aljabr.vnorm(p1), scale) # the point scaled to the thickness p2 = aljabr.quaternionVectorTransform(q, p1) # the other points p3 = aljabr.quaternionVectorTransform(q, p2) p4 = aljabr.quaternionVectorTransform(q, p3) p1 = aljabr.vadd(i, p1) # translate by i since we were working in the origin p2 = aljabr.vadd(i, p2) p3 = aljabr.vadd(i, p3) p4 = aljabr.vadd(i, p4) # The 6 vertices v = [] v.append(mesh.createVertex(o)) # 0 0 v.append(mesh.createVertex(p1)) # 1 /|\ v.append(mesh.createVertex(p2)) # 2 /.2.\ v.append(mesh.createVertex(p3)) # 3 1` | `3 v.append(mesh.createVertex(p4)) # 4 \`.4.`/ v.append(mesh.createVertex(e)) # 5 \ | / # \|/ # 5 # The 8 faces fg.createFace((v[0], v[1], v[4], v[0])) fg.createFace((v[0], v[4], v[3], v[0])) fg.createFace((v[0], v[3], v[2], v[0])) fg.createFace((v[0], v[2], v[1], v[0])) fg.createFace((v[5], v[4], v[1], v[5])) fg.createFace((v[5], v[1], v[2], v[5])) fg.createFace((v[5], v[2], v[3], v[5])) fg.createFace((v[5], v[3], v[4], v[5])) return p
def addPrism(mesh, o=[0.0, 0.0, 0.0], e=[0.0, 1.0, 0.0], name='prism'): fg = mesh.createFaceGroup(name) dir = aljabr.vsub(e, o) # direction vector from o to e if dir == [0.0, 0.0, 0.0]: dir = [0.0, 1.0, 0.0] len = aljabr.vlen(dir) # distance from o to e if len == 0: len = 1 scale = 0.5 # the thickness is 10% of the length i = aljabr.vadd(o, aljabr.vmul(dir, 0.25)) # the thickest part is 25% from o n = aljabr.vmul(dir, 1.0 / len) # the normalized direction q = aljabr.axisAngleToQuaternion(n, pi / 2.0) # a quaternion to rotate the point p1 to obtain the other points p = p1 = aljabr.randomPointFromNormal(n) # a random point in the plane defined by 0,0,0 and n p1 = aljabr.vmul(aljabr.vnorm(p1), scale) # the point scaled to the thickness p2 = aljabr.quaternionVectorTransform(q, p1) # the other points p3 = aljabr.quaternionVectorTransform(q, p2) p4 = aljabr.quaternionVectorTransform(q, p3) p1 = aljabr.vadd(i, p1) # translate by i since we were working in the origin p2 = aljabr.vadd(i, p2) p3 = aljabr.vadd(i, p3) p4 = aljabr.vadd(i, p4) # The 6 vertices v = [] v.append(mesh.createVertex(o)) # 0 0 v.append(mesh.createVertex(p1)) # 1 /|\ v.append(mesh.createVertex(p2)) # 2 /.2.\ v.append(mesh.createVertex(p3)) # 3 1` | `3 v.append(mesh.createVertex(p4)) # 4 \`.4.`/ v.append(mesh.createVertex(e)) # 5 \ | / # \|/ # 5 # The 8 faces fg.createFace((v[0], v[1], v[4], v[0])) fg.createFace((v[0], v[4], v[3], v[0])) fg.createFace((v[0], v[3], v[2], v[0])) fg.createFace((v[0], v[2], v[1], v[0])) fg.createFace((v[5], v[4], v[1], v[5])) fg.createFace((v[5], v[1], v[2], v[5])) fg.createFace((v[5], v[2], v[3], v[5])) fg.createFace((v[5], v[3], v[4], v[5])) return p
def generateHairInterpolation2(self,guide1,guide2,humanMesh,isCollision,startIndex=9,gravity=True): if isCollision: octree = simpleoctree.SimpleOctree(humanMesh.getData().verts,0.08) hairName = "strand%s-%s"%(guide1.name,guide2.name) hSet = HairGroup(hairName) if len(guide1.controlPoints)>= len(guide2.controlPoints): longerGuide = guide1 shorterGuide = guide2 else: longerGuide = guide2 shorterGuide = guide1 nVerts = min([len(guide1.controlPoints),len(guide2.controlPoints)]) interpFactor = 0 vertsListToModify1 = [] vertsListToModify2 = [] for n in range (self.numberOfHairsMultiStrand): h = Hair() interpFactor += 1.0/self.numberOfHairsMultiStrand for i in range(len(longerGuide.controlPoints)): if random.random() < self.randomPercentage: xRand = self.sizeMultiStrand*random.random()*self.randomFactMultiStrand yRand = self.sizeMultiStrand*random.random()*self.randomFactMultiStrand zRand = self.sizeMultiStrand*random.random()*self.randomFactMultiStrand randomVect = [xRand,yRand,zRand] else: randomVect = [0,0,0] if i == 0: i2 = 0 if i == len(longerGuide.controlPoints)-1: i2 = len(shorterGuide.controlPoints)-1 else: i2 = int(round(i*len(shorterGuide.controlPoints)/len(longerGuide.controlPoints))) vert1 = longerGuide.controlPoints[i] vert2 = shorterGuide.controlPoints[i2] #Slerp dotProd = aljabr.vdot(aljabr.vnorm(vert1),aljabr.vnorm(vert2)) #Python has a very very bad numerical accuracy.. we need to do this for very small angle between guides #this occurs when we do collision detection if dotProd>1: angleBetweenGuides = 0.0 else: angleBetweenGuides = math.acos(aljabr.vdot(aljabr.vnorm(vert1),aljabr.vnorm(vert2))) denom = math.sin(angleBetweenGuides) if denom == 0.0: #controlpoints of some guides coincide vert1[0] = self.randomPercentage*self.sizeMultiStrand*random.random()*self.randomFactMultiStrand+vert1[0] vert1[1] = self.randomPercentage*self.sizeMultiStrand*random.random()*self.randomFactMultiStrand+vert1[1] vert1[2] = self.randomPercentage*self.sizeMultiStrand*random.random()*self.randomFactMultiStrand+vert1[2] vert1= aljabr.vadd(vert1,randomVect) angleBetweenGuides = math.acos(aljabr.vdot(aljabr.vnorm(vert1),aljabr.vnorm(vert2))) denom = math.sin(angleBetweenGuides) f1 = math.sin((1-interpFactor)*angleBetweenGuides)/denom f2 = math.sin(interpFactor*angleBetweenGuides)/denom newVert = aljabr.vadd(aljabr.vmul(vert1,f1),aljabr.vmul(vert2,f2)) #Uncomment the following line we use lerp instead slerp #newVert = aljabr.vadd(aljabr.vmul(vert1,(1-interpFactor)),aljabr.vmul(vert2,interpFactor)) h.controlPoints.append([newVert[0]+randomVect[0],\ newVert[1]+randomVect[1],\ newVert[2]+randomVect[2]]) if isCollision: print "h is: ", h.controlPoints for j in (0,len(h.controlPoints)): #print "h.controlPts is : ", h.controlPoints[i] #print "h.controlPts[i] length is: ", len(h.controlPoints[i]) h.controlPoints[i][2] = -h.controlPoints[i][2] #Renderman to Blender coordinates! collision(h.controlPoints,humanMesh,octree.minsize,startIndex,gravity) for j in (0,len(h.controlPoints)): h.controlPoints[i][2] = -h.controlPoints[i][2] #Blender to Renderman coordinates! hSet.hairs.append(h) self.hairStyle.append(hSet)
def direction(self): direction = vnorm(self.offset) axis = vnorm(vcross([0.0, 0.0, 1.0], direction)) angle = acos(vdot([0.0, 0.0, 1.0], direction)) return axisAngleToQuaternion(axis, angle)
def projectBackground(self): if not hasattr(self, "leftTop"): gui3d.app.prompt("Warning", "You need to load a background before you can project it.", "OK") return mesh = gui3d.app.selectedHuman.getSeedMesh() # for all quads, project vertex to screen # if one vertex falls in bg rect, project screen quad into uv quad # warp image region into texture leftTop = gui3d.app.modelCamera.convertToScreen(*self.leftTop) rightBottom = gui3d.app.modelCamera.convertToScreen(*self.rightBottom) r = [leftTop[0], leftTop[1], rightBottom[0], rightBottom[1]] srcImg = mh.Image(self.backgroundImage.getTexture()) dstImg = mh.Image(gui3d.app.selectedHuman.getTexture()) srcW = srcImg.width srcH = srcImg.height dstW = dstImg.width dstH = dstImg.height eye = gui3d.app.modelCamera.eye focus = gui3d.app.modelCamera.focus transform = mesh.object3d.transform eye = mtransform(transform, eye) focus = mtransform(transform, focus) camera = vnorm(vsub(eye, focus)) for g in mesh.faceGroups: if g.name.startswith("joint") or g.name.startswith("helper"): continue for f in g.faces: # From hdusel in regard of issue 183: As agreed with marc I'll change the # call from packed to discrete because packed structs # are not available on Python 2.6.1 which is mandatory for MakeHuman to run # on OS X 10.5.x # # src = [gui3d.app.modelCamera.convertToScreen(*v.co, obj=mesh.object3d) for v in f.verts] # src = [gui3d.app.modelCamera.convertToScreen(v.co[0], v.co[1], v.co[2], obj=mesh.object3d) for v in f.verts] if any([pointInRect(p, r) for p in src]): for i, v in enumerate(f.verts): src[i][2] = max(0.0, vdot(v.no, camera)) if any([v[2] >= 0.0 for v in src]): for i, v in enumerate(f.verts): src[i][2] = max(0.0, vdot(v.no, camera)) co = [(mesh.uvValues[i][0]*dstW, dstH-(mesh.uvValues[i][1]*dstH)) for i in f.uv] uva = [((v[0]-leftTop[0])/(rightBottom[0] - leftTop[0]), (v[1]-leftTop[1])/(rightBottom[1] - leftTop[1]), v[2]) for v in src] RasterizeTriangle(dstImg, co[0], co[1], co[2], UvAlphaShader(dstImg, srcImg, (uva[:3]))) RasterizeTriangle(dstImg, co[2], co[3], co[0], UvAlphaShader(dstImg, srcImg, ((uva[2], uva[3], uva[0])))) dstImg.save(os.path.join(mh.getPath(''), 'data', 'skins', 'projection.tga')) gui3d.app.selectedHuman.setTexture(os.path.join(mh.getPath(''), 'data', 'skins', 'projection.tga'))
def getRestDirection(self): return aljabr.vnorm(self.getRestOffset())