Ejemplo n.º 1
0
        public void ApplyStampsToTerrain(TerrainWrapper wrapper)
        {
            wrapper.OnPostFinalise -= ApplyStampsToTerrain;
            if (!ApplyStamps)
            {
                return;
            }
            //Debug.Log("ApplyStampsToTerrain");
            if (!wrapper.ObjectContainer)
            {
                return;
            }
            var ws = wrapper.ObjectContainer.transform.FindTransformInChildren(LayerName);

            if (!ws)
            {
                return;
            }
            var           stamps = ws.GetComponentsInChildren <WorldStamp>();
            List <string> layers = new List <string>();

            foreach (var s in stamps)
            {
                if (layers.Contains(s.LayerName))
                {
                    continue;
                }
                layers.Add(s.LayerName);
            }
            layers = layers.OrderBy((x) => wrapper.Layers.FindIndex(0, (y) => x == y.name)).ToList();
            for (var i = 0; i < layers.Count; ++i)
            {
                LayerComponentApplyManager.ApplyAllLayerComponents(wrapper, layers[i]);
            }
        }
Ejemplo n.º 2
0
		public static void WeldToNextX (ref float[,] heights, TerrainWrapper neig, int margin)
		{
			#if WDEBUG
			Profiler.BeginSample("Weld Height");
			#endif
			//Debug.Log("NextX");
			int heightSize = heights.GetLength(0);

			var nStrip = neig.GetCompoundHeights(null,0,0,heightSize,1,heightSize);
			
			for (int z=0; z<heightSize; z++)
			{
				float thisHeight = Mathf.Clamp01(nStrip[z,0]);

				for (int x=heightSize-margin; x<heightSize; x++)
				{
					float percent = 1 - 1f*(heightSize-x-1)/margin;
					//percent = 3*percent*percent - 2*percent*percent*percent;
				
					//heights[z,x] += delta*percent;
					//float prevValue = Mathf.Clamp01(heights[z,x]) ;
					heights[z,x] = Mathf.Lerp(heights[z,x], thisHeight, percent);
					//Debug.Log(string.Format("Set ({0}, {1}) from {2} to {3} ({4}% to {5})", x, z, prevValue, heights[z,x], percent, thisHeight));
				}	
			}

			#if WDEBUG
			Profiler.EndSample();
			#endif
		}
Ejemplo n.º 3
0
		public static void WeldToPrevZ (ref float[,] heights, TerrainWrapper neig, int margin)
		{
			#if WDEBUG
			Profiler.BeginSample("Weld Height");
			#endif
			//Debug.Log("PrevZ");
			int heightSize = heights.GetLength(0);

			var nStrip = neig.GetCompoundHeights(null,heightSize-1,0,1,heightSize,heightSize);

			for (int x=0; x<heightSize; x++)
			{
				var delta = nStrip[0,x] - heights[0,x];
				
				//float percentFromSide = Mathf.Min( Mathf.Clamp01(1f*x/margin),  Mathf.Clamp01(1 - 1f*(x-(heightSize-1-margin))/margin) );
				//float invPercentFromSide = 2000000000; if (percentFromSide > 0.0001f) invPercentFromSide = 1f/percentFromSide;

				for (int z=0; z<margin; z++)
				{
					float percent = 1-1f*z/margin;
				//	if (percentFromSide < 0.999f) percent = Mathf.Pow(percent, invPercentFromSide);
					//percent = 3*percent*percent - 2*percent*percent*percent;
				
					heights[z,x] += delta*percent;
					//heights[z,x] = 1;
				}	
			}

			#if WDEBUG
			Profiler.EndSample();
			#endif
		}
Ejemplo n.º 4
0
		public static void WeldToPrevX (ref float[,] heights, TerrainWrapper neig, int margin)
		{
			#if WDEBUG
			Profiler.BeginSample("Weld Height");
			#endif
			
			int heightSize = heights.GetLength(0);
			//Debug.Log("PrevX:" + heightSize);

			var nStrip = neig.GetCompoundHeights(null,0,heightSize-1,heightSize,1,heightSize);
			//var nStrip = neig.GetCompoundHeights(null,0,0,heightSize,1,heightSize);
			
			for (int x=0; x<heightSize; x++)	
			{
				float delta = nStrip[x,0] - heights[x,0];

				for (int z=0; z<margin; z++)
				{
					float percent = 1-1f*z/margin;
					//percent = 3*percent*percent - 2*percent*percent*percent;
				
					heights[x,z] += delta*percent;
					//heights[z,x] = 1;
				}	
			}

			#if WDEBUG
			Profiler.EndSample();
			#endif
		}
Ejemplo n.º 5
0
        public override void ProcessTrees(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }

            if (!Network || Configuration == null)
            {
                return;
            }

            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                return;
            }

            var spline = NodeConnection.GetSpline();
            var rand   = new Random(NodeConnection.ThisNode.Seed);
            var length = spline.Length;
            var step   = config.StepDistance;
            var tSize  = wrapper.Terrain.terrainData.size;

            for (var i = 0f; i < length; i += step.GetRand(rand))
            {
                var roll     = rand.NextDouble();
                var randroll = (float)rand.NextDouble();
                var eval     = config.ProbablityThroughCurve.Evaluate(randroll);
                //Debug.Log(randroll + " " + eval);
                var offsetDist = eval * config.OffsetMultiplier;
                var uniformT   = i / length;
                var naturalT   = spline.UniformToNaturalTime(uniformT);

                var offset      = (spline.GetTangent(naturalT).normalized *offsetDist);
                var probability = config.ProbablityAlongCurve.Evaluate(uniformT) * config.ProbabilityMultiplier;

                if (probability < roll)
                {
                    continue;
                }

                // Place tree
                var randIndex = Mathf.FloorToInt((float)rand.NextDouble() * config.Trees.Count);
                var prefab    = config.Trees[randIndex];
                var wPos      = spline.GetUniformPointOnSpline(uniformT) + offset;
                //var h -
                //wPos.y = wrapper.GetCompoundHeight(layer, wPos)*tSize.y;
                wPos.y = config.YOffset;

                //Debug.DrawLine(wPos, wPos + Vector3.up *10, Color.red, 10);
                var tPos = wrapper.Terrain.WorldToTreePos(wPos);
                layer.Trees.Add(new MadMapsTreeInstance(tPos, Vector2.one * config.Size.GetRand(rand), prefab, config.Color.GetRand(rand)));
            }
        }
