Merge remote-tracking branch 'origin/master' into brownan-chunkscan
Conflicts: overviewer.py overviewer_core/quadtree.py
@@ -486,10 +486,81 @@ 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
|
||||||
down, not 5.
|
down, not 5.
|
||||||
|
|
||||||
|
To further illustrate this point, here are four tiles arranged on the grid of
|
||||||
|
chunks. Notice how the tiles are addressed by the col,row of the chunk in the
|
||||||
|
upper-left corner. Also notice how neighboring tiles are 2 columns apart but 4
|
||||||
|
rows apart.
|
||||||
|
|
||||||
|
.. image:: tilerendering/tilegrid.png
|
||||||
|
:alt: 4 tiles arranged on the grid of chunks
|
||||||
|
|
||||||
Quadtrees
|
Quadtrees
|
||||||
=========
|
=========
|
||||||
.. About the tile output
|
.. About the tile output
|
||||||
|
|
||||||
|
Tiles are rendered and stored in a quadtree on disk. Each node is a tile of the
|
||||||
|
world, and each node has four children representing a zoomed-in tile of the four
|
||||||
|
quadrants.
|
||||||
|
|
||||||
|
.. image:: tilerendering/4children.png
|
||||||
|
:alt: A tile has 4 children, each is a zoomed-in tile of one of the quadrants.
|
||||||
|
|
||||||
|
The tree is generated from the bottom-up. The highest zoom level is rendered
|
||||||
|
directly from the chunks and the blocks, then four of those rendered tiles are
|
||||||
|
shrunk and concatenated to get the next zoom level. The tree is built up in this
|
||||||
|
way until the entire world is compressed down to a single tile.
|
||||||
|
|
||||||
|
We've already seen how tiles can be identified by the column,row range of the
|
||||||
|
chunks that make up the tile. More precisely, since tiles are always the same
|
||||||
|
size, the chunk that goes in the tile's 0,0 col,row slot identifies the tile.
|
||||||
|
|
||||||
|
Now, tiles are also identified by their path in the quadtree. For example,
|
||||||
|
``3/0/0/1/1/2.png`` refers to the tile starting at the base, under the third
|
||||||
|
quadrant, then the 0th quadrant, then the 0th, and so fourth.
|
||||||
|
|
||||||
|
Quadtree Size
|
||||||
|
-------------
|
||||||
|
The size of the quadtree must be known before it's generated, that way the code
|
||||||
|
knows where to save the images. This is easily calculated from a few
|
||||||
|
realizations. Each depth in the quadtree doubles the number of tiles in each
|
||||||
|
dimension, or, quadruples the total tiles. While there is only one tile at level
|
||||||
|
0, there are four at level 1, 16 at level 2, and 4^n at level n.
|
||||||
|
|
||||||
|
To find how deep the quadtree must be, we look at the size of the world. First
|
||||||
|
find the maximum and minimum row and column of the chunks. Just looking at
|
||||||
|
columns, let's say the maximum column is 82 and the minimum column is -136. A
|
||||||
|
zoom level of 6 will be 2^6 tile across and 2^6 tiles high at the highest level.
|
||||||
|
|
||||||
|
Since horizontally tiles are two chunks wide, multiply 2^6 by 2 to get the total
|
||||||
|
diameter of this map in chunks: 2*2^6. Is this wide enough for our map?
|
||||||
|
|
||||||
|
It turns out it isn't (2*2^6=128, 136+82=218). A zoom level of 7 is 2^7 tiles
|
||||||
|
across, or 2*2^7 chunks across. This turns out is wide enough (2*2^7 = 256),
|
||||||
|
however, Overviewer maps are always centered at point 0,0 in the world. This is
|
||||||
|
so tiles will always line up no mater how the map may expand in the future.
|
||||||
|
|
||||||
|
So zoom level 7 is *not* enough because, while the chunk diameter is wide
|
||||||
|
enough, it only extends half that far from the origin. The chunk *radius* is 2^7
|
||||||
|
(half the diameter) and 2^7=128 is not wide enough for the minimum column at
|
||||||
|
absolute position 136.
|
||||||
|
|
||||||
|
So this example requires zoom level 8 (at least in the horizontal direction.
|
||||||
|
The vertical direction must also be checked).
|
||||||
|
|
||||||
|
Quadtree Paths
|
||||||
|
--------------
|
||||||
|
|
||||||
|
To illustrate the relationship between tile col,row addresses and their path,
|
||||||
|
consider these 16 tiles from a depth 2 quadtree:
|
||||||
|
|
||||||
|
.. image:: quadtree/depth2addresses.png
|
||||||
|
:alt: Addresses and paths for 16 tiles in a depth 2 tree
|
||||||
|
|
||||||
|
The top address in each tile is the col,row address, where the chunk outlined in
|
||||||
|
green in the center is at 0,0. The lower address in each tile is the path. The
|
||||||
|
first number indicates which quadrant the tile is in overall, and the second is
|
||||||
|
which quadrant within the first one.
|
||||||
|
|
||||||
get_range_by_path
|
get_range_by_path
|
||||||
-----------------
|
-----------------
|
||||||
.. Explain the quadtree.QuadtreeGen._get_range_by_path method
|
.. Explain the quadtree.QuadtreeGen._get_range_by_path method
|
||||||
@@ -518,5 +589,72 @@ Caching
|
|||||||
Lighting
|
Lighting
|
||||||
========
|
========
|
||||||
|
|
||||||
|
Minecraft stores precomputed lighting information in the chunk files
|
||||||
|
themselves, so rendering shadows on the map is a simple matter of
|
||||||
|
interpreting this data, then adding a few extra steps to the render
|
||||||
|
process. These few extra steps may be found in
|
||||||
|
``rendermode-lighting.c`` or ``rendermode-smooth-lighting.c``,
|
||||||
|
depending on the exact method used.
|
||||||
|
|
||||||
|
Each chunk contains two lighting arrays, each of which contains one
|
||||||
|
value between 0 and 15 for each block. These two arrays are the
|
||||||
|
BlockLight array, containing light received from other blocks, and the
|
||||||
|
SkyLight array, containing light received from the sky. Storing these
|
||||||
|
two seperately makes it easier to switch between daytime and
|
||||||
|
nighttime. To turn these two values into one value between 0 and 1
|
||||||
|
representing how much light there is in a block, we use the following
|
||||||
|
equation (where l\ :sub:`b` and l\ :sub:`s` are the block light and
|
||||||
|
sky light values, respectively):
|
||||||
|
|
||||||
|
.. image:: lighting/light-eqn.png
|
||||||
|
:alt: c = 0.8^{15 - min(l_b, l_s)}
|
||||||
|
|
||||||
|
For night lighting, the sky light values are shifted down by 11 before
|
||||||
|
this lighting coefficient is calculated.
|
||||||
|
|
||||||
|
Each block of light data applies to all the block faces that touch
|
||||||
|
it. So, each solid block doesn't receive lighting from the block it's
|
||||||
|
in, but from the three blocks it touches above, to the left, and to
|
||||||
|
the right. For transparent blocks with potentially strange shapes,
|
||||||
|
lighting is approximated by using the local block lighting on the
|
||||||
|
entire image.
|
||||||
|
|
||||||
|
.. image:: lighting/lighting-process.png
|
||||||
|
:alt: The lighting process
|
||||||
|
|
||||||
|
For some blocks, notably half-steps and stairs, Minecraft doesn't
|
||||||
|
generate valid lighting data in the local block like it does for all
|
||||||
|
other transparent blocks. In these cases, the lighting data is
|
||||||
|
estimated by averaging data from nearby blocks. This is not an ideal
|
||||||
|
solution, but it produces acceptable results in almost all cases.
|
||||||
|
|
||||||
|
Smooth Lighting
|
||||||
|
---------------
|
||||||
|
|
||||||
|
In the smooth-lighting rendermode, solid blocks are lit per-vertex
|
||||||
|
instead of per-face. This is done by covering all three faces with a
|
||||||
|
quadralateral where each corner has a lighting value associated with
|
||||||
|
it. These lighting values are then smoothly interpolated across the
|
||||||
|
entire face.
|
||||||
|
|
||||||
|
To calculate these values on each corner, we look at lighting data in
|
||||||
|
the 8 blocks surrounding the corner, and ignore the 4 blocks behind
|
||||||
|
the face the corner belongs to. We then calculate the lighting
|
||||||
|
coefficient for all 4 remaining blocks as normal, and average them to
|
||||||
|
obtain the coefficient for the corner. This is repeated for all 4
|
||||||
|
corners on a given face, and for all visible faces.
|
||||||
|
|
||||||
|
.. image:: lighting/smooth-average.png
|
||||||
|
:alt: An example face and vertex, with the 4 light sources.
|
||||||
|
|
||||||
|
The `ambient occlusion`_ effect so strongly associated with smooth
|
||||||
|
lighting in-game is a side effect of this method. Since solid blocks
|
||||||
|
have both light values set to 0, the lighting coefficient is very
|
||||||
|
close to 0. For verticies in corners, at least 1 (or more) of the 4
|
||||||
|
averaged lighting values is therefore 0, dragging the average down,
|
||||||
|
and creating the "dark corners" effect.
|
||||||
|
|
||||||
|
.. _ambient occlusion: http://en.wikipedia.org/wiki/Ambient_occlusion
|
||||||
|
|
||||||
Cave Mode
|
Cave Mode
|
||||||
=========
|
=========
|
||||||
|
|||||||
BIN
docs/design/lighting/light-eqn.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
docs/design/lighting/lighting-process.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
597
docs/design/lighting/lighting-process.svg
Normal file
@@ -0,0 +1,597 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="990.05859"
|
||||||
|
height="363.28781"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.2 r9819"
|
||||||
|
sodipodi:docname="lighting-process.svg"
|
||||||
|
inkscape:export-filename="/home/agrif/devel/minecraft/overviewer/docs/design/lighting/lighting-process.png"
|
||||||
|
inkscape:export-xdpi="72.722969"
|
||||||
|
inkscape:export-ydpi="72.722969">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path4162"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend-5"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4162-9"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend-4"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4162-94"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend-9"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path4162-3"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.7"
|
||||||
|
inkscape:cx="493.24452"
|
||||||
|
inkscape:cy="114.45456"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="1033"
|
||||||
|
inkscape:window-height="873"
|
||||||
|
inkscape:window-x="1178"
|
||||||
|
inkscape:window-y="92"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3360"
|
||||||
|
empspacing="5"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="0.5px"
|
||||||
|
spacingy="0.5px" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-1074.9414,-393.66687)">
|
||||||
|
<image
|
||||||
|
y="483.86218"
|
||||||
|
x="1630"
|
||||||
|
id="image3090"
|
||||||
|
xlink:href="data:image/png;base64,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 zuh1+eUAAAAASUVORK5CYII= "
|
||||||
|
height="105"
|
||||||
|
width="105" />
|
||||||
|
<g
|
||||||
|
id="g3220"
|
||||||
|
transform="translate(1870.0729,48.04841)">
|
||||||
|
<g
|
||||||
|
id="g3222"
|
||||||
|
transform="translate(11.46694,-150.49998)"
|
||||||
|
style="fill:none">
|
||||||
|
<rect
|
||||||
|
transform="matrix(0.89611053,0.44383096,-0.89611053,0.44383096,0,0)"
|
||||||
|
y="771.25336"
|
||||||
|
x="608.28253"
|
||||||
|
height="59.181324"
|
||||||
|
width="59.181324"
|
||||||
|
id="rect3224"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.12123179;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3226"
|
||||||
|
d="m -93.006853,691.08025 -53.032997,26.2665 -53.03301,-26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3228"
|
||||||
|
d="m -199.03985,638.81375 0,52"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3230"
|
||||||
|
d="m -93.039853,638.81375 0,52"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3232"
|
||||||
|
d="m -146.03985,664.81375 0,53"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3234"
|
||||||
|
d="m -81.53991,541.58027 -53.033,-26.2665 -53.03301,26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(1764.0729,48.04841)"
|
||||||
|
id="g3236">
|
||||||
|
<g
|
||||||
|
style="fill:none"
|
||||||
|
transform="translate(11.46694,-150.49998)"
|
||||||
|
id="g3238">
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.12123179;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect3240"
|
||||||
|
width="59.181324"
|
||||||
|
height="59.181324"
|
||||||
|
x="608.28253"
|
||||||
|
y="771.25336"
|
||||||
|
transform="matrix(0.89611053,0.44383096,-0.89611053,0.44383096,0,0)" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||||
|
d="m -93.006853,691.08025 -53.032997,26.2665 -53.03301,-26.2665"
|
||||||
|
id="path3242"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -199.03985,638.81375 0,52"
|
||||||
|
id="path3244"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -93.039853,638.81375 0,52"
|
||||||
|
id="path3246"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -146.03985,664.81375 0,53"
|
||||||
|
id="path3248"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4"
|
||||||
|
d="m -81.53991,541.58027 -53.033,-26.2665 -53.03301,26.2665"
|
||||||
|
id="path3250"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g3252"
|
||||||
|
transform="translate(1817.0729,-30.45159)">
|
||||||
|
<g
|
||||||
|
id="g3254"
|
||||||
|
transform="translate(11.46694,-150.49998)"
|
||||||
|
style="fill:none">
|
||||||
|
<rect
|
||||||
|
transform="matrix(0.89611053,0.44383096,-0.89611053,0.44383096,0,0)"
|
||||||
|
y="771.25336"
|
||||||
|
x="608.28253"
|
||||||
|
height="59.181324"
|
||||||
|
width="59.181324"
|
||||||
|
id="rect3256"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.12123179;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3258"
|
||||||
|
d="m -93.006853,691.08025 -53.032997,26.2665 -53.03301,-26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3260"
|
||||||
|
d="m -199.03985,638.81375 0,52"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3262"
|
||||||
|
d="m -93.039853,638.81375 0,52"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3264"
|
||||||
|
d="m -146.03985,664.81375 0,53"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3266"
|
||||||
|
d="m -81.53991,541.58027 -53.033,-26.2665 -53.03301,26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4" />
|
||||||
|
</g>
|
||||||
|
<image
|
||||||
|
width="105"
|
||||||
|
height="105"
|
||||||
|
xlink:href="data:image/png;base64,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 zuh1+eUAAAAASUVORK5CYII= "
|
||||||
|
id="image3268"
|
||||||
|
x="1290"
|
||||||
|
y="483.86218" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
|
||||||
|
d="m 1425,528.86218 120,0"
|
||||||
|
id="path3386"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<image
|
||||||
|
y="483.86218"
|
||||||
|
x="1960"
|
||||||
|
id="image3378"
|
||||||
|
xlink:href="data:image/png;base64,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
|
||||||
|
"
|
||||||
|
height="105"
|
||||||
|
width="105" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3381"
|
||||||
|
d="m 1815,528.86218 120,0"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)" />
|
||||||
|
<image
|
||||||
|
y="648.86218"
|
||||||
|
x="1630"
|
||||||
|
id="image3442"
|
||||||
|
xlink:href="data:image/png;base64,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
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
"
|
||||||
|
height="105"
|
||||||
|
width="105" />
|
||||||
|
<image
|
||||||
|
y="648.86218"
|
||||||
|
x="1960"
|
||||||
|
id="image3504"
|
||||||
|
xlink:href="data:image/png;base64,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
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
"
|
||||||
|
height="105"
|
||||||
|
width="105" />
|
||||||
|
<g
|
||||||
|
transform="translate(1817.0729,189.5484)"
|
||||||
|
id="g3507">
|
||||||
|
<g
|
||||||
|
style="fill:none"
|
||||||
|
transform="translate(11.46694,-150.49998)"
|
||||||
|
id="g3509">
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.12123179;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect3511"
|
||||||
|
width="59.181324"
|
||||||
|
height="59.181324"
|
||||||
|
x="608.28253"
|
||||||
|
y="771.25336"
|
||||||
|
transform="matrix(0.89611053,0.44383096,-0.89611053,0.44383096,0,0)" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||||
|
d="m -93.006853,691.08025 -53.032997,26.2665 -53.03301,-26.2665"
|
||||||
|
id="path3513"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -199.03985,638.81375 0,52"
|
||||||
|
id="path3515"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -93.039853,638.81375 0,52"
|
||||||
|
id="path3517"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -146.03985,664.81375 0,53"
|
||||||
|
id="path3519"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4"
|
||||||
|
d="m -81.53991,541.58027 -53.033,-26.2665 -53.03301,26.2665"
|
||||||
|
id="path3521"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
</g>
|
||||||
|
<image
|
||||||
|
width="105"
|
||||||
|
height="105"
|
||||||
|
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGkAAABpCAYAAAA5gg06AAAABHNCSVQICAgIfAhkiAAACnJJREFU
|
||||||
|
eJztXUtvI1kVPrbLLpftJI7jOI7zTrfTSUi6Gc00DK1BaJhhAUgskNgBQkhIiB0L2LLgPyC2sOAX
|
||||||
|
gDQL2DDSaCZkmM50J915v+w8nNjxM37bLFhMf+fUdLZzpfPtjn1u1XUdV537ncctz09+t0qvwuvz
|
||||||
|
0F2oV9riMyvgA7lSaN55nNi4c+dxOfp9lGvFltD52fIyaP11awt+VPG8I8aE7SDIHW8X5FBGnids
|
||||||
|
B0AeCgeEzmByFuT5CB736CIvxgSDfpC9QkPxlYMayQCokQyAxT1Q81Y+r52IX3zG0Wnhs3YgZoNs
|
||||||
|
O+iz/j+m99pj3lw2xGd/eP/dvosqoNfD4/6c+ShalmP+9kEOLoVVvYTv700nxJhOFw/r88qpRSy8
|
||||||
|
Lvvn1yDXm9IPDw+FQNY7yQCokQyAGskAqJEMgEUeXDp029L5cWLa60qd0akwyFyjcHYrxuTZZ3/8
|
||||||
|
wfs4DHk2ERFVb3HM5uGV0PnG8jTIOwdFkFfm5SLgVz+ag3P3aBK+X/84K1g+J9b5Sl0ct3l5BnLY
|
||||||
|
QQLfYqSZiKhWR+Ksd5IBUCMZADWSAbB6XSR+bgHWVuP1pJNI+q3iFRLRXz96Qzgybxr/I5k8Er1k
|
||||||
|
dFicxw5gEPOmKH3dv/+7D/LizAgqWPL32DbO5eQM5x+KO2L+n6wdwsUaYSSUiCg6PAByxMH5F2vS
|
||||||
|
j51dl0DWO8kAqJEMgBrJAKiRDIBVzqPDbzcluRqfHwT5eOtG6Pzm4bfBsTqL6CCzbFFARBS10NGO
|
||||||
|
DuB5Pnl+IsbMpKIoTw0JncRQBOTBMJ5n6wAj3EREO6fHIA+EcP7xIXmepVkkxbGII3ScIB7n5QmS
|
||||||
|
74BfZgdiAxoFNw5qJAOgRjIAViyJz9H9pwWh9D1nConcm1NCp1RGUpmnMsheryTJn25j8HE2heR1
|
||||||
|
Kok+iogoHLRAtv2SQO6f4W9oN9GH1hqSQPJs7mAIA8af7+BciYgSISSqXkv6l70sVgOFAjj/m6rM
|
||||||
|
PoeZH9M7yQCokQyAGskAeP7551/eXX3DsltXpeKXaH6BzT3kA6mxyJdofoHZBAZCeTCViOiz7VOQ
|
||||||
|
z/JloROweAUozt/tB59cYFCz20GtacbPiIioRuBoL67ldak1sPrqmywhmcnJMcfTNZD1TjIAaiQD
|
||||||
|
oEYyAGokA2DtZS/gg6gzIJTiMSR2z7dlhU5qHBcGyTiOKZVlK8zKXBLkl0cYhK3eynaTDsskR4JB
|
||||||
|
qdPBIPHpZQW/78kgcmwQSX2jjeW/kRCWTRMRZS6QJHuGUkJnMoy/KXuJ8s4oLhKIiIglm/VOMgBq
|
||||||
|
JAOgRjIA1kEGSdyTVVmhs7Z5CPLyvaTQ8QeQ/Dk2PsNPzvA8REQbOzmQ+4xmdrvSd/RZnDZzKcls
|
||||||
|
nwVL05OjIJfrssIozOZbb+O5945l22QkHAP5fDQjdHi4us8CA0G/RRytBp5b7yQDoEYyAGokA2Dd
|
||||||
|
m8Tnqlvxx1UB1/ITcVmU0Wyjszg+R3/Dj0FENDqESb1D1qp4lZe+w2Ht8xNjMjHY7CDHcRwcE7Ql
|
||||||
|
F1zfQn/SbGJg1PLI//PqAx84mLzlF5lNXtjjDOBcLEset1bSrgrjoEYyAGokA6BGMgCWzfYEmhiV
|
||||||
|
1TcpFixdey5JW4RVb85O4OIi79KisnmAwd1iGStnooMyqDkyjOdxKdAhrw8J4vomzrdUkXNps8Tr
|
||||||
|
j9/CzR4mXSqXODFN3IZE0rdcxUXABxfYLhMMSzJbudGFg3FQIxkANZIBsPaOMXF1f0YGWH0+tOXg
|
||||||
|
gPQVqTH0ZYdZDKie5apiTIL5l3gUE3i8G4KIqMTaF3dPZcVtpcoSjIxof/+dBTEm5tJK+SpsS/qO
|
||||||
|
8xz+xo1d2a0RZcnE3775BPxWuy33FvrTP9ZgwnonGQA1kgFQIxkANZIBsIajWMq7cygdcaeDmc6V
|
||||||
|
9JjQKZQxyj0jotOyuJcTaZ8X/zMbL87FmOotEt7VaZklXngL2yQTI7JNUhy3jsftdXCx8fFzbNd0
|
||||||
|
w9sPZUtQ14NR8EtWoj0SkSR5MRmHi6V3kgFQIxkANZIBsPieOjMTssXDx7KS61tZodNoISl7tIB+
|
||||||
|
y/bL/8PuEVbgFEsY+LS9cszjFXzuL8yNCJ1hFuxtdzHLmr2WFUb5G9mi+SrSLiQ/5Ed/XmvLitvB
|
||||||
|
AJLkv/z9M5CTIxi8JiKam8Zsud5JBkCNZADUSAbAOspgx8HinGyBdFhb+0xSVgtFwlgFs5tBvvVy
|
||||||
|
X1aAEqsS/eF3lkB2S7RxtDoyQFliibbtI6xc8okt64keLiDf8jI/zCtciYj4VrQfPZPJ0C7rAnm8
|
||||||
|
ip0XHpf3t5xk2fYKUkXxVYMayQCokQyAGskAWF9PT8AHn26eCiXekjI9Lglv34M6SzNIZu9PYPsJ
|
||||||
|
EdFYXBK5V9FoyhbOJmsLyV7LjG+rheT13cdpnCvfdZ2IPMyDX5XQeX+4fiTGdPu4KHgwKzeF5zq7
|
||||||
|
rOW077IH8dykklnjoEYyAGokA2CxQiCKDEgyG2AdHYWy24bjSConU7hlgFu1zeY+VrDOpeIgH7m0
|
||||||
|
cDaZv3ljcVLoPN1BUlmsYuD2poYEnojo2RZue9BmraBjozJxGPAjgf+PS9tQgAVhl+bRV5ddNm8P
|
||||||
|
h3S/O+OgRjIAaiQD4Pn9L94B0rCSlnyGc4jLgkya8cTgyQUWXHRdXoz1ZHUedfh2Mi7Bx2hYBjo5
|
||||||
|
PKyr4l9rO3eOCQXQvzghLJI5yMq90Pl0F6bjQsdic7ltYcFLoynfRlpmb67WO8kAqJEMgBrJAKiR
|
||||||
|
DID1IpQH99x70RMevshaSd5+NC4OFGSb2vIgpt9lD50Pn+Ibw4KM+N2flYHcCtsXKByUJPM0h04+
|
||||||
|
EcOKHdsvFx8HGcwc54ro0FOjcu8HPyPoiZjMWN+yIPHuCS663K7LyUhFW19MgxrJAKiRDIDVaWHW
|
||||||
|
Kb/UdKGQiI1nl8Jv2TY+W7+1OgfydVkS4NU0+ja/jxHIjKwwYlvZ0fy0fKbz4OhBhgdUJbFOJjEB
|
||||||
|
6SP0WxNxTMQRERWqmHB0S5iW2BumrQbeF4dTFXm9dQ9W86BGMgBqJAOgRjIAnvd+eg8+sEPSEfMo
|
||||||
|
uBv8rIUmXR7G/Qpashz4u48fgFxrYoS41ZIOnmdZL12qhQrsrWi2jQsSv0uZ8ViMZZJZ1nXrUG5Y
|
||||||
|
32kj4b0Ya9x5oTjJt1xagnSjXAOhRjIAaiQDYCVm8Fnc60g/UClgkDAclRVF9Sr6nJMxJGn8OUtE
|
||||||
|
9NHGEZysWMVtBpbvy4rQBvMD6WlJMis1bJnpeXCMx+VNnU+3cDuCANu+oFuSPrXwtS4cKMT8GNHd
|
||||||
|
G+X6XDbKrWtm1jyokQyAGskAWOUr5CbBiHyuBhx8PvOgLBFRgL1JmTcuNGqyKuZzfw6e6b4E/mci
|
||||||
|
2aJwkH723J9PyQqdWgO50+YOdjKUb2W3RnWu81qO0426tD8wiuYPyv+8h5U8FXPservtwZrH+emd
|
||||||
|
ZADUSAZAjWQA1EgGwOIBVZ9P+s965fWEzA2thlwoCLBTNRgh3h4oickMJ1l10IszWd1UwXaSSB9/
|
||||||
|
Y+5BXRy3V8eFgcMWUA2XFs4+K6xyW1DZDp47yK63W4CVL9T0TjIAaiQDoEYyAP8DjxpCfkPuNWoA
|
||||||
|
AAAASUVORK5CYII=
|
||||||
|
"
|
||||||
|
id="image3523"
|
||||||
|
x="1290"
|
||||||
|
y="648.86218" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3525"
|
||||||
|
d="m 1425,698.86218 120,0"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2.4000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-end:url(#Arrow1Lend)"
|
||||||
|
d="m 1815,698.86218 120,0"
|
||||||
|
id="path3527"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:20px;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="1145"
|
||||||
|
y="538.86218"
|
||||||
|
id="text4554-3"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1145"
|
||||||
|
y="538.86218"
|
||||||
|
id="tspan3619">Solid Block</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3623"
|
||||||
|
y="708.86218"
|
||||||
|
x="1075"
|
||||||
|
style="font-size:20px;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"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
id="tspan3625"
|
||||||
|
y="708.86218"
|
||||||
|
x="1075"
|
||||||
|
sodipodi:role="line">Transparent Block</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3627"
|
||||||
|
y="408.86218"
|
||||||
|
x="1315"
|
||||||
|
style="font-size:20px;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"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
id="tspan3629"
|
||||||
|
y="408.86218"
|
||||||
|
x="1315"
|
||||||
|
sodipodi:role="line">Unlit</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:20px;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="1605"
|
||||||
|
y="408.86218"
|
||||||
|
id="text3631"
|
||||||
|
sodipodi:linespacing="125%"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="1605"
|
||||||
|
y="408.86218"
|
||||||
|
id="tspan3633">Light Data Used</tspan></text>
|
||||||
|
<text
|
||||||
|
sodipodi:linespacing="125%"
|
||||||
|
id="text3635"
|
||||||
|
y="408.86218"
|
||||||
|
x="1995"
|
||||||
|
style="font-size:20px;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"
|
||||||
|
xml:space="preserve"><tspan
|
||||||
|
id="tspan3637"
|
||||||
|
y="408.86218"
|
||||||
|
x="1995"
|
||||||
|
sodipodi:role="line">Lit</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 37 KiB |
BIN
docs/design/lighting/smooth-average.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
297
docs/design/lighting/smooth-average.svg
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="214.04849"
|
||||||
|
height="184.09387"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.2 r9819"
|
||||||
|
sodipodi:docname="smooth-average.svg"
|
||||||
|
inkscape:export-filename="/home/agrif/devel/minecraft/overviewer/docs/design/lighting/smooth-average.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path4162"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend-5"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4162-9"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend-4"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path4162-94"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="Arrow1Lend"
|
||||||
|
orient="auto"
|
||||||
|
refY="0"
|
||||||
|
refX="0"
|
||||||
|
id="Arrow1Lend-9"
|
||||||
|
style="overflow:visible">
|
||||||
|
<path
|
||||||
|
id="path4162-3"
|
||||||
|
d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
|
||||||
|
transform="matrix(-0.8,0,0,-0.8,-10,0)"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="2.2545158"
|
||||||
|
inkscape:cx="94.313483"
|
||||||
|
inkscape:cy="90.94263"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:window-width="1033"
|
||||||
|
inkscape:window-height="873"
|
||||||
|
inkscape:window-x="977"
|
||||||
|
inkscape:window-y="115"
|
||||||
|
inkscape:window-maximized="0"
|
||||||
|
fit-margin-top="0"
|
||||||
|
fit-margin-left="0"
|
||||||
|
fit-margin-right="0"
|
||||||
|
fit-margin-bottom="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3360"
|
||||||
|
empspacing="5"
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
snapvisiblegridlinesonly="true"
|
||||||
|
spacingx="0.5px"
|
||||||
|
spacingy="0.5px" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-1289.9414,-421.95331)">
|
||||||
|
<image
|
||||||
|
width="105"
|
||||||
|
height="105"
|
||||||
|
xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAABHNCSVQICAgIfAhkiAAACyNJREFU eJzt3ctvXHcZxvG5nPFcPR7fYsdO7CRyKFBS1A1pQQI1SCA2/AHtAlWCDQtAsEIs2CE23bFkj6jE phuEEC2qEAq3BiSI3JBb6zi+x+O5j2fs4R8A6Ss0ivO238/61TmeM/P4bB69v/TS0lJK8dz4wdpo nNd7+4276XFeT09H5qz/AEn/PwMsBWaApcAMsBSYAZYCM8BSYAZYCswAS4EZYCmwtE2sZ8vL31oZ a8MqmWD/oy88PzfO26Z+8e2/2ux6CnwDS4EZYCkwAywFZoClwAywFJgBlgIzwFJgBlgKzABLgdnE +h++9N0rY21EjU7Z5XL5BM31OwM0N+gM0VxhMofm0pnxFqxyRfZ5f/vTOza7/gvfwFJgBlgKzABL gRlgKTADLAVmgKXADLAUmAGWAjPAUmAfuybWV3/0HKpEJRNZdL3jLms6VabzaC4L79s57KG5fJk1 rE4Gp2iuvt1Bc5PzRTTXqffZ9WYLaK4Pm2e/+cn7H4lml29gKTADLAVmgKXADLAUmAGWAjPAUmAG WArMAEuBGWApsDNrYt34/tpYd04N+idwkt12osR2NaXTrNBDG0LlqQk0V99qo7l8hV2vPMWaYkPY 2IKPJZXOskG6K6y+3WL3hX9gLs+acb974+6ZNLt8A0uBGWApMAMsBWaApcAMsBSYAZYCM8BSYAZY CswAS4GNvYn1lR+ynVPHbXa6XrHGmkTdBrsePSWQ1moKFbZzikoKrHHU3Ge7qQqT7PnRxtHRbhfN TcIdYBRtgHWb7HeQhq+uY9igK8Hf6fxqFc398ju30E/QN7AUmAGWAjPAUmAGWArMAEuBGWApMAMs BWaApcAMsBRY+vWfvTLe3VTHrLmyeKU2ztum9jeaaK5QZo0Zajhgu7h6sCE0gju7qBLcdZVNxvu/ vH3ITh3MFdh96amI1LnLU2iOfg5qNGLfbxk22XwDS4EZYCkwAywFZoClwAywFJgBlgIzwFJgBlgK zABLgSUF2AzJzLLdT6MBazo9eG8PzdFdTbXlCppr7LBGT7HKPi89FTGTsC1bgx7b/TS1WEJzp0P2 /faax2iuVKO7rth9Bz32/KYX2febr7CdYsMeawxSA3i9XJH9fZ1Ndsqib2ApMAMsBWaApcAMsBSY AZYCM8BSYAZYCswAS4EZYCmwpPsOa8JMvcQaUYVrrCHUP2qjuWypgOaOtllzJQdP/8vl2RzdOXUy ZA2rUzjX2menBJam2fMbHrP7HsHdVPTzLj43jebScFXY7v06mpu5MInm9h+x39XiVbZjq7/Onl/j PdjwQ1OSnkkGWArMAEuBGWApMAMsBWaApcAMsBSYAZYCM8BSYOnvff066rgcZllzpV98jObycIdV v85Oh8u+xBpRp3tsZ1cmy3ZYZXPsf+DUAmuotQ5YwyqbY00xvJuqC09ZbNNTFpky3LFVnYWNMnha 5MavN9DcRJX9Xo63WbNworeA5mon7Hq+gaXADLAUmAGWAjPAUmAGWArMAEuBGWApMAMsBWaApcCS XI41js6NWEPocnkFzf0hf4DmhndYEyt1nv0vKi+z5k+pUERzrSZrJjV22fOrzrP7bt9ju59O4OmE wy47Xe/iC3Nojp52mM2xXWs7D/fRXIfu7LrP/r7h59gplddLy2huo892bKVgLn0DS4EZYCkwAywF ZoClwAywFJgBlgIzwFJgBlgKzABLgSWXFtnpcDf/9SG7YJ41a2qbrGE1OTOD5h7eZM2kzmfRWGrt y6vseiXW/PmgwXaFFavslLvLL55Dc439HpvbZZ/j8DHb1TRfZTvPirDxtvNwC82NbrPf1WqthuZa /2Sfd2uSNe326g009+InWLPLN7AUmAGWAjPAUmAGWArMAEuBGWApMAMsBWaApcAMsBRY8qTJGiQX 5llDaG2RNafulObR3NHmXTSX6pyiscY7R2judvYOmiv34O6sFNuF9CjLTtfLDNjOpM4h2/10mrDd Wf3brNmVSbFdYd08a1i1/sgaTKU8O02wkWHNs+riZTR3qcK+t9QJm6u36XOWFJYBlgIzwFJgBlgK zABLgRlgKTADLAVmgKXADLAUWFIqsObKzhPWJHp/YwfN1eYW0Fy6wppOk6USmssl7H/W+tvscxxV l9DcTJ81pw7uHqK58ifZzqkhPD2xc4/tfppuFNDczgRrdiUttsvsUytsB9jwhN03m2FzlYQ1p+5t sdMTu332fUxPsd+zb2ApMAMsBWaApcAMsBSYAZYCM8BSYAZYCswAS4EZYCmwpNlhp7llsyzr+SRB c3uPN9DcYMTuO19lzZU0K0SlPrPGGlZJmjV6mn22U6xQZ6c7tv7CGj0JbP4sJmU0V5lnz3kVNrGG sJGXZNgXN2K3TR3AXXD9HXaqZLnIGoPHGdbsanfZLjPfwFJgBlgKzABLgRlgKTADLAVmgKXADLAU mAGWAjPAUmDJxi7bwVTI5dDcVIXtTErDZs3WATtN8Na/2edYWZhGc/kca0RdXWGnLB4+ZDu2ytU8 miuesl1mTdrogd/HcMiaXfPn59Dcg80naO54wBpMm/vs9zILd07VpifRXKXIvo96mzXAHsPP4RtY CswAS4EZYCkwAywFZoClwAywFJgBlgIzwFJgBlgKLP3jV7+Itgg1uz10wZNTduNrVxbRXKfLdnbt Nzpobgc2u2ZqrIHTbLO/7/SUPZjJMtuttDjNdljV2+x72ztiz6/VYdfLZNi7ATeYGuz0xDnYnJqB p14W4emd6x/uoTn4WFKVAmvk+QaWAjPAUmAGWArMAEuBGWApMAMsBWaApcAMsBSYAZYCS0Ypdpxb u8t2Ic3BUwLXP9hFc5eXZtBcKsNORUxmL6G5hQprWA3grqYSbPTsHrDdXsU8+7x0J1aj2UJzc9Ps lMUuPBVxrsoaZc0s22WWyrDGViZhO8/ubh6gudIE+z4OW6zJVoa/F9/AUmAGWArMAEuBGWApMAMs BWaApcAMsBSYAZYCM8BSYMnPf38PHUv3jS9cQpWtlUXWmHn3Hw/QXKvDTnNbPscaW4ODx2iuOMNO HTwZsSbbpXMVNFeaOY/mHt2/g+ZaPdaIunj5KpqbTVjTaf0RPfWSvUOGR+x0x2SWPef1h9tort0b ornrn15Bc6NUHc29+edHKJe+gaXADLAUmAGWAjPAUmAGWArMAEuBGWApMAMsBWaApcDSS0tLZ3Lj 1z9/AVWYnuQW0PUKXdbUOWywZtd0lZ1eNzyBO8XgqX7LF5fRXH/ATjtswvtOJOx/+fYWazCV4Ol6 2SwqHKWO4C6pqUoBzfULc2iuNtxHc9Svbu2yDwz5BpYCM8BSYAZYCswAS4EZYCkwAywFZoClwAyw FJgBlgI7sybWuL124wVUiaqm2Cl87T47dXDrgF2vAptJV5draO5vD9nOqU6PnU547SI7dfDBdgPN tfvsvgvT7HTC4gR717RS7Hpv3bwz1kbUWfENLAVmgKXADLAUmAGWAjPAUmAGWArMAEuBGWApMAMs BfaRaWKN22svr6Jm12Gzg65XzE+gudUF1sSqldn1DuEuqaMOa05t7rEmVu+YnYo4VWG7x6i3/r71 kWhYUb6BpcAMsBSYAZYCM8BSYAZYCswAS4EZYCkwAywFZoClwGxiPSXffGUNNbv6x0N0vdokazAd tftortGGpxjmsmjuzT9tfKwaUWfFN7AUmAGWAjPAUmAGWArMAEuBGWApMAMsBWaApcAMsBSYTayg vvb8PGp2tXtsNxX17r26DatniG9gKTADLAVmgKXADLAUmAGWAjPAUmAGWArMAEuBGWApsP8AF/OK zuh1+eUAAAAASUVORK5CYII= "
|
||||||
|
id="image3268"
|
||||||
|
x="1289.9414"
|
||||||
|
y="476.95468" />
|
||||||
|
<g
|
||||||
|
id="g4058">
|
||||||
|
<g
|
||||||
|
transform="translate(0,-75.966998)"
|
||||||
|
id="g3156">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3226"
|
||||||
|
d="m 1449.9743,654.78068 -53.0329,26.2665 -53.0331,-26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3228"
|
||||||
|
d="m 1343.9414,602.51418 0,52"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3230"
|
||||||
|
d="m 1449.9413,602.51418 0,52"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3232"
|
||||||
|
d="m 1396.9414,628.51418 0,53"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4"
|
||||||
|
d="m 1449.9744,655.78068 -53.033,-26.2665 -53.033,26.2665"
|
||||||
|
id="path3234"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0,-92.766498)"
|
||||||
|
id="g3167">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||||
|
d="m 1502.9743,645.04718 -53.0329,26.2665"
|
||||||
|
id="path3866"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 1502.9413,592.78068 0,52"
|
||||||
|
id="path3870"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 1449.9414,618.78068 0,53"
|
||||||
|
id="path3872"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3874"
|
||||||
|
d="m 1502.9744,646.04718 -53.033,-26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0,-165.96702)"
|
||||||
|
id="g3178">
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.12123179;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect3880"
|
||||||
|
width="59.181324"
|
||||||
|
height="59.181324"
|
||||||
|
x="-87.144646"
|
||||||
|
y="1471.7128"
|
||||||
|
transform="matrix(-0.89611053,0.44383096,0.89611053,0.44383096,0,0)" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||||
|
d="m 1343.8755,693.31368 53.033,26.2665 53.033,-26.2665"
|
||||||
|
id="path3882"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 1343.9085,641.04718 0,52"
|
||||||
|
id="path3886"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 1396.9085,667.04718 0,53"
|
||||||
|
id="path3888"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3890"
|
||||||
|
d="m 1343.8754,694.31368 53.033,-26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(0,138.74544)"
|
||||||
|
id="g4049">
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1.12123179;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect3030"
|
||||||
|
width="59.181324"
|
||||||
|
height="59.181324"
|
||||||
|
x="1128.4136"
|
||||||
|
y="-489.62494"
|
||||||
|
transform="matrix(0.89611053,0.44383096,-0.89611053,0.44383096,0,0)" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
d="m 1449.9414,388.58018 -53.0331,-26.2665"
|
||||||
|
id="path3032"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
d="m 1396.9414,310.04718 0,52"
|
||||||
|
id="path3034"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 1502.9413,310.04718 0,52"
|
||||||
|
id="path3036"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 1449.9414,336.04718 0,53"
|
||||||
|
id="path3038"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3040"
|
||||||
|
d="m 1502.9744,363.31368 -53.033,-26.2665"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 3;stroke-dashoffset:1.4" />
|
||||||
|
<path
|
||||||
|
id="path3079"
|
||||||
|
d="m 1502.9743,362.31368 -53.0329,26.2665"
|
||||||
|
style="color:#000000;fill:none;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<rect
|
||||||
|
style="fill:none;stroke:#ff0000;stroke-width:3.16591883;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="rect3043"
|
||||||
|
width="55.683594"
|
||||||
|
height="53.771385"
|
||||||
|
x="1497.8226"
|
||||||
|
y="1185.8828"
|
||||||
|
transform="matrix(0.89793102,-0.4401362,0,1,0,0)"
|
||||||
|
inkscape:transform-center-x="4.1666013"
|
||||||
|
inkscape:transform-center-y="12.497753" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3837"
|
||||||
|
sodipodi:cx="303.75"
|
||||||
|
sodipodi:cy="89.537811"
|
||||||
|
sodipodi:rx="6.25"
|
||||||
|
sodipodi:ry="6.25"
|
||||||
|
d="m 310,89.537811 a 6.25,6.25 0 1 1 -12.5,0 6.25,6.25 0 1 1 12.5,0 z"
|
||||||
|
transform="translate(1092.4414,411.50937)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 16 KiB |
BIN
docs/design/quadtree/depth2addresses.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
1553
docs/design/quadtree/depth2addresses.svg
Normal file
|
After Width: | Height: | Size: 68 KiB |
BIN
docs/design/tilerendering/4children.png
Normal file
|
After Width: | Height: | Size: 153 KiB |
15364
docs/design/tilerendering/4children.svg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
docs/design/tilerendering/tilegrid.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
1396
docs/design/tilerendering/tilegrid.svg
Normal file
|
After Width: | Height: | Size: 62 KiB |
@@ -303,6 +303,19 @@ Less Useful Options
|
|||||||
|
|
||||||
Default: False
|
Default: False
|
||||||
|
|
||||||
|
.. cmdoption:: --stochastic-render <probability>
|
||||||
|
|
||||||
|
Provides a probability that a non-updated tile will be rerendered
|
||||||
|
anyway. Use this if there's a new rendering feature you want to
|
||||||
|
use, but you don't want to rerender the entire map at once.
|
||||||
|
|
||||||
|
**Settings file:**
|
||||||
|
Option name: ``stochastic_render``
|
||||||
|
|
||||||
|
Format: a floating-point number in the range 0.0 to 1.0
|
||||||
|
|
||||||
|
Default: 0.0
|
||||||
|
|
||||||
.. cmdoption:: --textures-path <path>
|
.. cmdoption:: --textures-path <path>
|
||||||
|
|
||||||
Use this option to specify an alternate terrain.png to use for textures when
|
Use this option to specify an alternate terrain.png to use for textures when
|
||||||
@@ -337,6 +350,11 @@ Less Useful Options
|
|||||||
|
|
||||||
Prints more output. You can specify this multiple times.
|
Prints more output. You can specify this multiple times.
|
||||||
|
|
||||||
|
Specifying this option also has the effect of changing the output format to
|
||||||
|
a more verbose one with additional information, in addition to outputting
|
||||||
|
more lines. If you specify both :option:`-v` and :option:`-q`, you can get
|
||||||
|
the more verbose line without additional output from debug lines.
|
||||||
|
|
||||||
**Settings file:**
|
**Settings file:**
|
||||||
Option name: ``verbose``
|
Option name: ``verbose``
|
||||||
|
|
||||||
|
|||||||
@@ -102,36 +102,74 @@ from overviewer_core.configParser import ConfigOptionParser
|
|||||||
from overviewer_core import optimizeimages, world, quadtree
|
from overviewer_core import optimizeimages, world, quadtree
|
||||||
from overviewer_core import googlemap, rendernode
|
from overviewer_core import googlemap, rendernode
|
||||||
|
|
||||||
|
# definitions of built-in custom modes
|
||||||
|
# usually because what used to be a mode became an option
|
||||||
|
# for example, night mode
|
||||||
|
builtin_custom_rendermodes = {
|
||||||
|
'night' : {
|
||||||
|
'parent' : 'lighting',
|
||||||
|
'label' : 'Night',
|
||||||
|
'description' : 'like "lighting", except at night',
|
||||||
|
'options' : {'night' : True}
|
||||||
|
},
|
||||||
|
|
||||||
|
'smooth-night' : {
|
||||||
|
'parent' : 'smooth-lighting',
|
||||||
|
'label' : 'Smooth Night',
|
||||||
|
'description' : 'like "lighting", except smooth and at night',
|
||||||
|
'options' : {'night' : True}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
helptext = """
|
helptext = """
|
||||||
%prog [OPTIONS] <World # / Name / Path to World> <tiles dest dir>"""
|
%prog [OPTIONS] <World # / Name / Path to World> <tiles dest dir>"""
|
||||||
|
|
||||||
def configure_logger():
|
def configure_logger(loglevel=logging.INFO, verbose=False):
|
||||||
"Configures the root logger to our liking"
|
"""Configures the root logger to our liking
|
||||||
|
|
||||||
|
For a non-standard loglevel, pass in the level with which to configure the handler.
|
||||||
|
|
||||||
|
For a more verbose options line, pass in verbose=True
|
||||||
|
|
||||||
|
This function may be called more than once.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger = logging.getLogger()
|
||||||
|
|
||||||
outstream = sys.stderr
|
outstream = sys.stderr
|
||||||
|
|
||||||
if platform.system() == 'Windows':
|
if platform.system() == 'Windows':
|
||||||
# Our custom output stream processor knows how to deal with select ANSI
|
# Our custom output stream processor knows how to deal with select ANSI
|
||||||
# color escape sequences
|
# color escape sequences
|
||||||
outstream = util.WindowsOutputStream()
|
outstream = util.WindowsOutputStream()
|
||||||
formatter = util.ANSIColorFormatter()
|
formatter = util.ANSIColorFormatter(verbose)
|
||||||
|
|
||||||
elif sys.stderr.isatty():
|
elif sys.stderr.isatty():
|
||||||
# terminal logging with ANSI color
|
# terminal logging with ANSI color
|
||||||
formatter = util.ANSIColorFormatter()
|
formatter = util.ANSIColorFormatter(verbose)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Let's not assume anything. Just text.
|
# Let's not assume anything. Just text.
|
||||||
formatter = util.DumbFormatter()
|
formatter = util.DumbFormatter(verbose)
|
||||||
|
|
||||||
logger = logging.getLogger()
|
if hasattr(logger, 'overviewerHandler'):
|
||||||
handler = logging.StreamHandler(outstream)
|
# we have already set up logging so just replace the formatter
|
||||||
handler.setFormatter(formatter)
|
# this time with the new values
|
||||||
logger.addHandler(handler)
|
logger.overviewerHandler.setFormatter(formatter)
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(loglevel)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Save our handler here so we can tell which handler was ours if the
|
||||||
|
# function is called again
|
||||||
|
logger.overviewerHandler = logging.StreamHandler(outstream)
|
||||||
|
logger.overviewerHandler.setFormatter(formatter)
|
||||||
|
logger.addHandler(logger.overviewerHandler)
|
||||||
|
logger.setLevel(loglevel)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
|
# bootstrap the logger with defaults
|
||||||
configure_logger()
|
configure_logger()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -148,6 +186,7 @@ def main():
|
|||||||
parser.add_option("-z", "--zoom", dest="zoom", helptext="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles", action="store", type="int", advanced=True)
|
parser.add_option("-z", "--zoom", dest="zoom", helptext="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles", action="store", type="int", advanced=True)
|
||||||
parser.add_option("--regionlist", dest="regionlist", helptext="A file containing, on each line, a path to a regionlist to update. Instead of scanning the world directory for regions, it will just use this list. Normal caching rules still apply.")
|
parser.add_option("--regionlist", dest="regionlist", helptext="A file containing, on each line, a path to a regionlist to update. Instead of scanning the world directory for regions, it will just use this list. Normal caching rules still apply.")
|
||||||
parser.add_option("--forcerender", dest="forcerender", helptext="Force re-rendering the entire map (or the given regionlist). Useful for re-rendering without deleting it.", action="store_true")
|
parser.add_option("--forcerender", dest="forcerender", helptext="Force re-rendering the entire map (or the given regionlist). Useful for re-rendering without deleting it.", action="store_true")
|
||||||
|
parser.add_option("--stochastic-render", dest="stochastic_render", helptext="Rerender a non-updated tile randomly, with the given probability (between 0 and 1). Useful for incrementally updating a map with a new mode.", type="float", advanced=True, default=0.0, metavar="PROBABILITY")
|
||||||
parser.add_option("--rendermodes", dest="rendermode", helptext="Specifies the render types, separated by ',', ':', or '/'. Use --list-rendermodes to list them all.", type="choice", required=True, default=avail_rendermodes[0], listify=True)
|
parser.add_option("--rendermodes", dest="rendermode", helptext="Specifies the render types, separated by ',', ':', or '/'. Use --list-rendermodes to list them all.", type="choice", required=True, default=avail_rendermodes[0], listify=True)
|
||||||
parser.add_option("--list-rendermodes", dest="list_rendermodes", action="store_true", helptext="List available render modes and exit.", commandLineOnly=True)
|
parser.add_option("--list-rendermodes", dest="list_rendermodes", action="store_true", helptext="List available render modes and exit.", commandLineOnly=True)
|
||||||
parser.add_option("--rendermode-options", dest="rendermode_options", default={}, advanced=True, helptext="Used to specify options for different rendermodes. Only useful in a settings.py file")
|
parser.add_option("--rendermode-options", dest="rendermode_options", default={}, advanced=True, helptext="Used to specify options for different rendermodes. Only useful in a settings.py file")
|
||||||
@@ -172,6 +211,9 @@ def main():
|
|||||||
|
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
# re-configure the logger now that we've processed the command line options
|
||||||
|
configure_logger(logging.INFO + 10*options.quiet - 10*options.verbose,
|
||||||
|
options.verbose > 0)
|
||||||
|
|
||||||
if options.version:
|
if options.version:
|
||||||
try:
|
try:
|
||||||
@@ -186,6 +228,8 @@ def main():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# setup c_overviewer rendermode customs / options
|
# setup c_overviewer rendermode customs / options
|
||||||
|
for mode in builtin_custom_rendermodes:
|
||||||
|
c_overviewer.add_custom_render_mode(mode, builtin_custom_rendermodes[mode])
|
||||||
for mode in options.custom_rendermodes:
|
for mode in options.custom_rendermodes:
|
||||||
c_overviewer.add_custom_render_mode(mode, options.custom_rendermodes[mode])
|
c_overviewer.add_custom_render_mode(mode, options.custom_rendermodes[mode])
|
||||||
for mode in options.rendermode_options:
|
for mode in options.rendermode_options:
|
||||||
@@ -314,11 +358,6 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
|
|||||||
north_direction = options.north_direction
|
north_direction = options.north_direction
|
||||||
else:
|
else:
|
||||||
north_direction = 'auto'
|
north_direction = 'auto'
|
||||||
|
|
||||||
logging.getLogger().setLevel(
|
|
||||||
logging.getLogger().level + 10*options.quiet)
|
|
||||||
logging.getLogger().setLevel(
|
|
||||||
logging.getLogger().level - 10*options.verbose)
|
|
||||||
|
|
||||||
if options.changelist:
|
if options.changelist:
|
||||||
try:
|
try:
|
||||||
@@ -369,7 +408,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
|
|||||||
w.determine_bounds()
|
w.determine_bounds()
|
||||||
w.find_true_spawn()
|
w.find_true_spawn()
|
||||||
|
|
||||||
logging.info("Rending the following tilesets: %s", ",".join(options.rendermode))
|
logging.info("Rendering the following tilesets: %s", ",".join(options.rendermode))
|
||||||
|
|
||||||
bgcolor = (int(options.bg_color[1:3],16),
|
bgcolor = (int(options.bg_color[1:3],16),
|
||||||
int(options.bg_color[3:5],16),
|
int(options.bg_color[3:5],16),
|
||||||
@@ -388,6 +427,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
|
|||||||
'optimizeimg' : optimizeimg,
|
'optimizeimg' : optimizeimg,
|
||||||
'bgcolor' : bgcolor,
|
'bgcolor' : bgcolor,
|
||||||
'forcerender' : options.forcerender,
|
'forcerender' : options.forcerender,
|
||||||
|
'rerender_prob' : options.stochastic_render
|
||||||
}
|
}
|
||||||
for rendermode in options.rendermode:
|
for rendermode in options.rendermode:
|
||||||
if rendermode == 'normal':
|
if rendermode == 'normal':
|
||||||
@@ -478,6 +518,13 @@ def list_worlds():
|
|||||||
print 'No world saves found in the usual place'
|
print 'No world saves found in the usual place'
|
||||||
return
|
return
|
||||||
print "Detected saves:"
|
print "Detected saves:"
|
||||||
|
|
||||||
|
# get max length of world name
|
||||||
|
worldNameLen = max([len(str(x)) for x in worlds] + [len("World")])
|
||||||
|
|
||||||
|
formatString = "%-" + str(worldNameLen) + "s | %-8s | %-8s | %-16s "
|
||||||
|
print formatString % ("World", "Size", "Playtime", "Modified")
|
||||||
|
print formatString % ("-"*worldNameLen, "-"*8, "-"*8, '-'*16)
|
||||||
for name, info in sorted(worlds.iteritems()):
|
for name, info in sorted(worlds.iteritems()):
|
||||||
if isinstance(name, basestring) and name.startswith("World") and len(name) == 6:
|
if isinstance(name, basestring) and name.startswith("World") and len(name) == 6:
|
||||||
try:
|
try:
|
||||||
@@ -492,9 +539,15 @@ def list_worlds():
|
|||||||
playtime = info['Time'] / 20
|
playtime = info['Time'] / 20
|
||||||
playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60)
|
playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60)
|
||||||
size = "%.2fMB" % (info['SizeOnDisk'] / 1024. / 1024.)
|
size = "%.2fMB" % (info['SizeOnDisk'] / 1024. / 1024.)
|
||||||
print "World %s: %s Playtime: %s Modified: %s" % (name, size, playstamp, timestamp)
|
print formatString % (name, size, playstamp, timestamp)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
multiprocessing.freeze_support()
|
multiprocessing.freeze_support()
|
||||||
main()
|
try:
|
||||||
|
main()
|
||||||
|
except Exception, e:
|
||||||
|
logging.exception("""An error has occurred. This may be a bug. Please let us know!
|
||||||
|
See http://docs.overviewer.org/en/latest/index.html#help
|
||||||
|
|
||||||
|
This is the error that occurred:""")
|
||||||
|
|||||||
@@ -124,7 +124,11 @@ var overviewer = {
|
|||||||
for (i in overviewerConfig.mapTypes) {
|
for (i in overviewerConfig.mapTypes) {
|
||||||
var view = overviewerConfig.mapTypes[i];
|
var view = overviewerConfig.mapTypes[i];
|
||||||
var imageFormat = view.imgformat ? view.imgformat : 'png';
|
var imageFormat = view.imgformat ? view.imgformat : 'png';
|
||||||
mapOptions[view.label] = {
|
|
||||||
|
if (view.shortname == null)
|
||||||
|
view.shortname = view.label.replace(/\s+/g, "");
|
||||||
|
|
||||||
|
mapOptions[view.shortname] = {
|
||||||
'getTileUrl': overviewer.gmap.getTileUrlGenerator(view.path,
|
'getTileUrl': overviewer.gmap.getTileUrlGenerator(view.path,
|
||||||
view.base, imageFormat),
|
view.base, imageFormat),
|
||||||
'tileSize': new google.maps.Size(
|
'tileSize': new google.maps.Size(
|
||||||
@@ -134,19 +138,20 @@ var overviewer = {
|
|||||||
'minZoom': overviewerConfig.map.minZoom,
|
'minZoom': overviewerConfig.map.minZoom,
|
||||||
'isPng': imageFormat.toLowerCase() == 'png'
|
'isPng': imageFormat.toLowerCase() == 'png'
|
||||||
}
|
}
|
||||||
overviewer.collections.mapTypes[view.label] = new google.maps.ImageMapType(
|
overviewer.collections.mapTypes[view.shortname] = new google.maps.ImageMapType(
|
||||||
mapOptions[view.label]);
|
mapOptions[view.shortname]);
|
||||||
overviewer.collections.mapTypes[view.label].name = view.label;
|
overviewer.collections.mapTypes[view.shortname].name = view.label;
|
||||||
overviewer.collections.mapTypes[view.label].alt = 'Minecraft ' +
|
overviewer.collections.mapTypes[view.shortname].shortname = view.shortname;
|
||||||
|
overviewer.collections.mapTypes[view.shortname].alt = 'Minecraft ' +
|
||||||
view.label + ' Map';
|
view.label + ' Map';
|
||||||
overviewer.collections.mapTypes[view.label].projection =
|
overviewer.collections.mapTypes[view.shortname].projection =
|
||||||
new overviewer.classes.MapProjection();
|
new overviewer.classes.MapProjection();
|
||||||
if (view.overlay) {
|
if (view.overlay) {
|
||||||
overviewer.collections.overlays.push(
|
overviewer.collections.overlays.push(
|
||||||
overviewer.collections.mapTypes[view.label]);
|
overviewer.collections.mapTypes[view.shortname]);
|
||||||
} else {
|
} else {
|
||||||
overviewer.collections.mapTypeIds.push(
|
overviewer.collections.mapTypeIds.push(
|
||||||
overviewerConfig.CONST.mapDivId + view.label);
|
overviewerConfig.CONST.mapDivId + view.shortname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -245,7 +250,7 @@ var overviewer = {
|
|||||||
// Now attach the coordinate map type to the map's registry
|
// Now attach the coordinate map type to the map's registry
|
||||||
for (i in overviewer.collections.mapTypes) {
|
for (i in overviewer.collections.mapTypes) {
|
||||||
overviewer.map.mapTypes.set(overviewerConfig.CONST.mapDivId +
|
overviewer.map.mapTypes.set(overviewerConfig.CONST.mapDivId +
|
||||||
overviewer.collections.mapTypes[i].name,
|
overviewer.collections.mapTypes[i].shortname,
|
||||||
overviewer.collections.mapTypes[i]);
|
overviewer.collections.mapTypes[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +487,7 @@ var overviewer = {
|
|||||||
'getMapTypeBackgroundColor': function(mapTypeId) {
|
'getMapTypeBackgroundColor': function(mapTypeId) {
|
||||||
for(i in overviewerConfig.mapTypes) {
|
for(i in overviewerConfig.mapTypes) {
|
||||||
if( overviewerConfig.CONST.mapDivId +
|
if( overviewerConfig.CONST.mapDivId +
|
||||||
overviewerConfig.mapTypes[i].label == mapTypeId ) {
|
overviewerConfig.mapTypes[i].shortname == mapTypeId ) {
|
||||||
overviewer.util.debug('Found background color for: ' +
|
overviewer.util.debug('Found background color for: ' +
|
||||||
overviewerConfig.mapTypes[i].bg_color);
|
overviewerConfig.mapTypes[i].bg_color);
|
||||||
return overviewerConfig.mapTypes[i].bg_color;
|
return overviewerConfig.mapTypes[i].bg_color;
|
||||||
@@ -974,6 +979,11 @@ var overviewer = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
'setHash': function(x, y, z, zoom, maptype) {
|
'setHash': function(x, y, z, zoom, maptype) {
|
||||||
|
// remove the div prefix from the maptype (looks better)
|
||||||
|
if (maptype)
|
||||||
|
{
|
||||||
|
maptype = maptype.replace(overviewerConfig.CONST.mapDivId, "");
|
||||||
|
}
|
||||||
window.location.replace("#/" + Math.floor(x) + "/" + Math.floor(y) + "/" + Math.floor(z) + "/" + zoom + "/" + maptype);
|
window.location.replace("#/" + Math.floor(x) + "/" + Math.floor(y) + "/" + Math.floor(z) + "/" + zoom + "/" + maptype);
|
||||||
},
|
},
|
||||||
'updateHash': function() {
|
'updateHash': function() {
|
||||||
@@ -1023,7 +1033,20 @@ var overviewer = {
|
|||||||
// We can now set the map to use the 'coordinate' map type
|
// We can now set the map to use the 'coordinate' map type
|
||||||
overviewer.map.setMapTypeId(overviewer.util.getDefaultMapTypeId());
|
overviewer.map.setMapTypeId(overviewer.util.getDefaultMapTypeId());
|
||||||
} else {
|
} else {
|
||||||
overviewer.map.setMapTypeId(maptype);
|
// normalize the map type (this supports old-style,
|
||||||
|
// 'mcmapLabel' style map types, converts them to 'shortname'
|
||||||
|
if (maptype.lastIndexOf(overviewerConfig.CONST.mapDivId, 0) === 0) {
|
||||||
|
maptype = maptype.replace(overviewerConfig.CONST.mapDivId, "");
|
||||||
|
for (i in overviewer.collections.mapTypes) {
|
||||||
|
var type = overviewer.collections.mapTypes[i];
|
||||||
|
if (type.name == maptype) {
|
||||||
|
maptype = type.shortname;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
overviewer.map.setMapTypeId(overviewerConfig.CONST.mapDivId + maptype);
|
||||||
}
|
}
|
||||||
|
|
||||||
overviewer.map.setCenter(latlngcoords);
|
overviewer.map.setCenter(latlngcoords);
|
||||||
|
|||||||
@@ -172,6 +172,10 @@ var overviewerConfig = {
|
|||||||
* the js/html server.
|
* the js/html server.
|
||||||
* imgformat : string. File extension used for these tiles. Defaults to png.
|
* imgformat : string. File extension used for these tiles. Defaults to png.
|
||||||
* overlay : bool. If true, this tile set will be treated like an overlay
|
* overlay : bool. If true, this tile set will be treated like an overlay
|
||||||
|
* bg_color : string. A #RRGGBB format background color.
|
||||||
|
* shortname : string. Used in the dynamic anchor link mechanism. If not
|
||||||
|
* present, label is used instead.
|
||||||
|
*
|
||||||
* Example:
|
* Example:
|
||||||
* 'mapTypes': [
|
* 'mapTypes': [
|
||||||
* {'label': 'Day', 'path': 'lighting/tiles'},
|
* {'label': 'Day', 'path': 'lighting/tiles'},
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ class MapGen(object):
|
|||||||
|
|
||||||
# create generated map type data, from given quadtrees
|
# create generated map type data, from given quadtrees
|
||||||
maptypedata = map(lambda q: {'label' : get_render_mode_label(q.rendermode),
|
maptypedata = map(lambda q: {'label' : get_render_mode_label(q.rendermode),
|
||||||
|
'shortname' : q.rendermode,
|
||||||
'path' : q.tiledir,
|
'path' : q.tiledir,
|
||||||
'bg_color': self.bg_color,
|
'bg_color': self.bg_color,
|
||||||
'overlay' : 'overlay' in get_render_mode_inheritance(q.rendermode),
|
'overlay' : 'overlay' in get_render_mode_inheritance(q.rendermode),
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import cPickle
|
|||||||
import stat
|
import stat
|
||||||
import errno
|
import errno
|
||||||
import time
|
import time
|
||||||
|
import random
|
||||||
from time import gmtime, strftime, sleep
|
from time import gmtime, strftime, sleep
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
@@ -49,7 +50,7 @@ def iterate_base4(d):
|
|||||||
return itertools.product(xrange(4), repeat=d)
|
return itertools.product(xrange(4), repeat=d)
|
||||||
|
|
||||||
class QuadtreeGen(object):
|
class QuadtreeGen(object):
|
||||||
def __init__(self, worldobj, destdir, bgcolor="#1A1A1A", depth=None, tiledir=None, forcerender=False, imgformat='png', imgquality=95, optimizeimg=None, rendermode="normal"):
|
def __init__(self, worldobj, destdir, bgcolor="#1A1A1A", depth=None, tiledir=None, forcerender=False, imgformat='png', imgquality=95, optimizeimg=None, rendermode="normal", rerender_prob=0.0):
|
||||||
"""Generates a quadtree from the world given into the
|
"""Generates a quadtree from the world given into the
|
||||||
given dest directory
|
given dest directory
|
||||||
|
|
||||||
@@ -60,6 +61,7 @@ class QuadtreeGen(object):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
self.forcerender = forcerender
|
self.forcerender = forcerender
|
||||||
|
self.rerender_probability = rerender_prob
|
||||||
self.imgformat = imgformat
|
self.imgformat = imgformat
|
||||||
self.imgquality = imgquality
|
self.imgquality = imgquality
|
||||||
self.optimizeimg = optimizeimg
|
self.optimizeimg = optimizeimg
|
||||||
@@ -286,7 +288,7 @@ class QuadtreeGen(object):
|
|||||||
|
|
||||||
#stat the tile, we need to know if it exists or it's mtime
|
#stat the tile, we need to know if it exists or it's mtime
|
||||||
try:
|
try:
|
||||||
tile_mtime = os.stat(imgpath)[stat.ST_MTIME];
|
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
@@ -371,7 +373,7 @@ class QuadtreeGen(object):
|
|||||||
world = self.world
|
world = self.world
|
||||||
#stat the file, we need to know if it exists or it's mtime
|
#stat the file, we need to know if it exists or it's mtime
|
||||||
try:
|
try:
|
||||||
tile_mtime = os.stat(imgpath)[stat.ST_MTIME];
|
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
||||||
except OSError, e:
|
except OSError, e:
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
@@ -399,6 +401,7 @@ class QuadtreeGen(object):
|
|||||||
try:
|
try:
|
||||||
needs_rerender = False
|
needs_rerender = False
|
||||||
get_region_mtime = world.get_region_mtime
|
get_region_mtime = world.get_region_mtime
|
||||||
|
|
||||||
for col, row, chunkx, chunky, regionfile in chunks:
|
for col, row, chunkx, chunky, regionfile in chunks:
|
||||||
region, regionMtime = get_region_mtime(regionfile)
|
region, regionMtime = get_region_mtime(regionfile)
|
||||||
|
|
||||||
@@ -423,6 +426,10 @@ class QuadtreeGen(object):
|
|||||||
needs_rerender = True
|
needs_rerender = True
|
||||||
break
|
break
|
||||||
|
|
||||||
|
# stochastic render check
|
||||||
|
if not needs_rerender and self.rerender_probability > 0.0 and random.uniform(0, 1) < self.rerender_probability:
|
||||||
|
needs_rerender = True
|
||||||
|
|
||||||
# if after all that, we don't need a rerender, return
|
# if after all that, we don't need a rerender, return
|
||||||
if not needs_rerender:
|
if not needs_rerender:
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -358,3 +358,129 @@ tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
|||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* draws a triangle on the destination image, multiplicatively!
|
||||||
|
* used for smooth lighting
|
||||||
|
* (excuse the ridiculous number of parameters!)
|
||||||
|
*
|
||||||
|
* Algorithm adapted from _Fundamentals_of_Computer_Graphics_
|
||||||
|
* by Peter Shirley, Michael Ashikhmin
|
||||||
|
* (or at least, the version poorly reproduced here:
|
||||||
|
* http://www.gidforums.com/t-20838.html )
|
||||||
|
*/
|
||||||
|
PyObject *
|
||||||
|
draw_triangle(PyObject *dest, int inclusive,
|
||||||
|
int x0, int y0,
|
||||||
|
unsigned char r0, unsigned char g0, unsigned char b0,
|
||||||
|
int x1, int y1,
|
||||||
|
unsigned char r1, unsigned char g1, unsigned char b1,
|
||||||
|
int x2, int y2,
|
||||||
|
unsigned char r2, unsigned char g2, unsigned char b2,
|
||||||
|
int tux, int tuy, int *touchups, unsigned int num_touchups) {
|
||||||
|
|
||||||
|
/* destination image */
|
||||||
|
Imaging imDest;
|
||||||
|
/* ranges of pixels that are affected */
|
||||||
|
int xmin, xmax, ymin, ymax;
|
||||||
|
/* constant coefficients for alpha, beta, gamma */
|
||||||
|
int a12, a20, a01;
|
||||||
|
int b12, b20, b01;
|
||||||
|
int c12, c20, c01;
|
||||||
|
/* constant normalizers for alpha, beta, gamma */
|
||||||
|
float alpha_norm, beta_norm, gamma_norm;
|
||||||
|
/* temporary variables */
|
||||||
|
int tmp;
|
||||||
|
/* iteration variables */
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
imDest = imaging_python_to_c(dest);
|
||||||
|
if (!imDest)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* check the various image modes, make sure they make sense */
|
||||||
|
if (strcmp(imDest->mode, "RGBA") != 0) {
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"given destination image does not have mode \"RGBA\"");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up draw ranges */
|
||||||
|
xmin = MIN(x0, MIN(x1, x2));
|
||||||
|
ymin = MIN(y0, MIN(y1, y2));
|
||||||
|
xmax = MAX(x0, MAX(x1, x2)) + 1;
|
||||||
|
ymax = MAX(y0, MAX(y1, y2)) + 1;
|
||||||
|
|
||||||
|
xmin = MAX(xmin, 0);
|
||||||
|
ymin = MAX(ymin, 0);
|
||||||
|
xmax = MIN(xmax, imDest->xsize);
|
||||||
|
ymax = MIN(ymax, imDest->ysize);
|
||||||
|
|
||||||
|
/* setup coefficients */
|
||||||
|
a12 = y1 - y2; b12 = x2 - x1; c12 = (x1 * y2) - (x2 * y1);
|
||||||
|
a20 = y2 - y0; b20 = x0 - x2; c20 = (x2 * y0) - (x0 * y2);
|
||||||
|
a01 = y0 - y1; b01 = x1 - x0; c01 = (x0 * y1) - (x1 * y0);
|
||||||
|
|
||||||
|
/* setup normalizers */
|
||||||
|
alpha_norm = 1.0f / ((a12 * x0) + (b12 * y0) + c12);
|
||||||
|
beta_norm = 1.0f / ((a20 * x1) + (b20 * y1) + c20);
|
||||||
|
gamma_norm = 1.0f / ((a01 * x2) + (b01 * y2) + c01);
|
||||||
|
|
||||||
|
/* iterate over the destination rect */
|
||||||
|
for (y = ymin; y < ymax; y++) {
|
||||||
|
UINT8 *out = (UINT8 *)imDest->image[y] + xmin * 4;
|
||||||
|
|
||||||
|
for (x = xmin; x < xmax; x++) {
|
||||||
|
float alpha, beta, gamma;
|
||||||
|
alpha = alpha_norm * ((a12 * x) + (b12 * y) + c12);
|
||||||
|
beta = beta_norm * ((a20 * x) + (b20 * y) + c20);
|
||||||
|
gamma = gamma_norm * ((a01 * x) + (b01 * y) + c01);
|
||||||
|
|
||||||
|
if (alpha >= 0 && beta >= 0 && gamma >= 0 &&
|
||||||
|
(inclusive || (alpha * beta * gamma > 0))) {
|
||||||
|
unsigned int r = alpha * r0 + beta * r1 + gamma * r2;
|
||||||
|
unsigned int g = alpha * g0 + beta * g1 + gamma * g2;
|
||||||
|
unsigned int b = alpha * b0 + beta * b1 + gamma * b2;
|
||||||
|
|
||||||
|
*out = MULDIV255(*out, r, tmp); out++;
|
||||||
|
*out = MULDIV255(*out, g, tmp); out++;
|
||||||
|
*out = MULDIV255(*out, b, tmp); out++;
|
||||||
|
|
||||||
|
/* keep alpha the same */
|
||||||
|
out++;
|
||||||
|
} else {
|
||||||
|
/* skip */
|
||||||
|
out += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (num_touchups > 0) {
|
||||||
|
float alpha, beta, gamma;
|
||||||
|
unsigned int r, g, b;
|
||||||
|
UINT8 *out;
|
||||||
|
|
||||||
|
x = touchups[0] + tux;
|
||||||
|
y = touchups[1] + tuy;
|
||||||
|
touchups += 2;
|
||||||
|
num_touchups--;
|
||||||
|
|
||||||
|
if (x < 0 || x >= imDest->xsize || y < 0 || y >= imDest->ysize)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
out = (UINT8 *)imDest->image[y] + x * 4;
|
||||||
|
|
||||||
|
alpha = alpha_norm * ((a12 * x) + (b12 * y) + c12);
|
||||||
|
beta = beta_norm * ((a20 * x) + (b20 * y) + c20);
|
||||||
|
gamma = gamma_norm * ((a01 * x) + (b01 * y) + c01);
|
||||||
|
|
||||||
|
r = alpha * r0 + beta * r1 + gamma * r2;
|
||||||
|
g = alpha * g0 + beta * g1 + gamma * g2;
|
||||||
|
b = alpha * b0 + beta * b1 + gamma * b2;
|
||||||
|
|
||||||
|
*out = MULDIV255(*out, r, tmp); out++;
|
||||||
|
*out = MULDIV255(*out, g, tmp); out++;
|
||||||
|
*out = MULDIV255(*out, b, tmp); out++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
// increment this value if you've made a change to the c extesion
|
// increment this value if you've made a change to the c extesion
|
||||||
// and want to force users to rebuild
|
// and want to force users to rebuild
|
||||||
#define OVERVIEWER_EXTENSION_VERSION 11
|
#define OVERVIEWER_EXTENSION_VERSION 12
|
||||||
|
|
||||||
/* Python PIL, and numpy headers */
|
/* Python PIL, and numpy headers */
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
@@ -51,6 +51,14 @@ PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
|
|||||||
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
||||||
unsigned char sb, unsigned char sa,
|
unsigned char sb, unsigned char sa,
|
||||||
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
||||||
|
PyObject *draw_triangle(PyObject *dest, int inclusive,
|
||||||
|
int x0, int y0,
|
||||||
|
unsigned char r0, unsigned char g0, unsigned char b0,
|
||||||
|
int x1, int y1,
|
||||||
|
unsigned char r1, unsigned char g1, unsigned char b1,
|
||||||
|
int x2, int y2,
|
||||||
|
unsigned char r2, unsigned char g2, unsigned char b2,
|
||||||
|
int tux, int tuy, int *touchups, unsigned int num_touchups);
|
||||||
|
|
||||||
/* forward declaration of RenderMode object */
|
/* forward declaration of RenderMode object */
|
||||||
typedef struct _RenderMode RenderMode;
|
typedef struct _RenderMode RenderMode;
|
||||||
|
|||||||
@@ -51,6 +51,39 @@ calculate_light_color_fancy(void *data,
|
|||||||
Py_DECREF(color);
|
Py_DECREF(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* figures out the color from a given skylight and blocklight, used in
|
||||||
|
lighting calculations -- note this is *different* from the one above
|
||||||
|
(the "skylight - 11" part)
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
calculate_light_color_night(void *data,
|
||||||
|
unsigned char skylight, unsigned char blocklight,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
unsigned char v = 255 * powf(0.8f, 15.0 - MAX(blocklight, skylight - 11));
|
||||||
|
*r = v;
|
||||||
|
*g = v;
|
||||||
|
*b = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fancy night version that uses the colored light texture */
|
||||||
|
static void
|
||||||
|
calculate_light_color_fancy_night(void *data,
|
||||||
|
unsigned char skylight, unsigned char blocklight,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b) {
|
||||||
|
RenderModeLighting *mode = (RenderModeLighting *)(data);
|
||||||
|
unsigned int index;
|
||||||
|
PyObject *color;
|
||||||
|
|
||||||
|
index = skylight + blocklight * 16;
|
||||||
|
color = PySequence_GetItem(mode->lightcolor, index);
|
||||||
|
|
||||||
|
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||||
|
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||||
|
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||||
|
|
||||||
|
Py_DECREF(color);
|
||||||
|
}
|
||||||
|
|
||||||
/* loads the appropriate light data for the given (possibly non-local)
|
/* loads the appropriate light data for the given (possibly non-local)
|
||||||
* coordinates, and returns a black_coeff this is exposed, so other (derived)
|
* coordinates, and returns a black_coeff this is exposed, so other (derived)
|
||||||
* rendermodes can use it
|
* rendermodes can use it
|
||||||
@@ -162,9 +195,9 @@ get_lighting_color(RenderModeLighting *self, RenderState *state,
|
|||||||
PyObject *blocklight = NULL;
|
PyObject *blocklight = NULL;
|
||||||
int local_x = x, local_y = y, local_z = z;
|
int local_x = x, local_y = y, local_z = z;
|
||||||
unsigned char block, skylevel, blocklevel;
|
unsigned char block, skylevel, blocklevel;
|
||||||
|
|
||||||
/* find out what chunk we're in, and translate accordingly */
|
/* find out what chunk we're in, and translate accordingly */
|
||||||
if (x >= 0 && y < 16) {
|
if (x >= 0 && x < 16 && y >= 0 && y < 16) {
|
||||||
blocks = state->blocks;
|
blocks = state->blocks;
|
||||||
skylight = self->skylight;
|
skylight = self->skylight;
|
||||||
blocklight = self->blocklight;
|
blocklight = self->blocklight;
|
||||||
@@ -178,13 +211,23 @@ get_lighting_color(RenderModeLighting *self, RenderState *state,
|
|||||||
blocks = state->right_blocks;
|
blocks = state->right_blocks;
|
||||||
skylight = self->right_skylight;
|
skylight = self->right_skylight;
|
||||||
blocklight = self->right_blocklight;
|
blocklight = self->right_blocklight;
|
||||||
|
} else if (y < 0) {
|
||||||
|
local_y += 16;
|
||||||
|
blocks = state->up_left_blocks;
|
||||||
|
skylight = self->up_left_skylight;
|
||||||
|
blocklight = self->up_left_blocklight;
|
||||||
|
} else if (x >= 16) {
|
||||||
|
local_x -= 16;
|
||||||
|
blocks = state->up_right_blocks;
|
||||||
|
skylight = self->up_right_skylight;
|
||||||
|
blocklight = self->up_right_blocklight;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure we have correctly-ranged coordinates */
|
/* make sure we have correctly-ranged coordinates */
|
||||||
if (!(local_x >= 0 && local_x < 16 &&
|
if (!(local_x >= 0 && local_x < 16 &&
|
||||||
local_y >= 0 && local_y < 16 &&
|
local_y >= 0 && local_y < 16 &&
|
||||||
local_z >= 0 && local_z < 128)) {
|
local_z >= 0 && local_z < 128)) {
|
||||||
|
|
||||||
self->calculate_light_color(self, 15, 0, r, g, b);
|
self->calculate_light_color(self, 15, 0, r, g, b);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -193,7 +236,7 @@ get_lighting_color(RenderModeLighting *self, RenderState *state,
|
|||||||
if (blocks == Py_None || blocks == NULL ||
|
if (blocks == Py_None || blocks == NULL ||
|
||||||
skylight == Py_None || skylight == NULL ||
|
skylight == Py_None || skylight == NULL ||
|
||||||
blocklight == Py_None || blocklight == NULL) {
|
blocklight == Py_None || blocklight == NULL) {
|
||||||
|
|
||||||
self->calculate_light_color(self, 15, 0, r, g, b);
|
self->calculate_light_color(self, 15, 0, r, g, b);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -236,6 +279,39 @@ get_lighting_color(RenderModeLighting *self, RenderState *state,
|
|||||||
self->calculate_light_color(self, MIN(skylevel, 15), MIN(blocklevel, 15), r, g, b);
|
self->calculate_light_color(self, MIN(skylevel, 15), MIN(blocklevel, 15), r, g, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* does per-face occlusion checking for do_shading_with_mask */
|
||||||
|
inline int
|
||||||
|
rendermode_lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z) {
|
||||||
|
/* first, check for occlusion if the block is in the local chunk */
|
||||||
|
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
||||||
|
unsigned char block = getArrayByte3D(state->blocks, x, y, z);
|
||||||
|
|
||||||
|
if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) {
|
||||||
|
/* this face isn't visible, so don't draw anything */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (skip_sides && (x == -1) && (state->left_blocks != Py_None)) {
|
||||||
|
unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, state->z);
|
||||||
|
if (!is_transparent(block)) {
|
||||||
|
/* the same thing but for adjacent chunks, this solves an
|
||||||
|
ugly black doted line between chunks in night rendermode.
|
||||||
|
This wouldn't be necessary if the textures were truly
|
||||||
|
tessellate-able */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (skip_sides && (y == 16) && (state->right_blocks != Py_None)) {
|
||||||
|
unsigned char block = getArrayByte3D(state->right_blocks, state->x, 0, state->z);
|
||||||
|
if (!is_transparent(block)) {
|
||||||
|
/* the same thing but for adjacent chunks, this solves an
|
||||||
|
ugly black doted line between chunks in night rendermode.
|
||||||
|
This wouldn't be necessary if the textures were truly
|
||||||
|
tessellate-able */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* shades the drawn block with the given facemask, based on the
|
/* shades the drawn block with the given facemask, based on the
|
||||||
lighting results from (x, y, z) */
|
lighting results from (x, y, z) */
|
||||||
static inline void
|
static inline void
|
||||||
@@ -244,33 +320,9 @@ do_shading_with_mask(RenderModeLighting *self, RenderState *state,
|
|||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
float comp_shade_strength;
|
float comp_shade_strength;
|
||||||
|
|
||||||
/* first, check for occlusion if the block is in the local chunk */
|
/* check occlusion */
|
||||||
if (x >= 0 && x < 16 && y >= 0 && y < 16 && z >= 0 && z < 128) {
|
if (rendermode_lighting_is_face_occluded(state, self->skip_sides, x, y, z))
|
||||||
unsigned char block = getArrayByte3D(state->blocks, x, y, z);
|
return;
|
||||||
|
|
||||||
if (!is_transparent(block) && !render_mode_hidden(state->rendermode, x, y, z)) {
|
|
||||||
/* this face isn't visible, so don't draw anything */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (self->skip_sides && (x == -1) && (state->left_blocks != Py_None)) {
|
|
||||||
unsigned char block = getArrayByte3D(state->left_blocks, 15, state->y, state->z);
|
|
||||||
if (!is_transparent(block)) {
|
|
||||||
/* the same thing but for adjacent chunks, this solves an
|
|
||||||
ugly black doted line between chunks in night rendermode.
|
|
||||||
This wouldn't be necessary if the textures were truly
|
|
||||||
tessellate-able */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (self->skip_sides && (y == 16) && (state->right_blocks != Py_None)) {
|
|
||||||
unsigned char block = getArrayByte3D(state->right_blocks, state->x, 0, state->z);
|
|
||||||
if (!is_transparent(block)) {
|
|
||||||
/* the same thing but for adjacent chunks, this solves an
|
|
||||||
ugly black doted line between chunks in night rendermode.
|
|
||||||
This wouldn't be necessary if the textures were truly
|
|
||||||
tessellate-able */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get_lighting_color(self, state, x, y, z, &r, &g, &b);
|
get_lighting_color(self, state, x, y, z, &r, &g, &b);
|
||||||
comp_shade_strength = 1.0 - self->shade_strength;
|
comp_shade_strength = 1.0 - self->shade_strength;
|
||||||
@@ -300,6 +352,10 @@ rendermode_lighting_start(void *data, RenderState *state, PyObject *options) {
|
|||||||
if (!render_mode_parse_option(options, "shade_strength", "f", &(self->shade_strength)))
|
if (!render_mode_parse_option(options, "shade_strength", "f", &(self->shade_strength)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
self->night = 0;
|
||||||
|
if (!render_mode_parse_option(options, "night", "i", &(self->night)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
self->color_light = 0;
|
self->color_light = 0;
|
||||||
if (!render_mode_parse_option(options, "color_light", "i", &(self->color_light)))
|
if (!render_mode_parse_option(options, "color_light", "i", &(self->color_light)))
|
||||||
return 1;
|
return 1;
|
||||||
@@ -316,8 +372,16 @@ rendermode_lighting_start(void *data, RenderState *state, PyObject *options) {
|
|||||||
self->left_blocklight = PyObject_GetAttrString(state->self, "left_blocklight");
|
self->left_blocklight = PyObject_GetAttrString(state->self, "left_blocklight");
|
||||||
self->right_skylight = PyObject_GetAttrString(state->self, "right_skylight");
|
self->right_skylight = PyObject_GetAttrString(state->self, "right_skylight");
|
||||||
self->right_blocklight = PyObject_GetAttrString(state->self, "right_blocklight");
|
self->right_blocklight = PyObject_GetAttrString(state->self, "right_blocklight");
|
||||||
|
self->up_left_skylight = PyObject_GetAttrString(state->self, "up_left_skylight");
|
||||||
|
self->up_left_blocklight = PyObject_GetAttrString(state->self, "up_left_blocklight");
|
||||||
|
self->up_right_skylight = PyObject_GetAttrString(state->self, "up_right_skylight");
|
||||||
|
self->up_right_blocklight = PyObject_GetAttrString(state->self, "up_right_blocklight");
|
||||||
|
|
||||||
self->calculate_light_color = calculate_light_color;
|
if (self->night) {
|
||||||
|
self->calculate_light_color = calculate_light_color_night;
|
||||||
|
} else {
|
||||||
|
self->calculate_light_color = calculate_light_color;
|
||||||
|
}
|
||||||
|
|
||||||
if (self->color_light) {
|
if (self->color_light) {
|
||||||
self->lightcolor = PyObject_CallMethod(state->textures, "loadLightColor", "");
|
self->lightcolor = PyObject_CallMethod(state->textures, "loadLightColor", "");
|
||||||
@@ -326,7 +390,11 @@ rendermode_lighting_start(void *data, RenderState *state, PyObject *options) {
|
|||||||
self->lightcolor = NULL;
|
self->lightcolor = NULL;
|
||||||
self->color_light = 0;
|
self->color_light = 0;
|
||||||
} else {
|
} else {
|
||||||
self->calculate_light_color = calculate_light_color_fancy;
|
if (self->night) {
|
||||||
|
self->calculate_light_color = calculate_light_color_fancy_night;
|
||||||
|
} else {
|
||||||
|
self->calculate_light_color = calculate_light_color_fancy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self->lightcolor = NULL;
|
self->lightcolor = NULL;
|
||||||
@@ -347,6 +415,10 @@ rendermode_lighting_finish(void *data, RenderState *state) {
|
|||||||
Py_DECREF(self->left_blocklight);
|
Py_DECREF(self->left_blocklight);
|
||||||
Py_DECREF(self->right_skylight);
|
Py_DECREF(self->right_skylight);
|
||||||
Py_DECREF(self->right_blocklight);
|
Py_DECREF(self->right_blocklight);
|
||||||
|
Py_DECREF(self->up_left_skylight);
|
||||||
|
Py_DECREF(self->up_left_blocklight);
|
||||||
|
Py_DECREF(self->up_right_skylight);
|
||||||
|
Py_DECREF(self->up_right_blocklight);
|
||||||
|
|
||||||
/* now chain up */
|
/* now chain up */
|
||||||
rendermode_normal.finish(data, state);
|
rendermode_normal.finish(data, state);
|
||||||
@@ -403,6 +475,7 @@ rendermode_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject
|
|||||||
|
|
||||||
const RenderModeOption rendermode_lighting_options[] = {
|
const RenderModeOption rendermode_lighting_options[] = {
|
||||||
{"shade_strength", "how dark to make the shadows, from 0.0 to 1.0 (default: 1.0)"},
|
{"shade_strength", "how dark to make the shadows, from 0.0 to 1.0 (default: 1.0)"},
|
||||||
|
{"night", "whether to use nighttime skylight settings (default: False)"},
|
||||||
{"color_light", "whether to use colored light (default: False)"},
|
{"color_light", "whether to use colored light (default: False)"},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Minecraft Overviewer.
|
|
||||||
*
|
|
||||||
* Minecraft Overviewer is free software: you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as published
|
|
||||||
* by the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Minecraft Overviewer is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "overviewer.h"
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
/* figures out the color from a given skylight and blocklight, used in
|
|
||||||
lighting calculations -- note this is *different* from the one in
|
|
||||||
rendermode-lighting.c (the "skylight - 11" part) */
|
|
||||||
static void
|
|
||||||
calculate_light_color(void *data,
|
|
||||||
unsigned char skylight, unsigned char blocklight,
|
|
||||||
unsigned char *r, unsigned char *g, unsigned char *b) {
|
|
||||||
unsigned char v = 255 * powf(0.8f, 15.0 - MAX(blocklight, skylight - 11));
|
|
||||||
*r = v;
|
|
||||||
*g = v;
|
|
||||||
*b = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fancy version that uses the colored light texture */
|
|
||||||
static void
|
|
||||||
calculate_light_color_fancy(void *data,
|
|
||||||
unsigned char skylight, unsigned char blocklight,
|
|
||||||
unsigned char *r, unsigned char *g, unsigned char *b) {
|
|
||||||
RenderModeLighting *mode = (RenderModeLighting *)(data);
|
|
||||||
unsigned int index;
|
|
||||||
PyObject *color;
|
|
||||||
|
|
||||||
index = skylight + blocklight * 16;
|
|
||||||
color = PySequence_GetItem(mode->lightcolor, index);
|
|
||||||
|
|
||||||
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
|
||||||
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
|
||||||
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
|
||||||
|
|
||||||
Py_DECREF(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rendermode_night_start(void *data, RenderState *state, PyObject *options) {
|
|
||||||
RenderModeNight* self;
|
|
||||||
|
|
||||||
/* first, chain up */
|
|
||||||
int ret = rendermode_lighting.start(data, state, options);
|
|
||||||
if (ret != 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* override the darkness function with our night version! */
|
|
||||||
self = (RenderModeNight *)data;
|
|
||||||
self->parent.calculate_light_color = calculate_light_color;
|
|
||||||
if (self->parent.color_light)
|
|
||||||
self->parent.calculate_light_color = calculate_light_color_fancy;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rendermode_night_finish(void *data, RenderState *state) {
|
|
||||||
/* nothing special to do */
|
|
||||||
rendermode_lighting.finish(data, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rendermode_night_occluded(void *data, RenderState *state, int x, int y, int z) {
|
|
||||||
/* no special occlusion here */
|
|
||||||
return rendermode_lighting.occluded(data, state, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
rendermode_night_hidden(void *data, RenderState *state, int x, int y, int z) {
|
|
||||||
/* no special hiding here */
|
|
||||||
return rendermode_lighting.hidden(data, state, x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
rendermode_night_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
|
|
||||||
/* nothing special to do */
|
|
||||||
rendermode_lighting.draw(data, state, src, mask, mask_light);
|
|
||||||
}
|
|
||||||
|
|
||||||
RenderModeInterface rendermode_night = {
|
|
||||||
"night", "Night",
|
|
||||||
"like \"lighting\", except at night",
|
|
||||||
NULL,
|
|
||||||
&rendermode_lighting,
|
|
||||||
sizeof(RenderModeNight),
|
|
||||||
rendermode_night_start,
|
|
||||||
rendermode_night_finish,
|
|
||||||
rendermode_night_occluded,
|
|
||||||
rendermode_night_hidden,
|
|
||||||
rendermode_night_draw,
|
|
||||||
};
|
|
||||||
271
overviewer_core/src/rendermode-smooth-lighting.c
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Minecraft Overviewer.
|
||||||
|
*
|
||||||
|
* Minecraft Overviewer is free software: you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as published
|
||||||
|
* by the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* Minecraft Overviewer is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "overviewer.h"
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* structure representing one corner of a face (see below) */
|
||||||
|
struct SmoothLightingCorner {
|
||||||
|
/* where this corner shows up on each block texture */
|
||||||
|
int imgx, imgy;
|
||||||
|
|
||||||
|
/* the two block offsets that (together) determine the 4 blocks to use */
|
||||||
|
int dx1, dy1, dz1;
|
||||||
|
int dx2, dy2, dz2;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* structure for rule table handling lighting */
|
||||||
|
struct SmoothLightingFace {
|
||||||
|
/* offset from current coordinate to the block this face points towards
|
||||||
|
used for occlusion calculations, and as a base for later */
|
||||||
|
int dx, dy, dz;
|
||||||
|
|
||||||
|
/* the points that form the corners of this face */
|
||||||
|
struct SmoothLightingCorner corners[4];
|
||||||
|
|
||||||
|
/* pairs of (x,y) in order, as touch-up points, or NULL for none */
|
||||||
|
int *touch_up_points;
|
||||||
|
unsigned int num_touch_up_points;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* top face touchups, pulled from textures.py (_build_block) */
|
||||||
|
static int top_touchups[] = {3, 4, 7, 2, 11, 0};
|
||||||
|
|
||||||
|
/* the lighting face rule list! */
|
||||||
|
static struct SmoothLightingFace lighting_rules[] = {
|
||||||
|
/* since this is getting a little insane, here's the general layout:
|
||||||
|
|
||||||
|
{dx, dy, dz, { // direction this face is towards
|
||||||
|
// now, a list of 4 corners...
|
||||||
|
{imgx, imgy, // where the corner is on the block image
|
||||||
|
x1, y1, z1, // two vectors, describing the 4 (!!!)
|
||||||
|
x2, y2, z2}, // blocks neighboring this corner
|
||||||
|
// ...
|
||||||
|
},
|
||||||
|
{x, y, x, y}, 2}, // touch-up points, and how many there are (may be NULL)
|
||||||
|
|
||||||
|
// ...
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* top */
|
||||||
|
{0, 0, 1, {
|
||||||
|
{0, 6,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, -1, 0},
|
||||||
|
{12, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
0, -1, 0},
|
||||||
|
{24, 6,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 1, 0},
|
||||||
|
{12, 12,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, 1, 0},
|
||||||
|
},
|
||||||
|
top_touchups, 3},
|
||||||
|
|
||||||
|
/* left */
|
||||||
|
{-1, 0, 0, {
|
||||||
|
{0, 18,
|
||||||
|
0, -1, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
{0, 6,
|
||||||
|
0, -1, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
{12, 12,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
{12, 24,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
},
|
||||||
|
NULL, 0},
|
||||||
|
|
||||||
|
/* right */
|
||||||
|
{0, 1, 0, {
|
||||||
|
{24, 6,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
{12, 12,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, 0, 1},
|
||||||
|
{12, 24,
|
||||||
|
-1, 0, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
{24, 18,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0, -1},
|
||||||
|
},
|
||||||
|
NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* helpers for indexing the rule list */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FACE_TOP = 0,
|
||||||
|
FACE_LEFT = 1,
|
||||||
|
FACE_RIGHT = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_shading_with_rule(RenderModeSmoothLighting *self, RenderState *state, struct SmoothLightingFace face) {
|
||||||
|
int i;
|
||||||
|
RenderModeLighting *lighting = (RenderModeLighting *)self;
|
||||||
|
int x = state->imgx, y = state->imgy;
|
||||||
|
struct SmoothLightingCorner *pts = face.corners;
|
||||||
|
float comp_shade_strength = 1.0 - lighting->shade_strength;
|
||||||
|
unsigned char pts_r[4] = {0, 0, 0, 0};
|
||||||
|
unsigned char pts_g[4] = {0, 0, 0, 0};
|
||||||
|
unsigned char pts_b[4] = {0, 0, 0, 0};
|
||||||
|
int cx = state->x + face.dx;
|
||||||
|
int cy = state->y + face.dy;
|
||||||
|
int cz = state->z + face.dz;
|
||||||
|
|
||||||
|
/* first, check for occlusion if the block is in the local chunk */
|
||||||
|
if (rendermode_lighting_is_face_occluded(state, 0, cx, cy, cz))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* calculate the lighting colors for each point */
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
unsigned char r, g, b;
|
||||||
|
unsigned int rgather = 0, ggather = 0, bgather = 0;
|
||||||
|
|
||||||
|
get_lighting_color(lighting, state, cx, cy, cz,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
get_lighting_color(lighting, state,
|
||||||
|
cx+pts[i].dx1, cy+pts[i].dy1, cz+pts[i].dz1,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
get_lighting_color(lighting, state,
|
||||||
|
cx+pts[i].dx2, cy+pts[i].dy2, cz+pts[i].dz2,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
/* FIXME special far corner handling */
|
||||||
|
get_lighting_color(lighting, state,
|
||||||
|
cx+pts[i].dx1+pts[i].dx2, cy+pts[i].dy1+pts[i].dy2, cz+pts[i].dz1+pts[i].dz2,
|
||||||
|
&r, &g, &b);
|
||||||
|
rgather += r; ggather += g; bgather += b;
|
||||||
|
|
||||||
|
rgather += (255*4 - rgather) * comp_shade_strength;
|
||||||
|
ggather += (255*4 - ggather) * comp_shade_strength;
|
||||||
|
bgather += (255*4 - bgather) * comp_shade_strength;
|
||||||
|
|
||||||
|
pts_r[i] = rgather / 4;
|
||||||
|
pts_g[i] = ggather / 4;
|
||||||
|
pts_b[i] = bgather / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* draw the face */
|
||||||
|
draw_triangle(state->img, 1,
|
||||||
|
x+pts[0].imgx, y+pts[0].imgy, pts_r[0], pts_g[0], pts_b[0],
|
||||||
|
x+pts[1].imgx, y+pts[1].imgy, pts_r[1], pts_g[1], pts_b[1],
|
||||||
|
x+pts[2].imgx, y+pts[2].imgy, pts_r[2], pts_g[2], pts_b[2],
|
||||||
|
x, y, face.touch_up_points, face.num_touch_up_points);
|
||||||
|
draw_triangle(state->img, 0,
|
||||||
|
x+pts[0].imgx, y+pts[0].imgy, pts_r[0], pts_g[0], pts_b[0],
|
||||||
|
x+pts[2].imgx, y+pts[2].imgy, pts_r[2], pts_g[2], pts_b[2],
|
||||||
|
x+pts[3].imgx, y+pts[3].imgy, pts_r[3], pts_g[3], pts_b[3],
|
||||||
|
x, y, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rendermode_smooth_lighting_start(void *data, RenderState *state, PyObject *options) {
|
||||||
|
/* first, chain up */
|
||||||
|
int ret = rendermode_lighting.start(data, state, options);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rendermode_smooth_lighting_finish(void *data, RenderState *state) {
|
||||||
|
/* nothing special to do */
|
||||||
|
rendermode_lighting.finish(data, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rendermode_smooth_lighting_occluded(void *data, RenderState *state, int x, int y, int z) {
|
||||||
|
/* no special occlusion here */
|
||||||
|
return rendermode_lighting.occluded(data, state, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rendermode_smooth_lighting_hidden(void *data, RenderState *state, int x, int y, int z) {
|
||||||
|
/* no special hiding here */
|
||||||
|
return rendermode_lighting.hidden(data, state, x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rendermode_smooth_lighting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObject *mask_light) {
|
||||||
|
int light_top = 1;
|
||||||
|
int light_left = 1;
|
||||||
|
int light_right = 1;
|
||||||
|
RenderModeSmoothLighting *self = (RenderModeSmoothLighting *)data;
|
||||||
|
|
||||||
|
/* special case for leaves, water 8, water 9
|
||||||
|
-- these are also smooth-lit! */
|
||||||
|
if (state->block != 18 && state->block != 8 && state->block != 9 && is_transparent(state->block))
|
||||||
|
{
|
||||||
|
/* transparent blocks are rendered as usual, with flat lighting */
|
||||||
|
rendermode_lighting.draw(data, state, src, mask, mask_light);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* non-transparent blocks get the special smooth treatment */
|
||||||
|
|
||||||
|
/* nothing special to do, but we do want to avoid vanilla
|
||||||
|
* lighting mode draws */
|
||||||
|
rendermode_normal.draw(data, state, src, mask, mask_light);
|
||||||
|
|
||||||
|
/* special code for water */
|
||||||
|
if (state->block == 9)
|
||||||
|
{
|
||||||
|
if (!(state->block_pdata & (1 << 4)))
|
||||||
|
light_top = 0;
|
||||||
|
if (!(state->block_pdata & (1 << 1)))
|
||||||
|
light_left = 0;
|
||||||
|
if (!(state->block_pdata & (1 << 2)))
|
||||||
|
light_right = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (light_top)
|
||||||
|
do_shading_with_rule(self, state, lighting_rules[FACE_TOP]);
|
||||||
|
if (light_left)
|
||||||
|
do_shading_with_rule(self, state, lighting_rules[FACE_LEFT]);
|
||||||
|
if (light_right)
|
||||||
|
do_shading_with_rule(self, state, lighting_rules[FACE_RIGHT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderModeInterface rendermode_smooth_lighting = {
|
||||||
|
"smooth-lighting", "Smooth Lighting",
|
||||||
|
"like \"lighting\", except smooth",
|
||||||
|
NULL,
|
||||||
|
&rendermode_lighting,
|
||||||
|
sizeof(RenderModeSmoothLighting),
|
||||||
|
rendermode_smooth_lighting_start,
|
||||||
|
rendermode_smooth_lighting_finish,
|
||||||
|
rendermode_smooth_lighting_occluded,
|
||||||
|
rendermode_smooth_lighting_hidden,
|
||||||
|
rendermode_smooth_lighting_draw,
|
||||||
|
};
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
static RenderModeInterface *render_modes[] = {
|
static RenderModeInterface *render_modes[] = {
|
||||||
&rendermode_normal,
|
&rendermode_normal,
|
||||||
&rendermode_lighting,
|
&rendermode_lighting,
|
||||||
&rendermode_night,
|
&rendermode_smooth_lighting,
|
||||||
&rendermode_spawn,
|
&rendermode_spawn,
|
||||||
&rendermode_cave,
|
&rendermode_cave,
|
||||||
&rendermode_mineral,
|
&rendermode_mineral,
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ typedef struct {
|
|||||||
PyObject *skylight, *blocklight;
|
PyObject *skylight, *blocklight;
|
||||||
PyObject *left_skylight, *left_blocklight;
|
PyObject *left_skylight, *left_blocklight;
|
||||||
PyObject *right_skylight, *right_blocklight;
|
PyObject *right_skylight, *right_blocklight;
|
||||||
|
PyObject *up_left_skylight, *up_left_blocklight;
|
||||||
|
PyObject *up_right_skylight, *up_right_blocklight;
|
||||||
|
|
||||||
/* light color image, loaded if color_light is True */
|
/* light color image, loaded if color_light is True */
|
||||||
PyObject *lightcolor;
|
PyObject *lightcolor;
|
||||||
@@ -180,15 +182,24 @@ typedef struct {
|
|||||||
|
|
||||||
float shade_strength;
|
float shade_strength;
|
||||||
int color_light;
|
int color_light;
|
||||||
|
int night;
|
||||||
} RenderModeLighting;
|
} RenderModeLighting;
|
||||||
extern RenderModeInterface rendermode_lighting;
|
extern RenderModeInterface rendermode_lighting;
|
||||||
|
|
||||||
/* NIGHT */
|
/* exposed so it can be used in other per-face occlusion checks */
|
||||||
|
int rendermode_lighting_is_face_occluded(RenderState *state, int skip_sides, int x, int y, int z);
|
||||||
|
|
||||||
|
/* exposed so sub-modes can look at colors directly */
|
||||||
|
void get_lighting_color(RenderModeLighting *self, RenderState *state,
|
||||||
|
int x, int y, int z,
|
||||||
|
unsigned char *r, unsigned char *g, unsigned char *b);
|
||||||
|
|
||||||
|
/* SMOOTH LIGHTING */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* inherits from lighting */
|
/* inherits from lighting */
|
||||||
RenderModeLighting parent;
|
RenderModeLighting parent;
|
||||||
} RenderModeNight;
|
} RenderModeSmoothLighting;
|
||||||
extern RenderModeInterface rendermode_night;
|
extern RenderModeInterface rendermode_smooth_lighting;
|
||||||
|
|
||||||
/* SPAWN */
|
/* SPAWN */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -224,13 +224,17 @@ class HighlightingFormatter(logging.Formatter):
|
|||||||
"""Base class of our custom formatter
|
"""Base class of our custom formatter
|
||||||
|
|
||||||
"""
|
"""
|
||||||
fmtstr = '%(fileandlineno)-18s:PID(%(pid)s):%(asctime)s ' \
|
datefmt = "%Y-%m-%d %H:%M:%S"
|
||||||
'%(levelname)-8s %(message)s'
|
|
||||||
datefmt = "%H:%M:%S"
|
|
||||||
funcName_len = 15
|
funcName_len = 15
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, verbose=False):
|
||||||
logging.Formatter.__init__(self, self.fmtstr, self.datefmt)
|
if verbose:
|
||||||
|
fmtstr = '%(fileandlineno)-18s %(pid)s %(asctime)s ' \
|
||||||
|
'%(levelname)-8s %(message)s'
|
||||||
|
else:
|
||||||
|
fmtstr = '%(asctime)s ' '%(shortlevelname)-1s%(message)s'
|
||||||
|
|
||||||
|
logging.Formatter.__init__(self, fmtstr, self.datefmt)
|
||||||
|
|
||||||
def format(self, record):
|
def format(self, record):
|
||||||
"""Add a few extra options to the record
|
"""Add a few extra options to the record
|
||||||
@@ -244,8 +248,15 @@ class HighlightingFormatter(logging.Formatter):
|
|||||||
|
|
||||||
funcName
|
funcName
|
||||||
The function name truncated/padded to a fixed width characters
|
The function name truncated/padded to a fixed width characters
|
||||||
|
|
||||||
|
shortlevelname
|
||||||
|
The level name truncated to 1 character
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
record.shortlevelname = record.levelname[0] + ' '
|
||||||
|
if record.levelname == 'INFO': record.shortlevelname = ''
|
||||||
|
|
||||||
record.pid = os.getpid()
|
record.pid = os.getpid()
|
||||||
record.fileandlineno = "%s:%s" % (record.filename, record.lineno)
|
record.fileandlineno = "%s:%s" % (record.filename, record.lineno)
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class World(object):
|
|||||||
logging.debug(ex.str())
|
logging.debug(ex.str())
|
||||||
|
|
||||||
if os.path.exists(self.pickleFile):
|
if os.path.exists(self.pickleFile):
|
||||||
self.persistentDataIsNew = False;
|
self.persistentDataIsNew = False
|
||||||
with open(self.pickleFile,"rb") as p:
|
with open(self.pickleFile,"rb") as p:
|
||||||
self.persistentData = cPickle.load(p)
|
self.persistentData = cPickle.load(p)
|
||||||
if not self.persistentData.get('north_direction', False):
|
if not self.persistentData.get('north_direction', False):
|
||||||
@@ -165,7 +165,7 @@ class World(object):
|
|||||||
def get_region_path(self, chunkX, chunkY):
|
def get_region_path(self, chunkX, chunkY):
|
||||||
"""Returns the path to the region that contains chunk (chunkX, chunkY)
|
"""Returns the path to the region that contains chunk (chunkX, chunkY)
|
||||||
"""
|
"""
|
||||||
_, _, regionfile,_ = self.regionfiles.get((chunkX//32, chunkY//32),(None,None,None,None));
|
_, _, regionfile,_ = self.regionfiles.get((chunkX//32, chunkY//32),(None,None,None,None))
|
||||||
return regionfile
|
return regionfile
|
||||||
|
|
||||||
def load_from_region(self,filename, x, y):
|
def load_from_region(self,filename, x, y):
|
||||||
|
|||||||
2
setup.py
@@ -149,7 +149,7 @@ except Exception:
|
|||||||
|
|
||||||
|
|
||||||
# used to figure out what files to compile
|
# used to figure out what files to compile
|
||||||
render_modes = ['normal', 'overlay', 'lighting', 'night', 'spawn', 'cave', 'mineral']
|
render_modes = ['normal', 'overlay', 'lighting', 'smooth-lighting', 'spawn', 'cave', 'mineral']
|
||||||
|
|
||||||
c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c']
|
c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c']
|
||||||
c_overviewer_files += map(lambda mode: 'rendermode-%s.c' % (mode,), render_modes)
|
c_overviewer_files += map(lambda mode: 'rendermode-%s.c' % (mode,), render_modes)
|
||||||
|
|||||||