PointLocatorData

Object Hierarchy | Related C++ Class: PointLocatorData

Introduced

5.0

Description

A PointLocatorData object represents a collection of point locators. A point locator is a geometric surface coordinate, and represents a precise location on a geometry. Point locators are topologically defined, so they are not dependent on the position or the deformation of the geometry (they "stick" to the surface). The actual data defining a point locator is abstracted and depends on the geometry type.

Point locators are a generalization of Points. As points, point locators can be processed independently from the geometry type. Like point indices, point locators are not related to a particular geometry instance. You can query any geometry having the same topology with the same PointLocatorData. For instance, you can use point locators to evaluate positions of an animated geometry at different times.

Because point locators don't apply to a particular geometry instance, the PointLocatorData object has no functionality by itself. Most methods related to PointLocatorData are defined in Geometry, PolygonMesh and NurbsSurfaceMesh. PointLocatorData can be created by methods Geometry.GetClosestLocations, Geometry.GetClosestLocationsWithinRadius, Geometry.GetRaycastIntersections, Geometry.GetSurfacePointLocatorsFromPoints PolygonMesh.ConstructPointLocators and NurbsSurfaceMesh.ConstructPointLocators.

Other examples of PointLocatorData usage can be found in various related methods such as PointLocatorData.Count and PolygonMesh.ConstructPointLocators.

Note: Point locators are currently only supported by NurbsSurfaceMesh and PolygonMesh objects.

Properties

Count

Examples

1. Python Example

#
#  This example uses PointLocatorData to shrink-wrap a sphere to a cube,
#  and then pushes the sphere along cube's normals.
#
app = Application
app.NewScene( "", 0 )
root = app.ActiveSceneRoot
CubeGeom = root.AddGeometry("Cube", "MeshSurface").ActivePrimitive.Geometry

SphereObj = root.AddGeometry("Sphere", "MeshSurface")
SphereObj.subdivv = 24
SphereObj.subdivu = 24

# Freeze it, otherwise its position array cannot be set:
app.FreezeObj(SphereObj)
SphereGeom = SphereObj.ActivePrimitive.Geometry

SphereOnCubePointLocators = CubeGeom.GetClosestLocations(SphereGeom.Points.PositionArray)

SphereOnCubePositions = CubeGeom.EvaluatePositions(SphereOnCubePointLocators)
SphereOnCubeNormals = CubeGeom.EvaluateNormals(SphereOnCubePointLocators)

SphereNewPositions = []
i = 0
while i < len(SphereOnCubePositions) :
   j = 0
   tmplist = []
   while j < len(SphereOnCubePositions[i]) :
       tmplist.append( SphereOnCubeNormals[i][j]*3 )
       j = j + 1
   SphereNewPositions.append(tmplist)
   i = i + 1

SphereGeom.Points.PositionArray = SphereNewPositions;

2. JScript Example

/*
   This example uses PointLocatorData to deform a polygon mesh based on
   the closest weight map value of a NURBS surface mesh.
*/

// Scene creation:
//     Polygon mesh grid and a NURBS surface grid.
//     On the NURBS grid, a weight map having a radial gradient

NewScene( null, false );
var root = Application.ActiveSceneRoot;
var MeshGridObj = root.AddGeometry("Grid", "MeshSurface");
MeshGridObj.subdivu = 24;
MeshGridObj.subdivv = 24;

// We must freeze it, otherwise setting its position array will be forbidden:
FreezeObj(MeshGridObj);
var MeshGridGeom = MeshGridObj.ActivePrimitive.Geometry;

var NURBSGridObj = root.AddGeometry("Grid", "NurbsSurface");
NURBSGridObj.subdivu = 2;
NURBSGridObj.subdivv = 2;
var NURBSGridGeom = NURBSGridObj.ActivePrimitive.Geometry;

var NURBSWeightMap = CreateWeightMap(null, NURBSGridObj, "Weight_Map").item(0);
SetValue(NURBSWeightMap + ".weightmapop.type", 5);
SetValue(NURBSWeightMap + ".weightmapop.weight", 1);
SetValue(NURBSWeightMap + ".weightmapop.invert", true);
NURBSWeightMap = GetValue(NURBSWeightMap); // Get the weight map again to have an updated copy

// Applying the deformation

var MeshGridPos = MeshGridGeom.Points.PositionArray.toArray();
var MeshGridOnNURBSGridPointLocators = NURBSGridGeom.GetClosestLocations(MeshGridPos);
var WeightMapValuesForMesh = NURBSGridGeom.EvaluateClusterProperty(   MeshGridOnNURBSGridPointLocators,
                                NURBSWeightMap.Parent,
                                NURBSWeightMap ).toArray();

// Push mesh vertices along Y, modulated by NURBS grid's closest surface's weight map value
for(i = 0; i < MeshGridPos.length; i+=3)
   MeshGridPos[i+1] += WeightMapValuesForMesh[i/3]*5;