Ejemplo n.º 6
0
        public void Snap()
        {
            if (!Network || Configuration.SnappingMode == NodeConfiguration.ESnappingMode.None || Vector3.Distance(_lastSnapPosition, transform.position) < .01f)
            {
                return; // Do nothing in this case
            }

            if (Configuration.SnappingMode == NodeConfiguration.ESnappingMode.Wrapper)
            {
                var pos     = transform.position;
                var wrapper = TerrainWrapper.GetWrapper(pos);
                if (wrapper != null)
                {
                    if (wrapper.Layers.Count > 0)
                    {
                        var newY = wrapper.GetCompoundHeight(Network.GetLayer(wrapper), pos) * wrapper.Terrain.terrainData.size.y
                                   + wrapper.Terrain.GetPosition().y + Configuration.SnapOffset;
                        transform.position = new Vector3(transform.position.x, newY, transform.position.z);
                    }
                    else
                    {
                        Debug.LogWarning("Node with a Wrapper snap setting on a terrain, but wrapper has no layers - this won't work.", this);
                    }
                }
                else
                {
                    Debug.LogWarning("Node with a Wrapper snap setting on a terrain without a TerrainWrapper component - this won't work.", this);
                }
                _lastSnapPosition = transform.position;
            }

            if (Configuration.SnappingMode == NodeConfiguration.ESnappingMode.Terrain)
            {
                var terrain = TerrainX.FindEncompassingTerrain(transform.position);
                var newY    = terrain.SampleHeight(transform.position) + terrain.GetPosition().y + Configuration.SnapOffset;
                transform.position = new Vector3(transform.position.x, newY, transform.position.z);
                _lastSnapPosition  = transform.position;
            }

            if (Configuration.SnappingMode == NodeConfiguration.ESnappingMode.Raycast)
            {
                RaycastHit hitInfo;
                if (Physics.Raycast(
                        new Ray(transform.position + Vector3.up * Configuration.SnapDistance / 2, Vector3.down), out hitInfo,
                        Configuration.SnapDistance, Configuration.SnapMask))
                {
                    transform.position = hitInfo.point + Vector3.up * Configuration.SnapOffset;
                }
                _lastSnapPosition = transform.position;
            }

            var exitNode = GetComponent <StampExitNode>();

            if (exitNode)
            {
                exitNode.Update();
            }
        }
        void OnEnable()
        {
            var wrappers = FindObjectsOfType <TerrainWrapper>();

            if (wrappers.Length > 0)
            {
                Context = wrappers[0];
            }
            Sort();
        }
Ejemplo n.º 8
0
        public override void ProcessDetails(TerrainWrapper terrainWrapper, LayerBase baseLayer, int stencilKey)
        {
            if (!RemoveGrass)
            {
                return;
            }
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            stencilKey = GetPriority();
            var objectBounds = GetObjectBounds();
            var dRes         = terrainWrapper.Terrain.terrainData.detailResolution;
            var axisBounds   = objectBounds.Flatten().ToAxisBounds();

            var matrixMin = terrainWrapper.Terrain.WorldToDetailCoord(axisBounds.min);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, dRes), Mathf.Clamp(matrixMin.z, 0, dRes));

            var matrixMax = terrainWrapper.Terrain.WorldToDetailCoord(axisBounds.max);

            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, dRes), Mathf.Clamp(matrixMax.z, 0, dRes));

            var arraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);

            var details = layer.GetDetailMaps(matrixMin.x, matrixMin.z, arraySize.x, arraySize.z, dRes);

            for (var dx = 0; dx < arraySize.x; ++dx)
            {
                var xF = dx / (float)arraySize.x;
                for (var dz = 0; dz < arraySize.z; ++dz)
                {
                    var zF      = dz / (float)arraySize.z;
                    var falloff = GetFalloff(new Vector2(xF, zF));
                    foreach (var serializable2DByteArray in details)
                    {
                        if (IgnoredDetails.Contains(serializable2DByteArray.Key))
                        {
                            continue;
                        }
                        var readValue  = serializable2DByteArray.Value[dx, dz] / 255f;
                        var newValue   = readValue * (1 - falloff);
                        var writeValue = (byte)Mathf.Clamp(newValue * 255, 0, 255);
                        serializable2DByteArray.Value[dx, dz] = writeValue;
                    }
                }
            }
            foreach (var serializable2DByteArray in details)
            {
                layer.SetDetailMap(serializable2DByteArray.Key, matrixMin.x, matrixMin.z, serializable2DByteArray.Value, dRes);
            }
        }
Ejemplo n.º 9
0
        public override void ProcessTrees(TerrainWrapper terrainWrapper, LayerBase baseLayer, int stencilKey)
        {
            if (!RemoveTrees)
            {
                return;
            }
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            var objectBounds = GetObjectBounds();

            stencilKey = GetPriority();
            var trees = terrainWrapper.GetCompoundTrees(layer, true);

            objectBounds = new ObjectBounds(objectBounds.center,
                                            new Vector3(objectBounds.extents.x, 50000,
                                                        objectBounds.extents.z), objectBounds.Rotation);

            foreach (var hurtTreeInstance in trees)
            {
                if (IgnoredTrees.Contains(hurtTreeInstance.Prototype))
                {
                    //Debug.DrawLine(worldPos, worldPos + Vector3.up * 10, Color.red, 50);
                    continue;
                }

                var worldPos = terrainWrapper.Terrain.TreeToWorldPos(hurtTreeInstance.Position);
                worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);
                if (!objectBounds.Contains(new Vector3(worldPos.x, objectBounds.center.y, worldPos.z)))
                {
                    //Debug.DrawLine(worldPos, worldPos + Vector3.up * 10, Color.red, 50);
                    continue;
                }

                var localPos = Quaternion.Inverse(objectBounds.Rotation) * (worldPos - objectBounds.min);
                var xDist    = localPos.x / objectBounds.size.x;
                var zDist    = localPos.z / objectBounds.size.z;

                float falloff = GetFalloff(new Vector2(xDist, zDist));
                //DebugHelper.DrawPoint(worldPos, 1, Color.white, 5);
                if (falloff > .5f)
                {
                    layer.TreeRemovals.Add(hurtTreeInstance.Guid);
                    //Debug.DrawLine(worldPos, worldPos + Vector3.up * 10, Color.red, 50);
                }

                /*else{
                 *  Debug.DrawLine(worldPos, worldPos + Vector3.up * 10, Color.green, 50);
                 * }*/
            }
        }
        void OnSelectionChange()
        {
            if (!Selection.activeGameObject)
            {
                return;
            }
            var wrapper = Selection.activeGameObject.GetComponent <TerrainWrapper>();

            if (wrapper)
            {
                Context     = wrapper;
                NeedsResort = true;
            }
        }
