|
@@ -79,6 +79,7 @@ class HeightMap extends Object3D {
|
|
var normalScale = 1.;
|
|
var normalScale = 1.;
|
|
var tileX = 1;
|
|
var tileX = 1;
|
|
var tileY = 1;
|
|
var tileY = 1;
|
|
|
|
+ var heightTexturesCache : Array<hxd.Pixels>;
|
|
|
|
|
|
override function save():{} {
|
|
override function save():{} {
|
|
var o : Dynamic = super.save();
|
|
var o : Dynamic = super.save();
|
|
@@ -108,22 +109,105 @@ class HeightMap extends Object3D {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ override function localRayIntersection(ctx:Context, ray:h3d.col.Ray):Float {
|
|
|
|
+ if( ray.lz > 0 )
|
|
|
|
+ return -1; // only from top
|
|
|
|
+ var maxZ = getHScale() * 100;
|
|
|
|
+ var b = h3d.col.Bounds.fromValues(0,0,0,size * tileX, size * tileY, maxZ);
|
|
|
|
+ var dist = b.rayIntersection(ray, false);
|
|
|
|
+ if( dist < 0 )
|
|
|
|
+ return -1;
|
|
|
|
+ var prim = cast(ctx.local3d.toMesh().primitive, HeightGrid);
|
|
|
|
+ var pt = ray.getPoint(dist);
|
|
|
|
+ var m = hxd.Math.min(prim.cellWidth, prim.cellHeight) * 0.5;
|
|
|
|
+ var isTiled = tileX != 1 || tileY != 1;
|
|
|
|
+ var curX = -1, curY = -1, curMap = null, offX = 0., offY = 0., cw = 0., ch = 0.;
|
|
|
|
+ if( !isTiled ) {
|
|
|
|
+ curX = 0;
|
|
|
|
+ curY = 0;
|
|
|
|
+ curMap = getHeightMap(0,0);
|
|
|
|
+ cw = curMap.width / size;
|
|
|
|
+ ch = curMap.height / size;
|
|
|
|
+ }
|
|
|
|
+ var prevH = pt.z;
|
|
|
|
+ var hscale = getHScale();
|
|
|
|
+ while( true ) {
|
|
|
|
+ pt.x += ray.lx * m;
|
|
|
|
+ pt.y += ray.ly * m;
|
|
|
|
+ pt.z += ray.lz * m;
|
|
|
|
+ if( !b.contains(pt) )
|
|
|
|
+ break;
|
|
|
|
+ if( isTiled ) {
|
|
|
|
+ var px = Std.int(pt.x / size);
|
|
|
|
+ var py = Std.int(pt.y / size);
|
|
|
|
+ if( px != curX || py != curY ) {
|
|
|
|
+ curX = px;
|
|
|
|
+ curY = py;
|
|
|
|
+ offX = -px * size;
|
|
|
|
+ offY = -py * size;
|
|
|
|
+ curMap = getHeightMap(px, py);
|
|
|
|
+ cw = curMap.width / size;
|
|
|
|
+ ch = curMap.height / size;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var ix = Std.int((pt.x + offX)*cw);
|
|
|
|
+ var iy = Std.int((pt.y + offY)*ch);
|
|
|
|
+ var h = curMap.bytes.getFloat( (ix + iy * curMap.width) << 2 );
|
|
|
|
+ h *= hscale;
|
|
|
|
+ if( pt.z < h ) {
|
|
|
|
+ // todo : fix interpolation using getZ dichotomy
|
|
|
|
+ var k = 1 - (prevH - (pt.z - ray.lz * m)) / (ray.lz * m - (h - prevH));
|
|
|
|
+ pt.x -= k * ray.lx * m;
|
|
|
|
+ pt.y -= k * ray.ly * m;
|
|
|
|
+ pt.z -= k * ray.lz * m;
|
|
|
|
+ return pt.sub(ray.getPos()).length();
|
|
|
|
+ }
|
|
|
|
+ prevH = h;
|
|
|
|
+ }
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function getHeightMap( x : Int, y : Int ) {
|
|
|
|
+ var id = x + y * tileX;
|
|
|
|
+ if( heightTexturesCache == null )
|
|
|
|
+ heightTexturesCache = [];
|
|
|
|
+ else {
|
|
|
|
+ var b = heightTexturesCache[id];
|
|
|
|
+ if( b != null ) return b;
|
|
|
|
+ }
|
|
|
|
+ var pix : hxd.Pixels = null;
|
|
|
|
+ for( t in textures )
|
|
|
|
+ if( t.kind == Height && t.enable && t.path != null ) {
|
|
|
|
+ var path = resolveTexturePath(t.path, x, y);
|
|
|
|
+ pix = try hxd.res.Loader.currentInstance.load(path).toImage().getPixels() catch( e : hxd.res.NotFound ) null;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ if( pix == null ) pix = hxd.Pixels.alloc(1, 1, R32F);
|
|
|
|
+ pix.convert(R32F);
|
|
|
|
+ heightTexturesCache[id] = pix;
|
|
|
|
+ return pix;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function resolveTexturePath( path : String, x : Int, y : Int ) {
|
|
|
|
+ if( x != 0 && y != 0 ) {
|
|
|
|
+ var parts = path.split("0");
|
|
|
|
+ switch( parts.length ) {
|
|
|
|
+ case 2:
|
|
|
|
+ path = x + parts[0] + y + parts[1];
|
|
|
|
+ case 3:
|
|
|
|
+ path = parts[0] + x + parts[1] + y + parts[2];
|
|
|
|
+ default:
|
|
|
|
+ // pattern not recognized - should contain 2 zeroes
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return path;
|
|
|
|
+ }
|
|
|
|
+
|
|
function getTextures( ctx : Context, k : HeightMapTextureKind, x : Int, y : Int ) {
|
|
function getTextures( ctx : Context, k : HeightMapTextureKind, x : Int, y : Int ) {
|
|
var tl = [];
|
|
var tl = [];
|
|
for( t in textures )
|
|
for( t in textures )
|
|
if( t.kind == k && t.path != null && t.enable ) {
|
|
if( t.kind == k && t.path != null && t.enable ) {
|
|
- var path = t.path;
|
|
|
|
- if( x != 0 && y != 0 ) {
|
|
|
|
- var parts = path.split("0");
|
|
|
|
- switch( parts.length ) {
|
|
|
|
- case 2:
|
|
|
|
- path = x + parts[0] + y + parts[1];
|
|
|
|
- case 3:
|
|
|
|
- path = parts[0] + x + parts[1] + y + parts[2];
|
|
|
|
- default:
|
|
|
|
- // pattern not recognized - should contain 2 zeroes
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ var path = resolveTexturePath(t.path,x,y);
|
|
tl.push(ctx.loadTexture(path));
|
|
tl.push(ctx.loadTexture(path));
|
|
}
|
|
}
|
|
return tl;
|
|
return tl;
|
|
@@ -142,6 +226,8 @@ class HeightMap extends Object3D {
|
|
override function updateInstance( ctx : Context, ?propName : String ) {
|
|
override function updateInstance( ctx : Context, ?propName : String ) {
|
|
super.updateInstance(ctx, propName);
|
|
super.updateInstance(ctx, propName);
|
|
|
|
|
|
|
|
+ heightTexturesCache = null;
|
|
|
|
+
|
|
var mesh = cast(ctx.local3d, h3d.scene.Mesh);
|
|
var mesh = cast(ctx.local3d, h3d.scene.Mesh);
|
|
var grid = cast(mesh.primitive, HeightGrid);
|
|
var grid = cast(mesh.primitive, HeightGrid);
|
|
|
|
|
|
@@ -178,6 +264,10 @@ class HeightMap extends Object3D {
|
|
for( p in prev ) p.remove();
|
|
for( p in prev ) p.remove();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ function getHScale() {
|
|
|
|
+ return heightScale * size * 0.1;
|
|
|
|
+ }
|
|
|
|
+
|
|
function updateMesh( ctx : Context, mesh : h3d.scene.Mesh, x : Int, y : Int ) {
|
|
function updateMesh( ctx : Context, mesh : h3d.scene.Mesh, x : Int, y : Int ) {
|
|
inline function getTextures(k) return this.getTextures(ctx,k,x,y);
|
|
inline function getTextures(k) return this.getTextures(ctx,k,x,y);
|
|
|
|
|
|
@@ -193,7 +283,7 @@ class HeightMap extends Object3D {
|
|
shader.heightMap = hmap;
|
|
shader.heightMap = hmap;
|
|
shader.hasNormal = normal != null;
|
|
shader.hasNormal = normal != null;
|
|
shader.normalMap = normal;
|
|
shader.normalMap = normal;
|
|
- shader.heightScale = heightScale * size * 0.1;
|
|
|
|
|
|
+ shader.heightScale = getHScale();
|
|
shader.normalScale = 1 / normalScale;
|
|
shader.normalScale = 1 / normalScale;
|
|
shader.cellSize.set(prim.cellWidth,prim.cellHeight);
|
|
shader.cellSize.set(prim.cellWidth,prim.cellHeight);
|
|
if( hmap != null ) shader.heightOffset.set(1 / hmap.width,1 / hmap.height);
|
|
if( hmap != null ) shader.heightOffset.set(1 / hmap.width,1 / hmap.height);
|