| Description | Apply various wrapping and blending operations to generate a heightfield that may be wrapped onto a cube (nearly) seamlessly. |
|---|---|
| Author | Aaron |
| Created | 2012/03/09 |
| Updated | 2012/03/14 — new images with better blending. |
| Requires | L3DT v12.03 build 1 or later |
| Download | cube_mapped_heightfield.zs |
This script converts 4×3 aspect heightfields like this…
…into cube-wrapped maps such as this:
In principle, the above map could be 'folded' to create a 6 sided cube. With a some sort of spherical distortion calculation, this may allow spherical worlds to be generated from heightmaps.
In Sapphire, the raw (unfolded) results look like:
Note that the blending operations have some artefacts that you will need to clean up manually, including streaking near tile edges, and small steps at internal tile edges.
// Author: A. Torpy
// Updated: 10 Mar 2012
hvar hMap
set hMap <project.GetMap "HF">
int nx ny
set nx <map.GetWidth hMap>
set ny <map.GetHeight hMap>
assert <or nx ny> "Map not initialised"
int TileSize
set TileSize <div ny 3>
if <not <iseq 0 <mod ny TileSize>>>
echo <strcat "Height is not divisible by 3 (" <strcat ny <strcat " % " <strcat TileSize <strcat " = " <strcat <mod ny TileSize> ")">>>>>>
return -1
endif
if <not <iseq 4 <div nx TileSize>>>
echo "Width must be 4/3 height"
return -1
endif
if <not <iseq 0 <mod nx TileSize>>>
echo "Width must be exactly 4/3 height"
return -1
endif
int depth
set depth <div TileSize 3>
if <not <EditUI &depth "Enter blend depth">>
return -1
endif
if <islt depth 1>
echo "Blend depth must be greater than 0"
return -1
endif
if <isgt depth <div TileSize 2>>
echo <strcat "Blend depth must not be greater than TileSize/2 (i.e. " <strcat <div TileSize 2> ")">>
return -1
endif
L3DTio_Backup.BackupMap "HF" "BoxWrap HF" 0 "view.ShowMap \"HF\""
int px py
int p pmax
set p 0
set pmax 3
do
// east/west
calc.HF.BlendEdges hMap 0 TileSize 1 0 depth <sub nx 1> TileSize 1 2 depth TileSize 0.5 0 NULL
// easternmost top to mid topmost (reversed)
calc.HF.BlendEdges hMap <mul 3 TileSize> <mul 2 TileSize> 0 3 depth <mul TileSize 2> <sub ny 1> 2 3 depth TileSize 0.5 0 NULL
// easternmost bottom to mid bottommost (reversed)
calc.HF.BlendEdges hMap <mul 3 TileSize> TileSize 0 1 depth <mul TileSize 2> 0 2 1 depth TileSize 0.5 0 NULL
// northwest diag
set px TileSize
set py <mul TileSize 2>
calc.HF.BlendEdges hMap px py 2 3 depth px py 1 0 depth TileSize 0.5 0 NULL
// northeast diag
set px <mul TileSize 2>
set py <mul TileSize 2>
calc.HF.BlendEdges hMap px py 1 2 depth px py 0 3 depth TileSize 0.5 0 NULL
// southeast diag
set px <mul TileSize 2>
set py TileSize
calc.HF.BlendEdges hMap px py 0 1 depth px py 3 2 depth TileSize 0.5 0 NULL
// southwest diag
set px TileSize
set py TileSize
calc.HF.BlendEdges hMap px py 2 1 depth px py 3 0 depth TileSize 0.5 0 NULL
// interior vert b/w rightmost tiles (except for last pass, where we don't want changes
if <islt p <sub pmax 1>>
set px <mul TileSize 3>
set py TileSize
calc.HF.BlendEdges hMap px py 2 1 depth px py 0 1 depth TileSize 0.5 0 NULL
// interior of centre square, left edge
set px TileSize
set py TileSize
calc.HF.BlendEdges hMap px py 1 2 depth px py 1 0 depth TileSize 0.5f 0 NULL
// interior of centre square, right edge
set px <mul TileSize 2>
set py TileSize
calc.HF.BlendEdges hMap px py 1 0 depth px py 1 2 depth TileSize 0.5f 0 NULL
// interior of centre square, top edge
set px TileSize
set py <mul TileSize 2>
calc.HF.BlendEdges hMap px py 0 1 depth px py 0 3 depth TileSize 0.5f 0 NULL
// interior of centre square, bottom edge
set px TileSize
set py TileSize
calc.HF.BlendEdges hMap px py 0 3 depth px py 0 1 depth TileSize 0.5f 0 NULL
endif
while <islt <incr p> pmax>
// clear rects
calc.map.ZeroArea hMap 0 0 TileSize TileSize 0
calc.map.ZeroArea hMap <mul TileSize 2> 0 <mul TileSize 2> TileSize 0
calc.map.ZeroArea hMap 0 <mul TileSize 2> TileSize TileSize 0
calc.map.ZeroArea hMap <mul TileSize 2> <mul TileSize 2> <mul TileSize 2> TileSize 0
map.SetFlag hMap 5 true
view.ShowMap "HF"
return 0