今天主要看了Show Planet Axis、Show Position 、Show Cross Hairs功能,主要是它们在菜单调用方式上都是很类似。代码如下:
显示位置信息
private
void
menuItemShowPosition_Click(
object
sender, System.EventArgs e)
{
World.Settings.ShowPosition
=
!
World.Settings.ShowPosition;
this
.toolBarButtonPosition.Pushed
=
World.Settings.ShowPosition;
this
.menuItemShowPosition.Checked
=
World.Settings.ShowPosition;
this
.worldWindow.Invalidate();
}
//
显示中心十字标
private
void
menuItemShowCrosshairs_Click(
object
sender, System.EventArgs e)
{
//
控制中心十字标显示与否
World.Settings.ShowCrosshairs
=
!
World.Settings.ShowCrosshairs;
this
.menuItemShowCrosshairs.Checked
=
World.Settings.ShowCrosshairs;
this
.worldWindow.Invalidate();
}
从上面的代码看,我们只能惊叹代码封装的很好,同样都调用this.worldWindow.Invalidate();难道Invalidate()函数万能?!请参考我的Invalidate()方法学习(资料收集),原来该方法是界面区域失效,发送了重绘事件,将会调用WorldWindow.cs中重载了的OnPaint()。OnPaint方法里主要是调用了 Render()方法。所以我们的关键是看Render()中如何实现上面三个功能。(其实Render()中实现的功能很多,主要是控制界面绘制方面的,以后还会提到它的)
Render()实现上面三个功能也大量使用了DirectX和Direct 3D方面的知识,请网上搜索学习相关知识或参看我的Direct3D学习(资料收集)。
显示中心十字线功能
Render()中实现代码为
787行 if (World.Settings.ShowCrosshairs)
this.DrawCrossHairs();
实现显示十字标代码
实现显示十字标代码
protected
void
DrawCrossHairs()
{
int
crossHairSize
=
10
;
if
(
this
.crossHairs
==
null
)
{
crossHairs
=
new
Line(m_Device3d);
//
构造线对象
}
Vector2[] vertical
=
new
Vector2[
2
];
Vector2[] horizontal
=
new
Vector2[
2
];
//
Vector2[] test = new Vector2[2];
//
这是我试验添加的,效果请看下面的截图
horizontal[
0
].X
=
this
.Width
/
2
-
crossHairSize;
horizontal[
0
].Y
=
this
.Height
/
2
;
horizontal[
1
].X
=
this
.Width
/
2
+
crossHairSize;
horizontal[
1
].Y
=
this
.Height
/
2
;
vertical[
0
].X
=
this
.Width
/
2
;
vertical[
0
].Y
=
this
.Height
/
2
-
crossHairSize;
vertical[
1
].X
=
this
.Width
/
2
;
vertical[
1
].Y
=
this
.Height
/
2
+
crossHairSize;
//
test[0].X = this.Width / 2;
//
test[0].Y = this.Height / 2 + crossHairSize;
//
test[1].X = this.Width / 2 + crossHairSize;
//
test[1].Y = this.Height / 2;
crossHairs.Begin();
crossHairs.Draw(horizontal, crossHairColor);
crossHairs.Draw(vertical, crossHairColor);
//
crossHairs.Draw(test,Color.Red.ToArgb());
crossHairs.End();
}
上面注销部分(我加了红线)是我试验添加的,效果请看上面的截图。其实就是划几条两点之间的线。
显示位置信息
是在Render()中调用RenderPositionInfo()方法的,请看该段实现代码。
实现显示位置坐标信息
private
const
int
positionAlphaStep
=
20
;
private
int
positionAlpha
=
255
;
private
int
positionAlphaMin
=
40
;
private
int
positionAlphaMax
=
205
;
protected
void
RenderPositionInfo()
{
//
Render some Development information to screen
string
captionText
=
_caption;
captionText
+=
"
\n
"
+
this
.drawArgs.UpperLeftCornerText;
if
(World.Settings.ShowPosition)
{
string
alt
=
null
;
double
agl
=
this
.drawArgs.WorldCamera.AltitudeAboveTerrain;
/*
if(agl>100000)
alt = string.Format("{0:f2}km", agl/1000);
else
alt = string.Format("{0:f0}m", agl);
*/
alt
=
ConvertUnits.GetDisplayString(agl);
string
dist
=
null
;
double
dgl
=
this
.drawArgs.WorldCamera.Distance;
/*
if(dgl>100000)
dist = string.Format("{0:f2}km", dgl/1000);
else
dist = string.Format("{0:f0}m", dgl);
*/
dist
=
ConvertUnits.GetDisplayString(dgl);
//
Heading from 0 - 360
double
heading
=
this
.drawArgs.WorldCamera.Heading.Degrees;
if
(heading
<
0
)
heading
+=
360
;
//
构造显示位置坐标信息字符串
captionText
+=
String.Format(
"
Latitude: {0}\nLongitude: {1}\nHeading: {2:f2}\nTilt: {3}\nAltitude: {4}\nDistance: {5}\nFOV: {6}
"
,
this
.drawArgs.WorldCamera.Latitude,
this
.drawArgs.WorldCamera.Longitude,
heading,
this
.drawArgs.WorldCamera.Tilt,
alt,
dist,
this
.drawArgs.WorldCamera.Fov );
if
(agl
<
300000
)
{
captionText
+=
String.Format(
"
\nTerrain Elevation: {0:n} meters\n
"
,
this
.drawArgs.WorldCamera.TerrainElevation);
}
}
if
(
this
.showDiagnosticInfo)
captionText
+=
"
\nAvailable Texture Memory:
"
+
(m_Device3d.AvailableTextureMemory
/
1024
).ToString(
"
N0
"
)
+
"
kB
"
+
"
\nBoundary Points:
"
+
this
.drawArgs.numBoundaryPointsRendered.ToString()
+
"
/
"
+
this
.drawArgs.numBoundaryPointsTotal.ToString()
+
"
:
"
+
this
.drawArgs.numBoundariesDrawn.ToString()
+
"
\nTiles Drawn:
"
+
(
this
.drawArgs.numberTilesDrawn
*
0.25f
).ToString()
+
"
\n
"
+
this
.drawArgs.WorldCamera
+
"
\nFPS:
"
+
this
.fps.ToString(
"
f1
"
)
+
"
\nRO:
"
+
m_World.RenderableObjects.Count.ToString(
"
f0
"
)
+
"
\nmLat:
"
+
this
.cLat.Degrees.ToString()
+
"
\nmLon:
"
+
this
.cLon.Degrees.ToString()
+
"
\n
"
+
TimeKeeper.CurrentTimeUtc.ToLocalTime().ToLongTimeString();
captionText
=
captionText.Trim();
//
定义要画出文本的样式
DrawTextFormat dtf
=
DrawTextFormat.NoClip
|
DrawTextFormat.WordBreak
|
DrawTextFormat.Right;
int
x
=
7
;
int
y
=
_menuBar
!=
null
&&
World.Settings.ShowToolbar
?
65
:
7
;
//
定义盛放位置文本的矩形框
Rectangle textRect
=
Rectangle.FromLTRB(x,y,
this
.Width
-
8
,
this
.Height
-
8
);
//
我添加的测试用代码
Rectangle testRect
=
Rectangle.FromLTRB(x, y,
this
.Width,
this
.Height);
//
Hide position info when toolbar is open
if
(_menuBar.IsActive)
//
如果上面的_menuBar处于活动状态,则更改位置文本的Alpha值
{
positionAlpha
-=
positionAlphaStep;
if
(positionAlpha
<
positionAlphaMin)
{
positionAlpha
=
positionAlphaMin;
}
}
else
{
positionAlpha
+=
positionAlphaStep;
if
(positionAlpha
>
positionAlphaMax)
positionAlpha
=
positionAlphaMax;
}
int
positionBackColor
=
positionAlpha
<<
24
;
int
positionForeColor
=
(
int
)((
uint
)(positionAlpha
<<
24
)
+
0xffffffu
);
使用Font对象defaultDrawingFont的DrawText()实现绘制位置信息
this
.drawArgs.defaultDrawingFont.DrawText(
null
, captionText, textRect, dtf, positionBackColor);
textRect.Offset(
-
1
,
-
1
);
this
.drawArgs.defaultDrawingFont.DrawText(
null
, captionText, textRect, dtf, positionForeColor);
//
下面这行是我添加的,测试用
this
.drawArgs.defaultDrawingFont.DrawText(
null
,
"
无痕客在研究WorldWind应用!
"
, textRect, dtf,Color.Red.ToArgb());
}
上面需要注意的知识点就是:使用Font对象(实例:defaultDrawingFont)的DrawText()实现绘制文本信息。
地球轴线绘制
WorldWindow.cs的Render()方法中调用了World.cs中Render()方法,该方法又调用了DrawAxis()
方
法实现地球轴线绘制。
453行 if (Settings.showPlanetAxis)
this.DrawAxis(drawArgs);
画地球轴线
private
void
DrawAxis(DrawArgs drawArgs)
{
CustomVertex.PositionColored[] axis
=
new
CustomVertex.PositionColored[
2
];
Vector3 topV
=
MathEngine.SphericalToCartesian(
90
,
0
,
this
.EquatorialRadius
+
0.15f
*
this
.EquatorialRadius);
axis[
0
].X
=
topV.X;
axis[
0
].Y
=
topV.Y;
axis[
0
].Z
=
topV.Z;
axis[
0
].Color
=
System.Drawing.Color.Pink.ToArgb();
Vector3 botV
=
MathEngine.SphericalToCartesian(
-
90
,
0
,
this
.EquatorialRadius
+
0.15f
*
this
.EquatorialRadius);
axis[
1
].X
=
botV.X;
axis[
1
].Y
=
botV.Y;
axis[
1
].Z
=
botV.Z;
axis[
1
].Color
=
System.Drawing.Color.Pink.ToArgb();
drawArgs.device.VertexFormat
=
CustomVertex.PositionColored.Format;
drawArgs.device.TextureState[
0
].ColorOperation
=
TextureOperation.Disable;
drawArgs.device.Transform.World
=
Matrix.Translation(
(
float
)
-
drawArgs.WorldCamera.ReferenceCenter.X,
(
float
)
-
drawArgs.WorldCamera.ReferenceCenter.Y,
(
float
)
-
drawArgs.WorldCamera.ReferenceCenter.Z
);
drawArgs.device.DrawUserPrimitives(PrimitiveType.LineStrip,
1
, axis);
drawArgs.device.Transform.World
=
drawArgs.WorldCamera.WorldMatrix;
}
其他部分:
WorldWind学习系列三:简单功能分析——主窗体的键盘监听处理及拷贝和粘贴位置坐标功能
WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析
WorldWind学习系列二:擒贼先擒王篇2
WorldWind学习系列二:擒贼先擒王篇1
WorldWind学习系列一:顺利起航篇