浏览代码

Add "Set" for terrain height edition

ShiroSmith 7 年之前
父节点
当前提交
3916e9a9a0

+ 7 - 0
hide/prefab/terrain/Brush.hx

@@ -42,10 +42,17 @@ enum Mode {
 	Delete;
 	Delete;
 }
 }
 
 
+enum SculptMode {
+	AddSub;
+	Set;
+	Smooth;
+}
+
 class BrushMode {
 class BrushMode {
 	public var accumulate = false;
 	public var accumulate = false;
 	public var substract = false;
 	public var substract = false;
 	public var mode = Paint;
 	public var mode = Paint;
+	public var scultpMode = AddSub;
 	public function new(){}
 	public function new(){}
 }
 }
 
 

+ 17 - 0
hide/prefab/terrain/SetHeight.hx

@@ -0,0 +1,17 @@
+package hide.prefab.terrain;
+
+class SetHeight extends h3d.shader.ScreenShader {
+
+	static var SRC = {
+
+		@param var prevHeight : Sampler2D;
+		@param var strengthTex : Sampler2D;
+		@param var targetHeight : Float;
+
+		function fragment() {
+			var height = prevHeight.get(calculatedUV).r;
+			var strength = strengthTex.get(calculatedUV).r;
+			pixelColor = vec4(mix(height, targetHeight, clamp(strength,0,1)));
+		}
+	}
+}

+ 0 - 1
hide/prefab/terrain/StrokeBuffer.hx

@@ -42,7 +42,6 @@ class StrokeBuffer {
 		used = false;
 		used = false;
 		if(tex != null) tex.clear(0);
 		if(tex != null) tex.clear(0);
 		if(tempTex != null) tempTex.clear(0);
 		if(tempTex != null) tempTex.clear(0);
-		if(prevTex != null) prevTex.clear(0);
 	}
 	}
 }
 }
 
 

+ 142 - 63
hide/prefab/terrain/TerrainEditor.hx

@@ -47,10 +47,13 @@ class TerrainEditor {
 	var copyPass : h3d.pass.Copy;
 	var copyPass : h3d.pass.Copy;
 	var heightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray;
 	var heightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray;
 	var weightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray;
 	var weightStrokeBufferArray : hide.prefab.terrain.StrokeBuffer.StrokeBufferArray;
+
 	var normalizeWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.NormalizeWeight());
 	var normalizeWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.NormalizeWeight());
 	var clampWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.ClampWeight());
 	var clampWeight = new h3d.pass.ScreenFx(new hide.prefab.terrain.ClampWeight());
 	var generateIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.GenerateIndex());
 	var generateIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.GenerateIndex());
 	var swapIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.SwapIndex());
 	var swapIndex = new h3d.pass.ScreenFx(new hide.prefab.terrain.SwapIndex());
+	var setHeigth = new h3d.pass.ScreenFx(new hide.prefab.terrain.SetHeight());
+
 	var terrainPrefab : hide.prefab.terrain.Terrain;
 	var terrainPrefab : hide.prefab.terrain.Terrain;
 	var undo : hide.ui.UndoHistory;
 	var undo : hide.ui.UndoHistory;
 	var tileTrashBin : Array<h3d.scene.pbr.terrain.Tile> = [];
 	var tileTrashBin : Array<h3d.scene.pbr.terrain.Tile> = [];
@@ -104,13 +107,14 @@ class TerrainEditor {
 	}
 	}
 
 
 	function updateRender(){
 	function updateRender(){
-		for(tile in terrainPrefab.terrain.tiles) tile.material.removePass(tile.material.getPass("overlay"));
+		for(tile in terrainPrefab.terrain.tiles)
+			tile.material.removePass(tile.material.getPass("overlay"));
 		terrainPrefab.terrain.showChecker = false;
 		terrainPrefab.terrain.showChecker = false;
 		terrainPrefab.terrain.showComplexity = false;
 		terrainPrefab.terrain.showComplexity = false;
 		switch(renderMode){
 		switch(renderMode){
-			case PBR:
-			case ShaderComplexity: terrainPrefab.terrain.showComplexity = true;
-			case Checker: terrainPrefab.terrain.showChecker = true;
+			case PBR :
+			case ShaderComplexity : terrainPrefab.terrain.showComplexity = true;
+			case Checker : terrainPrefab.terrain.showChecker = true;
 		}
 		}
 	}
 	}
 
 
@@ -192,7 +196,21 @@ class TerrainEditor {
 				strokeBuffer.prevTex = null;
 				strokeBuffer.prevTex = null;
 				var revert = new TileRevertData(strokeBuffer.x, strokeBuffer.y);
 				var revert = new TileRevertData(strokeBuffer.x, strokeBuffer.y);
 				revert.prevHeightMapPixels = tile.getHeightPixels();
 				revert.prevHeightMapPixels = tile.getHeightPixels();
-				copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.substract ? Sub : Add);
+
+				switch(currentBrush.brushMode.scultpMode){
+					case AddSub :
+						copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.substract ? Sub : Add);
+						tile.needNewPixelCapture = true;
+					case Set :
+						copyPass.apply(tile.heightMap, strokeBuffer.tempTex);
+						setHeigth.shader.prevHeight = strokeBuffer.tempTex;
+						setHeigth.shader.targetHeight = currentBrush.strength;
+						setHeigth.shader.strengthTex = strokeBuffer.tex;
+						h3d.Engine.getCurrent().pushTarget(tile.heightMap);
+						setHeigth.render();
+					case Smooth :
+				}
+
 				tile.needNewPixelCapture = true;
 				tile.needNewPixelCapture = true;
 				revert.nextHeightMapPixels = tile.getHeightPixels();
 				revert.nextHeightMapPixels = tile.getHeightPixels();
 				revertDatas.push(revert);
 				revertDatas.push(revert);
@@ -294,8 +312,18 @@ class TerrainEditor {
 		for(strokeBuffer in heightStrokeBufferArray.strokeBuffers){
 		for(strokeBuffer in heightStrokeBufferArray.strokeBuffers){
 			if(strokeBuffer.used == true){
 			if(strokeBuffer.used == true){
 				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
 				var tile = terrainPrefab.terrain.getTile(strokeBuffer.x, strokeBuffer.y);
-				copyPass.apply(strokeBuffer.prevTex, tile.heightMap);
-				copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.substract ? Sub : Add);
+				switch(currentBrush.brushMode.scultpMode){
+					case AddSub :
+						copyPass.apply(strokeBuffer.prevTex, tile.heightMap);
+						copyPass.apply(strokeBuffer.tex, tile.heightMap, currentBrush.brushMode.substract ? Sub : Add);
+					case Set :
+						setHeigth.shader.prevHeight = strokeBuffer.prevTex;
+						setHeigth.shader.targetHeight = currentBrush.strength;
+						setHeigth.shader.strengthTex = strokeBuffer.tex;
+						h3d.Engine.getCurrent().pushTarget(tile.heightMap);
+						setHeigth.render();
+					case Smooth :
+				}
 			}
 			}
 		}
 		}
 
 
@@ -336,7 +364,7 @@ class TerrainEditor {
 		}
 		}
 	}
 	}
 
 
