def buildNurbsRibbon(self): if self.guideSpline: guideDeg = cmds.getAttr(self.guideSpline + '.degree' ) guideSpan = cmds.getAttr(self.guideSpline + '.spans' ) oneCurvePoints = [] otherCurvePoints = [] for i in xrange(guideDeg + guideSpan): cvPos = cmds.pointPosition(self.guideSpline + '.cv[' + str(i) + "]", w=True ) newPara = cmds.closestPointOnCurve(self.guideSpline, ip=cvPos, paramU=True) #Find the parameter Value newParaVal = cmds.getAttr(newPara + ".paramU") cmds.delete(newPara) infoNode = cmds.pointOnCurve(self.guideSpline, ch=True, pr=newParaVal) #Now find the Position and tangent! posy = (cmds.getAttr(infoNode + ".position"))[0] # returns the position posy = MVector(posy[0],posy[1],posy[2]) normy = (cmds.getAttr(infoNode + ".tangent"))[0] normy = MVector(normy[0],normy[1],normy[2]) #Use MVector from maya.openMaya normy = normy.normal() vertVect = MVector(0,1,0) sideMove = normy^vertVect #This is the notation for a cross product. Pretty cool. Should be a normal movement sideMove = sideMove.normal() * 0.5 sideMovePos = posy + sideMove otherSideMovePos = posy - sideMove oneCurvePoints.append([sideMovePos[0],sideMovePos[1],sideMovePos[2]]) otherCurvePoints.append([otherSideMovePos[0],otherSideMovePos[1],otherSideMovePos[2]]) oneSideCurve = cmds.curve(editPoint = oneCurvePoints, degree=3) OtherSideCurve = cmds.curve(editPoint = otherCurvePoints, degree=3) self.tempConstructionParts.append(oneSideCurve) self.tempConstructionParts.append(OtherSideCurve) #Now we loft the surface between the two Curves! nameStart = nameBase(self.totalMarkerList[0].getName(), self.searchString, "loc", "nbs") nameStart += "ribbonSurface" self.guideNurbsRibbon = cmds.loft(oneSideCurve, OtherSideCurve, name = nameStart, constructionHistory = True, uniform = True, close = False, autoReverse = True, degree = 3, sectionSpans = 1, range = False, polygon = 0, reverseSurfaceNormals = True) self.guideNurbsRibbon = self.guideNurbsRibbon[0] self.ribbonParts.append(self.guideNurbsRibbon)
def bary_2d(start, end, percent, barycentric=False): """ 2D Barycentric Co-ordinates Co-ordinates between start and end point: (start + end)* 0.5 Accepts a vector start and a vector end and a float/interger percentage. Coordinates at percentage between start and end point :param start: <list> :param end: <list> :param barycentric: <bool> return barycentric coordinates instead. :param percent: <float> percent value. """ if type(percent) not in [float, int]: if percent > 1 or percent < 0: raise ValueError("Percent must fall in between 1 and 0.") raise ValueError("Please input only float/ interger values for incrementing such as 1.0") # clamp = lambda n, minn, maxn: max(min(maxn, n), minn) # perc = clamp( percent, -1, 0) vc = lambda x, y, z, i, percent: ((x * (i + percent)), (y*(i + percent)), (z*(i + percent))) if start and end: vector1 = vc(*(start+(0, percent))) vector2 = vc(*(end+(-1, percent))) mvec_1 = MVector(*vector1) mvec_2 = MVector(*vector2) mvec_3 = mvec_1 + mvec_2 if barycentric: return (start * percent) + (end * (1-percent)) return mvec_3.x, mvec_3.y, mvec_3.z
def setPosUv(vtxs, length, side, uvDistorted): startUv = pm.ls(pm.polyListComponentConversion(vtxs[0], fv=1, tuv=1), fl=1) if side == 'left': pm.polyEditUV(startUv, r=0, u=0, v=0) else: pm.polyEditUV(startUv, r=0, u=1, v=0) for i in range(1, len(vtxs)): vtx1Pos = pm.xform(vtxs[i - 1], q=1, t=1, ws=1) vtx2Pos = pm.xform(vtxs[i], q=1, t=1, ws=1) vtx1PosVec = MVector(vtx1Pos[0], vtx1Pos[1], vtx1Pos[2]) vtx2PosVec = MVector(vtx2Pos[0], vtx2Pos[1], vtx2Pos[2]) dist = (vtx2PosVec - vtx1PosVec).length() factor = 0.0 if uvDistorted: factor = dist / length else: factor = 1.0 / (len(vtxs) - 1) uv1 = pm.ls(pm.polyListComponentConversion(vtxs[i - 1], fv=1, tuv=1), fl=1) uv2 = pm.ls(pm.polyListComponentConversion(vtxs[i], fv=1, tuv=1), fl=1) uv1Pos = pm.polyEditUV(uv1, q=1) uv2Pos = uv1Pos[1] + factor if side == 'left': pm.polyEditUV(uv2, r=0, u=0, v=uv2Pos) else: pm.polyEditUV(uv2, r=0, u=1, v=uv2Pos)
def buildNurbsRibbon(self): if self.guideSpline: guideDeg = cmds.getAttr(self.guideSpline + '.degree') guideSpan = cmds.getAttr(self.guideSpline + '.spans') oneCurvePoints = [] otherCurvePoints = [] for i in xrange(guideDeg + guideSpan): cvPos = cmds.pointPosition(self.guideSpline + '.cv[' + str(i) + "]", w=True) newPara = cmds.closestPointOnCurve( self.guideSpline, ip=cvPos, paramU=True) #Find the parameter Value newParaVal = cmds.getAttr(newPara + ".paramU") cmds.delete(newPara) infoNode = cmds.pointOnCurve( self.guideSpline, ch=True, pr=newParaVal) #Now find the Position and tangent! posy = (cmds.getAttr(infoNode + ".position"))[0] # returns the position posy = MVector(posy[0], posy[1], posy[2]) normy = (cmds.getAttr(infoNode + ".tangent"))[0] normy = MVector(normy[0], normy[1], normy[2]) #Use MVector from maya.openMaya normy = normy.normal() vertVect = MVector(0, 1, 0) sideMove = normy ^ vertVect #This is the notation for a cross product. Pretty cool. Should be a normal movement sideMove = sideMove.normal() * 0.5 sideMovePos = posy + sideMove otherSideMovePos = posy - sideMove oneCurvePoints.append( [sideMovePos[0], sideMovePos[1], sideMovePos[2]]) otherCurvePoints.append([ otherSideMovePos[0], otherSideMovePos[1], otherSideMovePos[2] ]) oneSideCurve = cmds.curve(editPoint=oneCurvePoints, degree=3) OtherSideCurve = cmds.curve(editPoint=otherCurvePoints, degree=3) self.tempConstructionParts.append(oneSideCurve) self.tempConstructionParts.append(OtherSideCurve) #Now we loft the surface between the two Curves! nameStart = nameBase(self.totalMarkerList[0].getName(), self.searchString, "loc", "nbs") nameStart += "ribbonSurface" self.guideNurbsRibbon = cmds.loft(oneSideCurve, OtherSideCurve, name=nameStart, constructionHistory=True, uniform=True, close=False, autoReverse=True, degree=3, sectionSpans=1, range=False, polygon=0, reverseSurfaceNormals=True) self.guideNurbsRibbon = self.guideNurbsRibbon[0] self.ribbonParts.append(self.guideNurbsRibbon)
def drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length): if (iteration < branches): iteration = iteration + 1 #Draw circle and extrude based on parameters shape = circle(nr=(nrX, nrY, nrZ), c=(cX, cY, cZ), r=radius) extrude(shape, et=0, d=(nrX, nrY, nrZ), l=length) #Delete the base circle, keep the cylinder delete(shape) #Define direction vector and normalize vector = MVector(nrX, nrY, nrZ) vector.normalize() cX = cX + (length * vector.x) cY = cY + (length * vector.y) cZ = cZ + (length * vector.z) randX = r.randint(0, 1) * 2 - 1 randY = r.randint(0, 1) * 2 - 1 randZ = r.randint(0, 1) * 2 - 1 #Random direction vector #For X, Y, Z, ( -1 or 1 )*angle + (randint from -angleVariance to +angleVariance) nrX = nrX + ((angle * randX) + r.randint(0, angleVariance * 2) - angleVariance) / 100.0 nrY = nrY + ((angle * randY) + r.randint(0, angleVariance * 2) - angleVariance) / 100.0 nrZ = nrZ + ((angle * randZ) + r.randint(0, angleVariance * 2) - angleVariance) / 100.0 #Length and Radius based on factor + (randint from -variance to +variance) length = length * (lengthFactor + (r.randint(0, lengthVariance * 2 * 100) / 100.0) - lengthVariance) radius = radius * (radiusFactor + (r.randint(0, radiusVariance * 2 * 100) / 100.0) - radiusVariance) #Draw first branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length) #Use opposite base angle from previous branch nrX = nrX + ((angle * randX * -1) + r.randint(0, angleVariance * 2) - angleVariance) / 100.0 nrY = nrY + ((angle * randY * -1) + r.randint(0, angleVariance * 2) - angleVariance) / 100.0 nrZ = nrZ + ((angle * randZ * -1) + r.randint(0, angleVariance * 2) - angleVariance) / 100.0 length = length * (lengthFactor + (r.randint(0, lengthVariance * 2 * 100) / 100.0) - lengthVariance) radius = radius * (radiusFactor + (r.randint(0, radiusVariance * 2 * 100) / 100.0) - radiusVariance) #Draw second branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length)
def getPlaneDirection(crv): curvePosition = pm.pointOnCurve(crv, pr=0, p=True) curveTangent = pm.pointOnCurve(crv, pr=0, tangent=True) curvePosVec = MVector(curvePosition[0],curvePosition[1],curvePosition[2]) curveTangentVec = MVector(curveTangent[0],curveTangent[1],curveTangent[2]).normal() yVec = MVector(0,1,0) dirVec = yVec ^ curveTangentVec return dirVec
def get_halfway_point(point1="", point2=""): """ returns a halfway point translate list :return: <list> halfway point. """ omv_1 = MVector(*get_object_transform(point1)) omv_2 = MVector(*get_object_transform(point2)) vector_result = (omv_1 + omv_2) / 2 return vector_result.x, vector_result.y, vector_result.z
def distanceBetween(p, q): """Return the distance between two points (vectors) The input vectors should be Python lists or tuples with 3 elements. """ v1 = MVector(*p) v2 = MVector(*q) v3 = v1 - v2 return v3.length()
def getTotalEdgesLength(vtxs): length = 0 for i in range(0, len(vtxs) - 1): vtx1Pos = pm.xform(vtxs[i], q=1, t=1, ws=1) vtx2Pos = pm.xform(vtxs[i + 1], q=1, t=1, ws=1) vtx1PosVec = MVector(vtx1Pos[0], vtx1Pos[1], vtx1Pos[2]) vtx2PosVec = MVector(vtx2Pos[0], vtx2Pos[1], vtx2Pos[2]) dist = (vtx2PosVec - vtx1PosVec).length() length += dist return length
def isMirrorOpen(A, B, mirrorPlane, tolerance): nAxis = mirrorPlaneReturn(mirrorPlane, mode='nAxis') A = (nAxis[0] * A[0], nAxis[1] * A[1], nAxis[2] * A[2]) mvA = MVector(*A) mvB = MVector(*B) diffVector = mvA - mvB if diffVector.length() < tolerance: return True else: return False
def mag(vector1, vector2): """ Adds two vectors and finds the length of the third vector :param vector1: <list> translation data. :param vector2: <list> translation data. :return: <int> value. Uses Maya MVector class """ omv_1 = MVector(*vector1) omv_2 = MVector(*vector2) omv_3 = omv_2 - omv_1 segment_mag = lambda x, y, z: ((x**2)+(y**2)+(z**2))**0.5 return segment_mag(omv_3.x, omv_3.y, omv_3.z)
def look_at(source, target, up_vector=(0, 1, 0), as_vector=True): """ allows the transform object to look at another target vector object. :return: <tuple> rotational vector. """ source_world = transform_utils.Transform(source).world_matrix_list() target_world = transform_utils.Transform(target).world_matrix_list() source_parent_name = object_utils.get_parent_name(source)[0] if source_parent_name == 'world': source_parent_name = None else: parent_world = transform_utils.Transform(source_parent_name).world_matrix_list() # build normalized vector from the translations from matrix data z = MVector(target_world[12] - source_world[12], target_world[13] - source_world[13], target_world[14] - source_world[14]) z *= -1 z.normalize() # get normalized cross product of the z against the up vector at origin # x = z ^ MVector(-up_vector[0], -up_vector[1], -up_vector[2]) x = z ^ MVector(up_vector[0], up_vector[1], up_vector[2]) x.normalize() # get the normalized y vector y = x ^ z y.normalize() # build the aim matrix local_matrix_list = ( x.x, x.y, x.z, 0, y.x, y.y, y.z, 0, z.x, z.y, z.z, 0, 0, 0, 0, 1.0) matrix = object_utils.ScriptUtil(local_matrix_list, matrix_from_list=True).matrix if source_parent_name: # transform the matrix in the local space of the parent object parent_matrix = object_utils.ScriptUtil(parent_world, matrix_from_list=True) matrix *= parent_matrix.matrix.inverse() # retrieve the desired rotation for "source" to aim at "target", in degrees if as_vector: rotation = MTransformationMatrix(matrix).eulerRotation() * RADIANS_2_DEGREES vector = rotation.asVector() return vector.x, vector.y, vector.z, else: return local_matrix_list
def reflection_vector(object_name, as_array=True): """ calculates the reflection vector from the origin. R = 2(N * L) * N - L :return: """ array_1 = transform_utils.Transform(object_name).translate_values(world=True) vector_1 = MVector(*array_1) normal = MVector(0.0, 1.0, 0.0) vector = normal * (2 * (normal * vector_1)) vector -= vector_1 if not as_array: return vector else: return vector.x, vector.y, vector.z
def get_matrix_from_normal(normal_xyz, position, parent_mat): """Converts averaged normal vectors to rotation eulers Return: List: A list representing a [4][4] matrix """ local_y = parent_mat[4:7] tangent_1 = cross(normal_xyz, local_y) tangent_1 = MVector(tangent_1[0], tangent_1[1], tangent_1[2]).normal() tangent_2 = cross(normal_xyz, tangent_1) tangent_2 = MVector(tangent_2[0], tangent_2[1], tangent_2[2]).normal() matrix = [ tangent_2[0], tangent_2[1], tangent_2[2], 0.0, normal_xyz[0], normal_xyz[1], normal_xyz[2], 0.0, tangent_1[0], tangent_1[1], tangent_1[2], 0.0, position[0], position[1], position[2], 1.0 ] return matrix
def averageNormals(normalLs, normalise): """Return the average vector of a list of MVectors If normalise is true, return the normalised vector (length 1) """ sumX = sumY = sumZ = 0 count = len(normalLs) for normal in normalLs: sumX += normal.x sumY += normal.y sumZ += normal.z avg = MVector(sumX / count, sumY / count, sumZ / count) if normalise: avg = avg.normal() return avg
def drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length): if(iteration < branches): iteration = iteration + 1 #Draw circle and extrude based on parameters shape = circle( nr=(nrX, nrY, nrZ), c=(cX, cY, cZ), r=radius) extrude (shape, et=0, d= (nrX, nrY, nrZ), l= length) #Delete the base circle, keep the cylinder delete(shape) #Define direction vector and normalize vector = MVector(nrX, nrY, nrZ) vector.normalize() cX = cX + (length*vector.x) cY = cY + (length*vector.y) cZ = cZ + (length*vector.z) randX = r.randint(0, 1)*2 -1 randY = r.randint(0, 1)*2 -1 randZ = r.randint(0, 1)*2 -1 #Random direction vector #For X, Y, Z, ( -1 or 1 )*angle + (randint from -angleVariance to +angleVariance) nrX = nrX + ((angle*randX) + r.randint(0, angleVariance*2) - angleVariance)/100.0 nrY = nrY + ((angle*randY) + r.randint(0, angleVariance*2) - angleVariance)/100.0 nrZ = nrZ + ((angle*randZ) + r.randint(0, angleVariance*2) - angleVariance)/100.0 #Length and Radius based on factor + (randint from -variance to +variance) length = length * (lengthFactor + (r.randint(0, lengthVariance*2*100)/100.0) - lengthVariance) radius = radius * (radiusFactor + (r.randint(0, radiusVariance*2*100)/100.0) - radiusVariance) #Draw first branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length) #Use opposite base angle from previous branch nrX = nrX + ((angle*randX*-1) + r.randint(0, angleVariance*2) - angleVariance)/100.0 nrY = nrY + ((angle*randY*-1) + r.randint(0, angleVariance*2) - angleVariance)/100.0 nrZ = nrZ + ((angle*randZ*-1) + r.randint(0, angleVariance*2) - angleVariance)/100.0 length = length * (lengthFactor + (r.randint(0, lengthVariance*2*100)/100.0) - lengthVariance) radius = radius * (radiusFactor + (r.randint(0, radiusVariance*2*100)/100.0) - radiusVariance) #Draw second branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length)
def getNormal(face_): ''' Extract the normal vector in a MVector from Maya Python's string format - face_: ID of the face we are getting the normal of ''' normal = mc.polyInfo(face_, faceNormals=True) # convert the string to array with regular expression normal = re.findall(r"[\w.-]+", normal[0]) normal = MVector( float(normal[2]),\ float(normal[3]),\ float(normal[4]) ) return normal
def createStartPoly(vert1, vert2, dirVec): vert1Pos = vert1.getPosition(space='world') vert2Pos = vert2.getPosition(space='world') midPos = getMidPointPos(vert1, vert2) vert1PosVec = MVector(vert1Pos[0], vert1Pos[1], vert1Pos[2]) vert2PosVec = MVector(vert2Pos[0], vert2Pos[1], vert2Pos[2]) midPosVec = MVector(midPos[0], midPos[1] + 3, midPos[2]) lengthPlane = (vert1PosVec - vert2PosVec).length() / 2 lengthDir = dirVec.length() scaleFactor = lengthPlane / lengthDir print scaleFactor dirVec *= scaleFactor newVert1Vec = midPosVec + dirVec newVert2Vec = midPosVec + dirVec * (-1) vert1Pos = [newVert1Vec.x, newVert1Vec.y, newVert1Vec.z] vert2Pos = [newVert2Vec.x, newVert2Vec.y, newVert2Vec.z] tempPoly = pm.polyCreateFacet(p=[vert1Pos, vert2Pos, midPos])[0] return tempPoly
def getVertexNormals(vertex): """Returns a list of MVector objects for each normal associated with the specified vertex (one per attached face) """ mc.select(vertex, replace=True) n = mc.polyNormalPerVertex(query=True, xyz=True) normalLs = [] for i in range(0, len(n), 3): # Pack returned values into a list of MVector objects normal = MVector(n[i], n[i + 1], n[i + 2]) normalLs.append(normal) return normalLs
def viewportSnap(): ''' Zbrush/Nvil like viewport snap ''' camList = cmds.listCameras(o=True) if 'bottom' not in camList: cmds.duplicate('top', name='bottom') cmds.setAttr('bottom.translateY', -512) cmds.setAttr('bottom.rotateX', 90) if 'back' not in camList: cmds.duplicate('front', name='back') cmds.setAttr('back.translateZ', -512) cmds.setAttr('back.rotateY', 180) if 'left' not in camList: cmds.duplicate('side', name='left') cmds.setAttr('left.translateX', -512) cmds.setAttr('left.rotateY', -90) if getCurrentCamera() == 'persp': tm = cmds.xform('persp', q=True, ws=True, matrix=True) perspV = MVector(-tm[8], -tm[9], -tm[10]) dotList = {} for view in camList: tm = cmds.xform(view, q=True, ws=True, matrix=True) tm = MVector(-tm[8], -tm[9], -tm[10]) tm = perspV * tm dotList[view] = tm bv = max(dotList, key=dotList.get) setCurrentCamera(bv) else: setCurrentCamera('persp')
def _align_to_normals(self, vertex, position): """Angles an object based on the position and normals of a vertex. Return: List: A 16 item list representing a [4][4] transformation matrix. """ cmds.select(vertex, r=True) vtx_normals = cmds.polyNormalPerVertex(q=True, xyz=True) avg_normal = self.average_normals(vtx_normals) avg_normal = MVector(avg_normal[0], avg_normal[1], avg_normal[2]).normal() parent_shape = cmds.listRelatives(vertex, parent=True)[0] parent_transform = cmds.listRelatives(parent_shape, parent=True)[0] parent_matrix = cmds.xform(parent_transform, q=True, m=True, ws=True) world_normal = self.world_normal_from_local(avg_normal, parent_matrix) transform_matrix = self.get_matrix_from_normal(world_normal, position, parent_matrix) return transform_matrix
def getMidPointPos(vert1, vert2): vert1Pos = vert1.getPosition(space='world') vert2Pos = vert2.getPosition(space='world') midPoint = (MVector(vert1Pos) + MVector(vert2Pos)) * 0.5 vert3Pos = [midPoint.x, midPoint.y, midPoint.z] return vert3Pos
def randomPopulation(subMeshNames, numberOfInstances, randomRotation): ''' Populate the base mesh with submeshes randomly - subMeshNames: list of names of the submeshes - numberOfInstances: how many submeshes should be instantiated - randRotation: whether the submesh is to receive a random rotation on the local Y axis after it has been instantiated ''' sampleArray = [] calculateFaceAreaArray(sampleArray) mc.progressWindow(title='Progress', progress=0, status='Populating...', isInterruptable=True, max=numberOfInstances) for i in range(numberOfInstances): # If the base mesh is animated, for the pointOnPoly contraint to work properly, submeshes need to be parented to # a dummy object, in this case, an empty group randomFace = rand.choice(sampleArray) randomFace = baseMeshName + '.f[' + str(randomFace) + ']' mc.select(randomFace, r=True) mc.select(mc.polyListComponentConversion(tv=True)) selectedVerts = mc.ls(sl=True, fl=True) # Pick a random triangle within the selected polygon currentTriangle = rand.sample(selectedVerts, 3) averageWeight = getAverageWeight(currentTriangle) while averageWeight < 0.05: randomFace = rand.choice(sampleArray) randomFace = baseMeshName + '.f[' + str(randomFace) + ']' mc.select(randomFace, r=True) mc.select(mc.polyListComponentConversion(tv=True)) selectedVerts = mc.ls(sl=True, fl=True) # Pick another random triangle within the selected polygon currentTriangle = rand.sample(selectedVerts, 3) averageWeight = getAverageWeight(currentTriangle) # Get random point within this face # https://math.stackexchange.com/questions/538458/triangle-point-picking-in-3d v1 = MVector(*mc.pointPosition(currentTriangle[0], w=True)) v2 = MVector(*mc.pointPosition(currentTriangle[1], w=True)) v3 = MVector(*mc.pointPosition(currentTriangle[2], w=True)) a = rand.random() b = rand.random() if a + b >= 1: a = 1 - a b = 1 - b randomPoint = v1 + (v2 - v1) * a + (v3 - v1) * b animatedGroupName = None if isBaseAnimated: animatedGroupName = mc.group(em=True) placeInstance(rand.choice(subMeshNames), randomPoint, averageWeight, randomFace, randomRotation, animatedGroupName) if mc.progressWindow(q=True, isCancelled=True): break mc.progressWindow(edit=True, step=1) mc.progressWindow(endProgress=1)
def drawBranch(self, iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length): if (iteration < self.branches): iteration = iteration + 1 #Draw circle and extrude based on parameters shape = mc.circle(nr=(nrX, nrY, nrZ), c=(cX, cY, cZ), r=radius) poly = mc.extrude(shape, et=0, d=(nrX, nrY, nrZ), l=length) mc.group(poly, parent=self.grp) #Delete the base circle and keep the cylinder mc.delete(shape) #direction vector to grow vector = MVector(nrX, nrY, nrZ) vector.normalize() cX = cX + (length * vector.x) cY = cY + (length * vector.y) cZ = cZ + (length * vector.z) randX = r.randint(0, 1) * 2 - 1 randY = r.randint(0, 1) * 2 - 1 randZ = r.randint(0, 1) * 2 - 1 #Random direction vector #For X, Y, Z, ( -1 or 1 )*angle + (randint from -angleVariance to +angleVariance) nrX = nrX + ((self.angle * randX) + random.randint( 0, self.angleVariance * 2) - self.angleVariance) / 100.0 nrY = nrY + ((self.angle * randY) + random.randint( 0, self.angleVariance * 2) - self.angleVariance) / 100.0 nrZ = nrZ + ((self.angle * randZ) + random.randint( 0, self.angleVariance * 2) - self.angleVariance) / 100.0 #Length and Radius based on factor + (randint from -variance to +variance) length = length * ( self.lengthFactor + (random.randint(0, self.lengthVariance * 2 * 100) / 100.0) - self.lengthVariance) radius = radius * ( self.radiusFactor + (random.randint(0, self.radiusVariance * 2 * 100) / 100.0) - self.radiusVariance) #Draw first branch self.drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length) #Use opposite base angle from previous branch nrX = nrX + ((self.angle * randX * -1) + random.randint( 0, self.angleVariance * 2) - self.angleVariance) / 100.0 nrY = nrY + ((self.angle * randY * -1) + random.randint( 0, self.angleVariance * 2) - self.angleVariance) / 100.0 nrZ = nrZ + ((self.angle * randZ * -1) + random.randint( 0, self.angleVariance * 2) - self.angleVariance) / 100.0 length = length * ( self.lengthFactor + (random.randint(0, self.lengthVariance * 2 * 100) / 100.0) - self.lengthVariance) radius = radius * ( self.radiusFactor + (random.randint(0, self.radiusVariance * 2 * 100) / 100.0) - self.radiusVariance) #Draw second branch self.drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length)
def evenPopulation(subMeshNames, numberOfInstances, randRotation): ''' Populate the base mesh randomly, while trying to keep the instantiated submeshes as far away from each other. - subMeshNames: list of names of the submeshes - numberOfInstances: how many submeshes should be instantiated - randRotation: whether the submesh is to receive a random rotation on the local Y axis after it has been instantiated Best Candidate Selection algorithm idea taken from: https://blog.demofox.org/2017/10/20/generating-blue-noise-sample-points-with-mitchells-best-candidate-algorithm/''' graph = g.getVertices() sampleList = [] # Generate the Samples list of polygon indices calculateFaceAreaArray(sampleList) numberOfVerts = mc.polyEvaluate(baseMeshName, v=True) startingVertex = rand.randrange(0, numberOfVerts) #Pick a random starting vertex while mc.getAttr(baseMeshShape + '.growthWeights')[startingVertex] < 0.05: startingVertex = rand.randrange(0, numberOfVerts) usedVertices = [] usedVertices.append(startingVertex) sel = om.MSelectionList() dag = om.MDagPath() sel.add(baseMeshName) sel.getDagPath(0, dag) mesh = om.MFnMesh(dag) sampleMultiplier = 0.7 dir = om.MVector() progrWindow = mc.progressWindow(title='Progress', progress=0, status='Populating mesh...', isInterruptable=True, max=numberOfInstances) for i in range(numberOfInstances): animatedGroupName = None if isBaseAnimated: animatedGroupName = mc.group(em=True) # We establish a number of candidates to generate and check, which increases linearly with the amount of submeshes # we have placed so far numberOfCandidates = len(usedVertices) * sampleMultiplier + 1 bestDist = 0 bestID = -1 bestWeight = 0 bestPos = [] bestFace = baseMeshName + '.f[0]' for k in range(int(numberOfCandidates)): randomFace = rand.choice(sampleList) randomFace = baseMeshName + '.f[' + str(randomFace) + ']' mc.select(randomFace, r=True) mc.select(mc.polyListComponentConversion(tv=True)) selectedVerts = mc.ls(sl=True, fl=True) # Pick a random triangle within the selected polygon currentTriangle = rand.sample(selectedVerts, 3) averageWeight = getAverageWeight(currentTriangle) while averageWeight < 0.05: randomFace = rand.choice(sampleList) randomFace = baseMeshName + '.f[' + str(randomFace) + ']' mc.select(randomFace, r=True) mc.select(mc.polyListComponentConversion(tv=True)) selectedVerts = mc.ls(sl=True, fl=True) # Pick another random triangle within the selected polygon currentTriangle = rand.sample(selectedVerts, 3) averageWeight = getAverageWeight(currentTriangle) #mc.select(currentTriangle, r = True) # Get random point within this face v1 = MVector(*mc.pointPosition(currentTriangle[0], w=True)) v2 = MVector(*mc.pointPosition(currentTriangle[1], w=True)) v3 = MVector(*mc.pointPosition(currentTriangle[2], w=True)) a = rand.random() b = rand.random() if a + b >= 1: a = 1 - a b = 1 - b randomPoint = v1 + (v2 - v1) * a + (v3 - v1) * b #GET A RANDOM VERTEX FROM THE SELECTED TRIANGLE vertID = int( re.findall(r"[\w]+", currentTriangle[rand.randint(0, 2)])[2]) # We compare the geodesic distance (using the Graph we generated before and using the Dijkstra pathfinding # algorithm) between our current vertex and all of the other vertices we have used to place submeshes distances = calculate_distances(graph, vertID) minDist = 999999.9 for vertexID in usedVertices: dist = distances[vertexID] if dist < minDist: minDist = dist # We take the smallest distance and compare it with our Best Distance (defaulted to 0 at the beginning of each # candidate search). If it's greater than it, then it means this is the vertex which is the furthest away from # any other vertex we've used, so we make it our new Best Candidate if minDist > bestDist: bestDist = minDist bestID = vertID bestWeight = averageWeight bestPos = randomPoint bestFace = randomFace # Once we've gone through all the candidates, we place and rotate the new submesh according to the # Best Candidate's information and add the Best Vertex to the "used vertices" list placeInstance(rand.choice(subMeshNames), bestPos, bestWeight, bestFace, randRotation, animatedGroupName) usedVertices.append(bestID) if mc.progressWindow(q=True, isCancelled=True): break mc.progressWindow(edit=True, step=1) mc.progressWindow(endProgress=1)
def drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length,old_circle,ShereBool): if(iteration < branches): iteration = iteration + 1 print("iteration= "+str(iteration)) #Draw circle and extrude based on parameters R=radius*math.fabs(math.sin(iteration)) R=radius+iteration-math.fabs(iteration) R=10-iteration circle( nr=(nrX, nrY, nrZ), c=(cX, cY, cZ), r=radius) shape = cmds.ls(sl=True)[0] circleReffArr.append(shape) cmds.select( clear=True ) cmds.select( old_circle, add=True ) cmds.select( shape, add=True ) cmds.loft( c=0, ch=1, d=3, ss=1, rsn=True, ar=1, u=1, rn=0, po=0) extrudedSurface = cmds.ls(sl=True)[0] print("nrX= "+str(nrX)+" nrY= "+str(nrY)+" nrZ= "+str(nrZ)) if(0==True): cmds.polySphere(createUVs=2, sy=20, ch=1, sx=20, r=radius*10) SpherePoly = cmds.ls(sl=True)[0] cmds.move( cX, cY, cZ, SpherePoly, absolute=True ) #extrudedSurface=extrude (shape, et=0, d= (nrX, nrY, nrZ), l= length) #extrudedSurface=extrude (shape, extrudeType=0, d= (nrX, nrY, nrZ), l= length,polygon=1) #extrudedSurface=extrude (shape, extrudeType=0, d= (nrX, nrY, nrZ), l= length) cmds.nurbsToPoly(extrudedSurface, uss=1, ch=1, ft=0.01, d=0.1, pt=0, f=0, mrt=0, mel=0.001, ntr=0, vn=3, pc=1000, chr=0.9, un=3, vt=1, ut=1, ucr=0, cht=0.01, mnd=1, es=0, uch=0) delete(extrudedSurface) #print("extrudedSurface= "+str(extrudedSurface)) extrudedPoly = cmds.ls(sl=True)[0] print("extrudedPoly= "+str(extrudedPoly)) cmds.polyCloseBorder(extrudedPoly, ch=1)# Close Holl hollface = cmds.ls(sl=True)[0] print("hollface= "+str(hollface)) cmds.polyTriangulate(hollface, ch=1) cmds.select(extrudedPoly) #cmds.polyClean(extrudedPoly) #cmds.eval('polyCleanupArgList 4 { "0","1","1","1","1","1","1","1","0","1e-05","0","1e-05","0","1e-05","0","1","1","0" };') #Delete the base circle, keep the cylinder #delete(shape) #Define direction vector and normalize vector = MVector(nrX, nrY, nrZ) vector.normalize() cX = cX + (length*vector.x) cY = cY + (length*vector.y) cZ = cZ + (length*vector.z) randX = random.randint(0, 1)*2 -1 randY = random.randint(0, 1)*2 -1 randZ = random.randint(0, 1)*2 -1 #Random direction vector #For X, Y, Z, ( -1 or 1 )*angle + (randint from -angleVariance to +angleVariance) nrX = nrX + ((angle*randX) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrY = nrY + ((angle*randY) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrZ = nrZ + ((angle*randZ) + random.randint(0, angleVariance*2) - angleVariance)/100.0 #Length and Radius based on factor + (randint from -variance to +variance) length = length * (lengthFactor + (random.randint(0, lengthVariance*2*100)/100.0) - lengthVariance) radius = radius * (radiusFactor + (random.randint(0, radiusVariance*2*100)/100.0) - radiusVariance) #Draw first branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length,shape,False) #drawBranch(iteration, cX, cY, cZ, 0, 1, 0, radius, length,shape,False) #-------------------- #Use opposite base angle from previous branch nrX = nrX + ((angle*randX*-1) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrY = nrY + ((angle*randY*-1) + random.randint(0, angleVariance*2) - angleVariance)/100.0 nrZ = nrZ + ((angle*randZ*-1) + random.randint(0, angleVariance*2) - angleVariance)/100.0 length = length * (lengthFactor + (random.randint(0, lengthVariance*2*100)/100.0) - lengthVariance) radius = radius * (radiusFactor + (random.randint(0, radiusVariance*2*100)/100.0) - radiusVariance) #Draw second branch drawBranch(iteration, cX, cY, cZ, nrX, nrY, nrZ, radius, length,shape,True)
# dotProduct.py # # Takes translates of two objects as vectors and # calculates the dot product these vectors # import maya.cmds as cmds import operator import sys from maya.OpenMaya import MVector selection = cmds.ls(selection=True, type='transform') if len(selection) < 2: print "Select target object and then bullet object." sys.exit() obj1 = selection[0] obj2 = selection[1] xP = cmds.getAttr('%s.translate' %(obj1))[0] yP = cmds.getAttr('%s.translate' %(obj2))[0] x = MVector(xP[0], xP[1], xP[2]) y = MVector(yP[0], yP[1], yP[2]) print x*y
# if there's only one way to intercept if determinant == 0: t1 = (-b) / (a * 2.0) return max(t1, 0) #---------------------------------------- # calculate intercept point #---------------------------------------- targetPos = cmds.getAttr('%s.translate' % (targetName))[0] targetSpeed = cmds.getAttr('%s.Speed' % (targetName)) targetDirection = cmds.getAttr('%s.Direction' % (targetName)) bulletPos = cmds.getAttr('%s.translate' % (bulletName))[0] bulletSpeed = cmds.getAttr('%s.Speed' % (bulletName)) vTargetPos = MVector(targetPos[0], targetPos[1], targetPos[2]) vTargetSpeed = MVector( math.cos(targetDirection) * targetSpeed, targetPos[1], math.sin(targetDirection) * targetSpeed) vBulletPos = MVector(bulletPos[0], bulletPos[1], bulletPos[2]) vInterceptPos = getInterceptPos(vTargetPos, vTargetSpeed, vBulletPos, bulletSpeed) vBulletDirection = vInterceptPos - vBulletPos vUnit = MVector(1, 0, 0) bulletDirection = vBulletDirection.angle(vUnit) if vBulletDirection.z < 0: bulletDirection *= -1.0 # create locator at intercept point cmds.spaceLocator(p=(vInterceptPos.x, vInterceptPos.y, vInterceptPos.z))