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; using System.IO; using System.Windows.Media.Imaging; using OpenMetaverse.Imaging; using Material = System.Windows.Media.Media3D.Material; namespace Xenki.DefaultRenderer { class DefaultRenderer : IRenderer { private readonly Viewport3D m_viewport; private readonly PerspectiveCamera m_camera; private CameraControl m_cameracontrol; private IRendering m_mesher; private DefaultTexture m_textureManager; private DefaultDataControl m_primitiveData; //public ITextureManage TextureManager //{ // set { m_textureManager = value; } //} 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 DiffuseMaterial m_terrainMaterial; private string textureImageFolderPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "texture"); private GridClient m_gridclient; private GridClient gridClient; public GridClient Gridclient { get { return gridClient; } set { gridClient = value; m_textureManager = DefaultTexture.SingleTextureManager(); m_textureManager.GridClient = Gridclient; m_textureManager.OnDownloadFinished = OnTextureDownloaded; m_textureManager.StartDownload(); } } public DefaultRenderer(Viewport3D m_viewport) { // Viewport this.m_viewport = m_viewport; // m_viewport.ClipToBounds = false; m_viewport.IsHitTestVisible = true; //setup data store control m_primitiveData = DefaultDataControl.SingleSceneDataManager(); // 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 Camera Control m_cameracontrol = new CameraControl(m_camera,m_primitiveData); m_cameracontrol.EventSource = m_viewport; 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] = 10.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; } } void OnTextureDownloaded(UUID downLoadedTextureID, bool success) { if (success) { UpdatePrimTexture(downLoadedTextureID); } } public void AddPrimitive(uint id, Primitive data) { if(Broken) return; m_viewport.Dispatcher.Invoke( DispatcherPriority.Normal, new System.Windows.Forms.MethodInvoker (delegate { // lock (m_primitiveData.PrimModelsInScene) { try { bool WaitParentIn = true; if (data.ParentID == 0) { //m_primitiveData.AddModelsParentPositions(id, data.Position); // test = true; WaitParentIn = false; } else { if (m_primitiveData.PrimModelsInScene.ContainsKey(data.ParentID)) WaitParentIn = false; /* Vector3 vec = m_primitiveData.GetModelsParentPosition(data.ParentID); if (vec != new Vector3()) { if (test) { OpenMetaverse.Quaternion qqq = m_primitiveData.GetParentRotation(data.ParentID); data.Position *= qqq; } test = false; data.Position += vec; //data.Position *= m_primitiveData.PrimModelsInScene[data.ParentID].Rotation ; m_primitiveData.AddModelsParentPositions(id, data.Position); WaitParentIn = false; } */ } if (WaitParentIn == false) { if (m_primitiveData.SceneContainVisual(data.LocalID)) { m_viewport.Children.Remove(m_primitiveData.GetVisualInScene(data.LocalID)); m_primitiveData.RemoveVisualInScene(data.LocalID); } ModelVisual3D model = CreateModel(data); m_primitiveData.AddNewPrimitive(data.LocalID, model, data.ParentID); m_primitiveData.AddNewPrimitivePrimData(data); m_primitiveData.RemoveWaitingParentPrimitive(data.LocalID); m_viewport.Children.Add(model); List waiting = m_primitiveData.GetModelsWaitingParent(data.LocalID); foreach (Primitive child in waiting) { //Vector3 vec = m_primitiveData.GetModelsParentPosition(data.ParentID); //if (vec != new Vector3()) //{ // OpenMetaverse.Quaternion qqq = m_primitiveData.GetParentRotation(child.ParentID); // child.Position *= qqq; // child.Position += data.Position; // //data.Position *= m_primitiveData.PrimModelsInScene[data.ParentID].Rotation ; // m_primitiveData.AddModelsParentPositions(child.LocalID, child.Position); //} //ModelVisual3D childmodel = CreateModel(child); //m_viewport.Children.Add(childmodel); //m_primitiveData.AddNewPrimitive(child.LocalID, childmodel, child.ParentID); //m_primitiveData.AddNewPrimitivePrimData(child); //m_primitiveData.RemoveWaitingParentPrimitive(child.LocalID); AddPrimitive(child.LocalID, child); } waiting.Clear(); waiting = null; model = null; } else m_primitiveData.AddWaitingParentPrimitive(id, data); } 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) { SimpleMesh basic = m_mesher.GenerateSimpleMesh(data, DetailLevel.Medium); MeshGeometry3D mesh = new MeshGeometry3D(); GeometryModel3D triangleModel = new GeometryModel3D(); lock(m_primitiveData.PrimModelsInScene) if (m_primitiveData.PrimModelsInScene.ContainsKey(data.ParentID)) { //OpenMetaverse.Quaternion rotate = m_primitiveData.GetParentPosition(data.ParentID); //if (m_primitiveData.PrimModelsInScene.ContainsKey(m_primitiveData.PrimModelsInScene[data.ParentID].ParentID)) // data.Position *= m_primitiveData.PrimModelsInScene[m_primitiveData.PrimModelsInScene[data.ParentID].ParentID].Rotation; //else //data.Position *= m_primitiveData.PrimModelsInScene[data.ParentID].Rotation; data.Position += m_primitiveData.PrimModelsInScene[data.ParentID].Position; } // 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. //Vector3D normal = new Vector3D(v.Normal.X, v.Normal.Y, v.Normal.Z); //mesh.Normals.Add(normal); double x = (v.Position.Length() == float.Parse("0")) ? 0 : (v.Position.X / v.Position.Length()); double y = (v.Position.Length() == float.Parse("0")) ? 0 : (v.Position.Y / v.Position.Length()); mesh.TextureCoordinates.Add(new Point(x, y)); } foreach (ushort ind in basic.Indices) { mesh.TriangleIndices.Add(ind); } triangleModel = PatchTexture(data, mesh, triangleModel); ModelVisual3D model = new ModelVisual3D(); model.Content = triangleModel; return model; } private GeometryModel3D PatchTexture(Primitive data, MeshGeometry3D mesh, GeometryModel3D triangleModel) { Color col = Colors.YellowGreen; if (data.Textures != null && data.Textures.DefaultTexture != null && data.Textures.DefaultTexture.TextureID != null) { Material m = m_primitiveData.GetMaterialFromCache(data.Textures.DefaultTexture.TextureID); if (m != null) { triangleModel = new GeometryModel3D(mesh, m); // m_primitiveData.RemoveUnAttachedTexture(data.LocalID); } else { //ImageDownload image = m_textureManager.RetireveTextureData(data.Textures.DefaultTexture.TextureID); // if (OpenJPEG.DecodeToImage(image.AssetData, out managedimg, out img)) //{ // System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(img); // ImageSourceConverter converter = new ImageSourceConverter(); // ImageSource imagesource = (BitmapImage) converter.ConvertFrom(bitmap); // ImageBrush brush = new ImageBrush(imagesource); // m = new DiffuseMaterial(brush); // triangleModel = new GeometryModel3D( // mesh, m); // // // m_primitiveData.RemoveUnAttachedTexture(data.LocalID); // if (m != null) // m_primitiveData.AddNewMaterial2Cache(data.Textures.DefaultTexture.TextureID, m); //} string bitmapPath = System.IO.Path.Combine(textureImageFolderPath, data.Textures.DefaultTexture.TextureID.ToString() + ".jpg"); if (File.Exists(bitmapPath)) { ImageSource imagesource = new BitmapImage(new Uri(bitmapPath)); ImageBrush brush = new ImageBrush(imagesource); m = new DiffuseMaterial(brush); triangleModel = new GeometryModel3D(mesh, m); // m_primitiveData.RemoveUnAttachedTexture(data.LocalID); if (m != null) m_primitiveData.AddNewMaterial2Cache(data.Textures.DefaultTexture.TextureID, m); imagesource = null; brush = null; m = null; } else { col = Color.FromScRgb(data.Textures.DefaultTexture.RGBA.A, data.Textures.DefaultTexture.RGBA.R, data.Textures.DefaultTexture.RGBA.G, data.Textures.DefaultTexture.RGBA.B); triangleModel = new GeometryModel3D( mesh, new DiffuseMaterial(new SolidColorBrush(col))); m_primitiveData.AddUnAttachedTexture(data.LocalID, data.Textures.DefaultTexture.TextureID); } } } else { col = Color.FromScRgb(data.Textures.DefaultTexture.RGBA.A, data.Textures.DefaultTexture.RGBA.R, data.Textures.DefaultTexture.RGBA.G, data.Textures.DefaultTexture.RGBA.B); triangleModel = new GeometryModel3D( mesh, new DiffuseMaterial(new SolidColorBrush(col))); //ADD the visual to the needUpdateTexute list.when the texture downloaded update it. m_primitiveData.AddUnAttachedTexture(data.LocalID, data.Textures.DefaultTexture.TextureID); } return triangleModel; } //private void SaveTexture2Image(ImageDownload image) //{ // ManagedImage managedimg; // Image img; // //byte[] bytes = GetTextureDataByTextureID(downLoadedTextureID); // if (OpenJPEG.DecodeToImage(image.AssetData, out managedimg, out img)) // { // Bitmap bitmap = new Bitmap(img); // ImageSource source = new BitmapMetadataBlob( // bitmap.Save(Path.Combine(bmpFilePath, image.ID.ToString() + ".jpg"), System.Drawing.Imaging.ImageFormat.Jpeg); // bitmap.Dispose(); // bitmap = null; // } // img.Dispose(); // img = null; // managedimg = null; //} ModelVisual3D CreateModelFromFaced(Primitive data) { FacetedMesh faceMesh = m_mesher.GenerateFacetedMesh(data, DetailLevel.Medium); lock (m_primitiveData.PrimModelsInScene) if (m_primitiveData.PrimModelsInScene.ContainsKey(data.ParentID)) { //OpenMetaverse.Quaternion rotate = m_primitiveData.GetParentPosition(data.ParentID); //if (m_primitiveData.PrimModelsInScene.ContainsKey(m_primitiveData.PrimModelsInScene[data.ParentID].ParentID)) // data.Position *= m_primitiveData.PrimModelsInScene[m_primitiveData.PrimModelsInScene[data.ParentID].ParentID].Rotation; //else //data.Position *= rotate;// m_primitiveData.PrimModelsInScene[data.ParentID].Rotation; data.Position += m_primitiveData.PrimModelsInScene[data.ParentID].Position; } // 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)); ModelVisual3D model = new ModelVisual3D(); GeometryModel3D triangleModel = new GeometryModel3D(); MeshGeometry3D mesh; ImageSource imagesource; ImageBrush brush; ModelVisual3D visual; // Draw the prim faces for (int j = 0; j < faceMesh.Faces.Count; j++) { mesh = new MeshGeometry3D(); Face face = faceMesh.Faces[j]; foreach (Vertex v in face.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)); double x = (v.Position.Length() == float.Parse("0")) ? 0 : (v.Position.X / v.Position.Length()); double y = (v.Position.Length() == float.Parse("0")) ? 0 : (v.Position.Y / v.Position.Length()); //mesh.TextureCoordinates.Add(new Point( x,y)); } //mesh.TextureCoordinates.Add(new Point(0, 0)); //mesh.TextureCoordinates.Add(new Point(1, 0)); //mesh.TextureCoordinates.Add(new Point(0, 1)); //mesh.TextureCoordinates.Add(new Point(1, 1)); foreach (ushort ind in face.Indices) { mesh.TriangleIndices.Add(ind); } Color col = Colors.YellowGreen; if (face.TextureFace.TextureID != null) { visual = new ModelVisual3D(); Material m = m_primitiveData.GetMaterialFromCache(data.Textures.DefaultTexture.TextureID); if (m != null) { triangleModel = new GeometryModel3D(mesh, m); // m_primitiveData.RemoveUnAttachedTexture(data.LocalID); } else { string bitmapPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "texture\\" + face.TextureFace.TextureID.ToString() + ".jpg"); if (File.Exists(bitmapPath) == false) { //ADD the visual to the needUpdateTexute list.when the texture downloaded update it. m_primitiveData.AddUnAttachedTexture(data.LocalID, face.TextureFace.TextureID); col = Color.FromScRgb(face.TextureFace.RGBA.A, face.TextureFace.RGBA.R, face.TextureFace.RGBA.G, face.TextureFace.RGBA.B); triangleModel = new GeometryModel3D( mesh, new DiffuseMaterial(new SolidColorBrush(col))); visual.Content = triangleModel; model.Children.Add(visual); continue; } imagesource = new BitmapImage(new Uri(bitmapPath)); brush = new ImageBrush(imagesource); m = new DiffuseMaterial(brush); triangleModel = new GeometryModel3D( mesh, m); // m_primitiveData.RemoveUnAttachedTexture(data.LocalID); if (m != null) m_primitiveData.AddNewMaterial2Cache(data.Textures.DefaultTexture.TextureID, m); } visual.Content = triangleModel; model.Children.Add(visual); } } return model; } //Dictionary m_materials = new Dictionary(); public void UpdatePrimTexture(UUID textureID) { List NeedUpdateVisuals = m_primitiveData.GetVisualByTextureID(textureID); foreach (Primitive visual in NeedUpdateVisuals) { //m_primitiveData.RemoveUnAttachedTexture(visual.LocalID); RemovePrimitive(visual.LocalID); AddPrimitive(visual.LocalID, visual); } NeedUpdateVisuals.Clear(); NeedUpdateVisuals = null; } public void RemovePrimitive(uint id) { m_viewport.Dispatcher.Invoke( DispatcherPriority.Normal, new System.Windows.Forms.MethodInvoker (delegate { { // Remove from scene and models list m_viewport.Children.Remove(m_primitiveData.GetVisualInScene(id)); m_primitiveData.RemoveVisualInScene(id); m_primitiveData.RemovePrimtivePrimData(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); } ) ); } } }