|
@@ -1,5 +1,7 @@
|
|
|
package hrt.prefab.terrain;
|
|
|
|
|
|
+import h3d.prim.Grid;
|
|
|
+
|
|
|
enum Direction{
|
|
|
Up; Down; Left; Right; UpLeft; UpRight; DownLeft; DownRight;
|
|
|
}
|
|
@@ -36,8 +38,8 @@ class Tile extends h3d.scene.Mesh {
|
|
|
shader = new hrt.shader.Terrain();
|
|
|
material.mainPass.addShader(shader);
|
|
|
material.mainPass.culling = Back;
|
|
|
- this.x = x * terrain.tileSize;
|
|
|
- this.y = y * terrain.tileSize;
|
|
|
+ this.x = x * terrain.tileSize.x;
|
|
|
+ this.y = y * terrain.tileSize.y;
|
|
|
name = "tile_" + x + "_" + y;
|
|
|
material.mainPass.setPassName("terrain");
|
|
|
}
|
|
@@ -79,8 +81,7 @@ class Tile extends h3d.scene.Mesh {
|
|
|
public function createBigPrim( bytes : haxe.io.Bytes ) {
|
|
|
|
|
|
var stride = 3 * 4 + 3 * 4; // Normal + Tangent
|
|
|
- var vertexCount = (terrain.cellCount + 1) * (terrain.cellCount + 1);
|
|
|
- var length = vertexCount * stride;
|
|
|
+ var vertexCount = (terrain.cellCount.x + 1) * (terrain.cellCount.y + 1);
|
|
|
if( bytes.length != stride * vertexCount ) {
|
|
|
throw "Bytes length doesn't match with the size of tiles";
|
|
|
return;
|
|
@@ -93,7 +94,7 @@ class Tile extends h3d.scene.Mesh {
|
|
|
bigPrim = new h3d.prim.BigPrimitive(9, true);
|
|
|
inline function addVertice(x : Float, y : Float, i : Int) {
|
|
|
// Pos
|
|
|
- bigPrim.addPoint(x, y, getHeight(x / terrain.tileSize, y / terrain.tileSize)); // Use addPoint() instead of addVertexValue() for the bounds
|
|
|
+ bigPrim.addPoint(x, y, getHeight(x / terrain.tileSize.x, y / terrain.tileSize.y)); // Use addPoint() instead of addVertexValue() for the bounds
|
|
|
// Normal
|
|
|
bigPrim.addVertexValue(bytes.getFloat(i * stride));
|
|
|
bigPrim.addVertexValue(bytes.getFloat(i * stride + 4));
|
|
@@ -107,40 +108,36 @@ class Tile extends h3d.scene.Mesh {
|
|
|
var cellCount = terrain.cellCount;
|
|
|
var cellSize = terrain.cellSize;
|
|
|
bigPrim.begin(0,0);
|
|
|
- for( y in 0 ... cellCount + 1 ) {
|
|
|
- for( x in 0 ... cellCount + 1 ) {
|
|
|
- addVertice(x * cellSize, y * cellSize, x + y * (terrain.cellCount + 1));
|
|
|
+ for( y in 0 ... cellCount.y + 1 ) {
|
|
|
+ for( x in 0 ... cellCount.x + 1 ) {
|
|
|
+ addVertice(x * cellSize.x, y * cellSize.y, x + y * (terrain.cellCount.x + 1));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- for( y in 0 ... cellCount ) {
|
|
|
- for( x in 0 ... cellCount ) {
|
|
|
- var i = x + y * (cellCount + 1);
|
|
|
+ for( y in 0 ... cellCount.y ) {
|
|
|
+ for( x in 0 ... cellCount.x ) {
|
|
|
+ var i = x + y * (cellCount.x + 1);
|
|
|
bigPrim.addIndex(i);
|
|
|
bigPrim.addIndex(i + 1);
|
|
|
- bigPrim.addIndex(i + cellCount + 2);
|
|
|
+ bigPrim.addIndex(i + cellCount.x + 2);
|
|
|
bigPrim.addIndex(i);
|
|
|
- bigPrim.addIndex(i + cellCount + 2);
|
|
|
- bigPrim.addIndex(i + cellCount + 1);
|
|
|
+ bigPrim.addIndex(i + cellCount.x + 2);
|
|
|
+ bigPrim.addIndex(i + cellCount.x + 1);
|
|
|
}
|
|
|
}
|
|
|
bigPrim.flush();
|
|
|
primitive = bigPrim;
|
|
|
}
|
|
|
|
|
|
- public function computeTangents() {
|
|
|
- if( grid != null )
|
|
|
- grid.addTangents();
|
|
|
- }
|
|
|
-
|
|
|
public function refreshGrid() {
|
|
|
if( bigPrim != null )
|
|
|
return;
|
|
|
- if( grid == null || grid.width != terrain.cellCount || grid.height != terrain.cellCount || grid.cellWidth != terrain.cellSize || grid.cellHeight != terrain.cellSize ) {
|
|
|
+ if( grid == null || grid.width != terrain.cellCount.x || grid.height != terrain.cellCount.y || grid.cellWidth != terrain.cellSize.x || grid.cellHeight != terrain.cellSize.y ) {
|
|
|
if( grid != null ) grid.dispose();
|
|
|
- grid = new h3d.prim.Grid(terrain.cellCount, terrain.cellCount, terrain.cellSize, terrain.cellSize);
|
|
|
+ grid = new h3d.prim.Grid(terrain.cellCount.x, terrain.cellCount.y, terrain.cellSize.x, terrain.cellSize.y);
|
|
|
primitive = grid;
|
|
|
}
|
|
|
+ computeHeight();
|
|
|
computeNormals();
|
|
|
computeTangents();
|
|
|
}
|
|
@@ -168,6 +165,8 @@ class Tile extends h3d.scene.Mesh {
|
|
|
flags.set(Left);
|
|
|
flags.set(Up);
|
|
|
flags.set(UpLeft);
|
|
|
+
|
|
|
+ computeHeight();
|
|
|
computeEdgesHeight(flags);
|
|
|
computeNormals();
|
|
|
computeEdgesNormals();
|
|
@@ -175,9 +174,9 @@ class Tile extends h3d.scene.Mesh {
|
|
|
}
|
|
|
|
|
|
function refreshHeightMap() {
|
|
|
- if( heightMap == null || heightMap.width != terrain.heightMapResolution + 1 ) {
|
|
|
+ if( heightMap == null || heightMap.width != terrain.heightMapResolution.x + 1 || heightMap.height != terrain.heightMapResolution.y + 1 ) {
|
|
|
var oldHeightMap = heightMap;
|
|
|
- heightMap = new h3d.mat.Texture(terrain.heightMapResolution + 1, terrain.heightMapResolution + 1, [Target], RGBA32F );
|
|
|
+ heightMap = new h3d.mat.Texture(terrain.heightMapResolution.x + 1, terrain.heightMapResolution.y + 1, [Target], RGBA32F );
|
|
|
heightMap.setName("terrainHeightMap");
|
|
|
heightMap.wrap = Clamp;
|
|
|
heightMap.filter = Linear;
|
|
@@ -196,9 +195,9 @@ class Tile extends h3d.scene.Mesh {
|
|
|
}
|
|
|
|
|
|
function refreshIndexMap() {
|
|
|
- if( surfaceIndexMap == null || surfaceIndexMap.width != terrain.weightMapResolution ) {
|
|
|
+ if( surfaceIndexMap == null || surfaceIndexMap.width != terrain.weightMapResolution.x || surfaceIndexMap.height != terrain.weightMapResolution.y ) {
|
|
|
var oldSurfaceIndexMap = surfaceIndexMap;
|
|
|
- surfaceIndexMap = new h3d.mat.Texture(terrain.weightMapResolution, terrain.weightMapResolution, [Target], RGBA);
|
|
|
+ surfaceIndexMap = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], RGBA);
|
|
|
surfaceIndexMap.setName("terrainSurfaceIndexMap");
|
|
|
surfaceIndexMap.filter = Nearest;
|
|
|
surfaceIndexMap.preventAutoDispose();
|
|
@@ -215,12 +214,12 @@ class Tile extends h3d.scene.Mesh {
|
|
|
}
|
|
|
|
|
|
function refreshSurfaceWeightArray() {
|
|
|
- if( terrain.surfaceArray.surfaceCount > 0 && (surfaceWeights.length != terrain.surfaceArray.surfaceCount || surfaceWeights[0].width != terrain.weightMapResolution) ) {
|
|
|
+ if( terrain.surfaceArray.surfaceCount > 0 && (surfaceWeights.length != terrain.surfaceArray.surfaceCount || surfaceWeights[0].width != terrain.weightMapResolution.x || surfaceWeights[0].height != terrain.weightMapResolution.y) ) {
|
|
|
var oldArray = surfaceWeights;
|
|
|
surfaceWeights = new Array<h3d.mat.Texture>();
|
|
|
surfaceWeights = [for( i in 0...terrain.surfaceArray.surfaceCount ) null];
|
|
|
for( i in 0 ... surfaceWeights.length ) {
|
|
|
- surfaceWeights[i] = new h3d.mat.Texture(terrain.weightMapResolution, terrain.weightMapResolution, [Target], R8);
|
|
|
+ surfaceWeights[i] = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target], R8);
|
|
|
surfaceWeights[i].setName("terrainSurfaceWeight"+i);
|
|
|
surfaceWeights[i].wrap = Clamp;
|
|
|
surfaceWeights[i].preventAutoDispose();
|
|
@@ -248,9 +247,9 @@ class Tile extends h3d.scene.Mesh {
|
|
|
}
|
|
|
|
|
|
public function generateWeightTextureArray() {
|
|
|
- if( surfaceWeightArray == null || surfaceWeightArray.width != terrain.weightMapResolution || surfaceWeightArray.layerCount != terrain.surfaceArray.surfaceCount ) {
|
|
|
+ if( surfaceWeightArray == null || surfaceWeightArray.width != terrain.weightMapResolution.x || surfaceWeightArray.height != terrain.weightMapResolution.y || surfaceWeightArray.layerCount != terrain.surfaceArray.surfaceCount ) {
|
|
|
if( surfaceWeightArray != null ) surfaceWeightArray.dispose();
|
|
|
- surfaceWeightArray = new h3d.mat.TextureArray(terrain.weightMapResolution, terrain.weightMapResolution, terrain.surfaceArray.surfaceCount, [Target], R8);
|
|
|
+ surfaceWeightArray = new h3d.mat.TextureArray(terrain.weightMapResolution.x, terrain.weightMapResolution.y, terrain.surfaceArray.surfaceCount, [Target], R8);
|
|
|
surfaceWeightArray.setName("terrainSurfaceWeightArray");
|
|
|
surfaceWeightArray.wrap = Clamp;
|
|
|
surfaceWeightArray.preventAutoDispose();
|
|
@@ -259,7 +258,7 @@ class Tile extends h3d.scene.Mesh {
|
|
|
surfaceWeightArray.realloc = function() {
|
|
|
var engine = h3d.Engine.getCurrent();
|
|
|
var unpackWeight = new h3d.pass.ScreenFx(new UnpackWeight());
|
|
|
- var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution, terrain.weightMapResolution, [Target]);
|
|
|
+ var tmpPackedWeightTexture = new h3d.mat.Texture(terrain.weightMapResolution.x, terrain.weightMapResolution.y, [Target]);
|
|
|
tmpPackedWeightTexture.uploadPixels(packedWeightMapPixel);
|
|
|
for( i in 0 ... surfaceWeightArray.layerCount ) {
|
|
|
engine.pushTarget(surfaceWeightArray, i);
|
|
@@ -275,6 +274,14 @@ class Tile extends h3d.scene.Mesh {
|
|
|
if( surfaceWeights[i] != null ) terrain.copyPass.apply(surfaceWeights[i], surfaceWeightArray, None, null, i);
|
|
|
}
|
|
|
|
|
|
+ public function computeHeight() {
|
|
|
+ for( p in grid.points ) {
|
|
|
+ p.z = getHeight(p.x / terrain.tileSize.x, p.y / terrain.tileSize.y);
|
|
|
+ }
|
|
|
+ needAlloc = true;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
public function computeEdgesHeight( flag : haxe.EnumFlags<Direction> ) {
|
|
|
|
|
|
if( heightMap == null ) return;
|
|
@@ -314,272 +321,196 @@ class Tile extends h3d.scene.Mesh {
|
|
|
}
|
|
|
|
|
|
public function computeEdgesNormals() {
|
|
|
- if( grid.normals == null ) return;
|
|
|
- var t0 = new h3d.col.Point(); var t1 = new h3d.col.Point(); var t2 = new h3d.col.Point();
|
|
|
- var triCount = Std.int(grid.triCount() / grid.width);
|
|
|
- var vertexCount = grid.width + 1;
|
|
|
- var step = hxd.Math.floor(grid.normals.length / grid.width) - 1;
|
|
|
- var s = hxd.Math.floor(grid.normals.length - grid.normals.length / grid.width + 2);
|
|
|
- var istep = triCount * 3 - 6;
|
|
|
- var i0, i1, i2 : Int = 0;
|
|
|
-
|
|
|
- inline function computeVertexPos( tile : Tile ) {
|
|
|
- t0.load(tile.grid.points[i0]); t1.load(tile.grid.points[i1]); t2.load(tile.grid.points[i2]);
|
|
|
- t0.z += tile.getHeight(t0.x / terrain.tileSize, t0.y / terrain.tileSize);
|
|
|
- t1.z += tile.getHeight(t1.x / terrain.tileSize, t1.y / terrain.tileSize);
|
|
|
- t2.z += tile.getHeight(t2.x / terrain.tileSize, t2.y / terrain.tileSize);
|
|
|
- }
|
|
|
-
|
|
|
- inline function computeNormal() : h3d.col.Point {
|
|
|
- var n1 = t1.sub(t0);
|
|
|
- n1.normalize();
|
|
|
- var n2 = t2.sub(t0);
|
|
|
- n2.normalize();
|
|
|
- return n1.cross(n2);
|
|
|
- }
|
|
|
|
|
|
- var adjUpTile = terrain.getTile(tileX, tileY + 1);
|
|
|
- var adjUpGrid = adjUpTile != null ? adjUpTile.grid: null;
|
|
|
- var adjDownTile = terrain.getTile(tileX, tileY - 1);
|
|
|
- var adjDownGrid = adjDownTile != null ? adjDownTile.grid: null;
|
|
|
- var adjLeftTile = terrain.getTile(tileX + 1, tileY);
|
|
|
- var adjLeftGrid = adjLeftTile != null ? adjLeftTile.grid: null;
|
|
|
- var adjRightTile = terrain.getTile(tileX - 1, tileY);
|
|
|
- var adjRightGrid = adjRightTile != null ? adjRightTile.grid: null;
|
|
|
- var adjUpRightTile = terrain.getTile(tileX - 1, tileY + 1);
|
|
|
- var adjUpRightGrid = adjUpRightTile != null ? adjUpRightTile.grid: null;
|
|
|
- var adjUpLeftTile = terrain.getTile(tileX + 1, tileY + 1);
|
|
|
- var adjUpLeftGrid = adjUpLeftTile != null ? adjUpLeftTile.grid: null;
|
|
|
- var adjDownLeftTile = terrain.getTile(tileX + 1, tileY - 1);
|
|
|
- var adjDownLeftGrid = adjDownLeftTile != null ? adjDownLeftTile.grid: null;
|
|
|
- var adjDownRightTile = terrain.getTile(tileX - 1, tileY - 1);
|
|
|
- var adjDownRightGrid = adjDownRightTile != null ? adjDownRightTile.grid: null;
|
|
|
+ if( grid.normals == null )
|
|
|
+ return;
|
|
|
|
|
|
+
|
|
|
+ inline function isEdgeIndex( grid : Grid, i : Int, side : Int ) : Bool {
|
|
|
+ var v = grid.points[grid.idx[i]];
|
|
|
+ return switch( side ) {
|
|
|
+ case 0: v.x == grid.width; // Left
|
|
|
+ case 1: v.y == grid.height; // Up
|
|
|
+ case 2: v.y == 0; // Down
|
|
|
+ case 3: v.x == 0; // Right
|
|
|
+ default: false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Need to recompute the normal before any blend
|
|
|
+ inline function computeNormal( grid : Grid, index : Int, assignOnSide : Int = -1 ) : h3d.col.Point {
|
|
|
+ var n1 = grid.points[grid.idx[index+1]].sub(grid.points[grid.idx[index]]).normalize();
|
|
|
+ var n2 = grid.points[grid.idx[index+2]].sub(grid.points[grid.idx[index]]).normalize();
|
|
|
+ var n = n1.cross(n2).normalize();
|
|
|
+ if( isEdgeIndex(grid, index, assignOnSide) ) grid.normals[grid.idx[index]] = grid.normals[grid.idx[index]].add(n);
|
|
|
+ if( isEdgeIndex(grid, index+1, assignOnSide) ) grid.normals[grid.idx[index+1]] = grid.normals[grid.idx[index+1]].add(n);
|
|
|
+ if( isEdgeIndex(grid, index+2, assignOnSide) ) grid.normals[grid.idx[index+2]] = grid.normals[grid.idx[index+2]].add(n);
|
|
|
+ return n;
|
|
|
+ }
|
|
|
+
|
|
|
+ var widthVertexCount = grid.width + 1;
|
|
|
+ var heightVertexCount = grid.height + 1;
|
|
|
+ var widthTriangleCount = grid.width * 2;
|
|
|
+ var heightTriangleCount = grid.height * 2;
|
|
|
+
|
|
|
+ var adjUpTile = terrain.getTile(tileX, tileY + 1);
|
|
|
+ var adjUpGrid = adjUpTile != null ? adjUpTile.grid : null;
|
|
|
if( adjUpGrid != null && adjUpGrid.normals != null ) {
|
|
|
- var pos = 0;
|
|
|
- for( i in 0 ... vertexCount )
|
|
|
+ for( i in 0 ... widthVertexCount )
|
|
|
adjUpGrid.normals[i].set(0,0,0);
|
|
|
- for( i in 0 ... triCount ) {
|
|
|
- i0 = adjUpGrid.idx[pos++]; i1 = adjUpGrid.idx[pos++]; i2 = adjUpGrid.idx[pos++];
|
|
|
- computeVertexPos(adjUpTile);
|
|
|
- var n = computeNormal();
|
|
|
- if( i0 <= adjUpGrid.width ) { adjUpGrid.normals[i0].x += n.x; adjUpGrid.normals[i0].y += n.y; adjUpGrid.normals[i0].z += n.z;}
|
|
|
- if( i1 <= adjUpGrid.width ) { adjUpGrid.normals[i1].x += n.x; adjUpGrid.normals[i1].y += n.y; adjUpGrid.normals[i1].z += n.z;}
|
|
|
- if( i2 <= adjUpGrid.width ) { adjUpGrid.normals[i2].x += n.x; adjUpGrid.normals[i2].y += n.y; adjUpGrid.normals[i2].z += n.z;}
|
|
|
- }
|
|
|
- for( i in 0 ... vertexCount )
|
|
|
+ for( i in 0 ... widthTriangleCount )
|
|
|
+ computeNormal(adjUpGrid, i * 3, 2);
|
|
|
+ for( i in 0 ... widthVertexCount ) {
|
|
|
adjUpGrid.normals[i].normalize();
|
|
|
- for( i in 1 ... vertexCount - 1 ) {
|
|
|
- var n = grid.normals[s + i].add(adjUpGrid.normals[i]);
|
|
|
- n.normalize();
|
|
|
- grid.normals[s + i].load(n);
|
|
|
+ var n = grid.normals[i + widthVertexCount * (heightVertexCount - 1)].add(adjUpGrid.normals[i]).normalize();
|
|
|
+ grid.normals[i + widthVertexCount * (heightVertexCount - 1)].load(n);
|
|
|
adjUpGrid.normals[i].load(n);
|
|
|
}
|
|
|
+ adjUpTile.needAlloc = true;
|
|
|
}
|
|
|
|
|
|
+ var adjDownTile = terrain.getTile(tileX, tileY - 1);
|
|
|
+ var adjDownGrid = adjDownTile != null ? adjDownTile.grid : null;
|
|
|
if( adjDownGrid != null && adjDownGrid.normals != null ) {
|
|
|
- var pos = triCount * (adjDownGrid.width - 1) * 3;
|
|
|
- for( i in 0 ... vertexCount)
|
|
|
- adjDownGrid.normals[s + i].set(0,0,0);
|
|
|
- for( i in 0 ... triCount ) {
|
|
|
- i0 = adjDownGrid.idx[pos++]; i1 = adjDownGrid.idx[pos++]; i2 = adjDownGrid.idx[pos++];
|
|
|
- computeVertexPos(adjDownTile);
|
|
|
- var n = computeNormal();
|
|
|
- if( i0 >= (adjDownGrid.width * adjDownGrid.height + adjDownGrid.height) ) { adjDownGrid.normals[i0].x += n.x; adjDownGrid.normals[i0].y += n.y; adjDownGrid.normals[i0].z += n.z;}
|
|
|
- if( i1 >= (adjDownGrid.width * adjDownGrid.height + adjDownGrid.height) ) { adjDownGrid.normals[i1].x += n.x; adjDownGrid.normals[i1].y += n.y; adjDownGrid.normals[i1].z += n.z;}
|
|
|
- if( i2 >= (adjDownGrid.width * adjDownGrid.height + adjDownGrid.height) ) { adjDownGrid.normals[i2].x += n.x; adjDownGrid.normals[i2].y += n.y; adjDownGrid.normals[i2].z += n.z;}
|
|
|
- }
|
|
|
- for( i in 1 ... vertexCount - 1 )
|
|
|
- adjDownGrid.normals[s + i].normalize();
|
|
|
- for( i in 1 ... vertexCount - 1 ){
|
|
|
- var n = grid.normals[i].add(adjDownGrid.normals[s + i]);
|
|
|
- n.normalize();
|
|
|
+ for( i in 0 ... widthVertexCount )
|
|
|
+ adjDownGrid.normals[i + widthVertexCount * (heightVertexCount - 1)].set(0,0,0);
|
|
|
+ for( i in 0 ... widthTriangleCount )
|
|
|
+ computeNormal(adjDownGrid, i * 3 + widthTriangleCount * 3 * (grid.height - 1), 1);
|
|
|
+ for( i in 0 ... widthVertexCount ) {
|
|
|
+ adjDownGrid.normals[i + widthVertexCount * (heightVertexCount - 1)].normalize();
|
|
|
+ var n = grid.normals[i].add(adjDownGrid.normals[i + widthVertexCount * (heightVertexCount - 1)]).normalize();
|
|
|
grid.normals[i].load(n);
|
|
|
- adjDownGrid.normals[s + i].load(n);
|
|
|
+ adjDownGrid.normals[i + widthVertexCount * (heightVertexCount - 1)].load(n);
|
|
|
}
|
|
|
+ adjDownTile.needAlloc = true;
|
|
|
}
|
|
|
|
|
|
+ var adjLeftTile = terrain.getTile(tileX + 1, tileY);
|
|
|
+ var adjLeftGrid = adjLeftTile != null ? adjLeftTile.grid : null;
|
|
|
if( adjLeftGrid != null && adjLeftGrid.normals != null ) {
|
|
|
- var pos = 0;
|
|
|
- var istep = triCount * 3 - 6;
|
|
|
- var needStep = false;
|
|
|
- for( i in 0 ... vertexCount )
|
|
|
- adjLeftGrid.normals[i * step].set(0,0,0);
|
|
|
- for( i in 0 ... triCount ) {
|
|
|
- i0 = adjLeftGrid.idx[pos++]; i1 = adjLeftGrid.idx[pos++]; i2 = adjLeftGrid.idx[pos++];
|
|
|
- computeVertexPos(adjLeftTile);
|
|
|
- var n = computeNormal();
|
|
|
- if( i0 % (adjLeftGrid.width + 1) == 0 ) { adjLeftGrid.normals[i0].x += n.x; adjLeftGrid.normals[i0].y += n.y; adjLeftGrid.normals[i0].z += n.z;}
|
|
|
- if( i1 % (adjLeftGrid.width + 1) == 0 ) { adjLeftGrid.normals[i1].x += n.x; adjLeftGrid.normals[i1].y += n.y; adjLeftGrid.normals[i1].z += n.z;}
|
|
|
- if( i2 % (adjLeftGrid.width + 1) == 0 ) { adjLeftGrid.normals[i2].x += n.x; adjLeftGrid.normals[i2].y += n.y; adjLeftGrid.normals[i2].z += n.z;}
|
|
|
- if( needStep) pos += istep;
|
|
|
- needStep = !needStep;
|
|
|
+ for( i in 0 ... heightVertexCount )
|
|
|
+ adjLeftGrid.normals[i * widthVertexCount].set(0,0,0);
|
|
|
+ for( i in 0 ... grid.height ) {
|
|
|
+ computeNormal(adjLeftGrid, i * widthTriangleCount * 3, 0);
|
|
|
+ computeNormal(adjLeftGrid, i * widthTriangleCount * 3 + 3, 3);
|
|
|
}
|
|
|
- for( i in 0 ... vertexCount )
|
|
|
- adjLeftGrid.normals[i * step].normalize();
|
|
|
- for( i in 1 ... vertexCount - 1 ){
|
|
|
- var n = grid.normals[i * step + (step - 1)].add(adjLeftGrid.normals[i * step]);
|
|
|
- n.normalize();
|
|
|
- grid.normals[i * step + (step - 1)].load(n);
|
|
|
- adjLeftGrid.normals[i * step].load(n);
|
|
|
+ for( i in 0 ... heightVertexCount ) {
|
|
|
+ adjLeftGrid.normals[i * widthVertexCount].normalize();
|
|
|
+ var n = grid.normals[(widthVertexCount - 1) + i * widthVertexCount].add(adjLeftGrid.normals[i * widthVertexCount]).normalize();
|
|
|
+ grid.normals[(widthVertexCount - 1) + i * widthVertexCount].load(n);
|
|
|
+ adjLeftGrid.normals[i * widthVertexCount].load(n);
|
|
|
}
|
|
|
+ adjLeftTile.needAlloc = true;
|
|
|
}
|
|
|
|
|
|
+ var adjRightTile = terrain.getTile(tileX - 1, tileY);
|
|
|
+ var adjRightGrid = adjRightTile != null ? adjRightTile.grid : null;
|
|
|
if( adjRightGrid != null && adjRightGrid.normals != null ) {
|
|
|
- var pos = (triCount - 2) * 3;
|
|
|
- var istep = (triCount - 2) * 3;
|
|
|
- var needStep = false;
|
|
|
- for( i in 0 ... vertexCount )
|
|
|
- adjRightGrid.normals[i * step + (step - 1)].set(0,0,0);
|
|
|
- for( i in 0 ... triCount ) {
|
|
|
- i0 = adjRightGrid.idx[pos++]; i1 = adjRightGrid.idx[pos++]; i2 = adjRightGrid.idx[pos++];
|
|
|
- computeVertexPos(adjRightTile);
|
|
|
- var n = computeNormal();
|
|
|
- if( (i0 + 1) % (adjRightGrid.width + 1) == 0 ) { adjRightGrid.normals[i0].x += n.x; adjRightGrid.normals[i0].y += n.y; adjRightGrid.normals[i0].z += n.z; }
|
|
|
- if( (i1 + 1) % (adjRightGrid.width + 1) == 0 ) { adjRightGrid.normals[i1].x += n.x; adjRightGrid.normals[i1].y += n.y; adjRightGrid.normals[i1].z += n.z; }
|
|
|
- if( (i2 + 1) % (adjRightGrid.width + 1) == 0 ) { adjRightGrid.normals[i2].x += n.x; adjRightGrid.normals[i2].y += n.y; adjRightGrid.normals[i2].z += n.z; }
|
|
|
- if( needStep) pos += istep;
|
|
|
- needStep = !needStep;
|
|
|
+ for( i in 0 ... heightVertexCount )
|
|
|
+ adjRightGrid.normals[(widthVertexCount - 1) + i * widthVertexCount].set(0,0,0);
|
|
|
+ for( i in 0 ... grid.height ) {
|
|
|
+ computeNormal(adjRightGrid, (widthTriangleCount - 1) * 3 + i * widthTriangleCount * 3, 0);
|
|
|
+ computeNormal(adjRightGrid, (widthTriangleCount - 2) * 3 + i * widthTriangleCount * 3, 0);
|
|
|
}
|
|
|
- for( i in 0 ... vertexCount )
|
|
|
- adjRightGrid.normals[i * step + (step - 1)].normalize();
|
|
|
- for( i in 1 ... vertexCount - 1 ) {
|
|
|
- var n = grid.normals[i * step].add(adjRightGrid.normals[i * step + (step - 1)]);
|
|
|
- n.normalize();
|
|
|
- grid.normals[i * step].load(n);
|
|
|
- adjRightGrid.normals[i * step + (step - 1)].load(n);
|
|
|
+ for( i in 0 ... heightVertexCount ) {
|
|
|
+ adjRightGrid.normals[(widthVertexCount - 1) + i * widthVertexCount].normalize();
|
|
|
+ var n = grid.normals[i * widthVertexCount].add(adjRightGrid.normals[(widthVertexCount - 1) + i * widthVertexCount]).normalize();
|
|
|
+ grid.normals[i * widthVertexCount].load(n);
|
|
|
+ adjRightGrid.normals[(widthVertexCount - 1) + i * widthVertexCount].load(n);
|
|
|
}
|
|
|
+ adjRightTile.needAlloc = true;
|
|
|
}
|
|
|
+
|
|
|
+ var adjUpRightTile = terrain.getTile(tileX - 1, tileY + 1);
|
|
|
+ var adjUpRightGrid = adjUpRightTile != null ? adjUpRightTile.grid : null;
|
|
|
+ var adjUpLeftTile = terrain.getTile(tileX + 1, tileY + 1);
|
|
|
+ var adjUpLeftGrid = adjUpLeftTile != null ? adjUpLeftTile.grid : null;
|
|
|
+ var adjDownLeftTile = terrain.getTile(tileX + 1, tileY - 1);
|
|
|
+ var adjDownLeftGrid = adjDownLeftTile != null ? adjDownLeftTile.grid : null;
|
|
|
+ var adjDownRightTile = terrain.getTile(tileX - 1, tileY - 1);
|
|
|
+ var adjDownRightGrid = adjDownRightTile != null ? adjDownRightTile.grid : null;
|
|
|
|
|
|
- var topLeft = grid.points.length - 1;
|
|
|
- var downLeft= step - 1;
|
|
|
+ var upLeft = grid.points.length - 1;
|
|
|
var downRight = 0;
|
|
|
- var upRight = step * grid.height;
|
|
|
-
|
|
|
+ var downLeft = grid.width;
|
|
|
+ var upRight = (grid.width + 1) * (grid.height);
|
|
|
var n = new h3d.col.Point();
|
|
|
- if( adjUpRightGrid != null && adjUpRightGrid.normals != null ) {
|
|
|
- var pos = (triCount) * 3 - 6;
|
|
|
- i0 = adjUpRightGrid.idx[pos++]; i1 = adjUpRightGrid.idx[pos++]; i2 = adjUpRightGrid.idx[pos++];
|
|
|
- computeVertexPos(adjUpRightTile);
|
|
|
- n = computeNormal();
|
|
|
- i0 = adjUpRightGrid.idx[pos++]; i1 = adjUpRightGrid.idx[pos++]; i2 = adjUpRightGrid.idx[pos++];
|
|
|
- computeVertexPos(adjUpRightTile);
|
|
|
- n = n.add(computeNormal());
|
|
|
- n.normalize();
|
|
|
- }
|
|
|
- if( adjRightGrid != null && adjRightGrid.normals != null ) n = n.add(adjRightGrid.normals[topLeft]);
|
|
|
- if( adjUpGrid != null && adjUpGrid.normals != null ) n = n.add(adjUpGrid.normals[downRight]);
|
|
|
- n = n.add(grid.normals[upRight]);
|
|
|
+
|
|
|
+ inline function computeUpLeftNormal( grid : Grid ) : h3d.col.Point {
|
|
|
+ return grid == null ? new h3d.col.Point() : computeNormal(grid, ((widthTriangleCount - 1) + (grid.height - 1) * widthTriangleCount) * 3);
|
|
|
+ }
|
|
|
+ inline function computeDownLeftNormal( grid : Grid ) : h3d.col.Point {
|
|
|
+ return grid == null ? new h3d.col.Point() : computeNormal(grid, (heightTriangleCount - 1) * 3).add(computeNormal(grid, (heightTriangleCount - 2) * 3));
|
|
|
+ }
|
|
|
+ inline function computeUpRightNormal( grid : Grid ) : h3d.col.Point {
|
|
|
+ return grid == null ? new h3d.col.Point() : computeNormal(grid, (grid.height - 1) * widthTriangleCount * 3).add(computeNormal(grid, (grid.height - 1) * widthTriangleCount * 3 + 3));
|
|
|
+ }
|
|
|
+ inline function computeDownRightNormal( grid : Grid ) : h3d.col.Point {
|
|
|
+ return grid == null ? new h3d.col.Point() : computeNormal(grid, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Up Right Corner
|
|
|
+ n.set(0,0,0);
|
|
|
+ n = n.add(computeDownLeftNormal(adjUpRightGrid));
|
|
|
+ n = n.add(computeUpLeftNormal(adjRightGrid));
|
|
|
+ n = n.add(computeDownRightNormal(adjUpGrid));
|
|
|
+ n = n.add(computeUpRightNormal(grid));
|
|
|
n.normalize();
|
|
|
- if( adjUpRightGrid != null && adjUpRightGrid.normals != null ) adjUpRightGrid.normals[downLeft].load(n);
|
|
|
- if( adjRightGrid != null && adjRightGrid.normals != null ) adjRightGrid.normals[topLeft].load(n);
|
|
|
- if( adjUpGrid != null && adjUpGrid.normals != null ) adjUpGrid.normals[downRight].load(n);
|
|
|
+ if( adjUpRightGrid != null ) adjUpRightGrid.normals[downLeft].load(n);
|
|
|
+ if( adjRightGrid != null ) adjRightGrid.normals[upLeft].load(n);
|
|
|
+ if( adjUpGrid != null ) adjUpGrid.normals[downRight].load(n);
|
|
|
grid.normals[upRight].load(n);
|
|
|
+ if( adjUpRightTile != null ) adjUpRightTile.needAlloc = true;
|
|
|
|
|
|
+ // Up Left Corner
|
|
|
n.set(0,0,0);
|
|
|
- if( adjUpLeftGrid != null && adjUpLeftGrid.normals != null ) {
|
|
|
- var pos = 0;
|
|
|
- i0 = adjUpLeftGrid.idx[pos++]; i1 = adjUpLeftGrid.idx[pos++]; i2 = adjUpLeftGrid.idx[pos++];
|
|
|
- computeVertexPos(adjUpLeftTile);
|
|
|
- n = computeNormal();
|
|
|
- n.normalize();
|
|
|
- }
|
|
|
- if( adjLeftGrid != null && adjLeftGrid.normals != null ) n = n.add(adjLeftGrid.normals[upRight]);
|
|
|
- if( adjUpGrid != null && adjUpGrid.normals != null ) n = n.add(adjUpGrid.normals[downLeft]);
|
|
|
- n = n.add(grid.normals[topLeft]);
|
|
|
+ n = n.add(computeDownLeftNormal(adjUpGrid));
|
|
|
+ n = n.add(computeUpLeftNormal(grid));
|
|
|
+ n = n.add(computeDownRightNormal(adjUpLeftGrid));
|
|
|
+ n = n.add(computeUpRightNormal(adjLeftGrid));
|
|
|
n.normalize();
|
|
|
- if( adjUpLeftGrid != null && adjUpLeftGrid.normals != null ) adjUpLeftGrid.normals[downRight].load(n);
|
|
|
- if( adjLeftGrid != null && adjLeftGrid.normals != null ) adjLeftGrid.normals[upRight].load(n);
|
|
|
- if( adjUpGrid != null && adjUpGrid.normals != null ) adjUpGrid.normals[downLeft].load(n);
|
|
|
- grid.normals[topLeft].load(n);
|
|
|
+ if( adjUpLeftGrid != null ) adjUpLeftGrid.normals[downRight].load(n);
|
|
|
+ if( adjLeftGrid != null ) adjLeftGrid.normals[upRight].load(n);
|
|
|
+ if( adjUpGrid != null ) adjUpGrid.normals[downLeft].load(n);
|
|
|
+ grid.normals[upLeft].load(n);
|
|
|
+ if( adjUpLeftTile != null ) adjUpLeftTile.needAlloc = true;
|
|
|
|
|
|
+ // Down Left Corner
|
|
|
n.set(0,0,0);
|
|
|
- if( adjDownLeftGrid != null && adjDownLeftGrid.normals != null ) {
|
|
|
- var pos = (triCount) * 3 * (adjDownLeftGrid.height - 1) ;
|
|
|
- i0 = adjDownLeftGrid.idx[pos++]; i1 = adjDownLeftGrid.idx[pos++]; i2 = adjDownLeftGrid.idx[pos++];
|
|
|
- computeVertexPos(adjDownLeftTile);
|
|
|
- n = computeNormal();
|
|
|
- i0 = adjDownLeftGrid.idx[pos++]; i1 = adjDownLeftGrid.idx[pos++]; i2 = adjDownLeftGrid.idx[pos++];
|
|
|
- computeVertexPos(adjDownLeftTile);
|
|
|
- n = n.add(computeNormal());
|
|
|
- n.normalize();
|
|
|
- }
|
|
|
- if( adjLeftGrid != null && adjLeftGrid.normals != null ) n = n.add(adjLeftGrid.normals[downRight]);
|
|
|
- if( adjDownGrid != null && adjDownGrid.normals != null ) n = n.add(adjDownGrid.normals[topLeft]);
|
|
|
- n = n.add(grid.normals[downLeft]);
|
|
|
+ n = n.add(computeDownLeftNormal(grid));
|
|
|
+ n = n.add(computeUpLeftNormal(adjDownGrid));
|
|
|
+ n = n.add(computeDownRightNormal(adjLeftGrid));
|
|
|
+ n = n.add(computeUpRightNormal(adjDownLeftGrid));
|
|
|
n.normalize();
|
|
|
- if( adjDownLeftGrid != null && adjDownLeftGrid.normals != null ) adjDownLeftGrid.normals[upRight].load(n);
|
|
|
- if( adjLeftGrid != null && adjLeftGrid.normals != null ) adjLeftGrid.normals[downRight].load(n);
|
|
|
- if( adjDownGrid != null && adjDownGrid.normals != null ) adjDownGrid.normals[topLeft].load(n);
|
|
|
+ if( adjDownLeftGrid != null ) adjDownLeftGrid.normals[upRight].load(n);
|
|
|
+ if( adjLeftGrid != null ) adjLeftGrid.normals[downRight].load(n);
|
|
|
+ if( adjDownGrid != null ) adjDownGrid.normals[upLeft].load(n);
|
|
|
grid.normals[downLeft].load(n);
|
|
|
+ if( adjDownLeftTile != null ) adjDownLeftTile.needAlloc = true;
|
|
|
|
|
|
+ // Down Right Corner
|
|
|
n.set(0,0,0);
|
|
|
- if( adjDownRightGrid != null && adjDownRightGrid.normals != null ) {
|
|
|
- var pos = triCount * 3 * adjDownRightGrid.width - 3;
|
|
|
- i0 = adjDownRightGrid.idx[pos++]; i1 = adjDownRightGrid.idx[pos++]; i2 = adjDownRightGrid.idx[pos++];
|
|
|
- computeVertexPos(adjDownRightTile);
|
|
|
- n = computeNormal();
|
|
|
- n.normalize();
|
|
|
- }
|
|
|
- if( adjRightGrid != null && adjRightGrid.normals != null ) n = n.add(adjRightGrid.normals[downLeft]);
|
|
|
- if( adjDownGrid != null && adjDownGrid.normals != null ) n = n.add(adjDownGrid.normals[upRight]);
|
|
|
- n = n.add(grid.normals[downRight]);
|
|
|
+ n = n.add(computeDownLeftNormal(adjRightGrid));
|
|
|
+ n = n.add(computeUpLeftNormal(adjDownRightGrid));
|
|
|
+ n = n.add(computeDownRightNormal(grid));
|
|
|
+ n = n.add(computeUpRightNormal(adjDownGrid));
|
|
|
n.normalize();
|
|
|
- if( adjDownRightGrid != null && adjDownRightGrid.normals != null ) adjDownRightGrid.normals[topLeft].load(n);
|
|
|
- if( adjRightGrid != null && adjRightGrid.normals != null ) adjRightGrid.normals[downLeft].load(n);
|
|
|
- if( adjDownGrid != null && adjDownGrid.normals != null ) adjDownGrid.normals[upRight].load(n);
|
|
|
+ if( adjDownRightGrid != null ) adjDownRightGrid.normals[upLeft].load(n);
|
|
|
+ if( adjRightGrid != null ) adjRightGrid.normals[downLeft].load(n);
|
|
|
+ if( adjDownGrid != null ) adjDownGrid.normals[upRight].load(n);
|
|
|
grid.normals[downRight].load(n);
|
|
|
-
|
|
|
- if( adjUpTile != null ) adjUpTile.needAlloc = true;
|
|
|
- if( adjDownTile != null ) adjDownTile.needAlloc = true;
|
|
|
- if( adjLeftTile != null ) adjLeftTile.needAlloc = true;
|
|
|
- if( adjRightTile != null ) adjRightTile.needAlloc = true;
|
|
|
- if( adjUpLeftTile != null ) adjUpLeftTile.needAlloc = true;
|
|
|
if( adjDownLeftTile != null ) adjDownLeftTile.needAlloc = true;
|
|
|
- if( adjUpRightTile != null ) adjUpRightTile.needAlloc = true;
|
|
|
- if( adjDownRightTile != null ) adjDownRightTile.needAlloc = true;
|
|
|
- this.needAlloc = true;
|
|
|
+
|
|
|
+ needAlloc = true;
|
|
|
}
|
|
|
|
|
|
public function computeNormals() {
|
|
|
- if( grid.normals == null ) grid.normals = new Array<h3d.col.Point>();
|
|
|
- grid.normals = [
|
|
|
- for ( i in 0...grid.points.length ) {
|
|
|
- if( i < grid.normals.length ) {
|
|
|
- grid.normals[i].set(0,0,0);
|
|
|
- grid.normals[i];
|
|
|
- } else
|
|
|
- new h3d.col.Point();
|
|
|
- }];
|
|
|
-
|
|
|
- var t0 = new h3d.col.Point(); var t1 = new h3d.col.Point(); var t2 = new h3d.col.Point();
|
|
|
- var pos = 0;
|
|
|
- for( i in 0...grid.triCount() ) {
|
|
|
- var i0, i1, i2;
|
|
|
- if( grid.idx == null ) {
|
|
|
- i0 = pos++; i1 = pos++; i2 = pos++;
|
|
|
- } else {
|
|
|
- i0 = grid.idx[pos++]; i1 = grid.idx[pos++]; i2 = grid.idx[pos++];
|
|
|
- }
|
|
|
- t0.load(grid.points[i0]); t1.load(grid.points[i1]); t2.load(grid.points[i2]);
|
|
|
- if(heightMap != null){
|
|
|
- t0.z += getHeight(t0.x / terrain.tileSize, t0.y / terrain.tileSize);
|
|
|
- t1.z += getHeight(t1.x / terrain.tileSize, t1.y / terrain.tileSize);
|
|
|
- t2.z += getHeight(t2.x / terrain.tileSize, t2.y / terrain.tileSize);
|
|
|
- }
|
|
|
- var n1 = t1.sub(t0);
|
|
|
- n1.normalizeFast();
|
|
|
- var n2 = t2.sub(t0);
|
|
|
- n2.normalizeFast();
|
|
|
- var n = n1.cross(n2);
|
|
|
- grid.normals[i0].x += n.x; grid.normals[i0].y += n.y; grid.normals[i0].z += n.z;
|
|
|
- grid.normals[i1].x += n.x; grid.normals[i1].y += n.y; grid.normals[i1].z += n.z;
|
|
|
- grid.normals[i2].x += n.x; grid.normals[i2].y += n.y; grid.normals[i2].z += n.z;
|
|
|
- }
|
|
|
- for( n in grid.normals )
|
|
|
- n.normalize();
|
|
|
+ if( grid != null )
|
|
|
+ grid.addNormals();
|
|
|
+ }
|
|
|
|
|
|
- needAlloc = true;
|
|
|
+ public function computeTangents() {
|
|
|
+ if( grid != null )
|
|
|
+ grid.addTangents();
|
|
|
}
|
|
|
|
|
|
public function getHeight( u : Float, v : Float, ?fast = false ) : Float {
|
|
@@ -590,7 +521,7 @@ class Tile extends h3d.scene.Mesh {
|
|
|
return pixels.getPixelF(Std.int(hxd.Math.clamp(u, 0, pixels.width - 1)), Std.int(hxd.Math.clamp(v, 0, pixels.height - 1))).r;
|
|
|
}
|
|
|
var px = u * (pixels.width - 1) ;
|
|
|
- var py = v * (pixels.width - 1) ;
|
|
|
+ var py = v * (pixels.height - 1) ;
|
|
|
var pxi = hxd.Math.floor(px);
|
|
|
var pyi = hxd.Math.floor(py);
|
|
|
var c00 = getPix(pxi, pyi);
|
|
@@ -616,9 +547,9 @@ class Tile extends h3d.scene.Mesh {
|
|
|
if( cachedBounds == null ) {
|
|
|
if( heightMap != null ) {
|
|
|
cachedBounds = new h3d.col.Bounds();
|
|
|
- cachedBounds.xMax = terrain.tileSize;
|
|
|
+ cachedBounds.xMax = terrain.tileSize.x;
|
|
|
cachedBounds.xMin = 0.0;
|
|
|
- cachedBounds.yMax = terrain.tileSize;
|
|
|
+ cachedBounds.yMax = terrain.tileSize.y;
|
|
|
cachedBounds.yMin = 0.0;
|
|
|
for( u in 0 ... heightMap.width ) {
|
|
|
for( v in 0 ... heightMap.height ) {
|
|
@@ -654,9 +585,8 @@ class Tile extends h3d.scene.Mesh {
|
|
|
shader.SURFACE_COUNT = terrain.surfaceArray.surfaceCount;
|
|
|
shader.PARALLAX = terrain.enableParallax && terrain.parallaxAmount != 0;
|
|
|
|
|
|
- shader.heightMapSize = heightMap != null ? heightMap.width : 0;
|
|
|
- shader.primSize = terrain.tileSize;
|
|
|
- shader.cellSize = terrain.cellSize;
|
|
|
+ shader.primSize.set(terrain.tileSize.x, terrain.tileSize.y);
|
|
|
+ shader.cellSize.set(terrain.cellSize.x, terrain.cellSize.y);
|
|
|
|
|
|
shader.albedoTextures = terrain.surfaceArray.albedo;
|
|
|
shader.normalTextures = terrain.surfaceArray.normal;
|