0

Merge branch 'smooth-lighting'

This commit is contained in:
Aaron Griffith
2011-11-07 19:46:10 -05:00
18 changed files with 1547 additions and 155 deletions

View File

@@ -589,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
========= =========

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View 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,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=
"
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,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
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View 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,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 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

View File

@@ -102,6 +102,24 @@ 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>"""
@@ -204,6 +222,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:

View File

@@ -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);

View File

@@ -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'},

View File

@@ -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),

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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}
}; };

View File

@@ -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,
};

View 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,
};

View File

@@ -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,

View File

@@ -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 {

View File

@@ -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)