-	public function projectToGround(ray: h3d.col.Ray) {
+	function projectToGround(ray: h3d.col.Ray) {
 		var minDist = -1.;
 		var minDist = -1.;
 		var normal = terrainPrefab.terrain.getAbsPos().up();
 		var normal = terrainPrefab.terrain.getAbsPos().up();
 		var plane = h3d.col.Plane.fromNormalPoint(normal.toPoint(), new h3d.col.Point(terrainPrefab.terrain.getAbsPos().tx, terrainPrefab.terrain.getAbsPos().ty, terrainPrefab.terrain.getAbsPos().tz));
 		var plane = h3d.col.Plane.fromNormalPoint(normal.toPoint(), new h3d.col.Point(terrainPrefab.terrain.getAbsPos().tx, terrainPrefab.terrain.getAbsPos().ty, terrainPrefab.terrain.getAbsPos().tz));
@@ -352,7 +380,7 @@ class TerrainEditor {
 		return dist >= 0 ? ray.getPoint(dist) : null;
 		return dist >= 0 ? ray.getPoint(dist) : null;
 	}
 	}
 
 
-	public function worldToScreen(wx: Float, wy: Float, wz: Float, ctx : Context) {
+	function worldToScreen(wx: Float, wy: Float, wz: Float, ctx : Context) {
 		var s2d = @:privateAccess ctx.local2d.getScene();
 		var s2d = @:privateAccess ctx.local2d.getScene();
 		var camera = @:privateAccess ctx.local3d.getScene().camera;
 		var camera = @:privateAccess ctx.local3d.getScene().camera;
 		var pt = camera.project(wx, wy, wz, s2d.width, s2d.height);
 		var pt = camera.project(wx, wy, wz, s2d.width, s2d.height);
@@ -446,6 +474,14 @@ class TerrainEditor {
 			renderTerrainUV(ctx);
 			renderTerrainUV(ctx);
 			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
 			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
 		}
 		}
+
+		currentBrush.bitmap.color = new h3d.Vector(1.0);
+		var shader : h3d.shader.pbr.Brush = currentBrush.bitmap.getShader(h3d.shader.pbr.Brush);
+		if( shader == null ) shader = currentBrush.bitmap.addShader(new h3d.shader.pbr.Brush());
+		currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
+		shader.strength = currentBrush.strength;
+		shader.size = currentBrush.size / terrainPrefab.tileSize;
+
 		for(tile in tiles){
 		for(tile in tiles){
 			var strokeBuffer = weightStrokeBufferArray.getStrokeBuffer(tile.tileX, tile.tileY);
 			var strokeBuffer = weightStrokeBufferArray.getStrokeBuffer(tile.tileX, tile.tileY);
 			if(strokeBuffer.used == false){
 			if(strokeBuffer.used == false){
@@ -459,17 +495,7 @@ class TerrainEditor {
 			}
 			}
 			var localPos = tile.globalToLocal(brushWorldPos.clone());
 			var localPos = tile.globalToLocal(brushWorldPos.clone());
 			localPos.scale3(1.0 / terrainPrefab.tileSize);
 			localPos.scale3(1.0 / terrainPrefab.tileSize);
-			currentBrush.bitmap.color = new h3d.Vector(1.0);
-			var shader : h3d.shader.pbr.Brush = currentBrush.bitmap.getShader(h3d.shader.pbr.Brush);
-			if( shader == null ) shader = currentBrush.bitmap.addShader(new h3d.shader.pbr.Brush());
-
-			shader.normalize = false;
-			shader.clamp = false;
-			shader.generateIndex = false;
-			shader.size = currentBrush.size / terrainPrefab.tileSize;
 			shader.pos = new h3d.Vector(localPos.x - (currentBrush.size  / terrainPrefab.tileSize * 0.5), localPos.y - (currentBrush.size  / terrainPrefab.tileSize * 0.5));
 			shader.pos = new h3d.Vector(localPos.x - (currentBrush.size  / terrainPrefab.tileSize * 0.5), localPos.y - (currentBrush.size  / terrainPrefab.tileSize * 0.5));
-			currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
-			shader.strength = currentBrush.strength;
 			currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.tileSize);
 			currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.tileSize);
 		}
 		}
 	}
 	}
@@ -483,6 +509,30 @@ class TerrainEditor {
 			renderTerrainUV(ctx);
 			renderTerrainUV(ctx);
 			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
 			brushWorldPos = getBrushWorldPosFromTex(pos, ctx);
 		}
 		}
+
+		switch(currentBrush.brushMode.scultpMode){
+			case AddSub : currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
+			case Set : currentBrush.bitmap.blendMode = Max;
+			case Smooth : currentBrush.bitmap.blendMode = None;
+		}
+
+		var shader : h3d.shader.pbr.Brush = currentBrush.bitmap.getShader(h3d.shader.pbr.Brush);
+		if( shader == null ) shader = currentBrush.bitmap.addShader(new h3d.shader.pbr.Brush());
+		currentBrush.bitmap.color = new h3d.Vector(1.0);
+		shader.size = currentBrush.size / terrainPrefab.tileSize;
+
+		switch(currentBrush.brushMode.scultpMode){
+			case AddSub :
+				currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
+				shader.strength = currentBrush.strength;
+			case Set :
+				currentBrush.bitmap.blendMode = Max;
+				shader.strength = 1;
+			case Smooth :
+				currentBrush.bitmap.blendMode = None;
+				shader.strength = 1;
+		}
+
 		for(tile in tiles){
 		for(tile in tiles){
 			var localPos = tile.globalToLocal(brushWorldPos.clone());
 			var localPos = tile.globalToLocal(brushWorldPos.clone());
 			localPos.scale3(1.0 / terrainPrefab.tileSize);
 			localPos.scale3(1.0 / terrainPrefab.tileSize);
@@ -492,9 +542,7 @@ class TerrainEditor {
 				tile.heightMap = strokeBuffer.tempTex;
 				tile.heightMap = strokeBuffer.tempTex;
 				strokeBuffer.used = true;
 				strokeBuffer.used = true;
 			}
 			}
-			currentBrush.bitmap.blendMode = currentBrush.brushMode.accumulate ? Add : Max;
-			currentBrush.bitmap.color = new h3d.Vector(currentBrush.strength);
-			if(currentBrush.bitmap.getShader(h3d.shader.pbr.Brush) != null ) currentBrush.bitmap.removeShader(currentBrush.bitmap.getShader(h3d.shader.pbr.Brush));
+			shader.pos = new h3d.Vector(localPos.x - (currentBrush.size  / terrainPrefab.tileSize * 0.5), localPos.y - (currentBrush.size  / terrainPrefab.tileSize * 0.5));
 			currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.tileSize, -1);
 			currentBrush.drawTo(strokeBuffer.tex, localPos, terrainPrefab.tileSize, -1);
 		}
 		}
 	}
 	}
