3

I have this texture representing internal area of a pipe:

enter image description here

I have created a simple cylinder model (GeometryModel3D) by dissecting the above texture to a grid of points and than wrapping this to form a cylinder, then mapping the above texture to it (each square on a grid having two triangles):

enter image description here

The left and right edges of the texture meet at the above black seam line, which is unwanted.

I could not use single vertex point for smooth continuation there, because that point corresponds to both 0 and 360 degrees which is single angle, but two distinct points on edges of the 2D texture.

So I have used pairs of vertices on the same location but each corresponding to different point in the source texture.

Is there anything I can do to hide the seam line?

Model creation code:

    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 code for the Viewport3D element containing the model:

<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>
Libor
  • 3,285
  • 1
  • 33
  • 41
  • I haven't tried this in WPF myself yet but from working with other frameworks it's usually the result of either the texture sampling not being set to wrap at the edges or the geometry edges at the seam running in opposite directions. Any chance you can post your cylinder geometry creation code? – Mark Feldman Jan 31 '14 at 08:35
  • @MarkFeldman I have added the code. It is the simplest possible way - the unwrapped cylinder image is wrapped back in 3D - the problem is the meeting point of the two edges which is not continuous. I would like to avoid editing the original texture. – Libor Jan 31 '14 at 08:55

2 Answers2

4

When you create your image brush try setting the TileMode to TileMode.Tile and ViewportUnits to BrushMappingMode.Absolute. If that still doesn't work then post a follow-up comment here and I'll try to reproduce it on my end.

Mark Feldman
  • 15,731
  • 3
  • 31
  • 58
2

I used DrawingBrush instead of Imagebrush. This fixed the seams and I also get an fps boost when setting the cachinghint.

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);
Andreas
  • 3,843
  • 3
  • 40
  • 53