import os
import Blender
from Blender import NMesh, Object
from Blender.BGL import *
from Blender.Draw import *



from math import pow

from string import strip

BL_VERSION = Blender.Get('version')

if BL_VERSION < 223:
	from dynoise import random, HTerrain, InitNoise
else:
	from Blender.Noise import random, heteroTerrain as HTerrain, setRandomSeed as InitNoise
	
#Get the current .fib filename
a = Blender.Get("filename")
b = Blender.sys.dirname(a)
a = a.split(os.sep)[len(a.split(os.sep)) -1]
fname = b + os.sep + str(a.split(".")[0]) + ".fib"



def readint(f):
	return int(f.readline())

def readfloat(f):
	return float(f.readline())

def readstr(f):
	s = (f.readline())
	return strip(s)

def writeln(f,x):
  f.write(str(x))
  f.write("\n")

def LoadPreset():
	#_______________________________________________________
	#Loads the preset .fib
	#_______________________________________________________
	global d, grav2, s, l2, w, n, FVersion
	global r, rl, follow, ctrl, CtrlSeg, SegRnd, Ff
	global txtDensity, txtGravity, txtSegments, txtLength, txtWidth, txtInit
	global txtRand, txtRloc, txtFalloff
	global pointed, UseVCol, UseWind, UseGuides, seed
	global objects
	global firstrun, grav2z, l2z, wz, nz, rz, rlz

	try:
		f = open(fname,'r')
	except:
		print "Unable to read parameters.  Please run the GUI first and make sure you have file creation permissions."
		Exit()

	FVersion = readfloat(f)

	d  = readfloat(f)	
	grav2z  = readfloat(f)
	grav2	= grav2z / 100.0
	s = readint(f)
	l2z		 = readfloat(f)
	l2 = l2z / 100.0
	wz    = readfloat(f)
	w = wz / 100.0
	nz     = readfloat(f)
	n = nz / 100.0
	rz     = readfloat(f)
	r = rz / 10.0
	rlz     = readfloat(f)
	rl = rlz / 100.0
	follow   = readfloat(f)
	ctrl 	= int(readfloat(f))
	CtrlSeg = int(readfloat(f))
	SegRnd  = readfloat(f)
	Ff = readfloat(f)
	txtDensity  = readint(f)
	txtGravity  = readint(f)
	txtSegments = readint(f)
	txtLength   = readint(f)
	txtWidth    = readint(f)
	txtInit     = readint(f)
	txtRand     = readint(f)
	txtRloc     = readint(f)
	txtFalloff	= readint(f)
	pointed  	= readint(f)
	UseVCol     = readint(f)
	UseWind     = readint(f)
	UseGuides	= readint(f)
	seed        = readint(f)
	firstrun	= readint(f)
	objects = []
	
	#Load object list
	while 0==0:
		item = readstr(f)
		if len(item) > 0:
			objects.append(item)
		else:
			break

	f.close()
	InitNoise(seed)
 
def SavePreset():
	#_______________________________________________________
	#Resaves the preset .fib, signifying that it's not the
	#first time the script has been run
	#_______________________________________________________  
	try:
		f = open(fname,'w')
	except:
		message = "unable to save file."
		return
	
	writeln(f,FVersion)
	
	writeln(f,d)
	writeln(f,grav2z)
	writeln(f,s)
	writeln(f,l2z)
	writeln(f,wz)
	writeln(f,nz)
	writeln(f,rz)
	writeln(f,rlz)
	writeln(f,follow)
	writeln(f,ctrl)
	writeln(f,CtrlSeg)
	writeln(f,SegRnd)
	writeln(f,Ff)
	writeln(f,txtDensity)
	writeln(f,txtGravity)
	writeln(f,txtSegments)
	writeln(f,txtLength)
	writeln(f,txtWidth)
	writeln(f,txtInit)
	writeln(f,txtRand)
	writeln(f,txtRloc)
	writeln(f,txtFalloff)
	writeln(f,pointed)
	writeln(f,UseVCol)
	writeln(f,UseWind)
	writeln(f,UseGuides)
	writeln(f,seed)
	writeln(f,0) #Not First Run
	
	for z in range(len(objects)):
		writeln(f,objects[z])
	f.close()
	