MeshGridGeom.Points.PositionArray = MeshGridPos;

3. JScript Example

// The following example is more complex but shows the PointLocatorData 
// at work in the context of a relatively complex scripted operator.
//
// This example creates a "skinning" custom operator, which a kind
// of shrink wrap-based cage deform operator. This operator
// wraps a deformed "body" object with a "skin" object having a different
// topology. In order to create the surface correspondance between
// the skin and the body, it uses a static copy of the "body", which
// is not animated and stands as a reference. The operator supports,
// too, arbitrary poses on each object.
//
// Since the skin and the reference body are not animated, the
// custom operator can create the point locators only once,
// at the first evaluation, and then only need to evaluate
// them on the deformed body at each frame. This improves a lot
// the performance since creating point locators from spatial
// proximity is much more costly than simply evaluating their
// positions or normals.
//
// Additionally, in order to improve the skinning result, the
// operator pushes the sking along the normals of the body,
// and the amplitude of this push can be controlled by a parameter.

NewScene( null, false );
var root = Application.ActiveSceneRoot;
Translate("Camera", 0, 0, 50.0, siRelative, siView, siObj, siXYZ);

// Create the reference body object, non-animated object (a cube),
// and move it to a non-trivial pose
var ReferenceCubeObj = root.AddGeometry("Cube", "MeshSurface");
Translate(ReferenceCubeObj, -25.0, 0, 0, siRelative, siView, siObj, siXYZ);

// Create the skin object (a sphere with more resolution),
// and move it to a non-trivial pose
var ShrinkWrappedSphereObj = root.AddGeometry("Sphere", "MeshSurface");
ShrinkWrappedSphereObj.subdivu = 25;
ShrinkWrappedSphereObj.subdivv = 25;
Rotate(ShrinkWrappedSphereObj, 0, 0, -60.0, siRelative, siLocal, siObj, siXYZ);
Scale(ShrinkWrappedSphereObj, 1.5, 1.5, 1.5, siRelative, siLocal, siObj, siXYZ);
Translate(ShrinkWrappedSphereObj, -25.0, 0, 0, siRelative, siView, siObj, siXYZ);

// Create the animated target body object.
// In order to show the scripted op at work, add kinematic and
// shape animation.
var TargetCubeObj = root.AddGeometry("Cube", "MeshSurface");
Translate(TargetCubeObj, 10.0, 10.0, 0, siRelative, siView, siObj, siXYZ);
SetValue("Context.constructionmode", 1);
Scale("cube1.pnt[2,3,6,LAST]", 0.3, 0.3, 0.3, siRelative, siLocal, siObj, siXYZ);
SaveShapeKey("cube1.pnt[2,3,6,LAST]", null, null, 1);
Scale("cube1.pnt[2,3,6,LAST]", 10.0, 10.0, 10.0, siRelative, siLocal, siObj, siXYZ);
SaveShapeKey("cube1.polymsh.cls.Shape", null, null, 100);
SaveKey("cube1.kine.local.posx,cube1.kine.local.posy,cube1.kine.local.posz");
SaveKey("cube1.kine.local.rotx,cube1.kine.local.roty,cube1.kine.local.rotz");
Rotate(TargetCubeObj, 50.0, 0, 50.0, siRelative, siLocal, siObj, siXYZ);
SetValue("PlayControl.Current", 100);
SaveKey("cube1.kine.local.rotx,cube1.kine.local.roty,cube1.kine.local.rotz", 100);
Translate(TargetCubeObj, -15.0, -15.0, 0.0, siRelative, siView, siObj, siXYZ);
SaveKey("cube1.kine.local.posx,cube1.kine.local.posy,cube1.kine.local.posz", 100);
SetValue("PlayControl.Current", 1);

// Apply the scripted op to the skin.
var SkinOp = ApplySkinOp( ShrinkWrappedSphereObj, ReferenceCubeObj, TargetCubeObj );

SetValue("PlayControl.Loop", true);
PlayForwardsFromStart();

InspectObj(SkinOp);

function ApplySkinOp( inSkinObj, inReferenceBody, inTargetBody )
{
   var op = XSIFactory.CreateScriptedOp( "MySkinOp", MySkinOp_Update.toString(), "JScript" );

   // Define connections
   var skin_group = op.AddPortGroup( "SkinGroup" );
   op.AddIOPort( inSkinObj.ActivePrimitive, "Geom", skin_group.Index );
   op.AddInputPort( inSkinObj.Kinematics.Global, "Pose", skin_group.Index );

   var ref_group = op.AddPortGroup( "ReferenceBodyGroup" );
   op.AddInputPort( inReferenceBody.ActivePrimitive, "Geom", ref_group.Index );
   op.AddInputPort( inReferenceBody.Kinematics.Global, "Pose", ref_group.Index );

   var tgt_group = op.AddPortGroup( "TargetBodyGroup" );
   op.AddInputPort( inTargetBody.ActivePrimitive, "Geom", tgt_group.Index );
   op.AddInputPort( inTargetBody.Kinematics.Global, "Pose", tgt_group.Index );

   // Define a parameter for the push amplitude
   var pdef = XSIFactory.CreateParamDef2( "PushAmplitude", siDouble, 2, -1, 5 );
   op.AddParameter(pdef);

   // Connect operator
   op.Connect(inSkinObj + ";" + inReferenceBody + ";" + inTargetBody);
   return op;
}

// This function contains the implementation of the scripted operator.
function MySkinOp_Update( ctx, out, InSkinGeom, InSkinPose, InReferenceBodyGeom, InReferenceBodyPose, InTargetBodyGeom, InTargetBodyPose )
{
   // TransformPositionArray: transforms in place an array of packed XYZ vectors
   function TransformPositionArray( array, transfo )
   {
       for (i = 0; i < array.length; i+=3)
       {
          var TempVector3 = XSIMath.CreateVector3()
          TempVector3.Set(array[i], array[i+1], array[i+2]);
          TempVector3.MulByTransformationInPlace(transfo);
          var XYZArray = TempVector3.Get2().toArray();
          array[i] = XYZArray[0];
          array[i+1] = XYZArray[1];
          array[i+2] = XYZArray[2];
       }
   }

   var SkinGeom = InSkinGeom.Value.Geometry;
   var ReferenceBodyGeom = InReferenceBodyGeom.Value.Geometry;

   /////////////////////////////////////////////////////////
   //1) Create skin point locators relatively to the surface 
   //   proximity to the reference body. We intentionally keep
   //   a snapshot of the point locators to speed up the 
   //   next evaluations; we assume that InSkinGeom, InSkinPose, 
   //   InReferenceBodyGeom and InReferenceBodyPose are not
   //   animated.

   var SkinPointLocators = ctx.UserData;
   if(SkinPointLocators == null) // No user data means that this is the first evaluation of the operator
   {
       // The skin object and the reference may have different poses, so we
       // will compute the surface proximity computation in global space.
       // We will use the closest smoothed surface method (2==siClosestSmoothedSurface).
       ReferenceBodyGeom.SetupPointLocatorQueries(2, InReferenceBodyPose.Value.Transform); 

       // Transform the skin positions in global space
       var SkinGeomPosArray = SkinGeom.Points.PositionArray.toArray();

       // TransformPositionArray: transforms in place an array of packed XYZ vectors
       TransformPositionArray( SkinGeomPosArray, InSkinPose.Value.Transform );
       SkinPointLocators = ReferenceBodyGeom.GetClosestLocations(SkinGeomPosArray);
       ctx.UserData = SkinPointLocators;
   }

   /////////////////////////////////////////////////////////
   //2) Evaluate the point locators on the target body, and
   //   displace them along target body's normals, with the
   //   amplitude given by the scirted op parameter.

   var TargetBodyGeom = InTargetBodyGeom.Value.Geometry;
   var SkinOnTargetBodyPositions = TargetBodyGeom.EvaluatePositions(SkinPointLocators).toArray();
   var SkinOnTargetBodyNormals = TargetBodyGeom.EvaluateNormals(SkinPointLocators).toArray();

   var SkinToTargetTransform = XSIMath.MapWorldPoseToObjectSpace(InSkinPose.Value.Transform, InTargetBodyPose.Value.Transform);
   var dPushAmplitude = ctx.Parameters("PushAmplitude").Value

   for (i = 0; i < SkinOnTargetBodyPositions.length; i++)
       SkinOnTargetBodyPositions[i] += SkinOnTargetBodyNormals[i]*dPushAmplitude;

   // TransformPositionArray: transforms in place an array of packed XYZ vectors
   TransformPositionArray( SkinOnTargetBodyPositions, SkinToTargetTransform );

   SkinGeom.Points.PositionArray = SkinOnTargetBodyPositions;
}

See Also

Geometry

Geometry.GetClosestLocations

Geometry.GetClosestLocationsWithinRadius

Geometry.GetRaycastIntersections

Geometry.SetupPointLocatorQueries

Geometry.GetSurfacePointLocatorsFromPoints

Geometry.EvaluatePositions

Geometry.EvaluateNormals

Geometry.EvaluateClusterProperty

PolygonMesh.GetPolygonIndexArray

PolygonMesh.GetTriangleVertexIndexArray

PolygonMesh.GetTriangleNodeIndexArray

PolygonMesh.GetTriangleWeightArray

PolygonMesh.ConstructPointLocators

NurbsSurfaceMesh.GetSubSurfaceIndexArray

NurbsSurfaceMesh.GetNormalizedUVArray

NurbsSurfaceMesh.ConstructPointLocators

 

 

 



Autodesk Softimage v7.5