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").ActivePrimitive2.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.ActivePrimitive2.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