Updated chunk placement and tile rendering sectiosn of design docs
@@ -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
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 19 KiB |
@@ -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 |
BIN
docs/design/tilerendering/entirechunk.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
47761
docs/design/tilerendering/entirechunk.svg
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 200 KiB After Width: | Height: | Size: 283 KiB |