using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Threading; using OpenMetaverse; using OpenMetaverse.Rendering; using Xenki.Framework; using Quaternion=System.Windows.Media.Media3D.Quaternion; namespace Xenki.DefaultRenderer { class DefaultRenderer : IRenderer { private readonly Viewport3D m_viewport; private readonly PerspectiveCamera m_camera; private Trackball m_trackball; private IRendering m_mesher; private bool Broken; private readonly Point3D[,] m_heightmapPoints = new Point3D[256,256]; private double[,] m_heightmap = new double[256,256]; private ModelVisual3D m_terrain; private readonly Dictionary m_models = new Dictionary(); private readonly Dictionary m_parentPositions = new Dictionary(); private readonly Material m_defaultMaterial; private readonly DiffuseMaterial m_terrainMaterial; public DefaultRenderer(Viewport3D m_viewport) { // Viewport this.m_viewport = m_viewport; m_viewport.ClipToBounds = false; m_viewport.IsHitTestVisible = true; // Camera Issues Point3D CameraPos = new Point3D(0,0,50); Point3D CameraLook = new Point3D(128,128,10); m_camera = new PerspectiveCamera(new Point3D(0, 0, 0), new Vector3D(0, 0, 0), new Vector3D(0, 0, 1), 90); m_camera.Position = CameraPos; m_camera.LookDirection = new Vector3D(CameraLook.X - m_camera.Position.X, CameraLook.Y - m_camera.Position.Y, CameraLook.Z - m_camera.Position.Z); m_camera.FarPlaneDistance = 1024; m_camera.NearPlaneDistance = 0.01; m_viewport.Camera = m_camera; // Setup Trackball m_trackball = new Trackball(m_camera); m_camera.Transform = m_trackball.Transform; m_trackball.EventSource = m_viewport; // Default Material Properties m_defaultMaterial = new DiffuseMaterial( new SolidColorBrush(Colors.DarkKhaki)); GradientBrush terGrad = new RadialGradientBrush(Colors.ForestGreen, Colors.SandyBrown); m_terrainMaterial = new DiffuseMaterial( terGrad); // Scene Lighting ModelVisual3D lights = new ModelVisual3D(); lights.Content = new DirectionalLight(Colors.White, new Vector3D(-20, -30, -10)); ModelVisual3D point = new ModelVisual3D(); PointLight pointLight = new PointLight(Colors.WhiteSmoke, new Point3D(128, 128, 80)); point.Content = pointLight; ModelVisual3D ambient = new ModelVisual3D(); AmbientLight ambientLight = new AmbientLight(Color.FromArgb(0xFF, 0x40, 0x40, 0x40)); ambient.Content = ambientLight; m_viewport.Children.Add(lights); m_viewport.Children.Add(point); m_viewport.Children.Add(ambient); // Terrain Base for(int x=0;x<256;x++) { for(int y=0;y<256;y++) { m_heightmap[x, y] = 30.0; } } m_terrain = CreateTerrain(m_heightmap); m_viewport.Children.Add(m_terrain); // Water Plane SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(128, 0, 128, 255)); DiffuseMaterial material = new DiffuseMaterial(brush); //m_viewport.Children.Add(DefaultUtil.CreateCube(new Point3D(0,0,0), new Point3D(256,256,20), // material)); } public IRendering Mesher { set { m_mesher = value; } } public void AddPrimitive(uint id, Primitive data) { lock(m_parentPositions) { m_parentPositions[id] = data.Position; } if(Broken) return; m_viewport.Dispatcher.Invoke( DispatcherPriority.Normal, new System.Windows.Forms.MethodInvoker (delegate { lock (m_models) { try { if (m_models.ContainsKey(id)) { m_viewport.Children.Remove(m_models[id]); m_models.Remove(id); } lock(m_parentPositions) { if(m_parentPositions.ContainsKey(data.ParentID)) { data.Position += m_parentPositions[data.ParentID]; } } // Add it to the scene appropriately. ModelVisual3D model = CreateModel(data); m_models.Add(id, model); m_viewport.Children.Add(model); } catch (Exception e) { MessageBox.Show(e.ToString()); Broken = true; } } } ) ); } private ModelVisual3D CreateTerrain(double[,] map) { MeshGeometry3D mesh = new MeshGeometry3D(); for (int y = 0; y < 256; y++) { for (int x = 0; x < 256; x++) { m_heightmapPoints[y, x] = new Point3D(x, y, map[x, y]); mesh.Positions.Add(m_heightmapPoints[y, x]); mesh.TextureCoordinates.Add(new Point(x/255.0, y/255.0)); } } for(int x=0;x<255;x++) { for(int y=0;y<255;y++) { int p0 = (x*256) + y; int p1 = (x*256) + (y + 1); int p2 = ((x + 1)*256) + y; int p3 = ((x + 1)*256) + (y + 1); // Δ 013 |\ mesh.TriangleIndices.Add(p1); //#0 mesh.TriangleIndices.Add(p3); //#1 mesh.TriangleIndices.Add(p2); //#3 // Δ 023 mesh.TriangleIndices.Add(p0); //#0 mesh.TriangleIndices.Add(p1); //#2 mesh.TriangleIndices.Add(p2); //#3 } } GeometryModel3D triangleModel = new GeometryModel3D( mesh, m_terrainMaterial); ModelVisual3D model = new ModelVisual3D(); model.Content = triangleModel; return model; } private ModelVisual3D CreateModel(Primitive data) { MeshGeometry3D mesh = new MeshGeometry3D(); SimpleMesh basic = m_mesher.GenerateSimpleMesh(data, DetailLevel.Medium); // Translation TranslateTransform3D tt = new TranslateTransform3D( new Vector3D(data.Position.X, data.Position.Y, data.Position.Z) ); Quaternion rot = new Quaternion(data.Rotation.X, data.Rotation.Y, data.Rotation.Z, data.Rotation.W); RotateTransform3D rt = new RotateTransform3D( new AxisAngleRotation3D(rot.Axis, rot.Angle) ); // Scale ScaleTransform3D st = new ScaleTransform3D( new Vector3D(data.Scale.X, data.Scale.Y, data.Scale.Z)); foreach (Vertex v in basic.Vertices) { Point3D d = new Point3D( v.Position.X, v.Position.Y, v.Position.Z); // Scale d = st.Transform(d); // Rotate d = rt.Transform(d); // Move d = tt.Transform(d); mesh.Positions.Add(d); // These normals dont appear to be working for some reason, // however the auto-generated normals appear adequate for now. // mesh.Normals.Add(new Vector3D(v.Normal.X, v.Normal.Y, v.Normal.Z)); mesh.TextureCoordinates.Add(new Point(v.TexCoord.X, v.TexCoord.Y)); } foreach (ushort ind in basic.Indices) { mesh.TriangleIndices.Add(ind); } GeometryModel3D triangleModel; Color[] colAry = new Color[5]; colAry[0] = Colors.Violet; colAry[1] = Colors.BlueViolet; colAry[2] = Colors.Navy; colAry[3] = Colors.CornflowerBlue; colAry[4] = Colors.PowderBlue; Random x = new Random(); Color col = colAry[x.Next(0, 5)]; triangleModel = new GeometryModel3D( mesh, new DiffuseMaterial(new SolidColorBrush(col))); //*/ /* GradientBrush Grad = new LinearGradientBrush(Colors.Red, Colors.Blue, 90); Material mat = new DiffuseMaterial(Grad); triangleModel = new GeometryModel3D( mesh, mat); */ ModelVisual3D model = new ModelVisual3D(); model.Content = triangleModel; model.Transform = new TranslateTransform3D(0,0,0); return model; } public void RemovePrimitive(uint id) { m_viewport.Dispatcher.Invoke( DispatcherPriority.Normal, new System.Windows.Forms.MethodInvoker (delegate { if(m_models.ContainsKey(id)) { // Remove from scene and models list m_viewport.Children.Remove(m_models[id]); m_models.Remove(id); } } ) ); } public void SetTerrain(int x, int y, double val) { m_heightmap[x, y] = val; } public void SetTerrain(double[,] map) { m_heightmap = map; m_viewport.Dispatcher.Invoke( DispatcherPriority.Normal, new System.Windows.Forms.MethodInvoker (delegate { m_viewport.Children.Remove(m_terrain); m_terrain = CreateTerrain(map); m_viewport.Children.Add(m_terrain); } ) ); } } }