private void CameraPreRender(Camera camera) { if (Material != null) { var cameraPosition = camera.transform.position; var localCameraPosition = transform.InverseTransformPoint(cameraPosition); var localDistance = localCameraPosition.magnitude; var scaleDistance = SgtHelper.Divide(localDistance, MeshRadius); if (scaleDistance > 1.0f) { SgtHelper.EnableKeyword("SGT_A", Material); // Outside } else { SgtHelper.DisableKeyword("SGT_A", Material); // Outside if (DepthTex != null) { #if UNITY_EDITOR SgtHelper.MakeTextureReadable(DepthTex); #endif Material.SetFloat("_Sky", Sky * DepthTex.GetPixelBilinear(1.0f - scaleDistance, 0.0f).a); } } UpdateMaterialNonSerialized(); } }
public void UpdateModels() { updateModelsCalled = true; var angleStep = SgtHelper.Divide(360.0f, Segments); for (var i = 0; i < Segments; i++) { var model = GetOrAddModel(i); var angle = angleStep * i; var rotation = Quaternion.Euler(0.0f, angle, 0.0f); model.SetMesh(Mesh); model.SetMaterial(Material); model.SetRotation(rotation); } // Remove any excess if (Models != null) { var min = Mathf.Max(0, Segments); for (var i = Models.Count - 1; i >= min; i--) { SgtRingModel.Pool(Models[i]); Models.RemoveAt(i); } } }
// TODO: Make this work correctly public override bool CalculateShadow() { if (base.CalculateShadow() == true) { var direction = default(Vector3); var position = default(Vector3); var color = default(Color); SgtHelper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color); var rotation = Quaternion.FromToRotation(direction, Vector3.back); SetVector(0, rotation * transform.right * transform.lossyScale.x * OuterRadius); SetVector(1, rotation * transform.up * transform.lossyScale.y * OuterRadius); SetVector(2, rotation * transform.forward * transform.lossyScale.z * OuterRadius); SortVectors(); var spin = Quaternion.LookRotation(Vector3.forward, new Vector2(-vectors[1].x, vectors[1].y)); // Orient the shadow ellipse var scale = SgtHelper.Reciprocal3(new Vector3(magnitudes[0], magnitudes[1], 1.0f)); var shadowT = SgtHelper.Translation(-transform.position); var shadowR = SgtHelper.Rotation(spin * rotation); var shadowS = SgtHelper.Scaling(scale); Matrix = shadowS * shadowR * shadowT; Ratio = SgtHelper.Divide(OuterRadius, OuterRadius - InnerRadius); return(true); } return(false); }
public override bool CalculateShadow(ref Matrix4x4 matrix, ref float ratio) { if (base.CalculateShadow(ref matrix, ref ratio) == true) { var direction = default(Vector3); var position = default(Vector3); var color = default(Color); SgtHelper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color); var dot = Vector3.Dot(direction, transform.up); var radiusXZ = (transform.lossyScale.x + transform.lossyScale.z) * 0.5f * RadiusMax; var radiusY = transform.lossyScale.y * RadiusMax; var radius = GetRadius(radiusY, radiusXZ, dot * Mathf.PI * 0.5f); var rotation = Quaternion.FromToRotation(direction, Vector3.back); var vector = rotation * transform.up; var spin = Quaternion.LookRotation(Vector3.forward, new Vector2(-vector.x, vector.y)); // Orient the shadow ellipse var scale = SgtHelper.Reciprocal3(new Vector3(radiusXZ, radius, 1.0f)); var shadowT = SgtHelper.Translation(-transform.position); var shadowR = SgtHelper.Rotation(spin * rotation); var shadowS = SgtHelper.Scaling(scale); matrix = shadowS * shadowR * shadowT; ratio = SgtHelper.Divide(RadiusMax, RadiusMax - RadiusMin); return(true); } return(false); }
public void UpdateModels() { updateModelsCalled = true; var meshCount = Meshes != null ? Meshes.Count : 0; var scale = SgtHelper.Divide(Radius, MeshRadius); for (var i = 0; i < meshCount; i++) { var mesh = Meshes[i]; var model = GetOrAddModel(i); model.SetMesh(mesh); model.SetMaterial(Material); model.SetScale(scale); } // Remove any excess if (Models != null) { for (var i = Models.Count - 1; i >= meshCount; i--) { SgtCloudsphereModel.Pool(Models[i]); Models.RemoveAt(i); } } }
private void CameraPreRender(Camera camera) { // Write CameraOffset if (Outers != null) { var dir = camera.transform.position - transform.position; var pos = transform.InverseTransformPoint(transform.position + dir.normalized * CameraOffset); for (var i = Outers.Count - 1; i >= 0; i--) { var outer = Outers[i]; if (outer != null) { outer.transform.localPosition = pos; } } } // Write camera-dependant shader values if (InnerMaterial != null && OuterMaterial != null) { var cameraPosition = camera.transform.position; var localCameraPosition = transform.InverseTransformPoint(cameraPosition); var localDistance = localCameraPosition.magnitude; var clampedSky = Mathf.InverseLerp(OuterRadius, InnerMeshRadius, localDistance); var innerAtmosphereDepth = default(float); var outerAtmosphereDepth = default(float); var radiusRatio = SgtHelper.Divide(InnerMeshRadius, OuterRadius); var scaleDistance = SgtHelper.Divide(localDistance, OuterRadius); var innerDensity = 1.0f - InnerFog; var outerDensity = 1.0f - OuterFog; SgtHelper.CalculateAtmosphereThicknessAtHorizon(radiusRatio, 1.0f, scaleDistance, out innerAtmosphereDepth, out outerAtmosphereDepth); SgtHelper.SetTempMaterial(InnerMaterial, OuterMaterial); if (scaleDistance > 1.0f) { SgtHelper.EnableKeyword("SGT_A"); // Outside } else { SgtHelper.DisableKeyword("SGT_A"); // Outside } InnerMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(innerAtmosphereDepth * innerDensity)); OuterMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(outerAtmosphereDepth * outerDensity)); if (OuterDepthTex != null) { #if UNITY_EDITOR SgtHelper.MakeTextureReadable(OuterDepthTex); #endif OuterMaterial.SetFloat("_Sky", Sky * OuterDepthTex.GetPixelBilinear(clampedSky / outerDensity, 0.0f).a); } UpdateMaterialNonSerialized(); } }
protected virtual void UpdateMaterial() { if (innerMaterial == null) { innerMaterial = SgtHelper.CreateTempMaterial(SgtHelper.ShaderNamePrefix + "CoronaInner"); } if (outerMaterial == null) { outerMaterial = SgtHelper.CreateTempMaterial(SgtHelper.ShaderNamePrefix + "CoronaOuter"); } var scale = SgtHelper.Divide(OuterMeshRadius, OuterRadius); var worldToLocal = SgtHelper.Scaling(scale) * transform.worldToLocalMatrix; var color = SgtHelper.Brighten(Color, Brightness); var renderQueue = (int)RenderQueue + RenderQueueOffset; innerMaterial.renderQueue = renderQueue; innerMaterial.SetColor("_Color", color); innerMaterial.SetTexture("_AtmosphereLut", atmosphereLut); innerMaterial.SetFloat("_AtmosphereScale", DensityScale); innerMaterial.SetFloat("_Power", InnerPower); innerMaterial.SetFloat("_SkyRadius", OuterRadius); innerMaterial.SetFloat("_SkyRadiusRecip", SgtHelper.Reciprocal(OuterRadius)); innerMaterial.SetMatrix("_WorldToLocal", worldToLocal); outerMaterial.renderQueue = renderQueue; outerMaterial.SetColor("_Color", color); outerMaterial.SetTexture("_AtmosphereLut", atmosphereLut); outerMaterial.SetFloat("_AtmosphereScale", DensityScale); outerMaterial.SetMatrix("_WorldToLocal", worldToLocal); }
public void UpdateOuters() { updateOutersCalled = true; var meshCount = OuterMeshes != null ? OuterMeshes.Count : 0; var outerScale = SgtHelper.Divide(OuterRadius, OuterMeshRadius); for (var i = 0; i < meshCount; i++) { var outerMesh = OuterMeshes[i]; var outer = GetOrAddOuter(i); outer.SetMesh(outerMesh); outer.SetMaterial(OuterMaterial); outer.SetScale(outerScale); } // Remove any excess if (Outers != null) { for (var i = Outers.Count - 1; i >= meshCount; i--) { var outer = Outers[i]; if (outer != null) { SgtAtmosphereOuter.Pool(outer); } Outers.RemoveAt(i); } } }
private void UpdateMaterialNonSerialized() { var scale = SgtHelper.Divide(OuterMeshRadius, OuterRadius); var worldToLocal = SgtHelper.Scaling(scale) * transform.worldToLocalMatrix; InnerMaterial.SetMatrix("_WorldToLocal", worldToLocal); OuterMaterial.SetMatrix("_WorldToLocal", worldToLocal); }
public static void CalculateAtmosphereThicknessAtHorizon(float groundRadius, float skyRadius, float distance, out float groundThickness, out float skyThickness) { var horizonDistance = DistanceToHorizon(groundRadius, distance); var maxSkyThickness = Mathf.Sin(Mathf.Acos(SgtHelper.Divide(groundRadius, skyRadius))) * skyRadius; var maxGroundThickness = Mathf.Min(horizonDistance, maxSkyThickness); groundThickness = Mathf.Max(maxGroundThickness, skyRadius - groundRadius); skyThickness = maxSkyThickness + maxGroundThickness; }
protected override void CalculateStars(out List <SgtStarfieldStar> stars, out bool pool) { var texture = SourceTex as Texture2D; stars = tempStars; tempStars.Clear(); pool = true; if (texture != null && Resolution > 0.0f && Resolution <= 1.0f) { #if UNITY_EDITOR SgtHelper.MakeTextureReadable(texture); SgtHelper.MakeTextureTruecolor(texture); #endif var samplesX = Mathf.FloorToInt(SourceTex.width * Resolution); var samplesY = Mathf.FloorToInt(SourceTex.height * Resolution); var stepX = SgtHelper.Reciprocal(samplesX); var stepY = SgtHelper.Reciprocal(samplesY); var halfSize = Size * 0.5f; var scale = SgtHelper.Divide(SourceTex.width, samplesX); SgtHelper.BeginRandomSeed(Seed); { for (var y = 0; y < samplesY; y++) { for (var x = 0; x < samplesX; x++) { var fracX = x * stepX; var fracY = y * stepY; var pixel = texture.GetPixelBilinear(fracX, fracY); var gray = pixel.grayscale; if (gray > Threshold) { var star = SgtClassPool <SgtStarfieldStar> .Pop() ?? new SgtStarfieldStar(); stars.Add(star); var position = -halfSize + Random.insideUnitSphere * Jitter * StarRadiusMax * scale; position.x += Size.x * fracX; position.y += Size.y * GetHeight(pixel); position.z += Size.z * fracY; star.Sprite = GetRandomStarSprite(); star.Color = pixel; star.Radius = Random.Range(StarRadiusMin, StarRadiusMax) * scale; star.Angle = Random.Range(0.0f, Mathf.PI * 2.0f); star.Position = position; star.PulseRange = Random.value * StarPulseMax; star.PulseSpeed = Random.value; star.PulseOffset = Random.value; } } } } SgtHelper.EndRandomSeed(); } }
private void UpdateOuters() { outers.RemoveAll(o => o == null); if (OuterMeshes.Count != outers.Count) { SgtHelper.ResizeArrayTo(ref outers, OuterMeshes.Count, i => SgtCoronaOuter.Create(this), o => SgtCoronaOuter.Pool(o)); } var outerScale = SgtHelper.Divide(OuterRadius, OuterMeshRadius); for (var i = OuterMeshes.Count - 1; i >= 0; i--) { outers[i].ManualUpdate(OuterMeshes[i], outerMaterial, outerScale); } }
private void UpdateModels() { models.RemoveAll(m => m == null); if (Meshes.Count != models.Count) { SgtHelper.ResizeArrayTo(ref models, Meshes.Count, i => SgtCloudsphereModel.Create(this), m => SgtCloudsphereModel.Pool(m)); } var scale = SgtHelper.Divide(Radius, MeshRadius); for (var i = Meshes.Count - 1; i >= 0; i--) { models[i].ManualUpdate(Meshes[i], material, scale); } }
public static Vector4 CalculateSpriteUV(Sprite s) { var uv = default(Vector4); if (s != null) { var r = s.textureRect; var t = s.texture; uv.x = SgtHelper.Divide(r.xMin, t.width); uv.y = SgtHelper.Divide(r.yMin, t.height); uv.z = SgtHelper.Divide(r.xMax, t.width); uv.w = SgtHelper.Divide(r.yMax, t.height); } return(uv); }
protected void UpdateSegments() { segments.RemoveAll(m => m == null); if (SegmentCount != segments.Count) { SgtHelper.ResizeArrayTo(ref segments, SegmentCount, i => SgtRingSegment.Create(this), s => SgtRingSegment.Pool(s)); } var angleStep = SgtHelper.Divide(360.0f, SegmentCount); for (var i = SegmentCount - 1; i >= 0; i--) { var angle = angleStep * i; var rotation = Quaternion.Euler(0.0f, angle, 0.0f); segments[i].ManualUpdate(mesh, material, rotation); } }
protected virtual void OnDrawGizmosSelected() { if (SgtHelper.Enabled(this) == true) { var matrix = default(Matrix4x4); var ratio = default(float); if (CalculateShadow(ref matrix, ref ratio) == true) { Gizmos.matrix = matrix.inverse; var distA = 0.0f; var distB = 1.0f; var scale = 1.0f * Mathf.Deg2Rad; var inner = SgtHelper.Divide(RadiusMin, RadiusMax); for (var i = 1; i < 10; i++) { var posA = new Vector3(0.0f, 0.0f, distA); var posB = new Vector3(0.0f, 0.0f, distB); Gizmos.color = new Color(1.0f, 1.0f, 1.0f, Mathf.Pow(0.75f, i) * 0.125f); for (var a = 1; a <= 360; a++) { posA.x = posB.x = Mathf.Sin(a * scale); posA.y = posB.y = Mathf.Cos(a * scale); Gizmos.DrawLine(posA, posB); posA.x = posB.x = posA.x * inner; posA.y = posB.y = posA.y * inner; Gizmos.DrawLine(posA, posB); } distA = distB; distB = distB * 2.0f; } } } }
public virtual void SetCurrentCamera(Camera c) { if (c != null) { UpdateMaterial(); var cameraPosition = c.transform.position; var localCameraPosition = transform.InverseTransformPoint(cameraPosition); var localDistance = localCameraPosition.magnitude; var clampedAltitude = Mathf.InverseLerp(MiddleRadius, OuterRadius, localDistance); var innerAtmosphereDepth = default(float); var outerAtmosphereDepth = default(float); var radiusRatio = SgtHelper.Divide(InnerMeshRadius, OuterRadius); var innerHeightRatio = SgtHelper.Divide(MiddleHeight, OuterRadius); var scaleDistance = SgtHelper.Divide(localDistance, OuterRadius); var fog = 1.0f - Fog; SgtHelper.CalculateAtmosphereThicknessAtHorizon(radiusRatio, 1.0f, scaleDistance, out innerAtmosphereDepth, out outerAtmosphereDepth); // Make the fog level reduce when you get closer than the ground height innerAtmosphereDepth = Mathf.Max(innerAtmosphereDepth, innerHeightRatio); if (scaleDistance > 1.0f) { innerKeywords.Add("SGT_A"); outerKeywords.Add("SGT_A"); } if (Smooth == true) { innerKeywords.Add("SGT_B"); outerKeywords.Add("SGT_B"); } SgtHelper.SetKeywords(innerMaterial, innerKeywords); innerKeywords.Clear(); SgtHelper.SetKeywords(outerMaterial, outerKeywords); outerKeywords.Clear(); innerMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(innerAtmosphereDepth * fog)); outerMaterial.SetFloat("_HorizonLengthRecip", SgtHelper.Reciprocal(outerAtmosphereDepth * fog)); outerMaterial.SetFloat("_Power", CalculateOuterPower(cameraPosition, clampedAltitude)); } }
public override bool CalculateShadow(ref Matrix4x4 matrix, ref float ratio) { if (base.CalculateShadow(ref matrix, ref ratio) == true) { if (Texture != null) { if (SgtHelper.Enabled(RingMesh) == true) { RadiusMin = RingMesh.RadiusMin; RadiusMax = RingMesh.RadiusMax; } var direction = default(Vector3); var position = default(Vector3); var color = default(Color); SgtHelper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color); var rotation = Quaternion.FromToRotation(direction, Vector3.back); var squash = Vector3.Dot(direction, transform.up); // Find how squashed the ellipse is based on light direction var width = transform.lossyScale.x * RadiusMax; var length = transform.lossyScale.z * RadiusMax; var axis = rotation * transform.up; // Find the transformed up axis var spin = Quaternion.LookRotation(Vector3.forward, new Vector2(-axis.x, axis.y)); // Orient the shadow ellipse var scale = SgtHelper.Reciprocal3(new Vector3(width, length * Mathf.Abs(squash), 1.0f)); var skew = Mathf.Tan(SgtHelper.Acos(-squash)); var shadowT = SgtHelper.Translation(-transform.position); var shadowR = SgtHelper.Rotation(spin * rotation); // Spin the shadow so lines up with its tilt var shadowS = SgtHelper.Scaling(scale); // Scale the ring into an oval var shadowK = SgtHelper.ShearingZ(new Vector2(0.0f, skew)); // Skew the shadow so it aligns with the ring plane matrix = shadowS * shadowK * shadowR * shadowT; ratio = SgtHelper.Divide(RadiusMax, RadiusMax - RadiusMin); return(true); } } return(false); }
protected virtual void RegenerateMesh() { mesh = SgtObjectPool <Mesh> .Add(mesh, m => m.Clear()); SgtProceduralMesh.Clear(); { if (SegmentDetail >= 3) { var angleTotal = SgtHelper.Divide(Mathf.PI * 2.0f, SegmentCount); var angleStep = SgtHelper.Divide(angleTotal, SegmentDetail); var coordStep = SgtHelper.Reciprocal(SegmentDetail); for (var i = 0; i <= SegmentDetail; i++) { var coord = coordStep * i; var angle = angleStep * i; var sin = Mathf.Sin(angle); var cos = Mathf.Cos(angle); SgtProceduralMesh.PushPosition(sin * InnerRadius, 0.0f, cos * InnerRadius); SgtProceduralMesh.PushPosition(sin * OuterRadius, 0.0f, cos * OuterRadius); SgtProceduralMesh.PushNormal(Vector3.up); SgtProceduralMesh.PushNormal(Vector3.up); SgtProceduralMesh.PushCoord1(0.0f, coord); SgtProceduralMesh.PushCoord1(1.0f, coord); } } } SgtProceduralMesh.SplitStrip(HideFlags.DontSave); mesh = SgtProceduralMesh.Pop(); SgtProceduralMesh.Discard(); if (mesh != null) { var bounds = mesh.bounds; mesh.bounds = SgtHelper.NewBoundsCenter(bounds, bounds.center + bounds.center.normalized * BoundsShift); } }
protected override void RegenerateMesh() { mesh = SgtObjectPool <Mesh> .Add(mesh, m => m.Clear()); SgtProceduralMesh.Clear(); { if (SegmentDetail >= 3) { var angleTotal = SgtHelper.Divide(Mathf.PI * 2.0f, SegmentCount); var angleStep = SgtHelper.Divide(angleTotal, SegmentDetail); var coordStep = SgtHelper.Reciprocal(SegmentDetail); for (var i = 0; i <= SegmentDetail; i++) { var coord = coordStep * i; var angle = angleStep * i; var sin = Mathf.Sin(angle); var cos = Mathf.Cos(angle); var iPos = new Vector3(sin * InnerRadius, 0.0f, cos * InnerRadius); var oPos = new Vector3(sin * OuterRadius, 0.0f, cos * OuterRadius); SgtProceduralMesh.PushPosition(iPos); SgtProceduralMesh.PushPosition(oPos); SgtProceduralMesh.PushNormal(Vector3.up); SgtProceduralMesh.PushNormal(Vector3.up); SgtProceduralMesh.PushCoord1(0.0f, coord * InnerRadius); SgtProceduralMesh.PushCoord1(1.0f, coord * OuterRadius); SgtProceduralMesh.PushCoord2(InnerRadius, 0.0f); SgtProceduralMesh.PushCoord2(OuterRadius, 0.0f); } } } SgtProceduralMesh.SplitStrip(HideFlags.DontSave); mesh = SgtProceduralMesh.Pop(); SgtProceduralMesh.Discard(); }
protected virtual void Update() { if (LightningSpawner == null) { Pool(this); } else { if (Application.isPlaying == true) { Age += Time.deltaTime; } if (Age >= Life) { SgtComponentPool <SgtLightning> .Add(this); } else if (material != null) { material.SetFloat("_Age", SgtHelper.Divide(Age, Life)); } } }
public void RebuildPatch(SgtPatch patch) { if (Resolution > 0) { var resAdd1 = Resolution + 1; var resAdd2 = Resolution + 2; var resAdd3 = Resolution + 3; var resRecip = SgtHelper.Reciprocal(Resolution); var mainVerts = resAdd1 * resAdd1; var skirtVerts = resAdd1 * 4; var mainIndices = Resolution * Resolution * 6; var skirtIndices = Resolution * 24; var mesh = patch.Mesh; var vertex = default(int); var vertex2 = default(int); var index = default(int); if (positions == null || positions.Length != mainVerts + skirtVerts) { positions = new Vector3[mainVerts + skirtVerts]; } if (coords1 == null || coords1.Length != mainVerts + skirtVerts) { coords1 = new Vector2[mainVerts + skirtVerts]; } if (coords2 == null || coords2.Length != mainVerts + skirtVerts) { coords2 = new Vector2[mainVerts + skirtVerts]; } if (normals == null || normals.Length != mainVerts + skirtVerts) { normals = new Vector3[mainVerts + skirtVerts]; } if (tangents == null || tangents.Length != mainVerts + skirtVerts) { tangents = new Vector4[mainVerts + skirtVerts]; } if (quadPoints == null || quadPoints.Length != resAdd3 * resAdd3) { quadPoints = new Vector3[resAdd3 * resAdd3]; } if (quadNormals == null || quadNormals.Length != resAdd2 * resAdd2) { quadNormals = new Vector3[resAdd2 * resAdd2]; } if (quadTangents == null || quadTangents.Length != resAdd2 * resAdd2) { quadTangents = new Vector3[resAdd2 * resAdd2]; } // Go through all vertices, but extend the borders by one for (var y = -1; y < resAdd2; y++) { for (var x = -1; x < resAdd2; x++) { var u = x * resRecip; var v = y * resRecip; var pointB = Lerp3(patch.PointBL, patch.PointBR, u); var pointT = Lerp3(patch.PointTL, patch.PointTR, u); var point = GetSurfacePositionLocal(Lerp3(pointB, pointT, v)); index = x + 1 + (y + 1) * resAdd3; quadPoints[index] = point; // Is this a main vertex? if (x >= 0 && x < resAdd1 && y >= 0 && y < resAdd1) { var coordB = Lerp2(patch.CoordBL, patch.CoordBR, u); var coordT = Lerp2(patch.CoordTL, patch.CoordTR, u); var coord1 = Lerp2(coordB, coordT, v); var coord2 = new Vector2(u, v); var center = (patch.PointBL + patch.PointBR + patch.PointTL + patch.PointTR) * 0.25f; if (OnCalculateCoord1 != null) { OnCalculateCoord1(point, center, ref coord1); } if (OnCalculateCoord2 != null) { OnCalculateCoord2(point, center, ref coord2); } vertex = x + y * resAdd1; positions[vertex] = point; coords1[vertex] = coord1; coords2[vertex] = coord2; } } } // Quad normals & tangents for (var y = 0; y < resAdd2; y++) { for (var x = 0; x < resAdd2; x++) { var bl = x + y * resAdd3; var br = x + 1 + y * resAdd3; var tl = x + (y + 1) * resAdd3; var tr = x + 1 + (y + 1) * resAdd3; var b = quadPoints[bl] - quadPoints[br]; var t = quadPoints[tl] - quadPoints[tr]; var l = quadPoints[bl] - quadPoints[tl]; var r = quadPoints[br] - quadPoints[tr]; var h = (b + t).normalized; var v = (l + r).normalized; var i = x + y * resAdd2; quadNormals[i] = Vector3.Cross(h, v); quadTangents[i] = v; } } // Normals & Tangents for (var y = 0; y < resAdd1; y++) { for (var x = 0; x < resAdd1; x++) { var bl = x + y * resAdd2; var br = x + 1 + y * resAdd2; var tl = x + (y + 1) * resAdd2; var tr = x + 1 + (y + 1) * resAdd2; var n = quadNormals[bl] + quadNormals[br] + quadNormals[tl] + quadNormals[tr]; var t = quadTangents[bl] + quadTangents[br] + quadTangents[tl] + quadTangents[tr]; var i = x + y * resAdd1; normals[i] = n.normalized; //normals[i] = positions[i].normalized; tangents[i] = SgtHelper.NewVector4(t.normalized, 1.0f); } } // Skirt vertices var scale = 1.0f - SgtHelper.Divide(SkirtThickness * Mathf.Pow(0.5f, patch.Depth), 1.0f); for (var i = 0; i < resAdd1; i++) { // Bottom vertex = mainVerts + i; vertex2 = i; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; // Top vertex = mainVerts + i + resAdd1; vertex2 = resAdd1 * Resolution + i; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; // Left vertex = mainVerts + i + resAdd1 + resAdd1; vertex2 = resAdd1 * i; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; // Right vertex = mainVerts + i + resAdd1 + resAdd1 + resAdd1; vertex2 = resAdd1 * i + Resolution; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; } // Indices if (indices == null || indices.Length != mainIndices + skirtIndices) { indices = new int[mainIndices + skirtIndices]; // Main for (var y = 0; y < Resolution; y++) { for (var x = 0; x < Resolution; x++) { index = (x + y * Resolution) * 6; vertex = x + y * resAdd1; indices[index + 0] = vertex; indices[index + 1] = vertex + 1; indices[index + 2] = vertex + resAdd1; indices[index + 3] = vertex + resAdd1 + 1; indices[index + 4] = vertex + resAdd1; indices[index + 5] = vertex + 1; } } // Skirt for (var i = 0; i < Resolution; i++) { // Bottom index = mainIndices + (Resolution * 0 + i) * 6; vertex = mainVerts + i; vertex2 = i; indices[index + 0] = vertex; indices[index + 1] = vertex + 1; indices[index + 2] = vertex2; indices[index + 3] = vertex2 + 1; indices[index + 4] = vertex2; indices[index + 5] = vertex + 1; // Top index = mainIndices + (Resolution * 1 + i) * 6; vertex = mainVerts + i + resAdd1; vertex2 = Resolution * resAdd1 + i; indices[index + 0] = vertex2; indices[index + 1] = vertex2 + 1; indices[index + 2] = vertex; indices[index + 3] = vertex + 1; indices[index + 4] = vertex; indices[index + 5] = vertex2 + 1; // Left index = mainIndices + (Resolution * 2 + i) * 6; vertex = mainVerts + i + resAdd1 + resAdd1; vertex2 = i * resAdd1; indices[index + 0] = vertex; indices[index + 1] = vertex2; indices[index + 2] = vertex + 1; indices[index + 3] = vertex2 + resAdd1; indices[index + 4] = vertex + 1; indices[index + 5] = vertex2; // Right index = mainIndices + (Resolution * 3 + i) * 6; vertex = mainVerts + i + resAdd1 + resAdd1 + resAdd1; vertex2 = i * resAdd1 + Resolution; indices[index + 0] = vertex2; indices[index + 1] = vertex; indices[index + 2] = vertex2 + resAdd1; indices[index + 3] = vertex + 1; indices[index + 4] = vertex2 + resAdd1; indices[index + 5] = vertex; } } if (mesh != null) { mesh.Clear(); } else { mesh = patch.Mesh = SgtObjectPool <Mesh> .Pop() ?? new Mesh(); mesh.name = "Patch"; mesh.hideFlags = HideFlags.DontSave; } mesh.vertices = positions; mesh.uv = coords1; mesh.uv2 = coords2; mesh.normals = normals; mesh.tangents = tangents; mesh.triangles = indices; mesh.RecalculateBounds(); patch.MeshCenter = mesh.bounds.center; } }
protected virtual void Update() { if (Follower == null) { ClearDebris(); return; } var followerPosition = Follower.position; var followerDensity = GetDensity(followerPosition); if (followerDensity > 0.0f) { var debrisCount = Debris != null ? Debris.Count : 0; if (debrisCount < SpawnLimit) { spawnCooldown -= Time.deltaTime; while (spawnCooldown <= 0.0f) { spawnCooldown += Random.Range(SpawnRateMin, SpawnRateMax); SpawnDebris(false); debrisCount += 1; if (debrisCount >= SpawnLimit) { break; } } } } if (Debris != null) { var distanceRange = HideDistance - ShowDistance; for (var i = Debris.Count - 1; i >= 0; i--) { var debris = Debris[i]; if (debris != null) { var targetScale = default(float); var distance = Vector3.Distance(followerPosition, debris.transform.position); // Fade its size in debris.Show = SgtHelper.Dampen(debris.Show, 1.0f, ShowSpeed, Time.deltaTime, 0.1f); if (distance < ShowDistance) { targetScale = 1.0f; } else if (distance > HideDistance) { targetScale = 0.0f; } else { targetScale = 1.0f - SgtHelper.Divide(distance - ShowDistance, distanceRange); } debris.transform.localScale = debris.Scale * debris.Show * Mathf.Max(minScale, targetScale); if (targetScale <= 0.0f) { Despawn(debris, i); } } else { Debris.RemoveAt(i); } } } }
public static void GenerateMesh(SgtPatch patch) { var terrain = patch.Terrain; if (terrain.Resolution > 0) { var positions = terrain.Positions; var coords1 = terrain.Coords1; var coords2 = terrain.Coords2; var normals = terrain.Normals; var tangents = terrain.Tangents; var quadPoints = terrain.QuadPoints; var quadNormals = terrain.QuadNormals; var quadTangents = terrain.QuadTangents; var indices = terrain.Indices; var res = terrain.Resolution; var resAdd1 = res + 1; var resAdd2 = res + 2; var resAdd3 = res + 3; var resRecip = SgtHelper.Reciprocal(res); var mainVerts = resAdd1 * resAdd1; var skirtVerts = resAdd1 * 4; var mainIndices = res * res * 6; var skirtIndices = res * 24; var vertex = default(int); var vertex2 = default(int); var index = default(int); if (positions.Length != mainVerts + skirtVerts) { terrain.Positions = positions = new Vector3[mainVerts + skirtVerts]; } if (coords1.Length != mainVerts + skirtVerts) { terrain.Coords1 = coords1 = new Vector2[mainVerts + skirtVerts]; } if (coords2.Length != mainVerts + skirtVerts) { terrain.Coords2 = coords2 = new Vector2[mainVerts + skirtVerts]; } if (normals.Length != mainVerts + skirtVerts) { terrain.Normals = normals = new Vector3[mainVerts + skirtVerts]; } if (tangents.Length != mainVerts + skirtVerts) { terrain.Tangents = tangents = new Vector4[mainVerts + skirtVerts]; } if (quadPoints.Length != resAdd3 * resAdd3) { terrain.QuadPoints = quadPoints = new Vector3[resAdd3 * resAdd3]; } if (quadNormals.Length != resAdd2 * resAdd2) { terrain.QuadNormals = quadNormals = new Vector3[resAdd2 * resAdd2]; } if (quadTangents.Length != resAdd2 * resAdd2) { terrain.QuadTangents = quadTangents = new Vector3[resAdd2 * resAdd2]; } // Go through all vertices, but extend the borders by one for (var y = -1; y < resAdd2; y++) { for (var x = -1; x < resAdd2; x++) { var u = x * resRecip; var v = y * resRecip; var pointB = Lerp3(patch.PointBL, patch.PointBR, u); var pointT = Lerp3(patch.PointTL, patch.PointTR, u); var point = Lerp3(pointB, pointT, v).normalized; point *= terrain.GetHeight(point); index = x + 1 + (y + 1) * resAdd3; quadPoints[index] = point; // Is this a main vertex? if (x >= 0 && x < resAdd1 && y >= 0 && y < resAdd1) { var coordB = Lerp2(patch.CoordBL, patch.CoordBR, u); var coordT = Lerp2(patch.CoordTL, patch.CoordTR, u); var coord1 = Lerp2(coordB, coordT, v); vertex = x + y * resAdd1; positions[vertex] = point; coords1[vertex] = coord1; coords2[vertex] = new Vector2(u, v); } } } // Quad normals & tangents for (var y = 0; y < resAdd2; y++) { for (var x = 0; x < resAdd2; x++) { var bl = x + y * resAdd3; var br = x + 1 + y * resAdd3; var tl = x + (y + 1) * resAdd3; var tr = x + 1 + (y + 1) * resAdd3; var b = quadPoints[bl] - quadPoints[br]; var t = quadPoints[tl] - quadPoints[tr]; var l = quadPoints[bl] - quadPoints[tl]; var r = quadPoints[br] - quadPoints[tr]; var h = (b + t).normalized; var v = (l + r).normalized; var i = x + y * resAdd2; quadNormals[i] = Vector3.Cross(h, v); quadTangents[i] = v; } } // Normals & Tangents for (var y = 0; y < resAdd1; y++) { for (var x = 0; x < resAdd1; x++) { var bl = x + y * resAdd2; var br = x + 1 + y * resAdd2; var tl = x + (y + 1) * resAdd2; var tr = x + 1 + (y + 1) * resAdd2; var n = quadNormals[bl] + quadNormals[br] + quadNormals[tl] + quadNormals[tr]; var t = quadTangents[bl] + quadTangents[br] + quadTangents[tl] + quadTangents[tr]; var i = x + y * resAdd1; normals[i] = n.normalized; //normals[i] = positions[i].normalized; tangents[i] = SgtHelper.NewVector4(t.normalized, 1.0f); } } // Skirt vertices var scale = 1.0f - SgtHelper.Divide(terrain.SkirtThickness * Mathf.Pow(0.5f, patch.Depth), 1.0f); for (var i = 0; i < resAdd1; i++) { // Bottom vertex = mainVerts + i; vertex2 = i; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; // Top vertex = mainVerts + i + resAdd1; vertex2 = resAdd1 * res + i; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; // Left vertex = mainVerts + i + resAdd1 + resAdd1; vertex2 = resAdd1 * i; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; // Right vertex = mainVerts + i + resAdd1 + resAdd1 + resAdd1; vertex2 = resAdd1 * i + res; positions[vertex] = positions[vertex2] * scale; coords1[vertex] = coords1[vertex2]; coords2[vertex] = coords2[vertex2]; normals[vertex] = normals[vertex2]; tangents[vertex] = tangents[vertex2]; } // Indices if (indices.Length != mainIndices + skirtIndices) { terrain.Indices = indices = new int[mainIndices + skirtIndices]; // Main for (var y = 0; y < res; y++) { for (var x = 0; x < res; x++) { index = (x + y * res) * 6; vertex = x + y * resAdd1; indices[index + 0] = vertex; indices[index + 1] = vertex + 1; indices[index + 2] = vertex + resAdd1; indices[index + 3] = vertex + resAdd1 + 1; indices[index + 4] = vertex + resAdd1; indices[index + 5] = vertex + 1; } } // Skirt for (var i = 0; i < res; i++) { // Bottom index = mainIndices + (res * 0 + i) * 6; vertex = mainVerts + i; vertex2 = i; indices[index + 0] = vertex; indices[index + 1] = vertex + 1; indices[index + 2] = vertex2; indices[index + 3] = vertex2 + 1; indices[index + 4] = vertex2; indices[index + 5] = vertex + 1; // Top index = mainIndices + (res * 1 + i) * 6; vertex = mainVerts + i + resAdd1; vertex2 = res * resAdd1 + i; indices[index + 0] = vertex2; indices[index + 1] = vertex2 + 1; indices[index + 2] = vertex; indices[index + 3] = vertex + 1; indices[index + 4] = vertex; indices[index + 5] = vertex2 + 1; // Left index = mainIndices + (res * 2 + i) * 6; vertex = mainVerts + i + resAdd1 + resAdd1; vertex2 = i * resAdd1; indices[index + 0] = vertex; indices[index + 1] = vertex2; indices[index + 2] = vertex + 1; indices[index + 3] = vertex2 + resAdd1; indices[index + 4] = vertex + 1; indices[index + 5] = vertex2; // Right index = mainIndices + (res * 3 + i) * 6; vertex = mainVerts + i + resAdd1 + resAdd1 + resAdd1; vertex2 = i * resAdd1 + res; indices[index + 0] = vertex2; indices[index + 1] = vertex; indices[index + 2] = vertex2 + resAdd1; indices[index + 3] = vertex + 1; indices[index + 4] = vertex2 + resAdd1; indices[index + 5] = vertex; } } if (patch.Mesh != null) { patch.Mesh.Clear(); } else { patch.Mesh = SgtObjectPool <Mesh> .Pop() ?? new Mesh(); patch.Mesh.hideFlags = HideFlags.DontSave; } patch.Mesh.vertices = positions; patch.Mesh.uv = coords1; patch.Mesh.uv2 = coords2; patch.Mesh.normals = normals; patch.Mesh.tangents = tangents; patch.Mesh.triangles = indices; patch.Mesh.RecalculateBounds(); patch.MeshCenter = patch.Mesh.bounds.center; } }
public void UpdateMesh() { updateMeshCalled = true; if (Mesh == null) { Mesh = SgtHelper.CreateTempMesh("Plane"); if (Planes != null) { for (var i = Planes.Count - 1; i >= 0; i--) { var plane = Planes[i]; if (plane != null) { plane.SetMesh(Mesh); } } } } else { Mesh.Clear(false); } if (PlaneDetail >= 2) { var detail = Mathf.Min(PlaneDetail, SgtHelper.QuadsPerMesh / 2); // Limit the amount of vertices that get made var positions = new Vector3[detail * 2 + 2]; var normals = new Vector3[detail * 2 + 2]; var coords1 = new Vector2[detail * 2 + 2]; var coords2 = new Vector2[detail * 2 + 2]; var indices = new int[detail * 6]; var angleStep = SgtHelper.Divide(Mathf.PI * 2.0f, detail); var coordStep = SgtHelper.Reciprocal(detail); for (var i = 0; i <= detail; i++) { var coord = coordStep * i; var angle = angleStep * i; var sin = Mathf.Sin(angle); var cos = Mathf.Cos(angle); var offV = i * 2; positions[offV + 0] = new Vector3(sin * InnerRadius, 0.0f, cos * InnerRadius); positions[offV + 1] = new Vector3(sin * OuterRadius, 0.0f, cos * OuterRadius); normals[offV + 0] = Vector3.up; normals[offV + 1] = Vector3.up; coords1[offV + 0] = new Vector2(0.0f, coord * InnerRadius); coords1[offV + 1] = new Vector2(1.0f, coord * OuterRadius); coords2[offV + 0] = new Vector2(InnerRadius, 0.0f); coords2[offV + 1] = new Vector2(OuterRadius, 0.0f); } for (var i = 0; i < detail; i++) { var offV = i * 2; var offI = i * 6; indices[offI + 0] = offV + 0; indices[offI + 1] = offV + 1; indices[offI + 2] = offV + 2; indices[offI + 3] = offV + 3; indices[offI + 4] = offV + 2; indices[offI + 5] = offV + 1; } Mesh.vertices = positions; Mesh.normals = normals; Mesh.uv = coords1; Mesh.uv2 = coords2; Mesh.triangles = indices; } }
public void UpdateDebris() { var size = (long)System.Math.Ceiling(SgtHelper.Divide(HideDistance, (float)CellSize)); if (Target != null && CellSize > 0.0f && Prefabs != null && DebrisCountTarget > 0 && size > 0) { var worldPoint = Target.position; var centerX = (long)System.Math.Round(worldPoint.x / CellSize); var centerY = (long)System.Math.Round(worldPoint.y / CellSize); var centerZ = (long)System.Math.Round(worldPoint.z / CellSize); var newBounds = new SgtBoundsL(centerX, centerY, centerZ, size); if (newBounds != bounds) { var probability = DebrisCountTarget / (size * size * size); var cellMin = (float)CellSize * (0.5f - CellNoise); var cellMax = (float)CellSize * (0.5f + CellNoise); for (var z = newBounds.minZ; z <= newBounds.maxZ; z++) { for (var y = newBounds.minY; y <= newBounds.maxY; y++) { for (var x = newBounds.minX; x <= newBounds.maxX; x++) { if (bounds.Contains(x, y, z) == false) { // Calculate seed for this grid cell and try to minimize visible symmetry var seed = Seed ^ (x * (1 << 8)) ^ (y * (1 << 16)) ^ (z * (1 << 24)); SgtHelper.BeginRandomSeed((int)(seed % int.MaxValue)); { // Can debris potentially spawn in this cell? if (Random.value < probability) { var debrisX = x * CellSize + Random.Range(cellMin, cellMax); var debrisY = y * CellSize + Random.Range(cellMin, cellMax); var debrisZ = z * CellSize + Random.Range(cellMin, cellMax); var debrisPoint = new Vector3((float)debrisX, (float)debrisY, (float)debrisZ); // Spawn everywhere, or only inside specified shapes? if (SpawnInside == null || Random.value < SpawnInside.GetDensity(debrisPoint)) { Spawn(x, y, z, debrisPoint); } } } SgtHelper.EndRandomSeed(); } } } } bounds = newBounds; if (Debris != null) { for (var i = Debris.Count - 1; i >= 0; i--) { var debris = Debris[i]; if (debris == null) { Debris.RemoveAt(i); } else if (bounds.Contains(debris.Cell) == false) { Despawn(debris, i); } } } } UpdateDebrisScale(worldPoint); } else { ClearDebris(); } }