Исключение шва в 3D-модели цилиндра

У меня есть эта текстура, представляющая внутреннюю область трубы:

введите здесь описание изображения

Я создал простую модель цилиндра (GeometryModel3D), разделив приведенную выше текстуру на сетку точек и обернув ее, чтобы сформировать цилиндр, а затем сопоставив с ней приведенную выше текстуру (каждый квадрат на сетке имеет два треугольника):

введите здесь описание изображения

Левый и правый края текстуры встречаются на указанной выше черной линии шва, что нежелательно.

Я не мог использовать одну точку вершины для плавного продолжения там, потому что эта точка соответствует как 0, так и 360 градусам, что является одним углом, но двумя разными точками на краях 2D-текстуры.

Поэтому я использовал пары вершин в одном и том же месте, но каждая из них соответствовала разным точкам исходной текстуры.

Можно ли скрыть линию шва?

Код создания модели:

    private void SceneViewerWindowOnLoaded(object sender, RoutedEventArgs e)
    {
        var imageSource = new BitmapImage(new Uri("pack://application:,,,/Resources/out1.jpg"));

        var meshGeometry3D = new MeshGeometry3D();

        double circumference = imageSource.PixelWidth;
        double radius = (circumference / (2.0 * Math.PI));

        double angleSegment = (2.0 * Math.PI / SegmentCountTrans);

        double sizeSegmentLong = ((double)imageSource.PixelHeight / SegmentCountLong);
        double sizeSegmentTrans = ((double)imageSource.PixelWidth / SegmentCountTrans);

        for (int indexSegmentLong = 0; indexSegmentLong < SegmentCountLong; indexSegmentLong++)
        {
            double depth = (indexSegmentLong * sizeSegmentLong);

            for (int indexSegmentTrans = 0; indexSegmentTrans < SegmentCountTrans; indexSegmentTrans++)
            {
                meshGeometry3D.Positions.Add(GetVertexPosition(indexSegmentTrans, depth, radius, angleSegment));
                meshGeometry3D.TextureCoordinates.Add(new Point(indexSegmentTrans * sizeSegmentTrans, depth));
            }

            // add one extra vertex representing 360 degrees for complete wrap-around
            meshGeometry3D.Positions.Add(GetVertexPosition(SegmentCountTrans, depth, radius, angleSegment));
            meshGeometry3D.TextureCoordinates.Add(new Point(SegmentCountTrans * sizeSegmentTrans, depth));
        }

        meshGeometry3D.TriangleIndices.Clear();

        for (int indexSegmentLong = 0; indexSegmentLong < (SegmentCountLong - 1); indexSegmentLong++)
        {
            for (int indexSegmentTrans = 0; indexSegmentTrans < SegmentCountTrans; indexSegmentTrans++)
            {
                int indexCurrent = (indexSegmentLong * (SegmentCountTrans + 1) + indexSegmentTrans);

                meshGeometry3D.TriangleIndices.Add(indexCurrent);
                meshGeometry3D.TriangleIndices.Add(indexCurrent + 1);
                meshGeometry3D.TriangleIndices.Add(indexCurrent + SegmentCountTrans + 1);

                meshGeometry3D.TriangleIndices.Add(indexCurrent + SegmentCountTrans + 1);
                meshGeometry3D.TriangleIndices.Add(indexCurrent + 1);
                meshGeometry3D.TriangleIndices.Add(indexCurrent + SegmentCountTrans + 2);
            }
        }

        var geometryModel3D = new GeometryModel3D
                            {
                                Geometry = meshGeometry3D,
                                Material = new DiffuseMaterial
                                           {
                                               Brush = new ImageBrush(imageSource)
                                           }
                            };

        this.SceneViewer.Model = geometryModel3D;
    }

    private static Point3D GetVertexPosition(int indexSegmentAngle, double depth, double radius, double angleSegment)
    {
        double angle = (StartAngle + indexSegmentAngle * angleSegment);

        return new Point3D(
            radius * Math.Cos(angle),
            radius * Math.Sin(angle),
            -depth);
    }

Код XAML для элемента Viewport3D, содержащего модель:

<Viewport3D x:Name="Viewport3D">
        <Viewport3D.Camera>
            <PerspectiveCamera x:Name="Camera" Position="0.0,0.0,0.0" LookDirection="0.0,0.0,-1.0" UpDirection="0.0,1.0,0.0" FieldOfView="90"/>
        </Viewport3D.Camera>
        <ModelVisual3D>
            <ModelVisual3D.Content>
                <AmbientLight Color="White"/>
            </ModelVisual3D.Content>
        </ModelVisual3D>
        <ModelVisual3D x:Name="ModelVisualModel"/>
    </Viewport3D>

person Libor    schedule 31.01.2014    source источник
comment
Я сам еще не пробовал это в WPF, но при работе с другими фреймворками это обычно является результатом либо выборки текстуры, не настроенной на перенос по краям, либо краев геометрии на шве, идущего в противоположных направлениях. Есть ли шанс, что вы можете опубликовать свой код создания геометрии цилиндра?   -  person Mark Feldman    schedule 31.01.2014
comment
@MarkFeldman Я добавил код. Это самый простой способ - развернутое изображение цилиндра заворачивается обратно в 3D - проблема заключается в точке встречи двух краев, которая не является непрерывной. Я хотел бы избежать редактирования исходной текстуры.   -  person Libor    schedule 31.01.2014


Ответы (2)


Когда вы создаете свою кисть изображения, попробуйте установить для TileMode значение TileMode.Tile, а для ViewportUnits — значение BrushMappingMode.Absolute. Если это все еще не работает, напишите здесь следующий комментарий, и я попытаюсь воспроизвести его со своей стороны.

person Mark Feldman    schedule 31.01.2014

Я использовал DrawingBrush вместо Imagebrush. Это исправило швы, и я также получил повышение частоты кадров при настройке подсказки кеширования.

Brush brush = new DrawingBrush(new ImageDrawing(_texture, new Rect(0,0,1,1)));
RenderOptions.SetCachingHint(brush , CachingHint.Cache);
RenderOptions.SetCacheInvalidationThresholdMinimum(brush , 0.5);
RenderOptions.SetCacheInvalidationThresholdMaximum(brush , 2.0);
person Andreas    schedule 09.07.2015
comment
Спасибо. Всегда полезно использовать трюки для дальнейшего повышения производительности. - person Libor; 09.07.2015