User Normals

You cannot interactively create User Normal properties in XSI. You either import objects with user normals, or you create the User Normal property through scripting. For example:

var oGeom = Selection(0).ActivePrimitive.Geometry;
var oCls = oGeom.AddCluster( siSampledPointCluster, "User Normal" );
var oProp = oCls.AddProperty( "User Normal Property" );

You can create a user normal property under any sampled point cluster (not only "User_Normal_Cluster), and the cluster can be a partial clustes (a cluster that does not contain all sampled points).

In addition, there can be more than one user normal property under the same mesh, in which case the priority order in overlapping parts will be arbitrary (if a sampled point is in more than one User Normal property).

Some notes about User Normals (from a 2002 post ( on the XSI mailing list).

  • Hard edges and geom approx autodisc settings are always overriden by UserNormals property.
  • User Normals always override the XSI automatic normals, unless you delete the UserNormals property.
  • UserNormals don't follow the surface deformations (they are fixed in object's local space).

An example.

'User normal demo
Newscene, false

'Create a grid, shrink wrap it to a sphere
CreatePrim "Grid", "MeshSurface"
CreatePrim "Sphere", "MeshSurface"
SetValue "sphere.sphere.radius", 6.809
SetValue "sphere.polymsh.geom.subdivu", 24
SetValue "sphere.polymsh.geom.subdivv", 24
SelectObj "grid", , True
ApplyOp "ShrinkWrap", "grid;sphere;", 3, siPersistentOperation
SetValue "grid.polymsh.shrinkwrap.rev", True
SetValue "grid.polymsh.shrinkwrap.proj", 2
SetValue "grid.polymsh.shrinkwrap.alongy", True
SetValue "grid.polymsh.shrinkwrap.ampl", -1.047
DeleteObj "sphere"
SelectObj "grid", , True
Translate , 0, -6.93717227456021, 0, siRelative, siView, siObj, siXYZ

'Copy geometric normals to user normals
set obj = GetValue("grid.polymsh")
nodesarray = obj.Geometry.Nodes.NormalArray

'Create user normals on all sample points
SelectGeometryComponents "grid.sample[*]"
AddProp "User Normal Property", , siDefaultPropagation

'Access prop OM object
set obj = GetValue("grid.polymsh.cls.sample.clslist.Sample.User_Normal_Property")
arr = obj.elements.array
obj.elements.array = nodesarray

'Planarize the grid
SelectObj "grid", , True
Scale , 1, 0, 1, siAbsolute, siParent, siObj, siY
Translate , 0, 8, 0, siRelative, siView, siObj, siXYZ
ResetTransform , siCtr, siSRT, siXYZ
SetValue "Camera.camvis.attrselnorm", True
SetValue "Views.ViewA.TopCamera.camvis.attrselnorm", True

'Split all polygons, to show that we propagate correctly user normals
SelectGeometryComponents "grid.poly[*]"
ApplyTopoOp "SubdividePolygon", "grid.poly[*]", siUnspecified, siPersistentOperation
SelectObj "grid", , True
SetDisplayMode "Camera", "shaded"


'Script that projects subdivision surface's normals onto the hull of a mesh.
'The created normals are stored in a UserNormals property.

function ProjectSubdivNormalsOnMesh()
	Set in_InputObjs = GetValue( "SelectionList" )

	set l_InputObjs = SIFilter( in_InputObjs, "polygon_mesh" )
	if IsEmpty(l_InputObjs) Or TypeName(l_InputObjs) = "Nothing" Then
		logmessage "You need to select one or more polygon meshes first."
		Exit function
	end if

	'Build the Dialog to know the subd level
	Dim l_Pset
	AddProp "Custom_parameter_list", "Scene_Root", , "Project subdiv normals on hull", l_Pset
	SIAddCustomParameter l_Pset, "Subdiv_Level"   , siInt2, 2, 1, 4, siSilent, 4, 0, ParamUIRange, "Subdiv_Level"
	l_PsetFullName = "Scene_Root." & l_Pset
	l_result = InspectObj(l_PsetFullName,,"Project subdiv normals on hull",siModal,False)
	if l_result = false then
		in_SubdivLevel = GetValue( l_PsetFullName & ".Subdiv_Level")
		for each l_obj in l_InputObjs

			'Create a dummy one because of a bug in OM with name "Sample"
			set dummyallnodecls = CreateCluster(l_obj.fullname & ".sample[*]")
			set allnodecls = CreateCluster(l_obj.fullname & ".sample[*]")
			set normalpropname = SIAddProp("User Normal Property", allnodecls(0).fullname, siDefaultPropagation)(0)
			set prop = GetValue( normalpropname(0) )
			DeleteObj dummyallnodecls(0).fullname

			arr = prop.elements.array
			total = prop.elements.count

			'Subdivide at level in_SubdivLevel
			MeshSubdivideWithCenter , l_obj.fullname, , siPersistentOperation
			set subdobj = GetValue( "SelectionList" )(0)
			SetValue subdobj.fullname & ".polymsh.MeshSubdivideWithCenter.SubdivisionDepth", in_SubdivLevel
			nodesarray = subdobj.ActivePrimitive.Geometry.Nodes.NormalArray
			for iIndex=0 to total-1
				arr(0,iIndex) = nodesarray(0,iIndex)
				arr(1,iIndex) = nodesarray(1,iIndex)
				arr(2,iIndex) = nodesarray(2,iIndex)
			prop.elements.array = arr
			DeleteObj subdobj.fullname
	end if
	DeleteObj l_PsetFullName
	SelectObj in_InputObjs
End function


This page was last modified 15:03, 25 Jan 2007.
This page has been accessed 7284 times.

© Copyright 2009 Autodesk Inc. All Rights Reserved. Privacy Policy | Legal Notices and Trademarks | Report Piracy