Ejemplo n.º 11
0
        public MMTerrainLayer GetLayer(TerrainWrapper terrainWrapper, bool createIfMissing = false)
        {
            MMTerrainLayer snapshot;

            if ((!LayerMapping.TryGetValue(terrainWrapper, out snapshot) || snapshot == null) && createIfMissing)
            {
                snapshot      = ScriptableObject.CreateInstance <MMTerrainLayer>();
                snapshot.name = "Road Network";
                LayerMapping[terrainWrapper] = snapshot;
                terrainWrapper.Layers.Insert(0, snapshot);
                snapshot.BlendMode = MMTerrainLayer.EMMTerrainLayerBlendMode.Stencil;
            }
            return(snapshot);
        }
Ejemplo n.º 12
0
        public override void ProcessObjects(TerrainWrapper terrainWrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            var regex        = new Regex(IgnoredObjectsRegex ?? string.Empty);
            var objectBounds = GetObjectBounds();

            stencilKey = GetPriority();
            var objects = terrainWrapper.GetCompoundObjects(layer);

            objectBounds = new ObjectBounds(objectBounds.center, new Vector3(objectBounds.extents.x, 5000, objectBounds.extents.z), objectBounds.Rotation);
            foreach (var prefabObjectData in objects)
            {
                if (!string.IsNullOrEmpty(IgnoredObjectsRegex) && regex.IsMatch(prefabObjectData.Prefab.name))
                {
                    continue;
                }

                var worldPos = terrainWrapper.Terrain.TreeToWorldPos(prefabObjectData.Position);
                worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);
                if (!objectBounds.Contains(new Vector3(worldPos.x, objectBounds.center.y, worldPos.z)))
                {
                    continue;
                }

                var localPos = Quaternion.Inverse(objectBounds.Rotation) * (worldPos - objectBounds.min);
                var xDist    = localPos.x / objectBounds.size.x;
                var zDist    = localPos.z / objectBounds.size.z;

                float falloff = GetFalloff(new Vector2(xDist, zDist));
                if (falloff > .5f)
                {
                    layer.ObjectRemovals.Add(prefabObjectData.Guid);
                }
            }
        }
Ejemplo n.º 13
0
        public override void ProcessObjects(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network)
            {
                return;
            }
            if (Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var spline = NodeConnection.GetSpline();
            var bounds = spline.GetApproximateXZObjectBounds();

            bounds.Expand(new Vector3(config.ObjectRemoveDistance, 1000, config.ObjectRemoveDistance));

            var tPos  = wrapper.transform.position;
            var tSize = wrapper.Terrain.terrainData.size;

            var regex = new Regex(config.RegexMatch ?? string.Empty);

            var objects = wrapper.GetCompoundObjects(layer, true);

            foreach (var data in objects)
            {
                if (data.Prefab == null || !regex.IsMatch(data.Prefab.name))
                {
                    continue;
                }

                var wPos = tPos +
                           new Vector3(data.Position.x * tSize.x, data.Position.y, data.Position.z * tSize.z);
                if (!bounds.Contains(wPos))
                {
                    //Debug.DrawLine(wPos, wPos + Vector3.up * 10, Color.cyan, 20);
                    continue;
                }

                var ut            = spline.GetClosestUniformTimeOnSplineXZ(wPos.xz());
                var pointOnSpline = spline.GetUniformPointOnSpline(ut);

                var dist = (pointOnSpline.xz() - wPos.xz()).magnitude;
                if (dist < config.ObjectRemoveDistance)
                {
                    if (!layer.ObjectRemovals.Contains(data.Guid))
                    {
                        layer.ObjectRemovals.Add(data.Guid);
                    }
                    if (ShowDebug)
                    {
                        Debug.DrawLine(pointOnSpline, wPos, Color.red, 20);
                    }
                }
                else
                {
                    if (ShowDebug)
                    {
                        Debug.DrawLine(pointOnSpline, wPos, Color.green, 20);
                    }
                }
            }
        }
Ejemplo n.º 14
0
        public override void ProcessDetails(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network || Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var terrain      = wrapper.Terrain;
            var dRes         = terrain.terrainData.detailResolution;
            var mainSpline   = NodeConnection.GetSpline();
            var radius       = config.Radius;
            var falloffCurve = config.GrassFalloff;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            // Early cull
            var axisBounds    = objectBounds.ToAxisBounds();
            var terrainBounds = terrain.GetComponent <Collider>().bounds;

            if (!terrainBounds.Intersects(axisBounds))
            {
                return;
            }

            // Get matrix space min/max
            var matrixMin = terrain.WorldToDetailCoord(bounds.min);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, dRes), Mathf.Clamp(matrixMin.z, 0, dRes));
            var matrixMax = terrain.WorldToDetailCoord(bounds.max);

            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, dRes), Mathf.Clamp(matrixMax.z, 0, dRes));

            var floatArraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);
            var layerDetails   = layer.GetDetailMaps(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, dRes);

            var writeStencil = new Serializable2DFloatArray(floatArraySize.x, floatArraySize.z);

            for (var dx = 0; dx < floatArraySize.x; ++dx)
            {
                for (var dz = 0; dz < floatArraySize.z; ++dz)
                {
                    var coordX = matrixMin.x + dx;
                    var coordZ = matrixMin.z + dz;

                    var worldPos = terrain.DetailCoordToWorldPos(new Common.Coord(coordX, coordZ));
                    worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);

                    if (!terrain.ContainsPointXZ(worldPos) || !objectBounds.Contains(worldPos))
                    {
                        continue;
                    }

                    var uniformT        = mainSpline.GetClosestUniformTimeOnSplineXZ(worldPos.xz()); // Expensive!
                    var closestOnSpline = mainSpline.GetUniformPointOnSpline(uniformT);

                    var normalizedFlatDistToSpline = (worldPos - closestOnSpline).xz().magnitude / radius;
                    var maskValue = Mathf.Clamp01(falloffCurve.Evaluate(normalizedFlatDistToSpline));
                    if (maskValue <= 0 || normalizedFlatDistToSpline < 0 || normalizedFlatDistToSpline > 1)
                    {
                        //DebugHelper.DrawPoint(worldPos, 1, Color.yellow, 20);
                        continue;
                    }

                    //DebugHelper.DrawPoint(worldPos, .2f, Color.green, 20);
                    //Debug.DrawLine(worldPos, worldPos + Vector3.up * maskValue, Color.green, 20);
                    writeStencil[dx, dz]          = 1;
                    layer.Stencil[coordX, coordZ] = MiscUtilities.CompressStencil(GetPriority(), 1);
                    foreach (var data in layerDetails)
                    {
                        float readValue = data.Value[dx, dz];
                        readValue /= 16;

                        var writeValue     = readValue * (1 - maskValue);
                        var writeByteValue = (byte)Mathf.Clamp(writeValue * 16, 0, 16);
                        data.Value[dx, dz] = writeByteValue;
                    }
                }
            }

            foreach (var serializable2DByteArray in layerDetails)
            {
                layer.SetDetailMap(serializable2DByteArray.Key, matrixMin.x, matrixMin.z, serializable2DByteArray.Value, dRes, writeStencil);
            }
        }
Ejemplo n.º 15
0
        public override void ProcessStencil(TerrainWrapper terrainWrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            stencilKey = GetPriority();
            var objectBounds  = GetObjectBounds();
            var flatObjBounds = objectBounds.Flatten();
            var flatBounds    = flatObjBounds.ToAxisBounds();
            var terrainSize   = terrainWrapper.Terrain.terrainData.size;
            var hRes          = terrainWrapper.Terrain.terrainData.heightmapResolution;

            var matrixMin = terrainWrapper.Terrain.WorldToHeightmapCoord(flatBounds.min,
                                                                         TerrainX.RoundType.Floor);
            var matrixMax = terrainWrapper.Terrain.WorldToHeightmapCoord(flatBounds.max,
                                                                         TerrainX.RoundType.Ceil);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, hRes), Mathf.Clamp(matrixMin.z, 0, hRes));
            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, hRes), Mathf.Clamp(matrixMax.z, 0, hRes));

            var floatArraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);


            layer.BlendMode = MMTerrainLayer.EMMTerrainLayerBlendMode.Stencil;

            if (layer.Stencil == null || layer.Stencil.Width != hRes || layer.Stencil.Height != hRes)
            {
                layer.Stencil = new Stencil(hRes, hRes);
            }
            var layerHeights = layer.GetHeights(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, hRes) ??
                               new Serializable2DFloatArray(floatArraySize.x, floatArraySize.z);

            var objectBoundsPlane = new Plane((objectBounds.Rotation * Vector3.up).normalized, objectBounds.center);

            for (var dz = 0; dz < floatArraySize.z; ++dz)
            {
                for (var dx = 0; dx < floatArraySize.x; ++dx)
                {
                    var coordX = matrixMin.x + dx;
                    var coordZ = matrixMin.z + dz;

                    int   existingStencilKey;
                    float existingStencilVal;
                    MiscUtilities.DecompressStencil(layer.Stencil[coordX, coordZ], out existingStencilKey,
                                                    out existingStencilVal);

                    var worldPos = terrainWrapper.Terrain.HeightmapCoordToWorldPos(new Common.Coord(coordX, coordZ));
                    worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);
                    if (!flatObjBounds.Contains(new Vector3(worldPos.x, flatObjBounds.center.y, worldPos.z)))
                    {
                        continue;
                    }

                    var localPos = Quaternion.Inverse(objectBounds.Rotation) * (worldPos - objectBounds.min);
                    var xDist    = localPos.x / objectBounds.size.x;
                    var zDist    = localPos.z / objectBounds.size.z;

                    float falloff = GetFalloff(new Vector2(xDist, zDist));
                    if (Mathf.Approximately(falloff, 0))
                    {
                        continue;
                    }

                    var   planeRay = new Ray(worldPos, Vector3.up);
                    float dist;

                    objectBoundsPlane.Raycast(planeRay, out dist);

                    var heightAtPoint  = (planeRay.GetPoint(dist) - terrainWrapper.transform.position).y / terrainSize.y;
                    var blendedHeight  = heightAtPoint;
                    var existingHeight = layerHeights[dx, dz];

                    if (SetHeights)
                    {
                        if (BlendMode == HeightBlendMode.Max && existingHeight > heightAtPoint)
                        {
                            layer.Stencil[matrixMin.x + dx, matrixMin.z + dz] = MiscUtilities.CompressStencil(0, 0);
                            continue;
                        }
                        if (BlendMode == HeightBlendMode.Min && existingHeight < heightAtPoint)
                        {
                            layer.Stencil[matrixMin.x + dx, matrixMin.z + dz] = MiscUtilities.CompressStencil(0, 0);
                            continue;
                        }
                    }

                    switch (BlendMode)
                    {
                    case HeightBlendMode.Set:
                        blendedHeight = Mathf.Lerp(existingHeight, blendedHeight, falloff);
                        break;

                    case HeightBlendMode.Max:
                        blendedHeight = Mathf.Max(existingHeight, blendedHeight);
                        break;

                    case HeightBlendMode.Min:
                        blendedHeight = Mathf.Min(existingHeight, blendedHeight);
                        break;

                    case HeightBlendMode.Average:
                        blendedHeight = (existingHeight + blendedHeight) / 2;
                        break;
                    }

                    layer.Stencil[matrixMin.x + dx, matrixMin.z + dz] = MiscUtilities.CompressStencil(stencilKey, 1);
                }
            }
        }
        public override void ProcessVegetationStudio(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }

            var config = Configuration.GetConfig <Config>();
            var spline = NodeConnection.GetSpline();
            var rand   = new Random(NodeConnection.ThisNode.Seed);

            if (config.Prototypes.SelectedIDs.Count == 0 || config.Prototypes.Package == null)
            {
                return;
            }

            var length = spline.Length;
            var step   = config.StepDistance;
            var tSize  = wrapper.Terrain.terrainData.size;

            for (var i = 0f; i < length; i += step.GetRand(rand))
            {
                var roll     = rand.NextDouble();
                var randroll = (float)rand.NextDouble();
                var eval     = config.ProbablityThroughCurve.Evaluate(randroll);
                //Debug.Log(randroll + " " + eval);
                var offsetDist = eval * config.OffsetMultiplier;
                var uniformT   = i / length;
                var naturalT   = spline.UniformToNaturalTime(uniformT);

                var offset      = (spline.GetTangent(naturalT).normalized *offsetDist);
                var probability = config.ProbablityAlongCurve.Evaluate(uniformT) * config.ProbabilityMultiplier;

                if (probability < roll)
                {
                    continue;
                }

                // Place tree
                var randIndex = Mathf.FloorToInt((float)rand.NextDouble() * config.Prototypes.SelectedIDs.Count);
                var id        = config.Prototypes.SelectedIDs[randIndex];
                var wPos      = spline.GetUniformPointOnSpline(uniformT) + offset;

                //Debug.DrawLine(wPos, wPos + Vector3.up *10, Color.red, 10);
                var tPos = wrapper.Terrain.WorldToTreePos(wPos);
                tPos.y = config.YOffset;
                var size        = Vector3.one * config.Size.GetRand(rand);
                var newInstance = new VegetationStudioInstance()
                {
                    Guid     = System.Guid.NewGuid().ToString(),
                    VSID     = id,
                    Position = tPos,
                    Scale    = size,
                    Rotation = config.Rotation.GetRand(rand),
                    Package  = config.Prototypes.Package,
                };
                layer.VSInstances.Add(newInstance);
            }
        }
