any scripts can generate curves along the normal ?
Posted: 25 May 2012, 05:29
any scripts or plug-ins can generate curves along the normal ?(polygon face or vertices )
or ICE ?
thx~!
or ICE ?
thx~!
unofficial SOFTIMAGE© community
https://si-community.com/community/
Code: Select all
# Python
from win32com.client import constants as c
from win32com.client import Dispatch as d
xsi = Application
log = xsi.LogMessage
collSel = xsi.Selection
def xformFromDirection(vecBase, vecTgt, vecUpV):
"""Creates a transform for base object pointing to target with an upvector upV."""
vecX = XSIMath.CreateVector3()
vecY = XSIMath.CreateVector3()
vecZ = XSIMath.CreateVector3()
vecToTgt = XSIMath.CreateVector3()
vecBaseToUpV = XSIMath.CreateVector3()
vecX.Sub(vecBase,vecTgt)
vecX.NormalizeInPlace()
vecBaseToUpV.Sub(vecUpV,vecBase)
vecBaseToUpV.NormalizeInPlace()
vecZ.Cross(vecX,vecBaseToUpV)
vecZ.NormalizeInPlace()
vecY.Cross(vecZ,vecX)
vecY.NormalizeInPlace()
return vecX,vecY,vecZ
def createCurveNormals(oTgtObj):
lNormalCurveData = [[0.0, 0.0], [0.0, 1.0], [0.0, 0.0], [1.0, 1.0]]
oTgtGeo = oTgtObj.ActivePrimitive.Geometry
collPoints = oTgtGeo.Points
aNormals = [[y for y in x] for x in list(oTgtGeo.Points.NormalArray)]
aPositions = [[y for y in x] for x in list(oTgtGeo.Points.PositionArray)]
xformUtil = XSIMath.CreateTransform()
for i in xrange(collPoints.Count):
oNormalCrv = oTgtObj.AddNurbsCurve(lNormalCurveData,None,True,1,c.siNonUniformParameterization,c.siSINurbs)
oNormalCrv.Name = oTgtObj.Name + "_Normal" + str(i).zfill(len(str(collPoints.Count))) + "_Crv"
xformUtil.SetTranslationFromValues(aPositions[0][i],aPositions[1][i],aPositions[2][i])
if aNormals[1][i] >= 0.001:
vecUpV = XSIMath.CreateVector3(0,1,0)
rotUtil = XSIMath.CreateRotation()
rotUtil.SetFromXYZAnglesValues(0,0,XSIMath.DegreesToRadians(-90))
else:
vecUpV = XSIMath.CreateVector3(0,-1,0)
rotUtil = XSIMath.CreateRotation()
rotUtil.SetFromXYZAnglesValues(0,XSIMath.DegreesToRadians(-180),XSIMath.DegreesToRadians(-90))
vecX, vecY, vecZ = xformFromDirection(xformUtil.Translation, XSIMath.CreateVector3(aNormals[0][i],aNormals[1][i],aNormals[2][i]), vecUpV)
xformUtil.SetRotationFromXYZAxes(vecX,vecY,vecZ)
xformUtil.AddLocalRotation(rotUtil)
xformUtil.MulInPlace(oTgtObj.Kinematics.Global.GetTransform2(None))
oNormalCrv.Kinematics.Global.PutTransform2(None,xformUtil)
createCurveNormals(collSel(0))
EricTRocks wrote:Good little exercise. Select object run script.
Code: Select all
# Python from win32com.client import constants as c from win32com.client import Dispatch as d xsi = Application log = xsi.LogMessage collSel = xsi.Selection def xformFromDirection(vecBase, vecTgt, vecUpV): """Creates a transform for base object pointing to target with an upvector upV.""" vecX = XSIMath.CreateVector3() vecY = XSIMath.CreateVector3() vecZ = XSIMath.CreateVector3() vecToTgt = XSIMath.CreateVector3() vecBaseToUpV = XSIMath.CreateVector3() vecX.Sub(vecBase,vecTgt) vecX.NormalizeInPlace() vecBaseToUpV.Sub(vecUpV,vecBase) vecBaseToUpV.NormalizeInPlace() vecZ.Cross(vecX,vecBaseToUpV) vecZ.NormalizeInPlace() vecY.Cross(vecZ,vecX) vecY.NormalizeInPlace() return vecX,vecY,vecZ def createCurveNormals(oTgtObj): lNormalCurveData = [[0.0, 0.0], [0.0, 1.0], [0.0, 0.0], [1.0, 1.0]] oTgtGeo = oTgtObj.ActivePrimitive.Geometry collPoints = oTgtGeo.Points aNormals = [[y for y in x] for x in list(oTgtGeo.Points.NormalArray)] aPositions = [[y for y in x] for x in list(oTgtGeo.Points.PositionArray)] xformUtil = XSIMath.CreateTransform() for i in xrange(collPoints.Count): oNormalCrv = oTgtObj.AddNurbsCurve(lNormalCurveData,None,True,1,c.siNonUniformParameterization,c.siSINurbs) oNormalCrv.Name = oTgtObj.Name + "_Normal" + str(i).zfill(len(str(collPoints.Count))) + "_Crv" xformUtil.SetTranslationFromValues(aPositions[0][i],aPositions[1][i],aPositions[2][i]) if aNormals[1][i] >= 0.001: vecUpV = XSIMath.CreateVector3(0,1,0) rotUtil = XSIMath.CreateRotation() rotUtil.SetFromXYZAnglesValues(0,0,XSIMath.DegreesToRadians(-90)) else: vecUpV = XSIMath.CreateVector3(0,-1,0) rotUtil = XSIMath.CreateRotation() rotUtil.SetFromXYZAnglesValues(0,XSIMath.DegreesToRadians(-180),XSIMath.DegreesToRadians(-90)) vecX, vecY, vecZ = xformFromDirection(xformUtil.Translation, XSIMath.CreateVector3(aNormals[0][i],aNormals[1][i],aNormals[2][i]), vecUpV) xformUtil.SetRotationFromXYZAxes(vecX,vecY,vecZ) xformUtil.AddLocalRotation(rotUtil) xformUtil.MulInPlace(oTgtObj.Kinematics.Global.GetTransform2(None)) oNormalCrv.Kinematics.Global.PutTransform2(None,xformUtil) createCurveNormals(collSel(0))
EricTRocks wrote:Not sure why that would happen. Do the normals look OK when displayed in the viewport? I tested on a sphere and it worked fine for me.
Code: Select all
# Python
from win32com.client import constants as c
from win32com.client import Dispatch as d
xsi = Application
log = xsi.LogMessage
collSel = xsi.Selection
def axesFromNormal(vecNormal, vecUpV):
"""Creates vectors for each axis of a transform."""
vecX = XSIMath.CreateVector3()
vecY = XSIMath.CreateVector3()
vecZ = XSIMath.CreateVector3()
vecToTgt = XSIMath.CreateVector3()
vecBaseToUpV = XSIMath.CreateVector3()
vecX.Cross(vecUpV, vecNormal)
vecX.NormalizeInPlace()
vecY.Copy(vecNormal)
vecY.NormalizeInPlace()
vecZ.Cross(vecX, vecNormal)
vecZ.NormalizeInPlace()
return vecX,vecY,vecZ
def ET_NormalCurves(oTgtObj, bUsePolys=False, sNormalScale=1.0):
try:
xsi.BeginUndo("ET_NormalCurves")
lNormalCurveData = [[0.0, 0.0], [0.0, sNormalScale], [0.0, 0.0], [1.0, 1.0]]
oTgtGeo = oTgtObj.ActivePrimitive.Geometry
if bUsePolys:
aPolygonPositionICEData = oTgtGeo.ICEAttributes("PolygonPosition").GetDataArrayChunk(0,0)
aPositions = [[i.X,i.Y,i.Z] for i in aPolygonPositionICEData]
aPolygonNormalICEData = oTgtGeo.ICEAttributes("PolygonNormal").GetDataArrayChunk(0,0)
aNormals = [[i.X,i.Y,i.Z] for i in aPolygonNormalICEData]
else:
aPointPositionICEData = oTgtGeo.ICEAttributes("PointPosition").GetDataArrayChunk(0,0)
aPositions = [[i.X,i.Y,i.Z] for i in aPointPositionICEData]
aPointNormalICEData = oTgtGeo.ICEAttributes("PointNormal").GetDataArrayChunk(0,0)
aNormals = [[i.X,i.Y,i.Z] for i in aPointNormalICEData]
xformUtil = XSIMath.CreateTransform()
vecNormal = XSIMath.CreateVector3()
vecUpV = XSIMath.CreateVector3()
for i in xrange(len(aPositions)):
oNormalCrv = oTgtObj.AddNurbsCurve(lNormalCurveData, None, True, 1, c.siNonUniformParameterization, c.siSINurbs)
oNormalCrv.Name = oTgtObj.Name + "_Normal" + str(i).zfill(len(str(len(aPositions)))) + "_Crv"
xformUtil.SetIdentity()
xformUtil.SetTranslationFromValues(aPositions[i][0],aPositions[i][1],aPositions[i][2])
vecNormal.Set(aNormals[i][0],aNormals[i][1],aNormals[i][2])
vecNormal.NormalizeInPlace()
if aNormals[i][1] >= 0.999:
vecUpV.Set(aPositions[i][0],aPositions[i][1],aPositions[i][2])
vecUpV.NormalizeInPlace()
elif aNormals[i][1] <= -0.999:
vecUpV.Set(aPositions[i][0],aPositions[i][1],aPositions[i][2])
vecUpV.NormalizeInPlace()
elif aNormals[i][1] >= 0.000 and aNormals[i][1] < 0.999:
vecUpV.Set(0,1,0)
vecUpV.NormalizeInPlace()
elif aNormals[i][1] < 0.000 and aNormals[i][1] > -0.999:
vecUpV.Set(0,-1,0)
vecUpV.NormalizeInPlace()
vecX, vecY, vecZ = axesFromNormal(vecNormal, vecUpV)
xformUtil.SetRotationFromXYZAxes(vecX,vecY,vecZ)
xformUtil.MulInPlace(oTgtObj.Kinematics.Global.GetTransform2(None))
oNormalCrv.Kinematics.Global.PutTransform2(None,xformUtil)
finally:
xsi.EndUndo()
ET_NormalCurves(collSel(0))
EricTRocks wrote:Try this one. I tried it on a torus and the mesh that was posted and worked. Change bUsePolys to True to do polygons and change sNormalScale to resize the length of the curve.
Edit: Fixed an issue with the scaling being doubled with each curve if the Target mesh was scaled.
Code: Select all
# Python from win32com.client import constants as c from win32com.client import Dispatch as d xsi = Application log = xsi.LogMessage collSel = xsi.Selection def axesFromNormal(vecNormal, vecUpV): """Creates vectors for each axis of a transform.""" vecX = XSIMath.CreateVector3() vecY = XSIMath.CreateVector3() vecZ = XSIMath.CreateVector3() vecToTgt = XSIMath.CreateVector3() vecBaseToUpV = XSIMath.CreateVector3() vecX.Cross(vecUpV, vecNormal) vecX.NormalizeInPlace() vecY.Copy(vecNormal) vecY.NormalizeInPlace() vecZ.Cross(vecX, vecNormal) vecZ.NormalizeInPlace() return vecX,vecY,vecZ def ET_NormalCurves(oTgtObj, bUsePolys=False, sNormalScale=1.0): try: xsi.BeginUndo("ET_NormalCurves") lNormalCurveData = [[0.0, 0.0], [0.0, sNormalScale], [0.0, 0.0], [1.0, 1.0]] oTgtGeo = oTgtObj.ActivePrimitive.Geometry if bUsePolys: aPolygonPositionICEData = oTgtGeo.ICEAttributes("PolygonPosition").GetDataArrayChunk(0,0) aPositions = [[i.X,i.Y,i.Z] for i in aPolygonPositionICEData] aPolygonNormalICEData = oTgtGeo.ICEAttributes("PolygonNormal").GetDataArrayChunk(0,0) aNormals = [[i.X,i.Y,i.Z] for i in aPolygonNormalICEData] else: aPointPositionICEData = oTgtGeo.ICEAttributes("PointPosition").GetDataArrayChunk(0,0) aPositions = [[i.X,i.Y,i.Z] for i in aPointPositionICEData] aPointNormalICEData = oTgtGeo.ICEAttributes("PointNormal").GetDataArrayChunk(0,0) aNormals = [[i.X,i.Y,i.Z] for i in aPointNormalICEData] xformUtil = XSIMath.CreateTransform() vecNormal = XSIMath.CreateVector3() vecUpV = XSIMath.CreateVector3() for i in xrange(len(aPositions)): oNormalCrv = oTgtObj.AddNurbsCurve(lNormalCurveData, None, True, 1, c.siNonUniformParameterization, c.siSINurbs) oNormalCrv.Name = oTgtObj.Name + "_Normal" + str(i).zfill(len(str(len(aPositions)))) + "_Crv" xformUtil.SetIdentity() xformUtil.SetTranslationFromValues(aPositions[i][0],aPositions[i][1],aPositions[i][2]) vecNormal.Set(aNormals[i][0],aNormals[i][1],aNormals[i][2]) vecNormal.NormalizeInPlace() if aNormals[i][1] >= 0.999: vecUpV.Set(aPositions[i][0],aPositions[i][1],aPositions[i][2]) vecUpV.NormalizeInPlace() elif aNormals[i][1] <= -0.999: vecUpV.Set(aPositions[i][0],aPositions[i][1],aPositions[i][2]) vecUpV.NormalizeInPlace() elif aNormals[i][1] >= 0.000 and aNormals[i][1] < 0.999: vecUpV.Set(0,1,0) vecUpV.NormalizeInPlace() elif aNormals[i][1] < 0.000 and aNormals[i][1] > -0.999: vecUpV.Set(0,-1,0) vecUpV.NormalizeInPlace() vecX, vecY, vecZ = axesFromNormal(vecNormal, vecUpV) xformUtil.SetRotationFromXYZAxes(vecX,vecY,vecZ) xformUtil.MulInPlace(oTgtObj.Kinematics.Global.GetTransform2(None)) oNormalCrv.Kinematics.Global.PutTransform2(None,xformUtil) finally: xsi.EndUndo() ET_NormalCurves(collSel(0))