// Use this for initialization void Start() { if (this.Controller == null) { this.Controller = GameObject.FindObjectOfType <ElectromagneticFieldControllerScript> (); } FieldValues = new VolumeBuffer <Vector3> (Cubic <int> .CreateSame(CubeSize)); if (this.UseDebugMesh) { var mf = this.GetComponent <MeshFilter> (); if (mf == null) { this.UseDebugMesh = false; Debug.Assert(mf != null, "Please setup a MeshFilter and MeshRenderer on this object"); } SurfaceMesh = new Mesh(); MeshVertices = new Vector3[FieldValues.Length * 3]; MeshNormals = new Vector3[FieldValues.Length * 3]; mf.mesh = SurfaceMesh; } }
public void EnsureSetup() { if (isSetup) { return; } isSetup = true; FieldOverallAlpha = 1.0f; ParticleFlowRate = 1.0f; if (!this.Body) { this.Body = this.gameObject.GetComponentInParent <BodyLandmarks> (); } if (!this.Body) { if (!this.Hand) { this.Hand = this.gameObject.GetComponentInParent <MainEnergyApp> (); } this.ChiBall = this.gameObject.GetComponentInParent <ChiHandEnergyBall> (); } Debug.Assert((this.Body) || (this.Hand) || (this.ChiBall)); if (!this.ExcersizeSystem) { this.ExcersizeSystem = GameObject.FindObjectOfType <ExcersizeSharedScheduler> (); } bool isMobile = (Application.platform == UnityEngine.RuntimePlatform.IPhonePlayer); int sideRes = (isMobile ? this.VoxelSideResMobile : this.VoxelSideRes); // 8; if (this.Body) { this.Body.EnsureSetup(); int chakraToShow = CurrentFocusChakra; //3; this.FieldsCells = new VolumeBuffer <DynFieldCell> (Cubic <int> .CreateSame(sideRes)); var scl = OneOver(this.FieldsCells.Header.Size.AsVector3()); var l2w = this.transform.localToWorldMatrix; var cntr = Body.Chakras.AllChakras [chakraToShow].transform.position; // l2w.MultiplyPoint (Vector3.zero); foreach (var nd in this.FieldsCells.AllIndices3()) { var cell = this.FieldsCells.Read(nd.AsCubic()); cell.Pos = this.transform.localToWorldMatrix.MultiplyPoint(FieldsCells.Header.CubicToDecimalUnit(nd) - (Vector3.one * 0.5f)); if (!(SkipRandomPlacement)) { cell.Pos += Scale(Random.insideUnitSphere, scl); // add random offset } cell.Direction = cntr - cell.Pos; cell.LatestColor = Color.white; cell.Twist = 0.0f; cell.VoxelIndex = nd; this.FieldsCells.Write(nd.AsCubic(), cell); } } else if (this.Hand) { var arrows = this.Hand.FindAllFlowNodes(); var n = arrows.Count; this.IsStaticLayout = true; this.FieldsCells = new VolumeBuffer <DynFieldCell> (Cubic <int> .Create(n, 1, 1)); for (int i = 0; i < n; i++) { var cell = this.FieldsCells.Array [i]; var arrow = arrows [i]; cell.Pos = arrow.transform.position; cell.Direction = arrow.transform.up * 50.0f; cell.LatestColor = Color.green; cell.Twist = 0.0f; cell.VoxelIndex = new Int3(i, 0, 0); this.FieldsCells.Array [i] = cell; } } else if (this.ChiBall) { this.FieldsCells = new VolumeBuffer <DynFieldCell> (Cubic <int> .CreateSame(sideRes)); var scl = OneOver(this.FieldsCells.Header.Size.AsVector3()); var cntr = this.ChiBall.transform.position; var l2w = this.transform.localToWorldMatrix; foreach (var nd in this.FieldsCells.AllIndices3()) { var cell = this.FieldsCells.Read(nd.AsCubic()); cell.Pos = this.transform.localToWorldMatrix.MultiplyPoint(FieldsCells.Header.CubicToDecimalUnit(nd) - (Vector3.one * 0.5f)); if (!(SkipRandomPlacement)) { cell.Pos += Scale(Random.insideUnitSphere, scl); // add random offset } cell.Direction = cntr - cell.Pos; cell.LatestColor = Color.white; cell.Twist = 0.0f; cell.VoxelIndex = nd; this.FieldsCells.Write(nd.AsCubic(), cell); } } this.UpdateCellFieldDir(snapToCurrent: true); }
public IEnumerable <bool> UpdateMultiChakras() { this.MultiChakras = this.gameObject.transform.parent .GetComponentsInChildren <VolumeTextureBehavior>() //.Where(k => (k.IsAura)||(k.name.Contains("Solar"))).ToArray() ; List <Matrix4x4> worldToChakras = new List <Matrix4x4>(); foreach (var c in this.MultiChakras) { c.EnsureSetup(); worldToChakras.Add(c.transform.worldToLocalMatrix); } Debug.Log("MULTI CHAKRA from " + this.MultiChakras.Length + " children."); var m2w = this.transform.localToWorldMatrix; bool debugMe = true; var proj = SpanAPI.spanProjFromCubicDomainAndRange( mColorBuffer.Size.Select(k => SpanAPI.span(0, k - 1)), Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)) ); var invProj = SpanAPI.spanProjFromCubicDomainAndRange( Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)), mColorBuffer.Size.Select(k => SpanAPI.span(0, k - 1)) ); var invProjForMath = SpanAPI.spanProjFromCubicDomainAndRange( Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)), Cubic <SpanF> .CreateSame(SpanAPI.span(-1.0, 1.0)) ); //var proj = SpanAPI.Example_SetupProjection (mColorBuffer.Size.X, mColorBuffer.Size.Y, mColorBuffer.Size.Z); //var invProj = SpanAPI.Example_SetupSignedUnitToIntProjection(mColorBuffer.Size.X, mColorBuffer.Size.Y, mColorBuffer.Size.Z); Color defaultVal = Color.clear; for (int i = 0; i < this.mColorBuffer.Length; i++) { var ndx = this.mColorBuffer.UnprojectIndex(i); var mpos = SpanAPI.spanProjCubicInt(proj, ndx); Color curColor = defaultVal; if (this.mColorBuffer.IsEdge(ndx)) { // it's an edge, ignore it } else { //foreach (var chakra in this.MultiChakras) for (int ci = 0; ci < this.MultiChakras.Length; ci++) { var chakra = this.MultiChakras[ci]; var w2c = worldToChakras[ci]; var cpos = MultiplySpanByMatrix(mpos, w2c * m2w);// m2w * w2c); //cpos = cpos.Select(k => SpanAPI.spanMult(k, SpanAPI.spanExactly(1.5))); if (MultiChakraFullEval && (!chakra.IsAura)) { var suSpan = SpanAPI.spanProjCubicSpan(invProjForMath, cpos); var suVal = chakra.ChakraFieldFromSignedUnit(suSpan); var suColor = chakra.ColorFromChakraField(suVal); curColor = MixColors(curColor, suColor); continue; } var fspan = SpanAPI.spanProjCubicSpan(invProj, cpos); fspan = fspan.Select(k => SpanAPI.spanMult(k, SpanAPI.spanExactly(1.01))); var ispan = fspan.Select(k => SpanI.FromSpanF(k)); var sample = chakra.mColorBuffer.SampleSpan(ispan, Color.clear, (a, b) => MixColors(a, b)); if (debugMe) { debugMe = false; Debug.Log("proj = " + proj); Debug.Log("invProj = " + invProj); Debug.Log("ndx = " + ndx); Debug.Log("mpos = " + mpos); var testInvPos = SpanAPI.spanProjCubicSpan(invProj, mpos); Debug.Log("testInvPos = " + testInvPos); var testISpan = testInvPos.Select(k => SpanI.FromSpanF(k)); Debug.Log("testISpan = " + testISpan); Debug.Log("mpos = " + mpos); Debug.Log("cpos = " + cpos); Debug.Log("fspan = " + fspan); Debug.Log("ispan = " + ispan); Debug.Log("sample = " + sample); } curColor = MixColors(curColor, sample); } } this.mColorBuffer.Write(ndx, curColor); if (((i % 100)) == 99) { this.UpdateTextureFromBuffer(); yield return(false); } } //return; this.UpdateTextureFromBuffer(); this.TrySaveToCache(); Debug.Log("MULTI CHAKRAS UPDATED!"); }
public IEnumerable <bool> DoFlowField() { var verts = GameObject.FindObjectsOfType <FlowVertexNode> (); this.CachedFlowVerts = verts; var proj = SpanAPI.spanProjFromCubicDomainAndRange( mColorBuffer.Size.Select(k => SpanAPI.span(0, k - 1)), Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)) ); var m2w = this.transform.localToWorldMatrix; var clearWhite = new Color(1, 1, 1, 0); var clearBlack = new Color(0, 0, 0, 0); //var curColor = Color.black; for (int i = 0; i < this.mColorBuffer.Length; i++) { var ndx = this.mColorBuffer.UnprojectIndex(i); var mpos = SpanAPI.spanProjCubicInt(proj, ndx); bool actMe = false; var clr = clearBlack; // clearWhite; var rgb = ndx.Select2(this.mColorBuffer.Size, (di, sz) => ((float)di) / ((float)(sz - 1))); //curColor = new Color(rgb.X, rgb.Y, rgb.Z); if (this.mColorBuffer.IsEdge(ndx)) { actMe = false; } else { var center = mpos.Select(k => (k.From + k.To) * 0.5f).AsVector(); var radius = mpos.Select(k => Mathf.Abs((float)((k.From - k.To) * 0.5f))).Aggregate((a, b) => ((a + b) * 0.5f)); var wcenter = m2w.MultiplyPoint(center); var wradius = m2w.MultiplyVector(Vector3.one * radius).magnitude; clr = EvalFlowVolume(wcenter, wradius, mpos); //if (Physics.CheckSphere (wcenter, wradius)) { // actMe = true; //} } //var clr = ((actMe) ? curColor : Color.clear ); this.mColorBuffer.Array[i] = clr; int updateEvery = 200; if (((i % updateEvery)) == (updateEvery - 1)) { this.UpdateTextureFromBuffer(); yield return(false); } } this.UpdateTextureFromBuffer(); this.TrySaveToCache(); this.RefreshCache = false; }
private IEnumerable <bool> UpdateAura() { Debug.Log("UPDATING AURA."); var m2w = this.transform.localToWorldMatrix; bool debugMe = true; var proj = SpanAPI.spanProjFromCubicDomainAndRange( mColorBuffer.Size.Select(k => SpanAPI.span(0, k - 1)), Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)) ); var invProj = SpanAPI.spanProjFromCubicDomainAndRange( Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)), mColorBuffer.Size.Select(k => SpanAPI.span(0, k - 1)) ); var invProjForMath = SpanAPI.spanProjFromCubicDomainAndRange( Cubic <SpanF> .CreateSame(SpanAPI.span(-0.5, 0.5)), Cubic <SpanF> .CreateSame(SpanAPI.span(-1.0, 1.0)) ); VolumeBuffer <float> distances = null; bool needsDistances = false; bool needsSurface = true; var sz = this.mColorBuffer.Size; var path = VolumeBufferFile.CacheFilePath(this.gameObject.name + "_sdf", sz); var pathOpacity = VolumeBufferFile.CacheFilePath(this.gameObject.name + "_opacity", sz); if ((!this.RefreshDistances) && VolumeBufferFile.CacheFileExists(path)) { distances = VolumeBufferFile.ReadFloatVolFromFile(sz, path); } if ((!this.RefreshDistances) && VolumeBufferFile.CacheFileExists(pathOpacity)) { distances = VolumeBufferFile.ReadFloatVolFromFile(sz, pathOpacity); needsDistances = true; needsSurface = false; } if (distances == null) { distances = new VolumeBuffer <float>(sz); distances.ClearAll(-1.0f); needsDistances = true; } if (needsDistances) { if (needsSurface) { Debug.Log("AURA SURFACES..."); // First see which points are touching: Color defaultVal = Color.clear; for (int i = 0; i < this.mColorBuffer.Length; i++) { var ndx = this.mColorBuffer.UnprojectIndex(i); var mpos = SpanAPI.spanProjCubicInt(proj, ndx); Color curColor = defaultVal; float curDistance = -1.0f; if (this.mColorBuffer.IsEdge(ndx)) { // it's an edge, ignore it } else { var center = mpos.Select(k => (k.From + k.To) * 0.5f).AsVector(); var radius = mpos.Select(k => Mathf.Abs((float)((k.From - k.To) * 0.5f))).Aggregate((a, b) => ((a + b) * 0.5f)); var wcenter = m2w.MultiplyPoint(center); var wradius = m2w.MultiplyVector(Vector3.one * radius).magnitude; if (Physics.CheckSphere(wcenter, wradius)) { //Debug.Log ("Touched something"); curColor = Color.white; curColor.a = 0.2f; curDistance = 0.0f; } } this.mColorBuffer.Write(ndx, curColor); distances.Write(ndx, curDistance); if (((i % 100)) == 99) { this.UpdateTextureFromBuffer(); yield return(false); } } VolumeBufferFile.SaveFloatVolToFile(distances, pathOpacity); } // Now calculate the actual distances: Debug.Log("AURA DISTANCES..."); if (false) { // if this works: VolumeBufferUtil.ConvertOpacityToDistanceBuffer(distances); } else { // this works but is super slow: float maxDist = CubicIntDist(Cubic <int> .CreateSame(0), distances.Size); for (int i = 0; i < this.mColorBuffer.Length; i++) { var ndx = this.mColorBuffer.UnprojectIndex(i); var centerDist = distances.Read(ndx); if (centerDist < 0.0f) { // needs recalc, slowest possible way O(n^6): float closestDistance = -1.0f; for (int j = 0; j < distances.Array.Length; j++) { if (distances.Array[j] == 0.0f) { float dist = CubicIntDist(distances.UnprojectIndex(j), ndx) / maxDist; if ((closestDistance < 0.0f) || (dist < closestDistance)) { closestDistance = dist; } } } distances.Write(ndx, closestDistance); Color testColor = Color.white; testColor.a = closestDistance; this.mColorBuffer.Write(ndx, testColor); if (((i % 100)) == 99) { this.UpdateTextureFromBuffer(); yield return(false); } } } } // Write out the results: VolumeBufferFile.SaveFloatVolToFile(distances, path); } ChakraAuraSettings auraSettings = this.GetComponent <ChakraAuraSettings>(); if (auraSettings.UseChakraAuraDistance) { Debug.Log("AURA-TO-CHAKRA DISTANCES..."); // modify distances based on chakra locality: var allChakras = this.gameObject .GetComponentInParent <ChakraControl>() .AllPoints .Where(k => ((!k.IsAura) && (!k.IsMultiChakras))) .Where(k => (!k.ChakraOneWay)) .Select(k => Matrix4x4.TRS(k.transform.position, k.transform.rotation, Vector3.one).inverse) .ToArray(); Debug.Log("Chakra Count = " + allChakras.Length); for (int li = 0; li < distances.Array.Length; li++) { var ndx = this.mColorBuffer.UnprojectIndex(li); var mpos = SpanAPI.spanProjCubicInt(proj, ndx).Select(k => (k.From + k.To) * 0.5f).AsVector(); var wpos = m2w.MultiplyPoint(mpos); var dist = distances.Array[li]; var origdist = dist; foreach (var c in allChakras) { var lpos = c.MultiplyPoint(wpos); var ldist = Mathf.Sqrt((lpos.x * lpos.x) + (lpos.z * lpos.z)) / (Mathf.Abs(lpos.y) * 1.5f); ldist = 0.5f - (ldist * ldist); if (ldist > dist) { dist = ldist; //(origdist - ldist); } } //if (origdist == dist) dist = 0.0f; // HACK REMOVE distances.Array[li] = dist; if (((li % 100)) == 99) { float pct = ((float)li) / ((float)distances.Array.Length); Debug.Log("Updating aura-chakra distance (" + (pct * 100.0f) + "%)"); yield return(false); } } } // Calculate the colors from the distances: float[] idealDistances = auraSettings.AuraDistances; // { 0.0165f, 0.05f, 0.1f }; Color[] idealColors = auraSettings.AuraColors; // { Color.red, Color.green, new Color(0.0f, 1.0f, 1.0f, 1.0f) }; //float IdealDistance = 0.0165f; //float AuraWidth = 0.0125f; Debug.Log("AURA COLORS..."); float previousDist = 0.0f; for (int i = 0; i < this.mColorBuffer.Length; i++) { var ndx = this.mColorBuffer.UnprojectIndex(i); var dist = distances.Read(ndx); dist = dist * dist; // 1.0f / (dist * dist); Color resColor = Color.clear; for (int layerNdx = idealDistances.Length - 1; layerNdx >= 0; layerNdx--) { var edgeDist = idealDistances[layerNdx] * auraSettings.WholeScaleDistances; if (dist < edgeDist) { var edgeColor = idealColors[layerNdx]; var nextDist = 0.0f; // ((layerNdx > 0) ? (idealDistances[layerNdx - 1] * auraSettings.WholeScaleDistances) : 0.0f); float strength = Mathf.Clamp01(1.0f - (Mathf.Abs(dist - edgeDist) / (edgeDist - nextDist))); Color curColor = edgeColor; curColor.a = curColor.a * strength; resColor = curColor;// Colors_BlendOver(auraSettings, resColor, curColor); } previousDist = edgeDist; } this.mColorBuffer.Write(ndx, resColor); if (((i % 100)) == 99) { Debug.Log("cur = " + dist); this.UpdateTextureFromBuffer(); yield return(false); } while (auraSettings.IsPauseCalculation) { yield return(false); } } this.mColorBuffer.ClearEdges(Color.clear); //return; this.UpdateTextureFromBuffer(); this.TrySaveToCache(); Debug.Log("AURA UPDATED!"); }