Ejemplo n.º 17
0
        public override void ProcessVegetationStudio(TerrainWrapper terrainWrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }

            var tSize = terrainWrapper.Terrain.terrainData.size;
            var tPos  = terrainWrapper.transform.position;

            var wrapperBounds =
                new Bounds(terrainWrapper.Terrain.GetPosition() + terrainWrapper.Terrain.terrainData.size / 2,
                           terrainWrapper.Terrain.terrainData.size);

            wrapperBounds.Expand(Vector3.up * 5000);
            if (RemoveExistingVSData)
            {
                var stampBounds = new ObjectBounds(transform.position, Size / 2, transform.rotation);
                stampBounds.Expand(Vector3.up * 5000);
                var compoundVSData = terrainWrapper.GetCompoundVegetationStudioData(layer, true);
                foreach (var vsdataInstance in compoundVSData)
                {
                    if (layer.VSRemovals.Contains(vsdataInstance.Guid))
                    {
                        continue;
                    }

                    if (IgnoredVSPrototypes.Contains(vsdataInstance.VSID))
                    {
                        continue;
                    }

                    var wPos = vsdataInstance.Position;
                    wPos  = new Vector3(wPos.x * tSize.x, wPos.y, wPos.z * tSize.z);
                    wPos += tPos;

                    if (stampBounds.Contains(wPos))
                    {
                        var stencilPos = wPos - tPos;
                        stencilPos = new Vector2(stencilPos.x / tSize.x, stencilPos.z / tSize.z);
                        var stencilAmount = layer.GetStencilStrength(stencilPos, stencilKey);
                        if (stencilAmount > 0.5f)
                        {
                            layer.VSRemovals.Add(vsdataInstance.Guid);
                            //Debug.DrawLine(wPos, wPos + Vector3.up * stencilAmount * 20, Color.red, 30);
                        }
                    }
                }
            }

            if (!VegetationStudioEnabled)
            {
                UnityEngine.Profiling.Profiler.EndSample();
                return;
            }

            for (var i = 0; i < Data.VSData.Count; i++)
            {
                var vsInstance = Data.VSData[i].Clone();
                var maskPos    = new Vector3(vsInstance.Position.x * Data.Size.x, 0, vsInstance.Position.z * Data.Size.z) /* + (Data.Size/2)*/;
                var maskValue  = GetMask().GetBilinear(Data.GridManager, maskPos);
                if (maskValue <= 0.25f)
                {
                    continue;
                }

                var wPos = transform.position + transform.rotation * (new Vector3(vsInstance.Position.x * Size.x, vsInstance.Position.y, vsInstance.Position.z * Size.z) - (Size.xz().x0z() / 2));
                if (!wrapperBounds.Contains(wPos))
                {
                    continue;
                }

                if (StencilVSData)
                {
                    var stencilPos = new Vector2((wPos.x - tPos.x) / tSize.x, (wPos.z - tPos.z) / tSize.z);
                    var stencilVal = layer.GetStencilStrength(stencilPos, stencilKey);
                    if (stencilVal <= 0.25f)
                    {
                        continue;
                    }
                }

                vsInstance.Guid = Guid.NewGuid().ToString();
                //var height = terrainWrapper.GetCompoundHeight(layer, wPos, true) * tSize.y * Vector3.up;
                vsInstance.Position   = wPos - terrainWrapper.transform.position;
                vsInstance.Position.y = Data.VSData[i].Position.y;
                vsInstance.Position   = new Vector3(vsInstance.Position.x / tSize.x, vsInstance.Position.y, vsInstance.Position.z / tSize.z);

                layer.VSInstances.Add(vsInstance);
            }

            UnityEngine.Profiling.Profiler.EndSample();
        }