def fncArea(f,mat):
	#_______________________________________________________
	#Finds the area of a face with global coordinates
	#Updated v1.4 to include matrix calculations (DUH!!!)
	#Parameters: f=NMesh face, mat = NMesh matrix
	#_______________________________________________________
	if len(f.v) > 2:
		
		v1 = multmat(mat,f.v[0])
		v2 = multmat(mat,f.v[1])
		v3 = multmat(mat,f.v[2])

		adist =	pow(pow(v1.co[0] - v2.co[0],2)+	pow(v1.co[1] - v2.co[1],2)+	pow(v1.co[2] - v2.co[2],2),.5)
		bdist =	pow(pow(v2.co[0] - v3.co[0],2)+ pow(v2.co[1] - v3.co[1],2)+ pow(v2.co[2] - v3.co[2],2),.5)
		cdist =	pow(pow(v3.co[0] - v1.co[0],2)+ pow(v3.co[1] - v1.co[1],2)+ pow(v3.co[2] - v1.co[2],2),.5)	
	
		semi = (adist+bdist+cdist)/2
		area = pow(semi*(semi-adist)*(semi-bdist)*(semi-cdist),.5)

		if len(f.v) == 4:
			v4 = multmat(mat,f.v[3])
			adist =	pow(pow(v1.co[0] - v3.co[0],2)+ pow(v1.co[1] - v3.co[1],2)+ pow(v1.co[2] - v3.co[2],2),.5)
			bdist =	pow(pow(v3.co[0] - v4.co[0],2)+ pow(v3.co[1] - v4.co[1],2)+ pow(v3.co[2] - v4.co[2],2),.5)	
			cdist =	pow(pow(v4.co[0] - v1.co[0],2)+ pow(v4.co[1] - v1.co[1],2)+ pow(v4.co[2] - v1.co[2],2),.5)	
	
			semi = (adist+bdist+cdist)/2
			area += pow(semi*(semi-adist)*(semi-bdist)*(semi-cdist),.5)
		return area
	else:
		return 0
def fncdistance(pt1,pt2):
	#_______________________________________________________
	#Returns the distance between two points
	#Parameters: pt1,pt2- 3 point tuples [x,y,z]
	#_______________________________________________________
	return pow(pow(pt1[0]-pt2[0],2)+pow(pt1[1]-pt2[1],2)+pow(pt1[2]-pt2[2],2),.5)

def fncFindWeight(pt1,pt2,pt3):
	#_______________________________________________________
	#Returns the weight between two points and an origin
	#Parameters: pt1,pt2- 3 point tuples [x,y,z]
	#pt3 is the origin
	#_______________________________________________________
	dist = [fncdistance(pt3,pt1),fncdistance(pt3,pt2)]
	return 1- (dist[1] / (dist[0] + dist[1]))

def fncFindWeightedVert(pt1,pt2,weight):
	#_______________________________________________________
	#Returns the weighted coordinates of a vert between two points
	#Parameters: pt1,pt2- 3 point tuples [x,y,z]
	#weight from 0 to 1
	#_______________________________________________________
	movedist = [pt1[0],pt1[2]]
	if pt1[0] - pt2[0] == 0:
		pt1[0] += .01
	slope = (pt1[1] - pt2[1]) / (pt1[0] - pt2[0])
	mult = [pt2[0] - pt1[0], pt2[2] - pt1[2]]
	return ([weight * mult[0] + movedist[0],float(slope * weight + (pt1[1]/mult[0])) * mult[0],weight * mult[1] + movedist[1]])

def multmat(mMatrix,vert):
	#_______________________________________________________
	#Finds the global coordinates of a vertex and takes into
	#consideration parenting and mesh deformation.
	#Parameters: mMatrix = NMesh matrix, vert = NMesh vertex
	#_______________________________________________________
	#Takes a vert and the parent's object matrix 
	x= vert.co[0];  y= vert.co[1]; z= vert.co[2] 
	x1 = (x * mMatrix[0][0]) + (y * mMatrix[1][0]) + (z * mMatrix[2][0]) + mMatrix[3][0] 
	y1 = (x * mMatrix[0][1]) + (y * mMatrix[1][1]) + (z * mMatrix[2][1]) + mMatrix[3][1] 
	z1 = (x * mMatrix[0][2]) + (y * mMatrix[1][2]) + (z * mMatrix[2][2]) + mMatrix[3][2] 

	newV = NMesh.Vert(x1,y1,z1)
	#vert.co[0]=x1; vert.co[1]=y1; vert.co[2]=z1
		
	return newV

def vecsub(a,b): 
	#_______________________________________________________
	#Finds a vector from two 3D points
	#Parameters: a,b = NMesh matrix coordinate
	#_______________________________________________________
	return [a[0]-b[0], a[1]-b[1], a[2]-b[2]] 

def renormal(p1,p2,p3):
	#_______________________________________________________
	#Takes three co-planar 3D points and returns the face normal
	#Parameters: p1,p2,p3 = NMesh verts
	#_______________________________________________________  
	norm = [0,0,0] 
	v1 = vecsub(p1.co, p2.co) 
	v2 = vecsub(p1.co, p3.co) 
	norm[0] = v1[1]*v2[2] - v1[2]*v2[1] 
	norm[1] = v1[2]*v2[0] - v1[0]*v2[2] 
	norm[2] = v1[0]*v2[1] - v1[1]*v2[0]

	#keep normals at a distance of 1 unit
	normaldist = 1/(pow(pow(norm[0],2)+pow(norm[1],2)+pow(norm[2],2),.5))
	for z in range(3):
		norm[z] *= normaldist
	
	return norm

def Bezier3(p1,p2,p3,mu):
	#_________________________________________
	#Three control point Bezier interpolation
	#Parameters: p1 to p3- 3 point tuple [x,y,z]
	#mu ranges from 0 to 1 (start to end of curve) 
	#_________________________________________
	p = [0,0,0]

	mu2 = mu * mu
	mum1 = 1 - mu
	mum12 = mum1 * mum1
 	for z in range(3):  
		p[z] = p1[z] * mum12 + 2 * p2[z] * mum1 * mu + p3[z] * mu2

	return(p);

def Bezier4(p1,p2,p3,p4,mu):
	#_________________________________________
	#Four control point Bezier interpolation
	#Parameters: p1 to p4- 3 point tuple [x,y,z]
	#mu ranges from 0 to 1 (start to end of curve) 
	#_________________________________________
	p = [0,0,0]
	mum1 = 1 - mu
	mum13 = mum1 * mum1 * mum1
	mu3 = mu * mu * mu

	for z in range(3):
		p[z] = mum13*p1[z] + 3*mu*mum1*mum1*p2[z] + 3*mu*mu*mum1*p3[z] + mu3*p4[z]
	return(p)

def Bezier(p,mu):
	#_________________________________________
	#General Bezier curve
	#Parameters: p array of points ( etc [[x1,y1,z1],[x2,y2,z2],...] )
	#mu ranges from 0 to 1 (start to end of curve)
	#IMPORTANT, the last point is not computed
	#_________________________________________
	b = [0,0,0]
	n = len(p)
	muk = 1
	munk = pow(1-mu,n)

	
	for k in range(n):  
		nn = n
		kn = k
		nkn = n - k
		blend = muk * munk
		muk *= mu
		munk /= (1-mu)
		while nn >= 1:
			blend *= nn
			nn -=1
			if kn > 1:
				blend /= float(kn)
				kn-=1
			if nkn > 1:
				blend /= float(nkn)
				nkn-=1
  		for z in range(3):    
			b[z] += p[k][z] * blend
	return(b)

def ControlPoints(ctrlnum, CtrlSeg):
	#_______________________________________________________
	#Creates 4 point bezier curves to act as guides for fibers
	#Parameters: ctrlnum- the number of control curves to create
	#_______________________________________________________  
	global mat, grav	
	grav = 0
	object = Object.GetSelected()
	for num in range(len(object)):
		i = 0
		if BL_VERSION<=223:
			original = object[num].data
		else:
			original = object[num].getData()

		if ctrlnum > len(original.faces):
			ctnm = len(original.faces)
		else:
			ctnm = ctrlnum
			
		mat = object[num].matrix

		vertex = [0,0,0]
	
		me = NMesh.GetRaw()
		for fs in range(0, len(original.faces), len(original.faces) / ctnm):
			f = original.faces[fs]
			
			normal = renormal(multmat(mat,f.v[0]),multmat(mat,f.v[1]),multmat(mat,f.v[2]))
					
			for z in range(3):
				vertex[z] = normal[z]
		
			#centerpoint coordinates
			vertex = [0,0,0]
			for va in f.v:
				v = multmat(mat,va)
				for z in range(3):
					#z is the coordinate plane (x,y,or z)
					vertex[z] += v.co[z]
			for z in range(3):
				vertex[z] /= len(f.v)
			
			for z in range(CtrlSeg):
				i += 1
				v = NMesh.Vert(vertex[0] + (z * normal[0]), vertex[1] + (z * normal[1]), vertex[2] + (z * normal[2]))
				me.verts.append(v)
			
			for z in range(CtrlSeg-1):
				face=NMesh.Face()
				face.v.append(me.verts[i-1-z])
				face.v.append(me.verts[i-2-z])
				me.faces.append(face)	
	
		GuideOBJ = NMesh.PutRaw(me,original.name+"_Fiber.C")	
		GuideOBJ.name = original.name+"_Fiber.C"
	Blender.Redraw()


