-
-
Save ameliemaia/5357070 to your computer and use it in GitHub Desktop.
Two Python scripts that generate a generative sculpture of Digit London's 'D' in Maya.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
D sculpture | |
""" | |
import pymel.core as pm | |
import random | |
from pointset import * | |
sets = 2 | |
points = [ ] | |
for i in range( sets ): | |
position = dt.FloatVector( 0, 0, i * 3 ) | |
ps = PointSet( ) | |
ps.generate( position, 10, 90 ) | |
#ps.createPathOutline( ) | |
points = points + ps.getPoints() | |
random.shuffle( points ) | |
meshLines = [] | |
curves = [] | |
length = len( points ) | |
for i in range( length ): | |
if i < length - 1: | |
p1 = points[ i ] | |
p2 = points[ i + 1 ] | |
size = random.uniform( 0.1, 0.15 ) | |
vector = p2 - p1 | |
curve = pm.curve( p=[ p1, p2 ], degree = 1 ) | |
plane = pm.polyPlane( axis = vector, width = size, height = size, subdivisionsX = 1, subdivisionsY = 1, constructionHistory = False ) | |
plane[0].setTranslation(p1) | |
pm.polyExtrudeFacet( plane[0].f, inputCurve = curve, divisions = 5, smoothingAngle = 30 ) | |
meshLines.append(plane) | |
curves.append(curve) | |
pm.select( meshLines ) | |
pm.polyUnite( constructionHistory = False ) | |
pm.xform( centerPivots = True ) | |
pm.delete( curves ) | |
pm.delete( constructionHistory = True ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This module generates a 2D point set of the Digit 'D' | |
""" | |
import pymel.core as pm | |
import pymel.core.datatypes as dt | |
import pymel.util as util | |
class PointSet(): | |
""" PointSet class """ | |
def __init__( self ): | |
self.WIDTH_RATIO = 0.809510045 | |
self.CURVE_START_RATIO = 0.406360424 | |
""" | |
Generate and return the pointset | |
Keyword arguments: | |
position (list) -- the position to create the pointset from | |
height (float) -- the height of the pointset | |
density (int) -- the amount of points to add to the default set, the density should be divisble by 5 | |
""" | |
def generate(self, position, height, density): | |
self.position = dt.FloatVector(position) | |
self.width = height | |
self.width *= self.WIDTH_RATIO | |
self.height = height | |
self.density = density | |
self.defaultPoints = [] | |
self.points = [] | |
w = self.width | |
h = self.height | |
x = self.position.x | |
y = self.position.y | |
z = self.position.z | |
cx = x + w / 2 | |
cy = y + h / 2 | |
cz = z | |
self.center = dt.FloatVector( cx, cy, cz ) | |
curveStart = self.width | |
curveStart *= self.CURVE_START_RATIO | |
# Default point set | |
p1 = dt.FloatVector( x, y, z ) | |
p2 = dt.FloatVector( x, y + height, z ) | |
p3 = dt.FloatVector( x + curveStart, y + h, z ) | |
p4 = dt.FloatVector( x + w, y + h / 2, z ) | |
p5 = dt.FloatVector( x + curveStart, y, z ) | |
self.defaultPoints = [ p1, p2, p3, p4, p5 ] | |
self.points = self.defaultPoints | |
if self.density < 1: | |
return self.defaultPoints | |
return self.setDensity( self.density ) | |
""" | |
Increase or decrease the density of the pointset | |
Arguments: | |
amount (int) -- the new amount | |
""" | |
def setDensity ( self, amount ): | |
# Make divisible by 5, take away default number of points | |
density = amount / 5 | |
density = round( density ) | |
density *= 5 | |
density -= 5 | |
self.density = int( density ) | |
self.points = self.defaultPoints | |
# New point set | |
newPoints = [ ] | |
# Points per edge | |
pointsPerEdge = self.density / len( self.points ) | |
# First set of points | |
p1 = self.points[ 0 ] | |
p2 = self.points[ 1 ] | |
vector = p2 - p1; | |
newPoints.append( p1 ) | |
for i in range( 1, pointsPerEdge ): | |
# Create points along vector | |
p = p1 + ( vector / pointsPerEdge ) * i | |
newPoints.append(p) | |
# Second set of points | |
p1 = self.points[ 1 ] | |
p2 = self.points[ 2 ] | |
vector = p2 - p1 | |
_pointsPerEdge = pointsPerEdge / 2 | |
newPoints.append( p1 ) | |
for i in range( 0, _pointsPerEdge ): | |
# Create points along vector | |
p = p1 + ( vector / _pointsPerEdge ) * i | |
newPoints.append( p ) | |
# Third and forth set of points | |
p1 = self.points[ 2 ] | |
p2 = self.points[ 3 ] | |
_pointsPerEdge = pointsPerEdge * 2 | |
newPoints.append( p1 ) | |
opposite = p2.x - p1.x | |
adjacent = p1.y - p2.y | |
tan = opposite / adjacent | |
radius = opposite | |
# Loop through the points on the curve | |
for i in range( 0, _pointsPerEdge ): | |
if i == ( _pointsPerEdge / 2 ): | |
newPoints.append( p2 ) | |
continue | |
cpx = p1.x - util.arrays.cos( util.radians(270 - (i * (180 / _pointsPerEdge))) ) * radius | |
cpy = p2.y - util.arrays.sin( util.radians(270 - (i * (180 / _pointsPerEdge))) ) * ( radius / tan ) | |
cpz = p1.z | |
cp = dt.FloatVector( cpx, cpy, cpz ) | |
newPoints.append( cp ) | |
# Fifth set of points | |
p1 = self.points[4] | |
p2 = self.points[0] | |
vector = p2 - p1 | |
# don't need the last point as there's already one there | |
_pointsPerEdge = ( pointsPerEdge / 2 ) - 1 | |
newPoints.append( p1 ) | |
for i in range( 0, _pointsPerEdge ): | |
# Create points along vector | |
p = p1 + ( vector / _pointsPerEdge ) * i | |
newPoints.append( p ) | |
self.points = newPoints | |
return self.points | |
""" Create a CV curve around the outline of the pointset. """ | |
def createPathOutline( self ): | |
curve = pm.curve( p = [ self.points[0], self.points[1] ], degree = 1 ) | |
length = len( self.points ) | |
for i in range( 2, length ): | |
p = self.points[ i ] | |
pm.curve( curve, p = [ p ], append = True ) | |
return curve | |
def createSphereOutline( self ): | |
length = len( self.points ) | |
for i in range( 0, length ): | |
p = self.points[ i ] | |
nurbsSphere = pm.sphere( radius = 0.2 ) | |
nurbsSphere[0].setTranslation( p ) | |
""" Return the position of the pointset (pymel.core.datatypes.FloatVector) """ | |
def position(self): | |
return self.position | |
""" Return the points of the pointset () """ | |
def getPoints(self): | |
return self.points | |
""" Return the width of the pointset (float) """ | |
def width(self): | |
return self.width | |
""" Return the height of the pointset (float) """ | |
def height(self): | |
return self.height | |
""" Return the center of the pointset (pymel.core.datatypes.FloatVector) """ | |
def center(self): | |
return self.center |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment