1

wpf でテクスチャを適切にマッピングするのに苦労しています。まず第一に、3D は私の得意分野ではありませんが、サンプル コードと出力のイメージを以下に示します。ポリゴンを取得し、三角形分割を実行してから、出力に長方形のテクスチャをマップしようとしています。私が得ている問題は、テクスチャをスムーズに曲線に沿ってマッピングできないことです。1 つのテクスチャ マップは 3dtools.dll ライブラリを利用し、うまく機能しますが、結果のテクスチャ マップは左側の出力を生成しました。思うように傾かない。右側の結果の画像は、テクスチャ座標を画像に手動でマッピングしようとしたものです。そのように見える理由は理解できますが、それを修正する方法が本当にわかりませんか?

 private void simpleButtonClick(object sender, RoutedEventArgs e)
        {
            ClearViewport();
            SetCamera();

            PathGeometry FlatPath;

            Geometry Geo = Geometry.Parse("M 0,0 L 0,10 C 4,4 6,6 10,10 V 0 C 6,-4 4,-6 0,0");
            var GeoText = FormattedText.BuildGeometry(new Point(0, 0));

            FlatPath =
                Geo.GetFlattenedPathGeometry(.01,
                                             ToleranceType.
                                                 Absolute);
            var vertices = new List<Vertex>();
            foreach (PathFigure Figure in FlatPath.Figures)
            {
                List<Point> PointList = DumpFigureToList(Figure);
                vertices.AddRange(PointList.Select(p=>new Vertex((float)p.X,(float)p.Y)));
            }

            // Write out the data set we're actually going to triangulate
            var angulator = new Triangulator();

            List<Triad> triangles = angulator.Triangulation(vertices, true);

            var Bounds = FlatPath.Bounds;

            var mesh = new MeshGeometry3D();
            var cube = new Model3DGroup();
            var Count = 0;
            foreach (var Tri in triangles)
            {
                Tri.MakeCounterClockwise(vertices);
                if (FlatPath.FillContains(new Point(Tri.circumcircleX, Tri.circumcircleY)))
                {
                    var p0 = new Point3D(vertices[Tri.a].x, vertices[Tri.a].y, 0);
                    var p1 = new Point3D(vertices[Tri.b].x, vertices[Tri.b].y, 0);
                    var p2 = new Point3D(vertices[Tri.c].x, vertices[Tri.c].y, 0);


                    mesh.Positions.Add(p0);
                    mesh.Positions.Add(p1);
                    mesh.Positions.Add(p2);
                    mesh.TriangleIndices.Add(Count);
                    Count++;
                    mesh.TriangleIndices.Add(Count);
                    Count++;
                    mesh.TriangleIndices.Add(Count);
                    Count++;
                    Vector3D normal = CalculateNormal(p0, p1, p2);
                    mesh.Normals.Add(normal);
                    mesh.Normals.Add(normal);
                    mesh.Normals.Add(normal);



                    mesh.TextureCoordinates.Add(new Point((Bounds.Left - vertices[Tri.a].x) / Bounds.Width, vertices[Tri.a].y > 0 ? 1 : 0));
                    mesh.TextureCoordinates.Add(new Point((Bounds.Left - vertices[Tri.b].x) / Bounds.Width, vertices[Tri.b].y > 0 ? 1 : 0));
                    mesh.TextureCoordinates.Add(new Point((Bounds.Left - vertices[Tri.c].x) / Bounds.Width, vertices[Tri.c].y > 0 ? 1 : 0));

                    if (wireframeCheckBox.IsChecked == true)
                    {
                        var wireframe = new ScreenSpaceLines3D();
                        wireframe.Points.Add(p0);
                        wireframe.Points.Add(p1);
                        wireframe.Points.Add(p2);
                        wireframe.Points.Add(p0);
                        wireframe.Color = Colors.LightBlue;
                        wireframe.Thickness = 2;

                        this.mainViewport.Children.Add(wireframe);
                    }
                }
            }


            //mesh.TextureCoordinates = _3DTools.MeshUtils.GeneratePlanarTextureCoordinates(mesh, new Vector3D(0, 0, 1));

            var myBrush = new ImageBrush();
            myBrush.ImageSource =
                new BitmapImage(new Uri(@"curvedown.png", UriKind.Absolute));
            Material material = new DiffuseMaterial(myBrush);
            var model = new GeometryModel3D(mesh, material);
            var group = new Model3DGroup();
            group.Children.Add(model);

            PointLight light = new PointLight(Colors.White, new Point3D(10,10,10));
            group.Children.Add(light);


            var Model = new ModelVisual3D();
            Model.Content = group;
            this.mainViewport.Children.Add(Model);

        }

これは、ワイヤーフレームを使用した上記の出力です。コメントアウトされたテクスチャ座標コードを使用しています。右側はマニュアルコード (コメントなし)。 出力イメージ

4

1 に答える 1

4

あなたが持っている三角測量では、期待どおりに適切に曲がることはありません。この種の曲線を実現するには、細いストライプを手動で生成する必要があります。何かのようなもの

    ++++++++
    ||||||||
    ||||||||
    ++++++++

-- ここで、各 + は頂点です -- ただし、直線にする代わりに、半径に沿った特定のオフセットで、共通点 (仮想円) から来るさまざまな線に沿ってマップします。

擬似コード:

    0 から nStripes までの各 i について
      let angle = start + (end-start) * i / nStripes
      let p1 = ポイント
        X = 内部半径 * cos(角度)
        Y = 内部半径 * sin(角度)
      let p2 = ポイント
        X = 外部半径 * cos(角度)
        Y = 外部半径 * sin(角度)
      p1 に頂点を追加
      p2 に頂点を追加

その後、以前に生成されたエッジをペアごとに接続します。したがって、(0,1)+(2,3) はクワッドを作成し、(2,3)+(4,5) は別のクワッドを作成します...

どの数のストライプが適切かを判断する必要があります。三角形内のテクスチャ マッピングは常に線形補間によって行われ、決して曲線ではないことに注意してください。そのため、曲線や台形などのものが魔法のように正しく見えるとは期待できません。

于 2012-12-27T14:05:11.723 に答える