views:

440

answers:

2

Hi

I'm porting a DirectX application into WPF, using the Windows.Media.Media3D toolkit. Which is working good and all, except that the Model is rendered in-complete, even when it have gotten all possible data.

I suspect it's because DirectX optimize and somehow smooth or help rendering additional content depending on the vertices and indicies.

So I'm wondering if there's a option to change how WPF renders 3D models? It's a bit hard to express precisely what I mean, but I hope it's somehow understandable.

Here's the important code:

private void DrawModel()
{
    SwordModel swordModel;

    string filename = "PG_S8_02";

    using(FileStream stream = File.OpenRead(string.Format("Media/Models/{0}.gb", filename)))
    using(BinaryReader reader = new BinaryReader(stream))
    {
        swordModel = new SwordModel(reader);         
    }

    var group = new Model3DGroup();

    foreach(var modelMesh in swordModel.Meshes)
    {
        var mesh3D = new MeshGeometry3D();

        // Indices
        foreach(var index in modelMesh.Indices)
        {
            mesh3D.TriangleIndices.Add(index);
        }

        // Vertices
        foreach(var vertex in modelMesh.Vertices)
        {
            mesh3D.Positions.Add(vertex);
        }

        // Normals
        foreach(var normal in modelMesh.Normals)
        {
            mesh3D.Normals.Add(normal);
        }

        // Texture Coordinates
        foreach(var vertex in modelMesh.Vertices)
        {
            mesh3D.TextureCoordinates.Add(new Point(vertex.X, vertex.Y));
        }

        // Material
        var material = new DiffuseMaterial();
        var texture  = new BitmapImage(new Uri(
            string.Format("Media/Textures/{0}.png", filename), 
            UriKind.RelativeOrAbsolute
        ));   
        material.Brush = new ImageBrush(texture);                               

        // Add to View
        group.Children.Add(
            new GeometryModel3D(mesh3D, material)
        );
    }    

    mainViewport.Children.Add(
        new ModelVisual3D() { Content = group }
    );         
}

And XAML:

<Viewport3D Name="mainViewport" ClipToBounds="True">
    <Viewport3D.Camera>
        <PerspectiveCamera 
            FarPlaneDistance="100"
                        LookDirection="-11,-10,-9"
                        UpDirection="0,1,0"
                        NearPlaneDistance="1" 
                        Position="11,10,9" 
                        FieldOfView="70" />
    </Viewport3D.Camera>
    <ModelVisual3D>
        <ModelVisual3D.Content>
            <DirectionalLight Color="White" Direction="-2,-3,-1" />
        </ModelVisual3D.Content>
    </ModelVisual3D>
</Viewport3D>
A: 

Is there a problem with sidedness? By default I think WPF renders facets onesided - you can't see them from the 'wrong' side.

Similarly with lighting you can get odd effects if your model isn't illuminated from all directions - try putting in an AmbientLight

Ian Hopkinson
+1  A: 

The only thing I can think of is that the normals aren't smoothed, but without seeing what the mesh looks like I couldn't say for sure.

By that I mean that the vertex normals are parallel to the face normals giving the mesh a faceted look. If the normals are smoothed then the whole shape looks smoothed. Something like this:

Flat Shading:

http://www.forman.free-online.co.uk/images/flatshading.png

Smooth Shading:

http://www.forman.free-online.co.uk/images/smoothshading.png

images replaced by links to limit my bandwidth usage

ChrisF
It looks like the "sidedness" of the faces is the issue (see Ian Hopkinson's answer), though so is DirectX (I think) so I can't immediately think why the conversion would go wrong.
ChrisF