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