Ejemplo n.º 18
0
        public override void ProcessSplats(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network || Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var terrain    = wrapper.Terrain;
            var splatRes   = wrapper.Terrain.terrainData.alphamapResolution;
            var mainSpline = NodeConnection.GetSpline();
            var radius     = config.Radius;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            // Early cull
            var axisBounds    = objectBounds.ToAxisBounds();
            var terrainBounds = wrapper.Terrain.GetComponent <Collider>().bounds;

            if (!terrainBounds.Intersects(axisBounds))
            {
                return;
            }

            float planeGive = -(wrapper.Terrain.terrainData.size.x / wrapper.Terrain.terrainData.alphamapResolution) * SplatOffset;
            Plane startPlane, endPlane;

            GenerateSplinePlanes(planeGive, mainSpline, out startPlane, out endPlane);

            // Get matrix space min/max
            var matrixMin = terrain.WorldToSplatCoord(bounds.min, TerrainX.RoundType.Floor);
            var matrixMax = terrain.WorldToSplatCoord(bounds.max, TerrainX.RoundType.Ceil);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, terrain.terrainData.alphamapResolution), Mathf.Clamp(matrixMin.z, 0, terrain.terrainData.alphamapResolution));
            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, terrain.terrainData.alphamapResolution), Mathf.Clamp(matrixMax.z, 0, terrain.terrainData.alphamapResolution));

            var floatArraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);

            // Get all the existing compound splats
            var currentPrototypes = wrapper.GetCompoundSplatPrototypes(layer, true);
            var baseData          = layer.GetSplatMaps(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, splatRes);

            stencilKey = GetStencilKey();
            Serializable2DFloatArray thisPatchStencil = new Serializable2DFloatArray(floatArraySize.x,
                                                                                     floatArraySize.z);

            foreach (var splatConfiguration in config.SplatConfigurations)
            {
                var splatPrototypeWrapper = splatConfiguration.SplatPrototype;
                Serializable2DByteArray baseLayerSplat;
                if (!baseData.TryGetValue(splatPrototypeWrapper, out baseLayerSplat))
                {
                    baseLayerSplat = new Serializable2DByteArray(floatArraySize.x, floatArraySize.z);
                    baseData[splatPrototypeWrapper] = baseLayerSplat;
                }

                for (var dz = 0; dz < floatArraySize.z; ++dz)
                {
                    for (var dx = 0; dx < floatArraySize.x; ++dx)
                    {
                        var coordX   = matrixMin.x + dx;
                        var coordZ   = matrixMin.z + dz;
                        var worldPos = terrain.SplatCoordToWorldPos(new Common.Coord(coordX, coordZ));
                        worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);

                        if (terrain.ContainsPointXZ(worldPos) &&
                            objectBounds.Contains(worldPos) &&
                            GeometryExtensions.BetweenPlanes(worldPos, startPlane, endPlane))
                        {
                            var uniformT                   = mainSpline.GetClosestUniformTimeOnSplineXZ(worldPos.xz()); // Expensive!
                            var closestOnSpline            = mainSpline.GetUniformPointOnSpline(uniformT);
                            var normalizedFlatDistToSpline = (worldPos - closestOnSpline).xz().magnitude / (config.Radius);
                            if (normalizedFlatDistToSpline != Mathf.Clamp01(normalizedFlatDistToSpline))
                            {
                                continue;
                            }
                            var maskValue       = config.SplatFalloff.Evaluate(normalizedFlatDistToSpline);
                            var writeFloatValue = splatConfiguration.SplatStrength * maskValue;
                            var writeValue      = (byte)Mathf.RoundToInt(Mathf.Clamp(writeFloatValue * 255f, 0, 255));
                            var mainRead        = baseLayerSplat[dx, dz];
                            var newVal          = (byte)Mathf.Clamp(Mathf.Max(writeValue, mainRead), 0, 255);
                            var delta           = newVal - mainRead;

                            if (delta < 1 / 255f)
                            {
                                continue;
                            }

                            foreach (var currentPrototype in currentPrototypes)
                            {
                                if (!baseData.ContainsKey(currentPrototype))
                                {
                                    continue;
                                }
                                if (currentPrototype == splatPrototypeWrapper)
                                {
                                    continue;
                                }
                                var otherSplatFloatValue    = baseData[currentPrototype][dx, dz] / 255f;
                                var otherSplatFloatWriteVal = (otherSplatFloatValue * (1 - (delta / 255f)));
                                var write = (byte)Mathf.Clamp(Mathf.RoundToInt(otherSplatFloatWriteVal * 255), 0, 255);
                                baseData[currentPrototype][dx, dz] = write;
                            }
                            //DebugHelper.DrawPoint(worldPos, 1, Color.red, 10);
                            baseLayerSplat[dx, dz]        = newVal;
                            layer.Stencil[coordX, coordZ] = MiscUtilities.CompressStencil(stencilKey, 1);
                            thisPatchStencil[dx, dz]      = 1;
                        }
                        else
                        {
                            thisPatchStencil[dx, dz] = 0;
                        }
                    }
                }
            }

            foreach (var existingSplatPrototype in baseData)
            {
                var splat = existingSplatPrototype.Key;
                var data  = existingSplatPrototype.Value;
                layer.SetSplatmap(splat, matrixMin.x, matrixMin.z, data, wrapper.Terrain.terrainData.alphamapResolution, thisPatchStencil);
            }
        }
Ejemplo n.º 19
0
        public override void ProcessObjects(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }

            if (Configuration == null || !Network)
            {
                return;
            }

            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid config for ConnectionObjectComponent " + name, this);
                return;
            }

            if (config.Objects == null || config.Objects.Count == 0)
            {
                return;
            }

            var seed = NodeConnection.ThisNode.Seed;
            var rand = new Random(seed);

            var spline = NodeConnection.GetSpline();
            var length = spline.Length;
            var step   = config.Distance;
            var tSize  = wrapper.Terrain.terrainData.size;

            for (var i = config.InitialOffset; i < length; i += step.GetRand(rand))
            {
                var randIndex = Mathf.FloorToInt((float)rand.NextDouble() * config.Objects.Count);
                var prefab    = config.Objects[randIndex];

                var roll = (float)rand.NextDouble();
                if (roll > config.Chance)
                {
                    continue;
                }

                var offset = config.LocalOffset.GetRand(rand);
                var scale  = config.Scale.GetRand(rand);
                if (config.UniformScale)
                {
                    scale = Vector3.one * scale.x;
                }

                var uniformT     = i / length;
                var splineOffset = config.SplineOffset.GetRand(rand) * (rand.Flip() ? -1 : 1);
                var tangent      = spline.GetTangent(uniformT).normalized;
                var rotation     = Quaternion.LookRotation(tangent) * Quaternion.Euler(config.Rotation.GetRand(rand));

                var worldPos = spline.GetUniformPointOnSpline(uniformT);
                worldPos += tangent * splineOffset;
                worldPos += offset;

                if (!config.AbsoluteHeight)
                {
                    worldPos.y = offset.y;
                }

                var tPos = worldPos - wrapper.transform.position;
                tPos = new Vector3(tPos.x / tSize.x, tPos.y, tPos.z / tSize.z);

                var prefabObject = new PrefabObjectData()
                {
                    AbsoluteHeight    = config.AbsoluteHeight,
                    Guid              = Guid.NewGuid().ToString(),
                    Position          = tPos,
                    Scale             = scale,
                    Rotation          = rotation.eulerAngles,
                    Prefab            = prefab,
                    ContainerMetadata = layer.name,
                };

                layer.Objects.Add(prefabObject);
            }
        }
