0

Updated chunk placement and tile rendering sectiosn of design docs

This commit is contained in:
Andrew Brown
2012-02-20 23:02:05 -05:00
parent dc50f6a044
commit 6734e12a7a
7 changed files with 53657 additions and 4193 deletions

View File

@@ -363,31 +363,41 @@ The process of assembling a chunk is simply a matter of iterating over this
array, reading the blockid values, looking up the appropriate sprite, and array, reading the blockid values, looking up the appropriate sprite, and
pasting it on the chunk image at the appropriate location. pasting it on the chunk image at the appropriate location.
Tile Rendering Chunk Placement
============== ===============
.. Covers the placement of chunk images on a tile .. Covers the placement of chunk images on a tile
So now that we know how to draw a single chunk, we can move on to placing them Now that we know how to draw a single chunk, let's move on to how to place
on an image. chunks relative to each other.
For the diagrams in this section, we are positioning an entire chunk, but Before we get started, let's take a moment to remember that one chunk section is
frequently, only the top face of the chunk is drawn (shown in green below). only 1/16th of a chunk:
.. image:: tilerendering/entirechunk.png
:alt: An entire chunk
A chunk is 16 chunk sections stacked together.
Since this is pretty tall, the diagrams in this section are simplified to only
show the *top face* of a chunk, as shown in green here:
.. image:: tilerendering/topofchunk.png .. image:: tilerendering/topofchunk.png
:alt: The top of a chunk is highlighted :alt: The top of a chunk is highlighted
This makes it easier and less cumbersome to describe chunk positionings. Just This makes it easier and less cumbersome to describe how to place chunks
remember that chunks extend down for 1536 more pixels. together on a tile. Just remember that chunks are actually very tall and extend
down far beyond the drawn diamonds in these diagrams.
Chunk Addressing Chunk Addressing
---------------- ----------------
Chunks in Minecraft have an X,Z address, starting at 0,0 and extending to Chunks in Minecraft have an X,Z address, with the origin at 0,0 and extending to
positive and negative infinity on both axes. Since we're looking at things positive and negative infinity on both axes (Recall from the introduction that
diagonally, however, we need a way of addressing these chunks in the final chunk addresses are simply the block addresses divided by 16). Since we're going
image. For that, we refer to them in rows and columns. Consider this grid to render at a diagonal perspective, it is convenient to perform a change of
showing the tops of a five by five region of chunks, labeled with their in-game coordinate system. For that, we translate X,Z coordinates into column,row
addresses. coordinates. Consider this grid showing 25 chunks around the origin. They are
labeled with their X,Z chunk addresses.
.. image:: tilerendering/chunkgrid.png .. image:: tilerendering/chunkgrid.png
:alt: A grid of 5x5 chunks showing how chunks are addressed. :alt: A grid of 5x5 chunks showing how chunks are addressed.
@@ -401,10 +411,12 @@ So the chunk at address 0,0 would be at col 0, row 0; while the chunk at address
1,1 would be at col 2, row 0. The intersection of the red and green lines 1,1 would be at col 2, row 0. The intersection of the red and green lines
addresses the chunk in col,row format. addresses the chunk in col,row format.
Notice that as a consequence of this addressing scheme, there is no chunk at .. note::
e.g. column 1 row 0. There are some col,row addresses that lie between chunks
(as can be seen where the red/green lines intersect at a chunk boundary instead As a consequence of this addressing scheme, there is no chunk at e.g. column
of the middle of a chunk). Something to keep in mind. 1 row 0. There are some col,row addresses that lie between chunks, and
therefore do not correspond to a chunk. (as can be seen where the red/green
lines intersect at a chunk boundary instead of the middle of a chunk).
So how does one translate between them? It turns out that a chunk's column So how does one translate between them? It turns out that a chunk's column
address is simply the sum of the X and the Z coordinate, while the row is the address is simply the sum of the X and the Z coordinate, while the row is the
@@ -420,21 +432,34 @@ difference. Try it!
Chunk Positioning Chunk Positioning
----------------- -----------------
Again just looking at the top of a chunk, we can work out how to position them
relative to each other. This is similar to how to position blocks relative to
each other, but this time, for chunks.
A chunk's top face is 384 pixels wide by 192 pixels tall. Similar to the block, This section will seem very familiar to the block positioning. In fact, it is
neighboring chunks have these relationships: exactly the same but with different numbers (because blocks and chunk sections
have the exact same proportions), so let's speed through this.
A chunk's top face is 384 pixels wide by 192 pixels tall. They therefore have
these offsets from their neighbors:
.. image:: tilerendering/chunkpositioning.png .. image:: tilerendering/chunkpositioning.png
:alt: Chunk positioning diagram :alt: Chunk positioning diagram
But that's all pretty trivial. With this knowledge, we could draw the chunks at
the above offsets in one large image, but for large worlds, that would quickly Tile Rendering
become too much to handle. (Early versions of the Overviewer did this, but the ==============
large, unwieldy images quickly motivated the development of rendering to
individual tiles) Now that we know how to translate chunk coordinates to col/row coordinates, and
know how to calculate the offset from the origin on the final image, we could
easily draw the chunks in one large image. However, for large worlds, that would
quickly become too much data to handle at once. (Early versions of the
Overviewer did this, but the large, unwieldy images quickly motivated the
development of rendering to individual tiles).
Hence choosing a technology like Google Maps, which draws small tiles together
to make it look like one large image, lets rendering even the largest worlds
possible. The Overviewer can draw each tile separately and not have to load the
entire map into memory at once. The next sections describe how to determine
which chunks to render in which tiles, and how to reason about tile ↔ chunk
mappings.
Tile Layout Tile Layout
----------- -----------
@@ -444,13 +469,29 @@ Only a handful of chunks need to be rendered into each tile. The downside is
that chunks must be rendered multiple times for each tile they appear in, but that chunks must be rendered multiple times for each tile they appear in, but
the upside is that arbitrarily sized maps can be viewed. the upside is that arbitrarily sized maps can be viewed.
The Overviewer uses a tile size of 384 by 384 pixels. This is the same as a The Overviewer uses a tile size of 384 by 384 pixels. This is the same as the
width of a chunk and is no coincidence. Just considering the top face of a size of a chunk section and is no coincidence. Just considering the top face of
chunk, 8 chunks get rendered into a tile in this configuration: a chunk, the 8 chunks directly below itget rendered into a tile in this
configuration:
.. image:: tilerendering/chunksintile.png .. image:: tilerendering/chunksintile.png
:alt: The 8 chunks that get rendered into a tile :alt: The 8 chunks that get rendered into a tile
.. note::
Don't forget that chunks are tall, so many more than 8 chunks get rendered
into this tile. If you think about it, chunks from the rows *above* the ones
in that diagram may have blocks that fall into this tile, since the diamonds
in the diagram correspond to the *tops* of the chunks, and chunks extend
*down*.
.. note::
This is an important diagram and we'll be coming back to it. Make sure it makes
sense. As a side note, if anything in this document *doesn't* make sense, please
let us know in IRC or by filing an issue. I want these docs to be as clear as
possible!
So the overall strategy is to convert all chunks into diagonal col,row So the overall strategy is to convert all chunks into diagonal col,row
coordinates, then for each tile decide which chunks belong in it, then render coordinates, then for each tile decide which chunks belong in it, then render
them in the appropriate place on the tile. them in the appropriate place on the tile.
@@ -468,14 +509,6 @@ out of the bounds get rendered off the tile and don't affect the final image.
(There is therefore no penalty for rendering out-of-bounds chunks for a tile (There is therefore no penalty for rendering out-of-bounds chunks for a tile
except increased processing) except increased processing)
.. note::
Remember that chunks are actually very tall, so there are actually several
rows above 0 in the above diagram that are rendered into the tile. Since the
chunk outlines in the diagrams are only the top face of the chunk, they most
likely don't contribute to the image since chunks usually don't have
anything to render way up at the top near the sky.
Since every other column of chunks is half-way in two tiles, they must be Since every other column of chunks is half-way in two tiles, they must be
rendered twice. Each neighboring tile is therefore only 2 columns over, not 3 as rendered twice. Each neighboring tile is therefore only 2 columns over, not 3 as
one may suspect at first. Same goes for the rows: The next tile down is 4 rows one may suspect at first. Same goes for the rows: The next tile down is 4 rows

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -14,7 +14,7 @@
id="svg4984" id="svg4984"
version="1.1" version="1.1"
inkscape:version="0.48.1 r9760" inkscape:version="0.48.1 r9760"
sodipodi:docname="New document 20"> sodipodi:docname="chunkpositioning.svg">
<defs <defs
id="defs4986"> id="defs4986">
<marker <marker
@@ -53,16 +53,16 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="0.7" inkscape:zoom="0.7"
inkscape:cx="259.41101" inkscape:cx="316.55387"
inkscape:cy="428.05724" inkscape:cy="428.05724"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
showborder="false" showborder="false"
inkscape:window-width="1920" inkscape:window-width="1920"
inkscape:window-height="1003" inkscape:window-height="1031"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="25" inkscape:window-y="0"
inkscape:window-maximized="1"> inkscape:window-maximized="1">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
@@ -80,7 +80,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@@ -158,32 +158,6 @@
d="m -430.5,442.36218 0,-60" d="m -430.5,442.36218 0,-60"
id="path5082-1" id="path5082-1"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-dashoffset:0"
d="m -430.5,562.36218 0,270"
id="path5641"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:3,3;stroke-dashoffset:0"
d="m -50.5,562.36218 0,270"
id="path5643"
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
style="font-size:36px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Andale Mono"
x="-560.5"
y="762.36218"
id="text5645"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan5647"
x="-560.5"
y="762.36218">(1536)</tspan></text>
<path
style="fill:none;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-mid:none;marker-end:url(#Arrow1Mend)"
d="m -500.5,782.36218 0,80"
id="path5649"
inkscape:connector-curvature="0" />
<rect <rect
style="fill:none;stroke:#000000;stroke-width:5.6126442;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" style="fill:none;stroke:#000000;stroke-width:5.6126442;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect2985-6-1-2" id="rect2985-6-1-2"

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 66 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 283 KiB