Object Hierarchy | 関連する C++クラス:PointLocatorData
v5.0
PointLocatorData オブジェクトは、ポイントロケータのコレクションを示します。ポイントロケータはジオメトリックサーフェイス座標で、ジオメトリ上の正確な位置を示します。ポイントロケータは、位相的に定義されるため、位置またはジオメトリのデフォーメーションに依存しません(サーフェイスに固定されます)。ポイントロケータの実際のデータは、抽出されジオメトリタイプに依存します。
ポイント ロケータは Point を一般化したものです。ポイントとして、ポイント ロケータはジオメトリ タイプとは別個に処理できます。ポイントインデックスのように、ポイントロケータは特定のジオメトリインスタンスには関連していません。同じPointLocatorDataと同じトポロジを持つジオメトリを問い合わせることができます。インスタンスのために、ポイントロケータを使用して異なる時間にアニメーションのジオメトリの位置を検証することができます。
ポイントロケータは特定のジオメトリインスタンスに適用できないため、PointLocatorData オブジェクトにはそれ自体の機能がありません。PointLocatorData に関連するほとんどのメソッドは、Geometry、PolygonMesh、および NurbsSurfaceMesh で定義されます。PointLocatorData は、Geometry.GetClosestLocations、Geometry.GetClosestLocationsWithinRadius、Geometry.GetRaycastIntersections、Geometry.GetSurfacePointLocatorsFromPoints、NurbsSurfaceMesh.ConstructPointLocators、および PolygonMesh.ConstructPointLocators メソッドを使用して作成できます。
PointLocatorData の使用方法のその他の例は、PointLocatorData.Count や PolygonMesh.ConstructPointLocators など、関連するさまざまなメソッドに記載されています。
ポイントロケータは現在、PolygonMesh および NurbsSurfaceMesh オブジェクトのみでサポートされています。
#
# 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; |
/*
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; |
// 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;
} |
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