WW目前的服务器似乎都连不上了,不知道Java版的是不是可以!
WW实现了旗帜标注,鼠标移动到旗帜的位置,旗帜会高亮显示。点击,探出对话框显示标注的信息。
1.WavingFlagLayer对象
public class WavingFlagLayer : RenderableObject
WavingFlagLayer继承自RenderableObject,定义了三个事件如下:
1 public event System.EventHandler OnMouseEnterEvent;
2 public event System.EventHandler OnMouseLeaveEvent;
3 public event System.Windows.Forms.MouseEventHandler OnMouseUpEvent;
string highlightTexturePath = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\Data\\ring.dds";
//高亮显示采用的图片路径
该对象重点查看PerformSelectionAction(DrawArgs drawArgs)方法,重载了RenderableObject的PerformSelectionAction方法。
1 public override bool PerformSelectionAction(DrawArgs drawArgs) 2 { 3 Vector3 surfacePos = MathEngine.SphericalToCartesian(m_latitude, m_longitude, World.EquatorialRadius); 4 Vector3 rc = new Vector3( 5 (float)drawArgs.WorldCamera.ReferenceCenter.X, 6 (float)drawArgs.WorldCamera.ReferenceCenter.Y, 7 (float)drawArgs.WorldCamera.ReferenceCenter.Z 8 ); 9 Vector3 projectedPoint = drawArgs.WorldCamera.Project(surfacePos - rc); 10 int mouseBuffer = 15; 11 if (projectedPoint.X > DrawArgs.LastMousePosition.X - mouseBuffer && 12 projectedPoint.X < DrawArgs.LastMousePosition.X + mouseBuffer && 13 projectedPoint.Y > DrawArgs.LastMousePosition.Y - mouseBuffer && 14 projectedPoint.Y < DrawArgs.LastMousePosition.Y + mouseBuffer)//通过包围盒判断是否选中,转换到屏幕坐标来判断 15 { 16 if (OnMouseUpEvent != null)//如果委托链不为空,执行事件委托链中的方法 17 { 18 OnMouseUpEvent(this, new System.Windows.Forms.MouseEventArgs(System.Windows.Forms.MouseButtons.Left, 1, DrawArgs.LastMousePosition.X, DrawArgs.LastMousePosition.Y, 0)); 19 } 20 return true; 21 } 22 return false; 23 }
2.WavingFlags是一个插件对象。
public class WavingFlags : WorldWind.PluginEngine.Plugin
WavingFlags的Load方法从文件中读取WavingFlagLayer信息,加载。绑定事件关联的方法。
1 /// <summary> 2 /// Plugin entry point - All plugins must implement this function 3 /// </summary> 4 public override void Load() 5 { 6 FileInfo savedFile = new FileInfo(SavedFilePath); 7 if (!savedFile.Exists) 8 { 9 if (!savedFile.Directory.Exists) 10 savedFile.Directory.Create(); 11 12 try 13 { 14 WorldWind.Net.WebDownload download = new WorldWind.Net.WebDownload(DataFileUri); 15 download.DownloadFile(savedFile.FullName); 16 download.Dispose(); 17 } 18 catch { } 19 } 20 21 m_wavingFlagsList = new RenderableObjectList("Waving Flags"); 22 m_wavingFlagsList.IsOn = false; 23 System.Collections.Hashtable countryHash = new System.Collections.Hashtable(); 24 25 using (StreamReader reader = savedFile.OpenText()) 26 { 27 string header = reader.ReadLine(); 28 string[] headers = header.Split('\t'); 29 30 string line = reader.ReadLine(); 31 while (line != null) 32 { 33 System.Collections.Hashtable fieldHash = new System.Collections.Hashtable(); 34 string[] lineParts = line.Split('\t'); 35 36 //Log.Write(string.Format("{0}\t{1}", lineParts[0], lineParts[1])); 37 try 38 { 39 double latitude = double.Parse(lineParts[3], System.Globalization.CultureInfo.InvariantCulture); 40 double longitude = double.Parse(lineParts[4], System.Globalization.CultureInfo.InvariantCulture); 41 42 if (lineParts[1].Length == 2) 43 { 44 string flagFileUri = FlagTextureDirectoryUri + "/" + lineParts[1] + FlagSuffix; 45 FileInfo savedFlagFile = new FileInfo(SavedFlagsDirectory + "\\" + lineParts[1] + ".dds"); 46 47 WavingFlagLayer flag = new WavingFlagLayer( 48 lineParts[0], 49 ParentApplication.WorldWindow.CurrentWorld, 50 latitude, 51 longitude, 52 flagFileUri); 53 54 flag.SavedImagePath = savedFlagFile.FullName; 55 flag.ScaleX = 100000; 56 flag.ScaleY = 100000; 57 flag.ScaleZ = 100000; 58 flag.Bar3D = new Bar3D(flag.Name, flag.World, latitude, longitude, 0, flag.ScaleZ, System.Drawing.Color.Red); 59 flag.Bar3D.ScaleX = 0.3f * flag.ScaleX; 60 flag.Bar3D.ScaleY = 0.3f * flag.ScaleY; 61 flag.Bar3D.IsOn = false; 62 flag.RenderPriority = RenderPriority.Custom; 63 64 flag.OnMouseEnterEvent += new EventHandler(flag_OnMouseEnterEvent); 65 flag.OnMouseLeaveEvent += new EventHandler(flag_OnMouseLeaveEvent); 66 flag.OnMouseUpEvent += new System.Windows.Forms.MouseEventHandler(flag_OnMouseUpEvent); 67 m_wavingFlagsList.Add(flag); 68 69 for (int i = 0; i < lineParts.Length; i++) 70 { 71 try 72 { 73 double value = double.Parse(lineParts[i], System.Globalization.CultureInfo.InvariantCulture); 74 fieldHash.Add(headers[i], value); 75 } 76 catch 77 { 78 fieldHash.Add(headers[i], lineParts[i]); 79 } 80 } 81 countryHash.Add(lineParts[0], fieldHash); 82 } 83 else 84 { 85 //Log.Write(Log.Levels.Debug, "blank: " + lineParts[0]); 86 } 87 } 88 catch(Exception ex) 89 { 90 Log.Write(Log.Levels.Warning, string.Format("Exception: {0} - {1}", lineParts[0], ex.ToString())); 91 } 92 93 line = reader.ReadLine(); 94 } 95 Headers = headers; 96 } 97 98 CountryHash = countryHash; 99 100 InitializeCiaForm(); 101 102 ParentApplication.WorldWindow.CurrentWorld.RenderableObjects.Add(m_wavingFlagsList); 103 }
WavingFlagLayer事件关联的方法。
1 void flag_OnMouseUpEvent(object sender, System.Windows.Forms.MouseEventArgs e) 2 { 3 if (DrawArgs.NewRootWidget.OnMouseMove(e) || DrawArgs.RootWidget.OnMouseMove(e)) 4 return; 5 6 m_ciaForm.Visible = true; 7 } 8 9 void flag_OnMouseLeaveEvent(object sender, EventArgs e) 10 { 11 WavingFlagLayer wavingFlag = (WavingFlagLayer)sender; 12 wavingFlag.ShowHighlight = false; 13 14 } 15 16 void flag_OnMouseEnterEvent(object sender, EventArgs e) 17 { 18 System.Windows.Forms.MouseEventArgs mea = new System.Windows.Forms.MouseEventArgs( 19 System.Windows.Forms.MouseButtons.None, 20 0, 21 DrawArgs.LastMousePosition.X, 22 DrawArgs.LastMousePosition.Y, 23 0); 24 25 // hack check to make sure that a widget isn't in the way 26 if (DrawArgs.NewRootWidget.OnMouseMove(mea) || DrawArgs.RootWidget.OnMouseMove(mea)) 27 return; 28 29 WavingFlagLayer flag = (WavingFlagLayer)sender; 30 if (m_wavingFlagsList.IsOn && flag.Initialized && flag.IsOn) 31 { 32 ChangeForm(flag.Name, m_currentCategoryIndex); 33 //m_ciaForm.Visible = true; 34 } 35 36 for (int i = 0; i < m_wavingFlagsList.ChildObjects.Count; i++) 37 { 38 if (m_wavingFlagsList.ChildObjects[i] is WavingFlagLayer) 39 { 40 WavingFlagLayer wavingFlag = (WavingFlagLayer)m_wavingFlagsList.ChildObjects[i]; 41 if (wavingFlag.Name != flag.Name) 42 wavingFlag.ShowHighlight = false; 43 else 44 wavingFlag.ShowHighlight = true; 45 } 46 } 47 }
该对象用到了Shader编程的知识,Effect类,需要具体查看。
1 private void RenderFlag(DrawArgs drawArgs, double offset) 2 { 3 if (m_effect == null) 4 { 5 string outerrors = ""; 6 System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); 7 Stream effectStream = assembly.GetManifestResourceStream("WorldWind.Shaders.flag.fx"); 8 m_effect = 9 Effect.FromStream( 10 drawArgs.device, 11 effectStream, 12 null, 13 null, 14 ShaderFlags.None, 15 null, 16 out outerrors); 17 if (outerrors != null && outerrors.Length > 0) 18 Log.Write(Log.Levels.Error, outerrors); 19 } 20 if (m_vertexBuffer == null) 21 { 22 drawArgs.device.DeviceReset += new EventHandler(device_DeviceReset); 23 device_DeviceReset(drawArgs.device, null); 24 } 25 if (m_flagPoleVertices == null) 26 { 27 CreateFlagPole(drawArgs.device); 28 } 29 Vector3 pos = 30 MathEngine.SphericalToCartesian(m_latitude, m_longitude, World.EquatorialRadius + World.Settings.VerticalExaggeration * ScaleZ + offset); 31 Vector3 surfacePos = MathEngine.SphericalToCartesian(m_latitude, m_longitude, World.EquatorialRadius + offset); 32 Vector3 rc = new Vector3( 33 (float)drawArgs.WorldCamera.ReferenceCenter.X, 34 (float)drawArgs.WorldCamera.ReferenceCenter.Y, 35 (float)drawArgs.WorldCamera.ReferenceCenter.Z 36 ); 37 drawArgs.device.Transform.World = Matrix.Scaling(World.Settings.VerticalExaggeration * ScaleX * 0.01f, World.Settings.VerticalExaggeration * ScaleY * 0.01f, -World.Settings.VerticalExaggeration * 2 * ScaleZ); 38 drawArgs.device.Transform.World *= Matrix.RotationY((float)-MathEngine.DegreesToRadians(90)); 39 drawArgs.device.Transform.World *= Matrix.RotationY((float)-MathEngine.DegreesToRadians(m_latitude)); 40 drawArgs.device.Transform.World *= Matrix.RotationZ((float)MathEngine.DegreesToRadians(m_longitude)); 41 drawArgs.device.Transform.World *= Matrix.Translation(surfacePos - rc); 42 drawArgs.device.VertexFormat = CustomVertex.PositionColored.Format; 43 drawArgs.device.TextureState[0].ColorOperation = TextureOperation.SelectArg1; 44 drawArgs.device.TextureState[0].ColorArgument1 = TextureArgument.Diffuse; 45 drawArgs.device.TextureState[0].AlphaArgument1 = TextureArgument.Diffuse; 46 drawArgs.device.TextureState[0].AlphaOperation = TextureOperation.SelectArg1; 47 drawArgs.device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, m_flagPoleVertices.Length, m_flagPoleIndices.Length / 3, m_flagPoleIndices, true, m_flagPoleVertices); 48 drawArgs.device.DrawIndexedUserPrimitives(PrimitiveType.LineList, 0, m_outlineFlagPoleVertices.Length, m_outlineFlagPoleIndices.Length / 2, m_outlineFlagPoleIndices, true, m_outlineFlagPoleVertices); 49 m_angle += .04f; 50 if (m_angle > 360) 51 m_angle = 0; 52 drawArgs.device.VertexFormat = CustomVertex.PositionNormalTextured.Format; 53 drawArgs.device.Transform.World = Matrix.Scaling(World.Settings.VerticalExaggeration * ScaleX, World.Settings.VerticalExaggeration * ScaleY, World.Settings.VerticalExaggeration * ScaleZ); 54 drawArgs.device.Transform.World *= Matrix.RotationY((float)-MathEngine.DegreesToRadians(m_latitude)); 55 drawArgs.device.Transform.World *= Matrix.RotationZ((float)MathEngine.DegreesToRadians(m_longitude)); 56 drawArgs.device.Transform.World *= Matrix.Translation(pos - rc); 57 58 Matrix worldViewProj = drawArgs.device.Transform.World * drawArgs.device.Transform.View * drawArgs.device.Transform.Projection; 59 System.DateTime currentTime = TimeKeeper.CurrentTimeUtc; 60 Point3d sunPosition = SunCalculator.GetGeocentricPosition(currentTime); 61 Vector3 sunVector = new Vector3( 62 (float)-sunPosition.X, 63 (float)-sunPosition.Y, 64 (float)-sunPosition.Z); 65 m_effect.Technique = "VertexAndPixelShader"; 66 m_effect.SetValue("angle", (float)m_angle); 67 m_effect.SetValue("attentuation", Attentuation); 68 m_effect.SetValue("World", drawArgs.device.Transform.World); 69 m_effect.SetValue("View", drawArgs.device.Transform.View); 70 m_effect.SetValue("Projection", drawArgs.device.Transform.Projection); 71 m_effect.SetValue("Tex0", m_texture); 72 m_effect.SetValue("lightDir", new Vector4(sunVector.X, sunVector.Y, sunVector.Z, 0)); 73 drawArgs.device.Indices = m_indexBuffer; 74 drawArgs.device.SetStreamSource(0, m_vertexBuffer, 0); 75 int numPasses = m_effect.Begin(0); 76 for (int i = 0; i < numPasses; i++) 77 { 78 m_effect.BeginPass(i); 79 drawArgs.device.DrawIndexedPrimitives( 80 PrimitiveType.TriangleList, 81 0, 82 0, 83 m_vertices.Length, 84 0, 85 m_indices.Length / 3); 86 m_effect.EndPass(); 87 } 88 m_effect.End(); 89 drawArgs.device.Indices = null; 90 drawArgs.device.Transform.World = drawArgs.WorldCamera.WorldMatrix; 91 drawArgs.device.Transform.View = drawArgs.WorldCamera.ViewMatrix; 92 }