Converted 3ds file to string giving error while rendering
#1
Hi,

We are evaluating the tool for purchasing. Following are some issues we are facing,
1) I am able to convert a 3ds model to a string using GetXAML() method. But when I try to render it again it throws an error. On closely looking at the converted string the object names have a space in between them and hence this error. Is there a way I can resolve this. XAML does not take a space for its x:Name property and this is where the error comes from.
2) I want to change the color of the model thru. code after I render the 3ds from a XAML stored on the disk. Is it possible and if yes how we can do that.

Regards,
Vidyadhar
#2
(01-04-2013, 11:52 AM)Vidyadhar Wrote: 1) I am able to convert a 3ds model to a string using GetXAML() method. But when I try to render it again it throws an error. On closely looking at the converted string the object names have a space in between them and hence this error. Is there a way I can resolve this. XAML does not take a space for its x:Name property and this is where the error comes from.

This is a bug in Reader3ds 8.3. I am preparing a fix that will be released soon.


(01-04-2013, 11:52 AM)Vidyadhar Wrote: 2) I want to change the color of the model thru. code after I render the 3ds from a XAML stored on the disk. Is it possible and if yes how we can do that.

With WPF it is quite easy to read xaml at runtime with XamlReader.Parse. But unfortunately when the root object in xaml is a 3D object (for example Model3DGroup or Model3DVisual) the names of the objects are not preserved. If the root object is Viewport3D (or probably some other object that derive from FrameworkElement), than you can call FindName on the read object and get the child objects.

I did not find any way to preserver the object names when reading pure xaml text.

However when using .Net 4.0 it is possible to get the object names when reading an xaml that was compiled into assembly (the xaml's BuildAction is Page and Custom Tool is MSBuild:Compile). The following code can be used to read the compiled xaml and than get on object by its name:

XAML:
Code:
<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="725">
    <Grid>
        <Viewport3D Name="MainViewport3D">
            <Viewport3D.Camera>
                <!-- Scene camera -->
                <PerspectiveCamera FieldOfView="45" NearPlaneDistance="0.125" FarPlaneDistance="Infinity" Position="-841.845062379205,655.098747538281,1468.0171928463" LookDirection="0.469846310392954,-0.342020143325669,-0.813797681349374" UpDirection="0.171010071662834,0.939692620785908,-0.296198132726024"/>
            </Viewport3D.Camera>
            <ModelVisual3D x:Name="RootModelVisual" />
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <DirectionalLight Direction="0.469846310392954,-0.342020143325669,-0.813797681349374" Color="White"/>
                </ModelVisual3D.Content>
            </ModelVisual3D>
        </Viewport3D>

        <Button Name="Button1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Height="30" Click="Button1_OnClick">Change color</Button>
    </Grid>
</Window>

Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Baml2006;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Xaml;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Model3DGroup _rootModel;
        
        private INameScope _modelNameScope;

        public MainWindow()
        {
            InitializeComponent();

            _rootModel = LoadModel("Resources/HouseWithTrees.xaml", out _modelNameScope) as Model3DGroup;
            RootModelVisual.Content = _rootModel;
        }

        private static object LoadModel(string uri, out INameScope nameScope)
        {
            object result;
            using (var stream = Application.GetResourceStream(new Uri(uri, UriKind.Relative)).Stream)
            {
                var reader = new Baml2006Reader(stream);
                var writer = new XamlObjectWriter(reader.SchemaContext);

                while (reader.Read())
                {
                    writer.WriteNode(reader);
                }

                // We need to save name scope so we can find objects later
                nameScope = writer.RootNameScope;

                result = writer.Result;
            }

            return result;
        }

        private void Button1_OnClick(object sender, RoutedEventArgs e)
        {
            var tree2 = _modelNameScope.FindName("Sphere02") as GeometryModel3D;

            tree2.Material = new DiffuseMaterial(Brushes.Red);
        }
    }
}

Notes:
This code is reading a file "Resources/HouseWithTrees.xaml". It was created with Viewer3ds with root object set to Model3DGroup.
Andrej Benedik
  


Forum Jump:


Users browsing this thread:
2 Guest(s)