Windows Vista Forums

Simple Grid Rendering

  1. #1


    Kristan Guest

    Simple Grid Rendering

    Hi there, I need to render a simple 50x50 grid / table, each cell in the
    table should highlight when the mouse is hovering over it.
    The hard part is: I really need to be able to tilt the grid, within the 3D
    world.... I hear the Viewport would support the 3D view - but how can I
    render the grid within the Viewport?



    Any advice would be great!
    thanks for your time
    Kristan


      My System SpecsSystem Spec

  2. #2


    Tim Mackey Guest

    Re: Simple Grid Rendering

    Hi Kristan,
    i ran into a similar problem. since everything is triangles in 3D, there is
    no 'line' as such. there is a class called ScreenSpaceLine3D which you can
    find online, but it didn't really work for me so i rolled my own.
    essentially i created a very long and thin cuboid, to effect a grid. here
    is a bunch of code i use in my hobby app attempting to create a 3d modelling
    tool to help with construction projects. i use the TrackBall class to allow
    3d fly/zoom around the world. there are a few helper methods to help with
    the 3d objects. i can mail you the whole thing if you want.
    good luck
    tim

    double scale = .05; // i use mm measurements and this is a useful scale,
    e.g. to render a 1500mm square on screen
    void mmSceneDrawGrid_Click(object sender, RoutedEventArgs e)
    {
    double thick = .03;
    double outsideThickFactor = 5;
    double len = 2000 * scale;
    double size = 5; // number of parellel lines in one side of the
    grid
    Color c = Colors.Red;
    double interval = len / size;

    for (int i = 0; i <= size; i++)
    {
    for (int j = 0; j <= size; j++)
    {
    // convert the loop iterators into the required grid cell size
    interval, relative to len
    double a = i * interval;
    double b = j * interval;

    // draw all the lines in the x-direction, size x size all starting at
    0x, moving to 'len' for each y, for each z
    this.CreateLine(new Point3D(0, a, b), new Point3D(len, a, b), thick *
    ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    c);
    // draw all the lines in the y-direction, size x size all starting at
    0y, moving to 'len' for each x, for each z
    this.CreateLine(new Point3D(a, 0, b), new Point3D(a, len, b), thick *
    ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    c);
    // draw all the lines in the z-direction, size x size all starting at
    0z, moving to 'len' for each x, for each y
    this.CreateLine(new Point3D(a, b, 0), new Point3D(a, b, len), thick *
    ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    c);
    }
    }
    }


    private Model3DGroup CreateTriangleModel(Point3D p0, Point3D p1, Point3D p2,
    Color c)
    {
    MeshGeometry3D mesh = new MeshGeometry3D();
    mesh.Positions.Add(p0);
    mesh.Positions.Add(p1);
    mesh.Positions.Add(p2);
    mesh.TriangleIndices.Add(0);
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(2);
    Vector3D normal = CalculateNormal(p0, p1, p2);
    mesh.Normals.Add(normal);
    mesh.Normals.Add(normal);
    mesh.Normals.Add(normal);
    Material material = new DiffuseMaterial(new SolidColorBrush(c));
    GeometryModel3D model = new GeometryModel3D(mesh, material);
    Model3DGroup group = new Model3DGroup();
    group.Children.Add(model);

    return group;
    }

    private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2)
    {
    Vector3D v0 = new Vector3D(
    p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
    Vector3D v1 = new Vector3D(
    p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
    return Vector3D.CrossProduct(v0, v1);
    }

    private void CreateLine(Point3D a, Point3D b, double t, Color c)
    {
    Model3DGroup cube = new Model3DGroup();
    Point3D p0 = new Point3D(a.X, a.Y, a.Z);
    Point3D p1 = new Point3D(a.X + t, a.Y, a.Z);
    Point3D p2 = new Point3D(b.X + t, b.Y, b.Z);
    Point3D p3 = new Point3D(b.X, b.Y, b.Z);
    Point3D p4 = new Point3D(a.X, a.Y + t, a.Z);
    Point3D p5 = new Point3D(a.X + t, a.Y + t, a.Z);
    Point3D p6 = new Point3D(b.X + t, b.Y + t, b.Z);
    Point3D p7 = new Point3D(b.X, b.Y + t, b.Z);
    //front side triangles
    cube.Children.Add(CreateTriangleModel(p3, p2, p6, c));
    cube.Children.Add(CreateTriangleModel(p3, p6, p7, c));
    //right side triangles
    cube.Children.Add(CreateTriangleModel(p2, p1, p5, c));
    cube.Children.Add(CreateTriangleModel(p2, p5, p6, c));
    //back side triangles
    cube.Children.Add(CreateTriangleModel(p1, p0, p4, c));
    cube.Children.Add(CreateTriangleModel(p1, p4, p5, c));
    //left side triangles
    cube.Children.Add(CreateTriangleModel(p0, p3, p7, c));
    cube.Children.Add(CreateTriangleModel(p0, p7, p4, c));
    //top side triangles
    cube.Children.Add(CreateTriangleModel(p7, p6, p5, c));
    cube.Children.Add(CreateTriangleModel(p7, p5, p4, c));
    //bottom side triangles
    cube.Children.Add(CreateTriangleModel(p2, p3, p0, c));
    cube.Children.Add(CreateTriangleModel(p2, p0, p1, c));

    ModelVisual3D model = new ModelVisual3D();
    model.Content = cube;
    this.mainViewport.Children.Add(model);
    }

    "Kristan" <kristan@NOSPAMhotmail.co.uk> wrote in message
    news:484580AC-A26F-45F2-8698-5A5D9AEE3F01@microsoft.com...
    > Hi there, I need to render a simple 50x50 grid / table, each cell in the
    > table should highlight when the mouse is hovering over it.
    > The hard part is: I really need to be able to tilt the grid, within the
    > 3D world.... I hear the Viewport would support the 3D view - but how can I
    > render the grid within the Viewport?
    >
    > Any advice would be great!
    > thanks for your time
    > Kristan
    >



      My System SpecsSystem Spec

  3. #3


    Kristan Guest

    Re: Simple Grid Rendering

    Hi there, I had a go at using the code, with the following XAML

    <Window x:Class="WindowsApplication4.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WindowsApplication4" Height="418" Width="626"
    >


    <Grid>
    <Button Width="100" Height="100" Name="mmSceneDrawGrid"
    Click="mmSceneDrawGrid_Click" HorizontalAlignment="Left"
    Margin="86,44.5,0,0" VerticalAlignment="Top">Hello, XAML!</Button>
    <Viewport3D Name="mainViewport"></Viewport3D>
    </Grid>

    </Window>

    The mmSceneDrawGrid_Click() handler does execute, but nothing is rendered
    onto the screen... hmmmm any ideas what I might be doing wrong?

    It would be good to get something showing up - then it'll be easier to play
    with it and work everything out!

    thanks,
    Kristan


    "Tim Mackey" <tim.mackey@community.nospam> wrote in message
    news:4EA9968D-61E1-4E45-808E-4AE8E95A92F5@microsoft.com...
    > Hi Kristan,
    > i ran into a similar problem. since everything is triangles in 3D, there
    > is no 'line' as such. there is a class called ScreenSpaceLine3D which you
    > can find online, but it didn't really work for me so i rolled my own.
    > essentially i created a very long and thin cuboid, to effect a grid. here
    > is a bunch of code i use in my hobby app attempting to create a 3d
    > modelling tool to help with construction projects. i use the TrackBall
    > class to allow 3d fly/zoom around the world. there are a few helper
    > methods to help with the 3d objects. i can mail you the whole thing if
    > you want.
    > good luck
    > tim
    >
    > double scale = .05; // i use mm measurements and this is a useful scale,
    > e.g. to render a 1500mm square on screen
    > void mmSceneDrawGrid_Click(object sender, RoutedEventArgs e)
    > {
    > double thick = .03;
    > double outsideThickFactor = 5;
    > double len = 2000 * scale;
    > double size = 5; // number of parellel lines in one side of the
    > grid
    > Color c = Colors.Red;
    > double interval = len / size;
    >
    > for (int i = 0; i <= size; i++)
    > {
    > for (int j = 0; j <= size; j++)
    > {
    > // convert the loop iterators into the required grid cell size
    > interval, relative to len
    > double a = i * interval;
    > double b = j * interval;
    >
    > // draw all the lines in the x-direction, size x size all starting at
    > 0x, moving to 'len' for each y, for each z
    > this.CreateLine(new Point3D(0, a, b), new Point3D(len, a, b), thick *
    > ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    > c);
    > // draw all the lines in the y-direction, size x size all starting at
    > 0y, moving to 'len' for each x, for each z
    > this.CreateLine(new Point3D(a, 0, b), new Point3D(a, len, b), thick *
    > ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    > c);
    > // draw all the lines in the z-direction, size x size all starting at
    > 0z, moving to 'len' for each x, for each y
    > this.CreateLine(new Point3D(a, b, 0), new Point3D(a, b, len), thick *
    > ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    > c);
    > }
    > }
    > }
    >
    >
    > private Model3DGroup CreateTriangleModel(Point3D p0, Point3D p1, Point3D
    > p2, Color c)
    > {
    > MeshGeometry3D mesh = new MeshGeometry3D();
    > mesh.Positions.Add(p0);
    > mesh.Positions.Add(p1);
    > mesh.Positions.Add(p2);
    > mesh.TriangleIndices.Add(0);
    > mesh.TriangleIndices.Add(1);
    > mesh.TriangleIndices.Add(2);
    > Vector3D normal = CalculateNormal(p0, p1, p2);
    > mesh.Normals.Add(normal);
    > mesh.Normals.Add(normal);
    > mesh.Normals.Add(normal);
    > Material material = new DiffuseMaterial(new SolidColorBrush(c));
    > GeometryModel3D model = new GeometryModel3D(mesh, material);
    > Model3DGroup group = new Model3DGroup();
    > group.Children.Add(model);
    >
    > return group;
    > }
    >
    > private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2)
    > {
    > Vector3D v0 = new Vector3D(
    > p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
    > Vector3D v1 = new Vector3D(
    > p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
    > return Vector3D.CrossProduct(v0, v1);
    > }
    >
    > private void CreateLine(Point3D a, Point3D b, double t, Color c)
    > {
    > Model3DGroup cube = new Model3DGroup();
    > Point3D p0 = new Point3D(a.X, a.Y, a.Z);
    > Point3D p1 = new Point3D(a.X + t, a.Y, a.Z);
    > Point3D p2 = new Point3D(b.X + t, b.Y, b.Z);
    > Point3D p3 = new Point3D(b.X, b.Y, b.Z);
    > Point3D p4 = new Point3D(a.X, a.Y + t, a.Z);
    > Point3D p5 = new Point3D(a.X + t, a.Y + t, a.Z);
    > Point3D p6 = new Point3D(b.X + t, b.Y + t, b.Z);
    > Point3D p7 = new Point3D(b.X, b.Y + t, b.Z);
    > //front side triangles
    > cube.Children.Add(CreateTriangleModel(p3, p2, p6, c));
    > cube.Children.Add(CreateTriangleModel(p3, p6, p7, c));
    > //right side triangles
    > cube.Children.Add(CreateTriangleModel(p2, p1, p5, c));
    > cube.Children.Add(CreateTriangleModel(p2, p5, p6, c));
    > //back side triangles
    > cube.Children.Add(CreateTriangleModel(p1, p0, p4, c));
    > cube.Children.Add(CreateTriangleModel(p1, p4, p5, c));
    > //left side triangles
    > cube.Children.Add(CreateTriangleModel(p0, p3, p7, c));
    > cube.Children.Add(CreateTriangleModel(p0, p7, p4, c));
    > //top side triangles
    > cube.Children.Add(CreateTriangleModel(p7, p6, p5, c));
    > cube.Children.Add(CreateTriangleModel(p7, p5, p4, c));
    > //bottom side triangles
    > cube.Children.Add(CreateTriangleModel(p2, p3, p0, c));
    > cube.Children.Add(CreateTriangleModel(p2, p0, p1, c));
    >
    > ModelVisual3D model = new ModelVisual3D();
    > model.Content = cube;
    > this.mainViewport.Children.Add(model);
    > }
    >
    > "Kristan" <kristan@NOSPAMhotmail.co.uk> wrote in message
    > news:484580AC-A26F-45F2-8698-5A5D9AEE3F01@microsoft.com...
    >> Hi there, I need to render a simple 50x50 grid / table, each cell in the
    >> table should highlight when the mouse is hovering over it.
    >> The hard part is: I really need to be able to tilt the grid, within the
    >> 3D world.... I hear the Viewport would support the 3D view - but how can
    >> I render the grid within the Viewport?
    >>
    >> Any advice would be great!
    >> thanks for your time
    >> Kristan
    >>

    >



      My System SpecsSystem Spec

  4. #4


    Tim Mackey Guest

    Re: Simple Grid Rendering

    hi kristan. here is the full code i'm using. hopefully it will work for
    you. sorry i don't have time to trim it down to a minimal solution, there
    is a lot of stuff that may not interest you. it's poorly commented (if at
    all) and the object rotations don't work well, but it's my first wpf
    application so i'm just using it as a learning tool.

    here's the xaml:

    <?Mapping XmlNamespace="local" ClrNamespace="WPF_Test" ?>
    <Window x:Class="WPF_Test.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="WPF_Test" WindowState="Maximized"
    xmlns:my="clr-namespace:System;assembly=mscorlib" Height="336" Width="351">
    <Grid Name="WorldGrid" >
    <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"></RowDefinition>
    <RowDefinition Height="*"></RowDefinition>
    <RowDefinition Height="Auto"></RowDefinition>
    <RowDefinition Height="Auto"></RowDefinition>
    </Grid.RowDefinitions>
    <Menu HorizontalAlignment="Stretch" Name="menu1" VerticalAlignment="Top"
    Grid.Row="0" Grid.Column="0" Focusable="True">
    <MenuItem Header="_File">
    <MenuItem Header="_Open" Name="mmOpen" ></MenuItem>
    <MenuItem Header="_Save" Name="mmSave"></MenuItem>
    <MenuItem Header="E_xit" Name="mmExit"></MenuItem>
    </MenuItem>
    <MenuItem Header="_Lights">
    <MenuItem Header="Add _Ambient Lights" Name="mmAddAmbientLights"
    ></MenuItem>

    <MenuItem Header="Add _Directional Lights" Name="mmAddDirectionalLights"
    ></MenuItem>

    <MenuItem Header="_Clear Lights" Name="mmClearLights" ></MenuItem>

    </MenuItem>
    <MenuItem Header="_Camera">
    <MenuItem Header="_Reset Camera" Name="mmResetCamera" ></MenuItem>
    <MenuItem Header="_Clear Scene" Name="mmClearObjects"></MenuItem>
    </MenuItem>
    <MenuItem Header="_Action">
    <MenuItem Header="Draw _Grid" Name="mmDrawGrid" ></MenuItem>
    <MenuItem Header="Deselect _Object" Name="mmDeselectObject" ></MenuItem>
    <MenuItem Header="View _Key Commands" Name="mmViewKeyCommands"
    ></MenuItem>

    </MenuItem>
    </Menu>
    <Viewport3D Name="mainViewport" ClipToBounds="True" Grid.Row="1"
    Grid.Column="0" >
    <Viewport3D.Camera>
    <PerspectiveCamera
    FarPlaneDistance="100"
    NearPlaneDistance="0"
    LookDirection="0,0,-1"
    UpDirection="0,1,0"
    Position="5,5,75"
    FieldOfView="70"
    />
    </Viewport3D.Camera>
    <ModelVisual3D>
    <ModelVisual3D.Content>
    <AmbientLight
    Color="White" />
    </ModelVisual3D.Content>
    </ModelVisual3D>
    </Viewport3D>
    <Border Name="Border1" Background="Transparent" Grid.Row="1"
    Grid.Column="0" Focusable="True" ForceCursor="True"
    KeyboardNavigation.AcceptsReturn="True"
    KeyboardNavigation.TabNavigation="Local"
    KeyboardNavigation.DirectionalNavigation="Local"
    KeyboardNavigation.ControlTabNavigation="Local" />
    <DockPanel Grid.Row="2" Grid.Column="0" HorizontalAlignment="Left"
    VerticalAlignment="Center">
    <TextBlock Text=" Length " VerticalAlignment="Center" />
    <TextBox Name="txtPlankLength" Width="70" Focusable="True" />
    <Button Click="AddPlank" Content="Add Plank" Width="70" Focusable="True"
    />
    </DockPanel>
    <StatusBar Name="statusBar1" Grid.Row="3" Grid.Column="0" >
    <StatusBarItem HorizontalAlignment="Left" Name="statusBarItem1"
    Content="Ready" ></StatusBarItem>
    </StatusBar>
    </Grid>
    </Window>

    and, the lengthy code behind.

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Windows.Markup;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Windows.Media.Media3D;
    using System.Xml;
    using System.Xml.Serialization;

    using _3DTools;
    using Microsoft.Win32;

    namespace WPF_Test
    {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>

    public partial class Window1 : System.Windows.Window
    {
    private List<Model3DGroup> FormObjects = new List<Model3DGroup>(); // a
    list of all 3d objects added to the viewport
    private Material previousMaterial;
    private Model3DGroup currentModel;
    double scale = .05; // 1mm : screen
    private Trackball trackball = new Trackball();

    public Window1()
    {
    InitializeComponent();

    this.Loaded += new RoutedEventHandler(Window1_Loaded);
    this.KeyDown += new KeyEventHandler(Window1_KeyDown);
    this.Border1.MouseDown += new
    MouseButtonEventHandler(ViewPort_MouseDown);

    this.mmOpen.Click += new RoutedEventHandler(mmFileOpen_Click);
    this.mmSave.Click += new RoutedEventHandler(mmFileSave_Click);
    this.mmExit.Click += new RoutedEventHandler(mmFileExit_Click);

    this.mmClearObjects.Click += new
    RoutedEventHandler(mmSceneClearObjects_Click);
    this.mmResetCamera.Click += new
    RoutedEventHandler(mmSceneResetCamera_Click);

    this.mmDrawGrid.Click += new RoutedEventHandler(mmSceneDrawGrid_Click);
    this.mmViewKeyCommands.Click += new
    RoutedEventHandler(mmSceneViewKeyCommands_Click);
    this.mmDeselectObject.Click += new
    RoutedEventHandler(mmSceneDeselect_Click);

    this.mmAddAmbientLights.Click += new
    RoutedEventHandler(mmSceneAddAmbientLights_Click);
    this.mmAddDirectionalLights.Click += new
    RoutedEventHandler(mmSceneAddDirectionalLights_Click);
    this.mmClearLights.Click += new RoutedEventHandler(mmClearLights_Click);
    }

    void Window1_Loaded(object sender, RoutedEventArgs e)
    {
    this.mmSceneResetCamera_Click(sender, e);
    this.mmSceneDrawGrid_Click(sender, e);
    }


    #region util shape grouping methods
    private List<GeometryModel3D> GetChildGeometryModels(Model3DGroup parent)
    {
    List<GeometryModel3D> list = new List<GeometryModel3D>();
    Queue<Model3DGroup> q = new Queue<Model3DGroup>();
    foreach (object o in parent.Children)
    if (o is Model3DGroup)
    q.Enqueue(o as Model3DGroup);

    while (q.Count > 0)
    {
    Model3DGroup m = q.Dequeue();
    foreach (object o in m.Children)
    {
    if (o is Model3DGroup)
    q.Enqueue(o as Model3DGroup);
    else
    list.Add(o as GeometryModel3D);
    }
    }
    return list;
    }

    private Model3DGroup FindParentModel(object find)
    {
    int hash = find.GetHashCode();
    System.Diagnostics.Trace.WriteLine("Searching for " + hash);

    // iterative approach to recursively scan child objects of the parent
    model
    foreach (Model3DGroup mod in FormObjects)
    foreach (GeometryModel3D geo in GetChildGeometryModels(mod))
    if (geo.GetHashCode() == hash)
    return mod;
    System.Diagnostics.Trace.WriteLine("Not found\n\n");
    return null;
    }

    private void HighlightObject(Model3DGroup parent, Color c)
    {
    this.mmSceneDeselect_Click(null, new RoutedEventArgs());

    Material m = new DiffuseMaterial(new SolidColorBrush(c));
    foreach (GeometryModel3D geo in GetChildGeometryModels(parent))
    {
    previousMaterial = geo.Material.Clone(); // overwritten but that
    doesn't matter.
    geo.Material = m;
    }


    // save the current Material to and Model for later reverting back
    currentModel = parent;

    // set local transformation variable
    if(!(currentModel.Transform is Transform3DGroup))
    {
    tg = new Transform3DGroup();
    tg.Children.Add(new TranslateTransform3D());
    tg.Children.Add(new RotateTransform3D(new AxisAngleRotation3D()));
    tg.Children.Add(new ScaleTransform3D());
    this.currentModel.Transform = tg;
    }
    else
    tg = currentModel.Transform as Transform3DGroup;
    }
    #endregion

    #region keyboard events
    private Transform3DGroup tg;
    void Window1_KeyDown(object sender, KeyEventArgs e)
    {
    PerspectiveCamera cam = (this.mainViewport.Camera as PerspectiveCamera);

    // TODO: bullet-time-cam, slide and look.

    if (Keyboard.Modifiers == ModifierKeys.Control)
    {
    // control the look direction via Ctrl-arrows / pg Up/down
    switch (e.Key)
    {
    case Key.Left:
    cam.LookDirection = new Vector3D(cam.LookDirection.X - .1,
    cam.LookDirection.Y, cam.LookDirection.Z);
    break;
    case Key.Right:
    cam.LookDirection = new Vector3D(cam.LookDirection.X + .1,
    cam.LookDirection.Y, cam.LookDirection.Z);
    break;
    case Key.Up:
    cam.LookDirection = new Vector3D(cam.LookDirection.X,
    cam.LookDirection.Y + .1, cam.LookDirection.Z);
    break;
    case Key.Down:
    cam.LookDirection = new Vector3D(cam.LookDirection.X,
    cam.LookDirection.Y - .1, cam.LookDirection.Z);
    break;
    case Key.PageDown:
    cam.LookDirection = new Vector3D(cam.LookDirection.X,
    cam.LookDirection.Y, cam.LookDirection.Z + .1);
    break;
    case Key.PageUp:
    cam.LookDirection = new Vector3D(cam.LookDirection.X,
    cam.LookDirection.Y, cam.LookDirection.Z - .1);
    break;
    default:
    return;
    }
    e.Handled = true;
    }
    else if (Keyboard.Modifiers == ModifierKeys.Shift)
    {
    if (this.currentModel == null)
    {
    this.statusBarItem1.Content = "No object selected!";
    return;
    }

    // shift moves the object via Ctrl-arrows / pg Up/down
    TranslateTransform3D t = tg.Children[0] as TranslateTransform3D;
    switch (e.Key)
    {
    case Key.Left:
    t.OffsetX--;
    break;
    case Key.Right:
    t.OffsetX++;
    break;
    case Key.Up:
    t.OffsetY++;
    break;
    case Key.Down:
    t.OffsetY--;
    break;
    case Key.PageDown:
    t.OffsetZ--;
    break;
    case Key.PageUp:
    t.OffsetZ++;
    break;
    default:
    return;
    }
    e.Handled = true;
    }
    else if (Keyboard.Modifiers == (ModifierKeys.Shift |
    ModifierKeys.Control))
    {
    // shift+control = rotate
    if (this.currentModel == null)
    {
    this.statusBarItem1.Content = "No object selected!";
    return;
    }
    RotateTransform3D t = tg.Children[1] as RotateTransform3D;
    AxisAngleRotation3D a = t.Rotation as AxisAngleRotation3D;
    switch (e.Key)
    {
    case Key.Left:
    a.Angle--;
    break;
    case Key.Right:
    a.Angle++;
    break;
    default:
    return;
    }
    e.Handled = true;
    }
    else // no modifiers, just move the camera
    {
    switch (e.Key)
    {
    case Key.Left:
    cam.Position = new Point3D(cam.Position.X - 1, cam.Position.Y,
    cam.Position.Z);
    break;
    case Key.Right:
    cam.Position = new Point3D(cam.Position.X + 1, cam.Position.Y,
    cam.Position.Z);
    break;
    case Key.Up:
    cam.Position = new Point3D(cam.Position.X, cam.Position.Y + 1,
    cam.Position.Z);
    break;
    case Key.Down:
    cam.Position = new Point3D(cam.Position.X, cam.Position.Y - 1,
    cam.Position.Z);
    break;
    case Key.PageDown:
    cam.Position = new Point3D(cam.Position.X, cam.Position.Y,
    cam.Position.Z + 1);
    break;
    case Key.PageUp:
    cam.Position = new Point3D(cam.Position.X, cam.Position.Y,
    cam.Position.Z - 1);
    break;
    case Key.Add:
    cam.FieldOfView++;
    break;
    case Key.Subtract:
    cam.FieldOfView--;
    break;
    default:
    return;
    }
    e.Handled = true;
    }
    this.statusBarItem1.Content = String.Format("Camera: x{0:0}, y{1:0},
    z{2:0}. Look: x{3:0.0}, y{4:0.0}, z{5:0.0}. Field of view: {6}",
    cam.Position.X, cam.Position.Y, cam.Position.Z,
    this.trackball.CameraLookDirection.X, this.trackball.CameraLookDirection.Y,
    this.trackball.CameraLookDirection.Z, cam.FieldOfView);
    }
    #endregion

    void AddPlank(object sender, EventArgs e)
    {
    try
    {
    double length = Convert.ToDouble(this.txtPlankLength.Text)*scale;
    this.CreateCuboid(new Point3D(0,0,0), 140*scale, length, 30*scale,
    Colors.Brown);
    }
    catch
    {
    MessageBox.Show("Please enter a milimetre measurement, decimal points
    are allowed, no letters etc. ", "Not a number");
    }
    }

    #region menu
    void mmSceneResetCamera_Click(object sender, RoutedEventArgs e)
    {
    this.mainViewport.Camera.Transform = null; // remove the trackball

    (this.mainViewport.Camera as PerspectiveCamera).Position = new Point3D(5,
    5, 75);
    (this.mainViewport.Camera as PerspectiveCamera).LookDirection = new
    Vector3D(0, 0, -1);

    trackball = new Trackball();
    trackball.EventSource = this.Border1;
    this.mainViewport.Camera.Transform = trackball.Transform;
    }

    void mmSceneClearObjects_Click(object sender, RoutedEventArgs e)
    {
    for(int i=this.mainViewport.Children.Count-1; i>=0; i--)
    {
    ModelVisual3D m = this.mainViewport.Children[i] as ModelVisual3D;
    if(m is Model3DGroup)
    this.mainViewport.Children.RemoveAt(i);
    }
    }

    void mmSceneAddAmbientLights_Click(object sender, RoutedEventArgs e)
    {
    ModelVisual3D lights = new ModelVisual3D();
    lights.Content = new AmbientLight(Colors.White);
    this.mainViewport.Children.Add(lights);
    }

    void mmClearLights_Click(object sender, RoutedEventArgs e)
    {
    for(int i=this.mainViewport.Children.Count-1; i>=0; i--)
    {
    ModelVisual3D m = this.mainViewport.Children[i] as ModelVisual3D;
    if(m.Content.GetType().Name.EndsWith("Light"))
    this.mainViewport.Children.RemoveAt(i);
    }
    }

    void mmSceneAddDirectionalLights_Click(object sender, RoutedEventArgs e)
    {
    ModelVisual3D lights = new ModelVisual3D();
    lights.Content = new DirectionalLight(Colors.Yellow,
    (this.mainViewport.Camera as PerspectiveCamera).LookDirection);
    this.mainViewport.Children.Add(lights);
    }

    void mmSceneDeselect_Click(object sender, RoutedEventArgs e)
    {
    if (this.currentModel != null)
    {
    // restore previous material
    foreach (GeometryModel3D geo in GetChildGeometryModels(currentModel))
    geo.Material = previousMaterial;
    }
    this.currentModel = null;
    this.previousMaterial = null;
    }

    void mmSceneDrawGrid_Click(object sender, RoutedEventArgs e)
    {
    double thick = .03;
    double outsideThickFactor = 5;
    double len = 2000 * scale;
    double size = 5;
    Color c = Colors.Red; //.FromRgb(220, 220, 220);

    double interval = len / size;

    for (int i = 0; i <= size; i++)
    {
    for (int j = 0; j <= size; j++)
    {
    // convert the loop iterators into the required grid cell size
    interval, relative to len
    double a = i * interval;
    double b = j * interval;

    // draw all the lines in the x-direction, size x size all starting at
    0x, moving to 'len' for each y, for each z
    this.CreateLine(new Point3D(0, a, b), new Point3D(len, a, b), thick *
    ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    c);
    // draw all the lines in the y-direction, size x size all starting at
    0y, moving to 'len' for each x, for each z
    this.CreateLine(new Point3D(a, 0, b), new Point3D(a, len, b), thick *
    ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    c);
    // draw all the lines in the z-direction, size x size all starting at
    0z, moving to 'len' for each x, for each y
    this.CreateLine(new Point3D(a, b, 0), new Point3D(a, b, len), thick *
    ((a % len) / size == 0 && (b % len) / size == 0 ? outsideThickFactor : 1),
    c);
    }
    }

    /* 3dLine class not working....
    *
    * ScreenSpaceLines3D ssl3D = new ScreenSpaceLines3D();
    Point3DCollection gridLines = new Point3DCollection();

    for (int i = 0; i <= size; i++)
    {
    for (int j = 0; j <= size; j++)
    {
    // convert the loop iterators into the required grid cell size
    interval, relative to len
    double a = i * interval;
    double b = j * interval;

    // x line
    gridLines.Add(new Point3D(0, a, b));
    gridLines.Add(new Point3D(len, a, b));

    // y line
    gridLines.Add(new Point3D(a, 0, b));
    gridLines.Add(new Point3D(a, len, b));

    // z line
    gridLines.Add(new Point3D(a, b, 0));
    gridLines.Add(new Point3D(a, b, len));
    }
    }
    ssl3D.Points = gridLines;
    ssl3D.Color = Colors.Red;
    ssl3D.Thickness = 5;
    this.mainViewport.Children.Add(ssl3D);*/
    }

    void mmSceneViewKeyCommands_Click(object sender, RoutedEventArgs e)
    {
    MessageBox.Show(@"Use arrows to move camera in x and y directions.
    Page up/down to move camera in/out in z direction.
    Ctrl+Arrow keys to change camera look vector in x and y direction.
    Ctrl+Page up/down to change camera look vector in z direction.
    + Increase Field of View
    - Decrease Field of View
    Click on an object to select
    Shift+Arrow keys to move the selected object
    Ctrl+Shift+Arrow left/right to rotate", "Key Commands");
    }

    void mmFileExit_Click(object sender, RoutedEventArgs e)
    {
    throw new Exception("The method or operation is not implemented.");
    }

    void mmFileOpen_Click(object sender, RoutedEventArgs e)
    {
    OpenFileDialog d = new OpenFileDialog();
    if (!d.ShowDialog().Value)
    return;

    this.statusBarItem1.Content = "Loading file, please wait...";
    this.Cursor = Cursors.Wait;
    Visual3DCollection controls;
    using (FileStream fs = File.OpenRead(d.FileName))
    controls = XamlReader.Load(fs) as Visual3DCollection;

    this.mainViewport.Children.Clear();
    foreach (Visual3D v in controls)
    this.mainViewport.Children.Add(v);
    this.Cursor = Cursors.Arrow;
    this.statusBarItem1.Content = "Ready";
    }

    void mmFileSave_Click(object sender, RoutedEventArgs e)
    {
    SaveFileDialog d = new SaveFileDialog();
    d.Filter = "XAML | *.xaml";
    if (!d.ShowDialog().Value)
    return;

    this.statusBarItem1.Content = "Saving, please wait...";
    this.Cursor = Cursors.Wait;
    using (FileStream fs = File.OpenWrite(d.SafeFileName))
    XamlWriter.Save(this.mainViewport.Children, fs);
    this.Cursor = Cursors.Arrow;
    this.statusBarItem1.Content = "Saved";
    }
    #endregion

    #region create shape methods
    private Model3DGroup CreateTriangleModel(Point3D p0, Point3D p1, Point3D
    p2, Color c)
    {
    MeshGeometry3D mesh = new MeshGeometry3D();
    mesh.Positions.Add(p0);
    mesh.Positions.Add(p1);
    mesh.Positions.Add(p2);
    mesh.TriangleIndices.Add(0);
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(2);
    Vector3D normal = CalculateNormal(p0, p1, p2);
    mesh.Normals.Add(normal);
    mesh.Normals.Add(normal);
    mesh.Normals.Add(normal);
    Material material = new DiffuseMaterial(new SolidColorBrush(c));
    GeometryModel3D model = new GeometryModel3D(mesh, material);
    Model3DGroup group = new Model3DGroup();
    group.Children.Add(model);

    return group;
    }

    private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2)
    {
    Vector3D v0 = new Vector3D(
    p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
    Vector3D v1 = new Vector3D(
    p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z);
    return Vector3D.CrossProduct(v0, v1);
    }

    private void CreateLine(Point3D a, Point3D b, double t, Color c)
    {
    Model3DGroup cube = new Model3DGroup();
    Point3D p0 = new Point3D(a.X, a.Y, a.Z);
    Point3D p1 = new Point3D(a.X + t, a.Y, a.Z);
    Point3D p2 = new Point3D(b.X + t, b.Y, b.Z);
    Point3D p3 = new Point3D(b.X, b.Y, b.Z);
    Point3D p4 = new Point3D(a.X, a.Y + t, a.Z);
    Point3D p5 = new Point3D(a.X + t, a.Y + t, a.Z);
    Point3D p6 = new Point3D(b.X + t, b.Y + t, b.Z);
    Point3D p7 = new Point3D(b.X, b.Y + t, b.Z);
    //front side triangles
    cube.Children.Add(CreateTriangleModel(p3, p2, p6, c));
    cube.Children.Add(CreateTriangleModel(p3, p6, p7, c));
    //right side triangles
    cube.Children.Add(CreateTriangleModel(p2, p1, p5, c));
    cube.Children.Add(CreateTriangleModel(p2, p5, p6, c));
    //back side triangles
    cube.Children.Add(CreateTriangleModel(p1, p0, p4, c));
    cube.Children.Add(CreateTriangleModel(p1, p4, p5, c));
    //left side triangles
    cube.Children.Add(CreateTriangleModel(p0, p3, p7, c));
    cube.Children.Add(CreateTriangleModel(p0, p7, p4, c));
    //top side triangles
    cube.Children.Add(CreateTriangleModel(p7, p6, p5, c));
    cube.Children.Add(CreateTriangleModel(p7, p5, p4, c));
    //bottom side triangles
    cube.Children.Add(CreateTriangleModel(p2, p3, p0, c));
    cube.Children.Add(CreateTriangleModel(p2, p0, p1, c));

    ModelVisual3D model = new ModelVisual3D();
    model.Content = cube;
    this.mainViewport.Children.Add(model);
    }

    private Model3DGroup CreateCuboid(Point3D pos, double w, double l, double
    d, Color c)
    {
    Model3DGroup cuboid = new Model3DGroup();

    Point3D p0 = new Point3D(pos.X, pos.Y, pos.Z);
    Point3D p1 = new Point3D(pos.X + w, pos.Y, pos.Z);
    Point3D p2 = new Point3D(pos.X + w, pos.Y, pos.Z + d);
    Point3D p3 = new Point3D(pos.X, pos.Y, pos.Z + d);
    Point3D p4 = new Point3D(pos.X, pos.Y + l, pos.Z);
    Point3D p5 = new Point3D(pos.X + w, pos.Y + l, pos.Z + 0);
    Point3D p6 = new Point3D(pos.X + w, pos.Y + l, pos.Z + d);
    Point3D p7 = new Point3D(pos.X, pos.Y + l, pos.Z + d);

    cuboid.Children.Add(CreateTriangleModel(p3, p2, p6, c));
    cuboid.Children.Add(CreateTriangleModel(p3, p6, p7, c));
    //right side triangles
    cuboid.Children.Add(CreateTriangleModel(p2, p1, p5, c));
    cuboid.Children.Add(CreateTriangleModel(p2, p5, p6, c));
    //back side triangles
    cuboid.Children.Add(CreateTriangleModel(p1, p0, p4, c));
    cuboid.Children.Add(CreateTriangleModel(p1, p4, p5, c));
    //left side triangles
    cuboid.Children.Add(CreateTriangleModel(p0, p3, p7, c));
    cuboid.Children.Add(CreateTriangleModel(p0, p7, p4, c));
    //top side triangles
    cuboid.Children.Add(CreateTriangleModel(p7, p6, p5, c));
    cuboid.Children.Add(CreateTriangleModel(p7, p5, p4, c));
    //bottom side triangles
    cuboid.Children.Add(CreateTriangleModel(p2, p3, p0, c));
    cuboid.Children.Add(CreateTriangleModel(p2, p0, p1, c));

    ModelVisual3D model = new ModelVisual3D();
    model.Content = cuboid;
    this.mainViewport.Children.Add(model);

    // add the cube to the 3d object tracker array (for grouping, hit test
    etc)
    this.FormObjects.Add(cuboid);
    return cuboid;
    }
    #endregion

    #region hit test
    public HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult
    rawresult)
    {
    RayHitTestResult rayResult = rawresult as RayHitTestResult;
    if (rayResult != null)
    {
    RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as
    RayMeshGeometry3DHitTestResult;
    if (rayMeshResult != null)
    {
    GeometryModel3D hitGeo = rayMeshResult.ModelHit as GeometryModel3D;

    // currentModel is just a triangle, try to identify the parent group
    and select the entire group
    Model3DGroup parent = FindParentModel(hitGeo);
    if (parent != null)
    HighlightObject(parent, Colors.Yellow);
    }
    }
    return HitTestResultBehavior.Stop;
    }
    void ViewPort_MouseDown(object sender, MouseButtonEventArgs e)
    {
    Point mouseposition = e.GetPosition(mainViewport);
    Point3D testpoint3D = new Point3D(mouseposition.X, mouseposition.Y, 0);
    Vector3D testdirection = new Vector3D(mouseposition.X, mouseposition.Y,
    10);
    PointHitTestParameters pointparams = new
    PointHitTestParameters(mouseposition);
    RayHitTestParameters rayparams = new RayHitTestParameters(testpoint3D,
    testdirection);

    //test for a result in the Viewport3D
    VisualTreeHelper.HitTest(mainViewport, null, HTResult, pointparams);
    }
    #endregion
    }
    }

    i also made a slight modification to the TrackBall class, to provide access
    to the look direction of the camera. but you could use the existing 3dTools
    dll and just remove the bit of code that uses this new property.

    public Vector3D CameraLookDirection
    {
    get
    {
    return this._rotation.Axis;
    }
    }


    any q's give me a shout!
    tim


      My System SpecsSystem Spec

Simple Grid Rendering

Similar Threads
Thread Thread Starter Forum Replies Last Post
games Rendering everywhere! mikadee Vista Games 5 10 May 2008
Vista not rendering 3D... wrobes21 Vista General 3 06 Apr 2008
Page Rendering REE Vista mail 0 11 Dec 2007
Graphics and Rendering Rodrigo Vista installation & setup 1 06 Nov 2007
Grid.Row Grid.Column set programatically at runtime craig kelly-soens www.XpectWorld.com Avalon 0 10 Jan 2006