Ejemplo n.º 20
0
        public override void ProcessSplats(TerrainWrapper terrainWrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!SetSplat || Splat == null || SplatStrength == 0)
            {
                return;
            }
            stencilKey = GetPriority();
            var objectBounds = GetObjectBounds();
            var aRes         = terrainWrapper.Terrain.terrainData.alphamapResolution;
            var axisBounds   = objectBounds.Flatten().ToAxisBounds();

            var matrixMin = terrainWrapper.Terrain.WorldToSplatCoord(axisBounds.min);

            matrixMin = new Common.Coord(Mathf.Clamp(matrixMin.x, 0, aRes), Mathf.Clamp(matrixMin.z, 0, aRes));

            var matrixMax = terrainWrapper.Terrain.WorldToSplatCoord(axisBounds.max);

            matrixMax = new Common.Coord(Mathf.Clamp(matrixMax.x, 0, aRes), Mathf.Clamp(matrixMax.z, 0, aRes));

            var arraySize = new Common.Coord(matrixMax.x - matrixMin.x, matrixMax.z - matrixMin.z);

            var existingSplats = layer.GetSplatMaps(matrixMin.x, matrixMin.z, arraySize.x, arraySize.z, aRes);

            for (var dx = 0; dx < arraySize.x; ++dx)
            {
                var xF = dx / (float)arraySize.x;
                for (var dz = 0; dz < arraySize.z; ++dz)
                {
                    var zF      = dz / (float)arraySize.z;
                    var falloff = GetFalloff(new Vector2(xF, zF));

                    float splatStrength = falloff * SplatStrength;
                    if (!existingSplats.ContainsKey(Splat))
                    {
                        existingSplats.Add(Splat, new Serializable2DByteArray(arraySize.x, arraySize.z));
                    }
                    var existingbaseVal = existingSplats[Splat][dx, dz] / 255f;
                    var newBaseVal      = Mathf.Max(existingbaseVal, splatStrength);
                    var writeBaseValue  = (byte)Mathf.Clamp(newBaseVal * 255, 0, 255);
                    existingSplats[Splat][dx, dz] = writeBaseValue;

                    foreach (var serializable2DByteArray in existingSplats)
                    {
                        if (serializable2DByteArray.Key == Splat)
                        {
                            continue;
                        }

                        var readValue  = serializable2DByteArray.Value[dx, dz] / 255f;
                        var newValue   = readValue * (1 - newBaseVal);
                        var writeValue = (byte)Mathf.Clamp(newValue * 255, 0, 255);
                        serializable2DByteArray.Value[dx, dz] = writeValue;
                    }
                }
            }
            foreach (var serializable2DByteArray in existingSplats)
            {
                layer.SetSplatmap(serializable2DByteArray.Key, matrixMin.x, matrixMin.z, serializable2DByteArray.Value, aRes);
            }
        }
        void OnGUI()
        {
            titleContent = new GUIContent("WS Priorities");
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.BeginVertical();
            Context = (TerrainWrapper)EditorGUILayout.ObjectField("Terrain Wrapper", Context, typeof(TerrainWrapper), true);
            Filter  = EditorGUILayout.TextField("Layer Filter", Filter);
            EditorGUILayout.EndVertical();
            GUI.enabled = Context;
            if (GUILayout.Button(EditorGUIUtility.IconContent("TreeEditor.Refresh"), GUILayout.Width(32), GUILayout.Height(32)))
            {
                NeedsResort = true;
            }
            GUI.enabled = true;
            EditorGUILayout.EndHorizontal();

            if (Context == null)
            {
                EditorGUILayout.HelpBox("Please Select a Terrain Wrapper", MessageType.Info);
                return;
            }

            if (NeedsResort)
            {
                NeedsResort = false;
                Sort();
            }

            if ((_list == null || _list.Count == 0))
            {
                EditorGUILayout.HelpBox("No Eligible Layer Components Found In Scene", MessageType.Info);
                return;
            }

            _scroll = EditorGUILayout.BeginScrollView(_scroll);

            foreach (var mapping in _list)
            {
                EditorExtensions.Seperator();
                EditorGUILayout.LabelField(string.Format("[{0}]  Layer '{1}'", mapping.LayerIndex, mapping.LayerName));

                foreach (var stamp in mapping.Components)
                {
                    EditorGUILayout.BeginHorizontal();
                    if (GUILayout.Button(string.Format("    {0}", stamp.name), EditorStyles.boldLabel))
                    {
                        Selection.activeGameObject = stamp.gameObject;
                    }
                    EditorGUILayout.LabelField("Priority", GUILayout.Width(50));
                    var currentPriority = stamp.GetPriority();
                    currentPriority = EditorGUILayout.DelayedIntField(currentPriority, GUILayout.Width(100));
                    if (currentPriority != stamp.GetPriority())
                    {
                        stamp.SetPriority(currentPriority);
                        NeedsResort = true;
                    }
                    EditorGUILayout.EndHorizontal();
                }
                EditorGUILayout.Space();
            }

            EditorGUILayout.EndScrollView();
        }
