📄 default.htm
字号:
at all. with the mesh, i could render the earth as a white sphere in the view. the
next step was to apply the texture. i started out just trying to load the same texture
that WW does, but got a -2147024809 Exception : Value does not fall within the expected
range. my 1st assumption was the texture was just too large, so i use the D3D Texture
tool to resize it to 512x1024 ... but that failed too. so then i just converted
it to a BMP, and that was able to load. it also loaded in JPG/PNG/GIF formats, but
not TIF. i'm not sure why it did not load as DDS, because i can get some other DDS
textures to load? granted, i have other DDS files that wont load either ... but
i didnt want time to waste too much time investigating this. so now the app starts
up and initializes the earth meth and texture. then the render method just sets
the texture and draws the mesh. which as far as i'm concerned is the coolest 'hello
world' application ever.
</p>
<p>
<img src="images/mesh.jpg" />
<img src="images/earth.jpg" /></p>
<ul>
<li>single sphere mesh wireframe with no texture</li>
<li>single texture applied to the mesh. one of the coolest 'hello world' moments i've
ever had</li>
</ul>
<h3>
On the 3rd day, "let the user have controls"
</h3>
<p>
now that i had a simple earth rendering, i wanted to nail down the user controls.
this was challenging, because its sometimes hard to even control WW on the desktop.
the 1st decision was how much i wanted to use the stylus. the outcome was to downplay
the stylus in favor of the directional keypad, so that i could ultimately port this
over to a Smartphone as well. this also dictated that it would only use 2 hardware
keys. made the left hardware key handle changing what mode the directionaly keypad
was in, and the right key handle the options menu. the option menu maps almost exactly
to the menu provided by WW. the directional keypad is the tricky part. it has 3
modes : Spin World, Zoom/Rotate World, and Tilt Camera. it starts out in Spin World
mode, so the direction keypad is used to spin the world up/down/left/right. if you
hit the left hardware key, then it switches to Zoom/Rotate mode. Zoom uses the up/down
direction to zoom in/out respectively. Rotate is done with the left/right directions.
the 3rd mode is Tilt camera. this angles the camera up/down/left/right accordingly.
wanted to get this feature in but it wont really make it cool until there is terrain
(which doesnt happen in this version). those controls are handled just by changing
the 3 views : world, view, and projection. the world view never changes and is always
Matrix.Identity. the view is where most of the work happens. spinning the world
is handled by changing the position of the camera and always having it point to
the origin. zoom is also handled by the cameras position. camera tilt and rotation
is handled by applying Matrix.RotationYawPitchRoll. projection just sets up the
frustum for what should be rendered. to help with these calculations i copied both
the MathEngine and Angle classes directly from WW. these ended up being the only
classes that i copied directly. the only changes that had to be made were commenting
out the use of the DirectX Plane class, because MD3DM does not provide an implementation.
i really wish that it would have provided a Plane class, because then i could have
ported over WW's class for doing frustum culling (ViewFrustum.cs?). that left 2
other hardware keys, 1 to switch to Landscape mode, and the other 2 open the Pocket
Calendar. first, i had to disable the switch to Landscape mode because MD3DM does
not support it. so now it just captures that change and suppresses it. i disabled
the Calendar hardware button because /cfWW is very memory intensive. the menus still
work as expected, the only problem i get is that they are not rendering initially.
i have to tap them with the stylus or press one of their hardware buttons to get
the proper menu name to display. dont know if this is a bug in my program, the version
of the OS, or the version of the runtime? the last control was to add the stylus.
all i did was grab the method from WW and this allowed you to tap a position on
the earth, and get the view to center on that spot. finally, i added a class to
render the positional info (lat, lon, alt) as text, as well as the crosshairs. the
cross hairs was trickier than expected because MD3DM does not provide a Line class.
my 1st try was to try and do it the GDI+ way. just grab the Graphics of the form
and call DrawLine() on it. this sort of worked in that the lines were drawn, but
the crosshairs flickered. so the moral of the story is, dont mix MD3DM and GDI+.
the MD3DM way to do this involved initializing VertexBuffers, and then just rendering
those. this is what WW does, but they do it a little lazier by just creating the
Vertices and calling DrawUserPrimitives. i could not do this because DrawUserPrimitives
is not supported by MD3DM. the other problem i had was getting them to render the
correct color. even though i was using PositionColored vertices with a specific
color, i could not get the correct color to render without changing the color on
the device first. my guess this is due to a bug in my code ... but i dont know DirectX
well enough to see it. so now the user can change their view of earth.
</p>
<p>
<img src="images/control.jpg" />
<img src="images/keys.jpg" border="1" /></p>
<ul>
<li>shows the earth rotated, zoomed, spun, and the camera tilted</li>
<li>form that explains the directional pad controls</li>
</ul>
<p>
<img src="images/fileMenu.jpg" />
<img src="images/viewMenu.jpg" />
</p>
<ul>
<li>file menu</li>
<li>view menu</li>
</ul>
<p>
<img src="images/diagMenu.jpg" />
<img src="images/helpMenu.jpg" /></p>
<ul>
<li>diagnostic menu</li>
<li>help menu</li>
</ul>
<h3>
On the 4th day, "let there be tiles"
</h3>
<p>
now that you could zoom in, you would quickly find out that the texture gets pixelated.
WW handles this by having 4 levels of the BlueMarbleTexture, and applying those
to tiles of the earth. so instead of having 1 single sphere mesh of the earch, the
mesh is broken up into multiple tiles. then each tile has a texture applied to it.
as you zoom in, the tile sizes become more granular and the textures are of a higher
resolution. the first step was to rip out the code for creating tile meshes. i got
this working on a desktop application first, and had it save those mesh tiles to
.md3dm files. this was done to save calculations on the device. then i created a
set of tile images that i could test with. these images were just all white and
had text on them that specified what row/column they represented. let me back up
here. the BlueMarbleTexture tiles are broken up in 4 levels. each level has directories
that represent rows of tiles, and each row directory has the actual tile DDS texture
files for the columns. so level 0 has 5 rows and 10 columns. level 1 increases in
resolution with 10 rows and 20 columns; and so on. now i had test images that would
let me see if the proper row/column of tiles was being rendered.
</p>
<p>
<img id="IMG1" src="images/rowColTiles.jpg" /> <img src="images/blueSky.jpg" /></p>
<ul>
<li>test images that shows how tiles are rendered as rows / columns. this is at level
0</li>
<li>shows tiled earth images. see how low resolution is further from the view. also
note how the sky is blue as you get closer to earth</li>
</ul>
<p>
and the rendering was a bit tricky too. WW uses frustum culling to determine which
tiles to render. i could not use this class because of the missing Plane class,
nor am i advanced enough to implement my own Plane, so i used a simpler technique.
all /cfWW does is determine which tile is the view centered on. then it renders
the 8 neighbor tiles that surround it. this technique ends up being less accurate,
but really fast. generally, about 90% of the screen will be rendered with higher
resolution tiles, while the remaining 10% will render the basic texture from day
2 above. the only other calculation done is to figure ou the altitude to determine
which level the tiles should be rendered from. so as you zoom in, if you pass the
threshold from one level to another, then there is a slight delay as the new set
of 9 meshes and textures are loaded. if you just spin the world left and right,
then it only has to load the 3 new neighbor textures and dump the 3 nodes that went
out of scope. once i had that working, i created a desktop app to convert the BlueMarbleTextures
on the desktop. it resized them from 512x512 to 256x256 and saved them as BMP files
instead of DDS. i tried to do this initially with a mix of DirectX and GDI+ bitmap
handling. but the problem this introduced rendered seams between the tiles. if i
used DirectX alone to resize and save, then the seams did not show. once again,
dont mix DirectX and GDI+. the DirectX code below is what was used to resize and
convert the tiles (posted by cadull in the directx.graphics newsgroup)</p>
<pre>Texture t = TextureLoader.FromFile(device, realTexturePath);
// dimensions are scaled by 1/2^n (e.g. n=2 to divide by 4)
int n = 2; //divide by 4
Surface sn = t.GetSurfaceLevel(n);
SurfaceLoader.Save(bmpTexturePath, ImageFileFormat.Bmp, sn);
sn.Dispose();
t.Dispose();</pre>
<p>
now
i had something like 250 megs of mesh and texture files for the device. went to
Sams and bought a 1 gig SD card for only $70. wow, when did they get that cheap?
now when the app starts up, it initially loads with the single mesh and single texture
as before for a quicker startup time. if you zoom in below 10,000 kilometers then
the 1st level of 9 tiles load. as you keep zooming in it loads more and more detailed
tiles for each level. the base texture always loads to render the edges of the world,
and the tiles overlay it with more detailed resolutions. if i were to continue down
this path, the next step would be to start changing the height of particularly points
on the mesh tiles to represent terrain (e.g. mountains and valleys) and then overlay
satellite images. but i did not continue because i was starting to run into CPU
vs RAM tradeoffs on the device. instead i just moved on to the next type of local
data.
</p>
<p>
<img src="images/tiledMesh.jpg" />
<img src="images/tiles0.jpg" />
</p>
<ul>
<li>shows 9 tiled meshes overlayed on main mesh</li>
<li>level 0 earth tiles with orange outline around tles</li>
</ul>
<p>
<img src="images/tiles1.jpg" />
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -