Ejemplo n.º 1
0
    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!");
    }
Ejemplo n.º 2
0
    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;
    }
Ejemplo n.º 3
0
    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!");
    }