Texture issues
#1
Hello,

We have been testing the trial version of the library and it works great but we have found some issues with textures that we need to fix before purchasing the library. Our project works well with WPF but when using DXEngine some 3D objects with textures are not shown properly.

We have found two issues:

- Sometimes the texture of the first ModelVisual3D we add to the Viewport3D is not shown. Next objects we add are not shown at all. When this happens the output shows the next error:

DXEngine Fatal: Unhandled exception in Update: Esta operación no se admite en un URI relativo.
Esta operación no se admite en un URI relativo.
InvalidOperationException
en System.Uri.get_LocalPath()
en Ab3d.DirectX.Materials.WpfMaterial.g(Boolean a)
en Ab3d.DirectX.Materials.WpfMaterial.c(DiffuseMaterial a)
en Ab3d.DirectX.Materials.WpfMaterial.a(Material a)
en Ab3d.DirectX.Materials.WpfMaterial.Refresh()
en Ab3d.DirectX.Materials.WpfMaterial..ctor(Material material, Rect textureCoordinatesBounds, DXDevice dxDevice)
en Ab3d.DirectX.Models.WpfGeometryModel3DNode.c(Boolean a)
en Ab3d.DirectX.Models.WpfGeometryModel3DNode.a()
en Ab3d.DirectX.Models.WpfGeometryModel3DNode.OnInitializeResources(DXScene dxScene)
en Ab3d.DirectX.SharedDXSceneResource.InitializeResources(DXScene dxScene)
en Ab3d.DirectX.SceneNode.(SceneNode , Int32 , Boolean , Boolean )
en Ab3d.DirectX.SceneNode.AddChild(SceneNode childNode)
en Ab3d.DirectX.Models.WpfModel3DGroupNode.c(Model3D a)
en Ab3d.DirectX.Models.WpfModel3DGroupNode.RecreateChildNodes()
en Ab3d.DirectX.Models.WpfModel3DGroupNode.OnInitializeResources(DXScene dxScene)
en Ab3d.DirectX.SharedDXSceneResource.InitializeResources(DXScene dxScene)
en Ab3d.DirectX.SceneNode.(SceneNode , Int32 , Boolean , Boolean )
en Ab3d.DirectX.SceneNode.AddChild(SceneNode childNode)
en Ab3d.DirectX.Models.WpfModelVisual3DNode.RecreateContentSceneNode()
en Ab3d.DirectX.Models.WpfModelVisual3DNode.OnInitializeResources(DXScene dxScene)
en Ab3d.DirectX.SharedDXSceneResource.InitializeResources(DXScene dxScene)
en Ab3d.DirectX.SceneNode.(SceneNode , Int32 , Boolean , Boolean )
en Ab3d.DirectX.SceneNode.AddChild(SceneNode childNode)
en Ab3d.DirectX.Models.WpfVisual3DCollectionNode.e(Visual3D a)
en Ab3d.DirectX.Models.WpfVisual3DCollectionNode.b()
en Ab3d.DirectX.Models.WpfVisual3DCollectionNode.Update()
en Ab3d.DirectX.DXScene.Update()
en Ab3d.DirectX.Controls.DXView.Update()
en Ab3d.DirectX.Controls.DXView.h(Object a, EventArgs b)

The error message says that the operation is not valid for a relative URI because is not admitted. Sometimes this error is not fatal. In that case all ModelVisual3D are shown properly with their texture.

This is the code we use:

var boxTex = (BitmapImage)Application.Current.Resources["TexBox"];
Material boxMat = new DiffuseMaterial(new ImageBrush(boxTex)) { Color = palet.Color };

var geoms = mg.Select((m, i) => new GeometryModel3D(m, baseMat)).ToList();

var ourModel3D = new Model3DGroup();
ourModel3D.Children.AddRange(geoms);

Viewport3D.Children.Add(ourModel3D);

Where mg is an array of MeshGeometry3D that contains the points of the object.

- Tileables textures don't work well

With the next code WPF tiles the texture as many times as we scale the brush. However, with DXEngine the texture is not tiled and is displayed only once.

var brush = new ImageBrush(tex)
{
TileMode = TileMode.Tile,
ViewportUnits = BrushMappingMode.Absolute

};

diffuse = new DiffuseMaterial(brush) { Color = DiffuseColor.ToColor(1 - Transparency) };
diffuse.Brush.Transform = new ScaleTransform(1 / scale.X, 1 / scale.Y);


Please, let me know if you find what could be wrong and if you have any hint of how these issues could be fixed.

Thanks in advance
Regards
#2
The error was caused because a BitmapImage was using a relative Uri. The code in DXEngine is reading the bitmapImage.UriSource.LocalPath and I did not expect that the LocalPath getter would throw an exception when the path was not absolute.

I have fixed that with checking for absolute path before getting LocalPath. This fix is available in the pre-release version (v1.4) - if you need it, please send me an email or private message and I will send you a link to pre-release version.

Alternatively you can change the Uri to an absolute uri.


The other problem is related to showing tiled textures. To show tiled textures, please use Viewport property instead of Transform. This is also a standard WPF's way to provide tiled images in 2D graphics - see :https://msdn.microsoft.com/en-us/library/system.windows.media.tilebrush.viewport(v=vs.110).aspx

The problem with Transform on the ImageBrush is that it is very hard to implement for all cases (this would require a support in pixel shader that would require a lot of additional shader versions that would support texture transformations).

For example to show 4 x 2 tiles, set TileMode to Tile and then set Viewport to "0 0 0.25 0.5".

<visuals:BoxVisual3D x:Name="Box1" CenterPosition="30 10 30" Size="100 20 100">
<visuals:BoxVisual3D.Material>
<DiffuseMaterial>
<DiffuseMaterial.Brush>
<ImageBrush TileMode="Tile" Viewport="0 0 0.25 0.5"> <!-- 4 x 2 -->
<ImageBrush.ImageSource>
<BitmapImage UriSource="/Resources/PowerToysTexture.png" />
</ImageBrush.ImageSource>
</ImageBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</visuals:BoxVisual3D.Material>
</visuals:BoxVisual3D>


After writing all that I got an idea: when the ImageBrush (or any other TileBrush) has TileMode set to Tile and Viewport set to 0,0,1,1 and it has a single ScaleTransform, it is possible to convert ScaleTransform into Viewport Rect value:

imageBrush.Viewport = new Rect(0, 0, scaleTransform.ScaleX, scaleTransform.ScaleY);
usedTransform = null;

This was also added to the development version of DXEngine and will come with next version. Until then please use Viewport for tiled images.
Andrej Benedik
  


Forum Jump:


Users browsing this thread:
1 Guest(s)