@@ -518,7 +566,7 @@ class TerrainEditor {
 					e.propagate = false;
 					e.propagate = false;
 					if(currentBrush.isValid()){
 					if(currentBrush.isValid()){
 						lastPos = worldPos.clone();
 						lastPos = worldPos.clone();
-						currentBrush.brushMode.substract = K.isDown(K.CTRL);
+						currentBrush.brushMode.substract = K.isDown(K.ALT);
 						useBrush( lastPos, worldPos, ctx);
 						useBrush( lastPos, worldPos, ctx);
 						previewStrokeBuffers();
 						previewStrokeBuffers();
 						drawBrushPreview(worldPos, ctx);
 						drawBrushPreview(worldPos, ctx);
@@ -713,50 +761,77 @@ class TerrainEditor {
 		}
 		}
 	}
 	}
 
 
+	function refreshBrushParams(props : hide.Element, ctx : EditContext){
+		var brusheModeParams = props.find(".brushModeParams");
+		//brusheModeParams.empty();
+		//if(currentBrush.brushMode.mode == Sculpt)
+		brusheModeParams.append(sculptModeParams);
+	}
+
+	var brushMode =
+	'<div class="group" name="Mode">
+		<dt>AutoCreate</dt><dd><input type="checkbox" field="autoCreateTile"/></dd>
+		<dt>Accumulate</dt><dd><input type="checkbox" field="editor.currentBrush.brushMode.accumulate"/></dd>
+		<dt>Mode</dt>
+		<dd><select field="editor.currentBrush.brushMode.mode">
+			<option value="Paint">Paint</option>
+			<option value="Sculpt">Sculpt</option>
+			<option value="Delete">Delete</option>
+		</select></dd>
+		<div class="brushModeParams"></div>
+	</div>';
+
+	var sculptModeParams =
+	'<dt>Sculpt Mode</dt>
+		<dd><select field="editor.currentBrush.brushMode.scultpMode">
+			<option value="AddSub">Add / Sub</option>
+			<option value="Set">Set</option>
+			<option value="Smooth">Smooth</option>
+	</select></dd>';
+
+	var brushParams =
+	'<div class="group" name="Brush">
+		<div class="terrain-brushes"></div>
+		<dt>Size</dt><dd><input type="range" min="0.01" max="10" field="editor.currentBrush.size"/></dd>
+		<dt>Strength</dt><dd><input type="range" min="0" max="1" field="editor.currentBrush.strength"/></dd>
+		<dt>Step</dt><dd><input type="range" min="0.01" max="10" field="editor.currentBrush.step"/></dd>
+	</div>';
+
+	var surfaceParams =
+	'<div class="group" name="Surface">
+		<dt>Add</dt><dd><input type="texturepath" field="editor.tmpTexPath"/></dd>
+		<div class="terrain-surfaces"></div>
+		<div class="group" name="Params">
+			<dt>Tilling</dt><dd><input type="range" min="0" max="10" field="editor.currentSurface.tilling"/></dd>
+			<dt>Offset X</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.offset.x"/></dd>
+			<dt>Offset Y</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.offset.y"/></dd>
+			<dt>Rotate</dt><dd><input type="range" min="0" max="360" field="editor.currentSurface.angle"/></dd>
+		</div>
+	</div>';
+
 	public function setupUI(props : hide.Element, ctx : EditContext){
 	public function setupUI(props : hide.Element, ctx : EditContext){
+		props.append(brushMode);
+		props.append(brushParams);
+		props.append(surfaceParams);
+		refreshBrushParams(props, ctx);
 		props.append(
 		props.append(
-			'<div class="group" name="Mode">
-				<dt>Accumulate</dt><dd><input type="checkbox" field="editor.currentBrush.brushMode.accumulate"/></dd>
-				<dt>Mode</dt>
-				<dd><select field="editor.currentBrush.brushMode.mode">
-					<option value="Paint">Paint</option>
-					<option value="Sculpt">Sculpt</option>
-					<option value="Delete">Delete</option>
-				</select></dd>
-				<dt>AutoCreate</dt><dd><input type="checkbox" field="autoCreateTile"/></dd>
-			</div>
-			<div class="group" name="Brush">
-				<div class="terrain-brushes"></div>
-				<dt>Size</dt><dd><input type="range" min="0.01" max="10" field="editor.currentBrush.size"/></dd>
-				<dt>Strength</dt><dd><input type="range" min="0" max="1" field="editor.currentBrush.strength"/></dd>
-				<dt>Step</dt><dd><input type="range" min="0.01" max="10" field="editor.currentBrush.step"/></dd>
-			</div>
-			<div class="group" name="Surface">
-				<dt>Add</dt><dd><input type="texturepath" field="editor.tmpTexPath"/></dd>
-				<div class="terrain-surfaces"></div>
-				<div class="group" name="Params">
-					<dt>Tilling</dt><dd><input type="range" min="0" max="10" field="editor.currentSurface.tilling"/></dd>
-					<dt>Offset X</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.offset.x"/></dd>
-					<dt>Offset Y</dt><dd><input type="range" min="0" max="1" field="editor.currentSurface.offset.y"/></dd>
-					<dt>Rotate</dt><dd><input type="range" min="0" max="360" field="editor.currentSurface.angle"/></dd>
-				</div>
-			</div>
-			<div align="center">
+			'<div align="center">
 				<input type="button" value="Save" class="save" />
 				<input type="button" value="Save" class="save" />
 			</div>');
 			</div>');
 
 
-			props.find(".save").click(function(_) {
-				var datPath = new haxe.io.Path(ctx.rootContext.shared.currentPath);
-				datPath.ext = "dat";
-				var fullPath = hide.Ide.inst.getPath(datPath.toString() + "/" + terrainPrefab.name);
-				if( sys.FileSystem.isDirectory(fullPath)){
-					var files = sys.FileSystem.readDirectory(fullPath);
-					for(file in files)
-						sys.FileSystem.deleteFile(fullPath + "/" + file);
-				}
-				terrainPrefab.saveWeightTextures(ctx.rootContext);
-				terrainPrefab.saveHeightTextures(ctx.rootContext);
-			});
+		// Save Button
+		props.find(".save").click(function(_) {
+			var datPath = new haxe.io.Path(ctx.rootContext.shared.currentPath);
+			datPath.ext = "dat";
+			var fullPath = hide.Ide.inst.getPath(datPath.toString() + "/" + terrainPrefab.name);
+			if( sys.FileSystem.isDirectory(fullPath)){
+				var files = sys.FileSystem.readDirectory(fullPath);
+				for(file in files)
+					sys.FileSystem.deleteFile(fullPath + "/" + file);
+			}
+			terrainPrefab.saveWeightTextures(ctx.rootContext);
+			terrainPrefab.saveHeightTextures(ctx.rootContext);
+		});
 
 
 		var brushes : Array<Dynamic> = ctx.scene.config.get("terrain.brushes");
 		var brushes : Array<Dynamic> = ctx.scene.config.get("terrain.brushes");
 		var brushesContainer = props.find(".terrain-brushes");
 		var brushesContainer = props.find(".terrain-brushes");
@@ -799,6 +874,10 @@ class TerrainEditor {
 	}
 	}
 
 
 	public function onChange(ctx : EditContext, pname, props){
 	public function onChange(ctx : EditContext, pname, props){
+
+		//if( pname == "editor.currentBrush.brushMode.mode")
+			//refreshBrushParams(props, ctx);
+
 		if(pname == "editor.tmpTexPath" && tmpTexPath != null){
 		if(pname == "editor.tmpTexPath" && tmpTexPath != null){
 			var split : Array<String> = [];
 			var split : Array<String> = [];
 			var curTypeIndex = 0;
 			var curTypeIndex = 0;
@@ -807,7 +886,6 @@ class TerrainEditor {
 				curTypeIndex++;
 				curTypeIndex++;
 			}
 			}
 			if(split.length > 1) {
 			if(split.length > 1) {
-				var t : h3d.mat.Texture;
 				var name = split[0];
 				var name = split[0];
 				var albedo = ctx.rootContext.shared.loadTexture(name + textureType[0] + ".png");
 				var albedo = ctx.rootContext.shared.loadTexture(name + textureType[0] + ".png");
 				var normal = ctx.rootContext.shared.loadTexture(name + textureType[1] + ".png");
 				var normal = ctx.rootContext.shared.loadTexture(name + textureType[1] + ".png");
@@ -843,6 +921,7 @@ class TerrainEditor {
 				wait();
 				wait();
 			}
 			}
 		}
 		}
+
 		tmpTexPath = null;
 		tmpTexPath = null;
 	}
 	}
 }
 }