Ejemplo n.º 22
0
        public override void ProcessHeights(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network || Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }
            var terrain     = wrapper.Terrain;
            var terrainPos  = wrapper.Terrain.GetPosition();
            var terrainSize = wrapper.Terrain.terrainData.size;
            var heightRes   = terrain.terrainData.heightmapResolution;

            var mainSpline   = NodeConnection.GetSpline();
            var radius       = config.Radius;
            var falloffCurve = config.Falloff;
            var heightCurve  = config.Height;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            // Early cull
            var axisBounds    = objectBounds.ToAxisBounds();
            var terrainBounds = terrain.GetComponent <Collider>().bounds;

            terrainBounds.Expand(Vector3.up * 10000);
            if (!terrainBounds.Intersects(axisBounds))
            {
                return;
            }

            // Get matrix space min/max
            var matrixMin = terrain.WorldToHeightmapCoord(bounds.min, TerrainX.RoundType.Floor) - Coord.One;

            matrixMin = matrixMin.Clamp(0, heightRes);
            var matrixMax = terrain.WorldToHeightmapCoord(bounds.max, TerrainX.RoundType.Ceil) + Coord.One;

            matrixMax = matrixMax.Clamp(0, heightRes);

            var xDelta = matrixMax.x - matrixMin.x;
            var zDelta = matrixMax.z - matrixMin.z;

            var floatArraySize = new Common.Coord(
                Mathf.Min(xDelta, terrain.terrainData.heightmapResolution - matrixMin.x),
                Mathf.Min(zDelta, terrain.terrainData.heightmapResolution - matrixMin.z));

            float planeGive = (wrapper.Terrain.terrainData.size.x / wrapper.Terrain.terrainData.heightmapResolution) * 0;
            Plane startPlane, endPlane;

            GenerateSplinePlanes(planeGive, mainSpline, out startPlane, out endPlane);

            var layerHeights = layer.GetHeights(matrixMin.x, matrixMin.z, floatArraySize.x, floatArraySize.z, heightRes) ??
                               new Serializable2DFloatArray(floatArraySize.x, floatArraySize.z);

            stencilKey = GetStencilKey();
            if (layer.Stencil == null || layer.Stencil.Width != heightRes || layer.Stencil.Height != heightRes)
            {
                layer.Stencil = new Stencil(heightRes, heightRes);
            }

            for (var dz = 0; dz < floatArraySize.z; ++dz)
            {
                for (var dx = 0; dx < floatArraySize.x; ++dx)
                {
                    var coordX = matrixMin.x + dx;
                    var coordZ = matrixMin.z + dz;

                    var worldPos = terrain.HeightmapCoordToWorldPos(new Common.Coord(coordX, coordZ));
                    worldPos = new Vector3(worldPos.x, objectBounds.center.y, worldPos.z);
                    if (!terrain.ContainsPointXZ(worldPos) ||
                        !objectBounds.Contains(worldPos) ||
                        !GeometryExtensions.BetweenPlanes(worldPos, startPlane, endPlane))
                    {
                        // Cull if we're outside of the approx bounds
                        continue;
                    }

                    var uniformT                   = mainSpline.GetClosestUniformTimeOnSplineXZ(worldPos.xz()); // Expensive!
                    var closestOnSpline            = mainSpline.GetUniformPointOnSpline(uniformT);
                    var normalizedFlatDistToSpline = (worldPos - closestOnSpline).xz().magnitude / (radius);
                    if (normalizedFlatDistToSpline >= 1)
                    {
                        continue;
                    }

                    var maskValue   = Mathf.Clamp01(falloffCurve.Evaluate(normalizedFlatDistToSpline));
                    var heightDelta = heightCurve.Evaluate(normalizedFlatDistToSpline);

                    float existingStencilStrength;
                    int   existingStencilKey;
                    MiscUtilities.DecompressStencil(layer.Stencil[coordX, coordZ], out existingStencilKey, out existingStencilStrength);

                    if (existingStencilKey != stencilKey &&
                        existingStencilKey > stencilKey &&
                        !(existingStencilStrength < maskValue && maskValue > 0))
                    {
                        continue;
                    }

                    // Refine our worldposition to be on the same XZ plane as the spline point
                    worldPos = new Vector3(worldPos.x, closestOnSpline.y, worldPos.z);

                    // Find the point on the spline closest to this given point
                    var naturalT = mainSpline.UniformToNaturalTime(uniformT);

                    // Get the upvec from the natural time
                    var up = mainSpline.GetUpVector(naturalT).normalized;

                    // Create a plane and cast against it
                    var plane = new Plane(up, closestOnSpline);

                    float dist    = 0;
                    var   castRay = new Ray(worldPos, Vector3.down);
                    plane.Raycast(castRay, out dist);
                    var castPoint     = castRay.GetPoint(dist);
                    var heightAtPoint = (castPoint.y + heightDelta);

                    heightAtPoint -= terrainPos.y;
                    heightAtPoint /= terrainSize.y;
                    heightAtPoint  = MiscUtilities.FloorToUshort(heightAtPoint);

                    var existingHeight = layerHeights[dx, dz];
                    var newHeight      = Mathf.Lerp(existingHeight, heightAtPoint, Mathf.Clamp01(maskValue));

                    layerHeights[dx, dz] = newHeight;

                    var key = maskValue > existingStencilStrength ? stencilKey : existingStencilKey;
                    var newRawStencilValue = MiscUtilities.CompressStencil(key, /*stencilKey == existingStencilKey ?*/ Mathf.Max(maskValue, existingStencilStrength) /* : maskValue + existingStencilStrength*/);
                    //newRawStencilValue = MiscUtilities.CompressStencil(key, 1);

                    layer.Stencil[coordX, coordZ] = newRawStencilValue;
                }
            }

            layer.SetHeights(matrixMin.x, matrixMin.z,
                             layerHeights, wrapper.Terrain.terrainData.heightmapResolution);
        }
        public override void ProcessVegetationStudio(TerrainWrapper wrapper, LayerBase baseLayer, int stencilKey)
        {
            var layer = baseLayer as MMTerrainLayer;

            if (layer == null)
            {
                Debug.LogWarning(string.Format("Attempted to write {0} to incorrect layer type! Expected Layer {1} to be {2}, but it was {3}", name, baseLayer.name, GetLayerType(), baseLayer.GetType()), this);
                return;
            }
            if (!Network)
            {
                Debug.LogError("Unable to find network! " + name, this);
                return;
            }
            if (Configuration == null)
            {
                return;
            }
            var config = Configuration.GetConfig <Config>();

            if (config == null)
            {
                Debug.LogError("Invalid configuration! Expected ConnectionTerrainHeightConfiguration");
                return;
            }

            var mainSpline = NodeConnection.GetSpline();
            var radius     = config.InstanceRemoveDistance;

            // Create bounds to encapsulate spline (axis aligned)
            var bounds = mainSpline.GetApproximateBounds();

            bounds.Expand(radius * 2 * Vector3.one);

            // Create object bounds
            var objectBounds = mainSpline.GetApproximateXZObjectBounds();

            objectBounds.Expand(radius * 2 * Vector3.one);
            objectBounds.Expand(Vector3.up * 10000);

            var flatCullbounds = objectBounds.ToAxisBounds();
            //DebugHelper.DrawCube(flatCullbounds.center, flatCullbounds.extents, Quaternion.identity, Color.yellow, 20);
            //DebugHelper.DrawCube(objectBounds.center, objectBounds.extents, objectBounds.Rotation, Color.cyan, 20);

            Plane startPlane, endPlane;

            GenerateSplinePlanes(0, mainSpline, out startPlane, out endPlane);

            var vsData = wrapper.GetCompoundVegetationStudioData(layer, true, flatCullbounds);

            for (int i = vsData.Count - 1; i >= 0; i--)
            {
                var vsInstance = vsData[i];
                if (config.IgnoredPrototypes.Contains(vsInstance.VSID))
                {
                    continue;
                }
                var wPos = wrapper.Terrain.TreeToWorldPos(vsInstance.Position);
                if (!objectBounds.Contains(wPos) || !GeometryExtensions.BetweenPlanes(wPos, startPlane, endPlane))
                {
                    continue;
                }

                var ut        = mainSpline.GetClosestUniformTimeOnSplineXZ(wPos.xz());
                var splinePos = mainSpline.GetUniformPointOnSpline(ut);
                var d         = splinePos.xz() - wPos.xz();

                if (d.sqrMagnitude < config.InstanceRemoveDistance * config.InstanceRemoveDistance && !layer.VSRemovals.Contains(vsInstance.Guid))
                {
                    layer.VSRemovals.Add(vsInstance.Guid);
                    //DebugHelper.DrawPoint(wPos, .5f, Color.red, 20);
                }
            }
        }