def RunFiber():
	#_______________________________________________________
	#The main routine that is called from outside this script
	#Parameters: none- loads settings from .fib file.
	#_______________________________________________________  
	global firstrun, mat, FpF, UseWind, UseGuides
	LoadPreset()
	if firstrun == 1:
		SavePreset()

	InitNoise(seed)
	print "\n"
	print "RipSting's Fiber Generator v2.03, running on", str(len(objects)), "object(s)"

	
	#____________________________________________________________
	#Extract properties from the empty "Wind" if enabled
	#____________________________________________________________
	if UseWind == 1:
		try:
			Wind = Object.Get("Wind")
			Height = Wind.SizeZ / 50.0
			SizeX = Wind.SizeX
			SizeY = Wind.SizeY
			DirX = Wind.LocX / 100.0
			DirY = Wind.LocY / 100.0
			Falloff = Wind.LocZ /100.0
			Roughness = .5
		except:
			print "Cannot find an empty named \"wind\": Not using wind engine."
			UseWind = 0

	#____________________________________________________________
	#Other variable declarations
	#____________________________________________________________

	vertexcount = 0
	objnum = 0

	polycenter = [0,0,0]
	corner1 = [0,0,0]
	corner2 = [0,0,0]
	normal = [0,0,0]
	dir = [0,0,0]
	basevertex = [0,0,0]
	vertex = [0,0,0]
	vertexold = [0,0,0]
	vertexno = [0,0,0]
	randomdir = [0,0,0]
	gravitydir = [0,0,0]
	WindDir = [0,0,0,0] #First two are initial, second two are incremental
	vCorner = [0,0] #Vertex color corners
	vColor1 = [0,0,0]
	vColor2 = [0,0,0]
	aColor = [0,0,0]
	vPercent = [0,0,0]
	addVariables = [0,0,0]
	VcolClump = 1

	frame = Blender.Get('curframe')
	redoFpF = 0
	try:
		test = FpF
	except:
		redoFpF = 1
	#____________________________________________________________
	#Setup Density if not already initialized
	#____________________________________________________________
	if firstrun == 1 or redoFpF == 1:
		print "Storing fiber information for animation"
		dens = d
		seg = s
		FpF = []
		for num in range(len(objects)):
			mat = Object.Get(objects[num]).matrix
			if BL_VERSION<=223:
				original = Object.Get(objects[num]).data
			else:
				original = Object.Get(objects[num]).getData()
			for f in original.faces:
				if len(f.v) < 3: break
				FpF.append(int(fncArea(f,mat) * d))
	#____________________________________________________________
	
	fnum = -1
	for num in range(len(objects)):
		i=0 #set vertex count to zero
		if BL_VERSION<=223:
			original = Object.Get(objects[num]).data
		else:
			original = Object.Get(objects[num]).getData()
		
		mat = Object.Get(objects[num]).matrix
		
		meshname = original.name
		if firstrun == 0:
			me = NMesh.GetRaw(meshname+"_Fiber."+str(objnum))
		else:
			me = NMesh.GetRaw()
			if BL_VERSION <= 223:
				me.has_uvco = 1
		

		#____________________________________________________________
		#Test for fiber guides
		#____________________________________________________________
		if UseGuides == 1:
			try:
				Guides = NMesh.GetRaw(meshname +"_Fiber.C")
				GuideOBJ = Object.Get(meshname+"_Fiber.C")
				GMat = GuideOBJ.matrix
				if (len(Guides.verts)/CtrlSeg) != int(len(Guides.verts)/CtrlSeg):
					print "Uneven number of control points non-divisible by" , CtrlSeg ,"\nPlease re-create fiber guides."
					print len(Guides.verts)
					UseGuides = 0
			except:
				UseGuides = 0
				
		#____________________________________________________________
		for f in original.faces:
			#Skip over faces with only 2 verts (Edges) v1.3
			if len(f.v) < 3: break
			
			fnum += 1
		
			p=0
			if UseGuides == 0:
				#____________________________________________________________
				#find normal direction
				#____________________________________________________________	

				normal = renormal(multmat(mat,f.v[0]),multmat(mat,f.v[1]),multmat(mat,f.v[2]))

				#follownormals- 1 = follow, 0 = don't follow
				normal[0] *= follow
				normal[1] *= follow
				normal[2] = (1 - follow) + (normal[2] * follow)
				#____________________________________________________________

			#centerpoint coordinates
			polycenter = [0,0,0]
			for va in f.v:
				v = multmat(mat,va)
				for z in range(3):
					#z is the coordinate plane (x,y,or z)
					polycenter[z] += v.co[z]
			for z in range(3):
				polycenter[z] /= len(f.v)
			
			if UseVCol == 1 and original.hasVertexColours() == 1:
					# colorvalues of centerpoint
					for z in range(len(f.v)):
 						aColor[0] += f.col[z].r
						aColor[1] += f.col[z].g
						aColor[2] += f.col[z].b
					for z in range(3):
						aColor[z] /= len(f.v)

			for x in range (FpF[fnum]): #loop for density in each poly
				#no need to calculate things if density for face is 0
				if UseVCol == 1 and original.hasVertexColours() == 1:
					if f.col[0].b + f.col[1].b + f.col[1].b == 0:
						break

				vertexcount += s*2 + 2
				if vertexcount > 60000: 
					#____________________________________________________________
					#create new mesh if vertex count is close to limit (v1.1)
					#____________________________________________________________
					
					# reminder: for all versions, if it really is new, PutRaw returns the new linked object, otherwise it returns None
					# but lets not worry about that here, since GetSelected()[0] will always return the object
					NMesh.PutRaw(me, meshname+"_Fiber."+str(objnum))

					tO=Object.Get(objects[num])
					tN=Object.GetSelected()[0]

					#tN=Object.GetSelected()[0]
					#tN.loc = mat[3][0],mat[3][1],mat[3][2]
			
					Blender.Redraw()
					objnum += 1
					if firstrun == 0:
						me = NMesh.GetRaw(meshname+"_Fiber."+str(objnum))
					else:
						me = NMesh.GetRaw()
						if BL_VERSION <= 223:
							me.has_uvco = 1
					vertexcount = 0
					i = 0
						
				#_____________________________________________________________
				#Find a point on the current face for the fiber to grow out of
				#My logic behind this:
				#pick a random point between the center of the poly and any corner
				#pick a random point between the center and the next corner adjacent to the original
				#pick a random distance between those other two random points
				#This ensures that the blade will actually be on the face
				#____________________________________________________________
				cornernum = int(random() * len(f.v)) #Pick a random corner
				vCorner[0] = cornernum
				cornernum += 1
				if cornernum > len(f.v)-1:
					cornernum = 0
				vCorner[1] = cornernum
				#____________________________________________________________
				#Find random location for new fiber on the current face
				#Much simplified randomization speeds process (v1.3)
				#____________________________________________________________
				percent = pow(random(),.5) #optimized V1.3: replaced 14 different random() statements!!!
				vPercent[0] = percent
				vPercent[1] = percent
				
				for z in range(3):
					corner1[z] = (multmat(mat,f.v[vCorner[0]]).co[z] - polycenter[z]) * percent + polycenter[z]			
				for z in range(3):
					corner2[z] = (multmat(mat,f.v[vCorner[1]]).co[z] - polycenter[z]) * percent + polycenter[z]
					
				percent = random()
				vPercent[2] = percent
				for z in range(3):
					basevertex[z] = (corner2[z] - corner1[z]) * percent + corner1[z]
				vertex = basevertex
				
				#____________________________________________________________
				#Vertex color Stuff (v1.2)
				#____________________________________________________________
				if UseVCol == 1 and original.hasVertexColours() == 1:
					vColor1[0] = f.col[vCorner[0]].r
					vColor1[1] = f.col[vCorner[0]].g
					vColor1[2] = f.col[vCorner[0]].b
					vColor2[0] = f.col[vCorner[1]].r
					vColor2[1] = f.col[vCorner[1]].g
					vColor2[2] = f.col[vCorner[1]].b

					for z in range(2):
						addVariables[z] = ((aColor[z] * (1-vPercent[0])) + (vColor1[z] * vPercent[0]))/2
						addVariables[z] = (addVariables[z] * (1-vPercent[2]) + (((aColor[z] * (1-vPercent[1])) + (vColor2[z] * vPercent[1]))/2) * vPercent[2])/2
					addVariables[2] = (vColor1[2] + vColor2[2])/2
				else:
					#Use these values if no vertex colors are present
					addVariables = [63.75,63.75,255] 
					
				#Green ties into the length of the fibers
				#If Using fiber guides, Green ties into clumpiness
				l = l2 * ((addVariables[1]) / 2)
				VcolClump = 1#addVariables[1] / 85.0
				#Red ties into the gravity effect on the fibers
				grav = grav2 * ((addVariables[0]) / 5)
				#Blue ties into density...  x is the faces generated so far for the face... v1.3
				FaceDensity = int(FpF[fnum] * addVariables[2]) -1
				#print FaceDensity, x
				if x >= FaceDensity:
					break
			
				#____________________________________________________________
				#Wind
				#____________________________________________________________
				if UseWind == 1:
					WindStrength = ((HTerrain([vertex[0]/SizeX+(frame*DirX), vertex[1]/SizeY+(frame*DirY), frame*Falloff], 1, 1, Height, Roughness) -(Height/2)) * Height)*pow(l,1.5)
				
					#Find Y/X Slope that the wind is blowing at
					if abs(Wind.LocX) > abs(Wind.LocY):
						WindDir[0] = (Wind.LocY / Wind.LocX) * WindStrength
						WindDir[1] = WindStrength
						if Wind.LocY < 0:
							WindDir[1] = -WindDir[1]
					else:
						WindDir[0] = WindStrength
						if Wind.LocY == 0:
							Wind.LocY = .001

						WindDir[1] = (Wind.LocX / Wind.LocY) * WindStrength
							
						if Wind.LocX < 0:
							WindDir[0] = -WindDir[0]
					if Wind.LocY < 0:
						WindDir[0] = -WindDir[0]
					WindDir[2] = 0
					WindDir[3] = 0

				if UseGuides == 0:
					#____________________________________________________________
					#Normal stuff
					#____________________________________________________________
					for z in range(3):
						vertexno[z] = normal[z] + (r * (random()-.5))	
				#____________________________________________________________
				#Find random direction that the blade is rotated
				#(So that it looks good from all angles, and isn't uniform)
				#____________________________________________________________
				rw= [random() -.5, random() -.5]

				#Find Y/X Slope that the blade is facing
				if abs(rw[0]) > abs(rw[1]):
					dir[0] = (rw[1] / rw[0]) * w
					dir[1] = w
					if rw[1] < 0:
						dir[1] = - dir[1]
				else:
					dir[0] = w
					dir[1] = (rw[0] / rw[1]) * w
					if rw[0] < 0:
						dir[0] = -dir[0]
				#dir[2] = rw
				#____________________________________________________________
				#Start the creation process!
				#____________________________________________________________
				i = i + 2 #increment vertex count
				gravitydir = [0,0,n] #right now I only have gravity working on the Z axis
					
				#____________________________________________________________
				#If the fiber mesh already exists, simply move the verts instead
				#of creating new ones.  Preserves material data.
				#____________________________________________________________
				if firstrun == 0:
					#Move base verts
					for z in range(3):
						#vertex[z] = me.verts[i-2].co[z]
						me.verts[i-1].co[z] = vertex[z] + dir[z]
						me.verts[i-2].co[z] = vertex[z]
				else:	
					#Create base verts
					v = NMesh.Vert(vertex[0], vertex[1], vertex[2])
					me.verts.append(v)
					v = NMesh.Vert(vertex[0] + dir[0], vertex[1] + dir[1], vertex[2] + dir[2])
					me.verts.append(v)
				
				if UseGuides == 0:
					#____________________________________________________________
					#Normal creation routine with gravity, randomdir, etc.
					#____________________________________________________________
					for y in range (s):
						
						for z in range(3):
							randomdir[z] = (random()-.5) * rl
							vertexold[z] = vertex[z]
					
						WindDir[2] += WindDir[0]
						WindDir[3] += WindDir[1]
						
						gravitydir[2] += grav
						vertex[0] += (vertexno[0]) * l - gravitydir[0] + WindDir[2] + randomdir[0]
						vertex[1] += (vertexno[1]) * l - gravitydir[1] + WindDir[3] + randomdir[1]
						vertex[2] += (vertexno[2]) * l - gravitydir[2] + randomdir[2]
			
						#____________________________________________________________
						#Fix segment length issues with gravity
						#____________________________________________________________	
						distance = pow(pow(vertexold[0] - vertex[0],2)+pow(vertexold[1] - vertex[1],2)+pow(vertexold[2] - vertex[2],2),.5)
						divide = (distance/(l +.001))
						#for z in range(3):
						vertex[0] =  (vertex[0]-vertexold[0]) / divide + vertexold[0]
						vertex[1] =  (vertex[1]-vertexold[1]) / divide + vertexold[1]
						vertex[2] =  (vertex[2]-vertexold[2]) / divide + vertexold[2]
						#____________________________________________________________					

						face=NMesh.Face()
						if pointed == 1 and y == s-1:
							i += 1 #increment vertex count
							if firstrun == 0:
								#Move base verts
								me.verts[i-1].co[0] = vertex[0]+dir[0]/2
								me.verts[i-1].co[1] = vertex[1]+dir[1]/2
								me.verts[i-1].co[2] = vertex[2]+dir[2]/2
							else:	
								#Create base verts
								v = NMesh.Vert(vertex[0]+dir[0]/2,vertex[1]+dir[1]/2,vertex[2]+dir[2]/2)
								me.verts.append(v)
						else:
							i += 2 #increment vertex count
							if firstrun == 0:
								#Move base verts
								me.verts[i-2].co[0] = vertex[0]
								me.verts[i-2].co[1] = vertex[1]
								me.verts[i-2].co[2] = vertex[2]
								me.verts[i-1].co[0] = vertex[0]+dir[0]
								me.verts[i-1].co[1] = vertex[1]+dir[1]
								me.verts[i-1].co[2] = vertex[2]+dir[2]
							else:	
								#Create base verts
								v = NMesh.Vert(vertex[0],vertex[1],vertex[2]+randomdir[2])
								me.verts.append(v)
								v = NMesh.Vert(vertex[0]+dir[0],vertex[1]+dir[1],vertex[2]+dir[2])
								me.verts.append(v)
								face.v.append(me.verts[i-4])
								
						if firstrun == 1:
							face.v.append(me.verts[i-2])
							face.v.append(me.verts[i-1])
							face.v.append(me.verts[i-3])
							
							face.uv.append((0,float(y)/s))
							if pointed == 1 and y == s-1:
								face.uv.append((.5,1))
							else:
								face.uv.append((0,float(y)/s + (1.0/s)))
								face.uv.append((1,float(y)/s + (1.0/s)))
							face.uv.append((1,float(y)/s))

							me.faces.append(face)

				else:
					#____________________________________________________________
					#Use Guides instead of gravity, segment length, etc.	(check)	
					#____________________________________________________________
					Guide = []
					Guide1 = []
					Guide2 = []

					
					GuideOBJ = Object.Get(original.name+"_Fiber.C")
					GMat = GuideOBJ.matrix
					gv = Guides.verts

					#____________________________________________________________
					#Find Closest two fiber guides and store them in c[]	(check)
					#____________________________________________________________
					c = [0,CtrlSeg]
					if fncdistance(multmat(GMat,gv[c[1]]).co, basevertex) < fncdistance(multmat(GMat,gv[c[0]]).co, basevertex):
						#Swap
						temp = c[1]
						c[1] = c[0]
						c[0] = temp
					for y in range(CtrlSeg*2,len(gv),CtrlSeg):
						if fncdistance(multmat(GMat,gv[y]).co,basevertex) < fncdistance(multmat(GMat,gv[c[0]]).co,basevertex):
							c[1] = c[0]	
							c[0] = y
						elif fncdistance(multmat(GMat,gv[y]).co,basevertex) < fncdistance(multmat(GMat,gv[c[1]]).co,basevertex):
							c[1] = y

					#____________________________________________________________
					#Get the coordinates of the guides' control points		(check)
					#____________________________________________________________
					Guide0 = []
					for y in range(CtrlSeg):
						Guide1.append ([multmat(GMat,gv[c[0]+y]).co[0],multmat(GMat,gv[c[0]+y]).co[1],multmat(GMat,gv[c[0]+y]).co[2]])
						Guide2.append ([multmat(GMat,gv[c[1]+y]).co[0],multmat(GMat,gv[c[1]+y]).co[1],multmat(GMat,gv[c[1]+y]).co[2]])
					for y in range(len(Guide1)):
						Guide0.append([0,0,0])
						for z in range(3):
							Guide0[y][z] = Guide1[y][z]
					for y in range(1,CtrlSeg):
						for z in range(3):
							Guide1[y][z] -= Guide1[0][z]
							Guide2[y][z] -= Guide2[0][z]

					#____________________________________________________________
					#Determine weight of the two fiber guides ()			(check)	
					#____________________________________________________________
					weight = fncFindWeight(gv[c[0]].co,gv[c[1]].co,vertex)
					#____________________________________________________________
					#Find single, weighted, control fiber					(check)
					#____________________________________________________________
					Guide.append ([0,0,0])
					for y in range(1,CtrlSeg):
						Guide.append (fncFindWeightedVert(Guide1[y],Guide2[y],weight))
					Flen = SegRnd * random()
					#print Guide
					#____________________________________________________________
					#Create the Fiber	
					#____________________________________________________________
					for y in range(1,s):
						#____________________________________________________________
						#Impliment Wind
						#____________________________________________________________
						WindDir[2] += WindDir[0]
						WindDir[3] += WindDir[1]
						for z in range(3):
							randomdir[z] = (random()-.5) * rl
						#____________________________________________________________
						#Use Bezier interpolation
						#____________________________________________________________
						if CtrlSeg == 3:
							v = Bezier3(Guide[0],Guide[1],Guide[2],float(y)/s * (1-Flen))
						elif CtrlSeg == 4:
							v = Bezier4(Guide[0],Guide[1],Guide[2],Guide[3],float(y)/s * (1-Flen))
						else:
							v = Bezier(Guide,float(y)/s * (1-Flen))
						face=NMesh.Face()
						vertex = [v[0]+basevertex[0],v[1]+basevertex[1],v[2]+basevertex[2]]
						
						#____________________________________________________________
						#Clumping
						#____________________________________________________________
						if follow != 0:
							for z in range(1,len(Guide1)):
								Guide1[z] += Guide0
							
							weight = pow(1-((float(y)/s) * (follow * VcolClump)),Ff) #Ff = Clumpiness Falloff
							if CtrlSeg == 3:
								v = Bezier3(Guide0[0],Guide0[1],Guide0[2],float(y)/s * (1-Flen)) #Flen = random fiber length
							elif CtrlSeg == 4:
								v = Bezier4(Guide0[0],Guide0[1],Guide0[2],Guide0[3],float(y)/s * (1-Flen))
							else:
								v = Bezier(Guide0,float(y)/s * (1-Flen))
	
							vertex = fncFindWeightedVert(v, vertex, weight)

						#____________________________________________________________
						#Create Verts & Faces
						#____________________________________________________________
						vertex = [vertex[0]+randomdir[0]+WindDir[2],vertex[1]+randomdir[1]+WindDir[3], vertex[2] + randomdir[2]]
						
						if y == s-1 and pointed == 1:
							i += 1
							if firstrun == 1:
								me.verts.append(NMesh.Vert(vertex[0] + dir[0]/2, vertex[1] + dir[1]/2, vertex[2] + dir[2]/2))	
							else:
								me.verts[i-1].co[0] = vertex[0]+dir[0]/2
								me.verts[i-1].co[1] = vertex[1]+dir[1]/2
								me.verts[i-1].co[2] = vertex[2]+dir[2]/2
						else:
							i +=2
							if firstrun == 1:
								vert = NMesh.Vert(vertex[0], vertex[1], vertex[2])
								me.verts.append(vert)
								vert = NMesh.Vert(vertex[0]+dir[0], vertex[1]+dir[1], vertex[2]+dir[2])
								me.verts.append(vert)
								face.v.append(me.verts[i-4])
							else:
								#Move base verts
								me.verts[i-2].co[0] = vertex[0]
								me.verts[i-2].co[1] = vertex[1]
								me.verts[i-2].co[2] = vertex[2]
								me.verts[i-1].co[0] = vertex[0]+dir[0]
								me.verts[i-1].co[1] = vertex[1]+dir[1]
								me.verts[i-1].co[2] = vertex[2]+dir[2]
							
						if firstrun == 1:
							face.v.append(me.verts[i-2])
							face.v.append(me.verts[i-1])
							face.v.append(me.verts[i-3])
							
							face.uv.append((0,float(y)/s))
							if pointed == 1 and y == s-1:
								face.uv.append((.5,1))
							else:
								face.uv.append((0,float(y)/s + (1.0/s)))
								face.uv.append((1,float(y)/s + (1.0/s)))
							face.uv.append((1,float(y)/s))
							
							me.faces.append(face)
							

		NMesh.PutRaw(me,meshname+"_Fiber."+str(objnum))
		vertexcount = 0	
		
	#print "Generation finished with " + str(faces) + " faces!"
	Blender.Redraw()
