Пример #1
0
        protected override void _SimulationStep(float timestep)
        {
            HairStrand[] strands    = this.instance.strands.cpuReference;
            Vector3[]    vertices   = this.instance.vertices.cpuReference;
            uint[]       movability = this.instance.movability.cpuReference;

            for (int s = 0; s < strands.Length; s++)
            {
                HairStrand strand = strands[s];
                for (int j = strand.firstVertex + 1; j <= strand.lastVertex; j++)
                {
                    if (!HairMovability.IsMovable(j, movability))
                    {
                        continue;
                    }

                    float   nDist = this.lengths[j];
                    Vector3 p = vertices[j], pPrev = vertices[j - 1], pDir = (p - pPrev);
                    float   dist     = pDir.magnitude;
                    float   distDiff = (nDist - dist);

                    vertices[j] = p + ((pDir / dist) * (distDiff * this.stiffness * timestep));
                }
            }

            this.instance.vertices.SetGPUDirty();
        }
Пример #2
0
            public void Execute(int index)
            {
                HairStrand strand    = this.strands[index];
                quaternion rotGlobal = this.globalTransform[strand.firstVertex];

                for (int j = strand.firstVertex + 1; j < strand.lastVertex - 1; j++)
                {
                    quaternion rotGlobalWorld = math.mul(rotation, rotGlobal);

                    float3 p1 = vertices[j], p2 = vertices[j + 1];
                    float3 orgP2 = math.mul(rotGlobalWorld, this.referenceVectors[j + 1]) + p1;
                    float3 delta = stiffness * (orgP2 - p2);

                    if (HairMovability.IsMovable(j, movability))
                    {
                        p1 -= delta;
                    }
                    if (HairMovability.IsMovable(j + 1, movability))
                    {
                        p2 += delta;
                    }

                    float3 vec = (p2 - p1);

                    rotGlobal       = math.mul(rotGlobal, quaternion.LookRotation(math.normalize(math.mul(math.inverse(rotGlobalWorld), vec)), new float3(0, 1, 0)));
                    vertices[j]     = p1;
                    vertices[j + 1] = p2;
                }
            }
Пример #3
0
            public void Execute(int i)
            {
                // Is hair movable?
                if (HairMovability.IsMovable(i, movability))
                {
                    bool   wasModified = false;
                    float3 v           = vertices[i];
                    for (int j = 0; j < colliderCount; j++)
                    {
                        // Read collider
                        var c = colliders[j];

                        // Intersection?
                        float3 dir   = (v - c.center);
                        float  sqMag = math.lengthsq(dir);
                        if (sqMag <= c.radiusSq)                         // if (Vector3.Distance(v, c.center) <= c.radius)
                        {
                            // Intersection! push the vertex out
                            float d = math.sqrt(sqMag);                             // dir.magnitude;
                            v          += (dir / d) * (c.radius - d);
                            wasModified = true;
                        }
                    }

                    if (wasModified)
                    {
                        vertices[i] = v;                         // Sync
                    }
                }
            }
Пример #4
0
        protected override void _SimulationStep(float timestep)
        {
            NativeArray <float3>     vertices   = this.instance.vertices.CpuReference;
            NativeArray <uint>       movability = this.instance.movability.CpuReference;
            NativeArray <HairStrand> strands    = this.instance.strands.CpuReference;

            Matrix4x4 matrix = this.transform.localToWorldMatrix;

            for (int j = 0; j < strands.Length; j++)
            {
                HairStrand strand = strands[j];
                int        target = Mathf.Min(strand.firstVertex + this.vertexRange, strand.lastVertex);
                for (int i = strand.firstVertex; i <= target; i++)
                {
                    if (!HairMovability.IsMovable(i, movability))
                    {
                        continue;
                    }

                    Vector3 iV = this.simulation.initialVertices[i], v = vertices[i];
                    iV = matrix.MultiplyPoint3x4(iV);

                    Vector3 delta = (iV - v);
                    vertices[i] = v + (delta * this.stiffness * timestep);
                }
            }

            this.instance.vertices.SetGPUDirty();
        }
Пример #5
0
        protected override void _SimulationStep(float timestep)
        {
            List <CollisionSphere> colliders = ListPool <CollisionSphere> .Get();

            for (int i = 0; i < this.colliders.Length; i++)
            {
                colliders.Add(new CollisionSphere()
                {
                    center   = this.colliders[i].transform.TransformPoint(this.colliders[i].center),
                    radius   = this.colliders[i].radius,
                    radiusSq = this.colliders[i].radius * this.colliders[i].radius
                });
            }
            int colliderCount = colliders.Count;

            NativeArray <float3> vertices   = this.instance.vertices.CpuReference;
            NativeArray <uint>   movability = this.instance.movability.CpuReference;

            bool wasAnythingModified = false;

            for (int i = 0; i < vertices.Length; i++)
            {
                // Is hair movable?
                if (HairMovability.IsMovable(i, movability))
                {
                    bool    wasModified = false;
                    Vector3 v           = vertices[i];
                    for (int j = 0; j < colliderCount; j++)
                    {
                        // Read collider
                        var c = colliders[j];

                        // Intersection?
                        Vector3 dir    = (v - c.center);
                        float   sqrMag = dir.sqrMagnitude;
                        if (sqrMag <= c.radiusSq)                         // if (Vector3.Distance(v, c.center) <= c.radius)
                        {
                            // Intersection! push the vertex out
                            float d = Mathf.Sqrt(sqrMag);                             // dir.magnitude;
                            v          += (dir / d) * (c.radius - d);
                            wasModified = true;
                        }
                    }

                    if (wasModified)
                    {
                        vertices[i] = v;                         // Sync
                    }
                    wasAnythingModified |= wasModified;
                }
            }

            if (wasAnythingModified)
            {
                this.instance.vertices.SetGPUDirty();
            }

            ListPool <CollisionSphere> .Return(colliders);
        }
Пример #6
0
            public void Execute(int i)
            {
                if (!HairMovability.IsMovable(i, movability))
                {
                    return;
                }

                vertices[i] = vertices[i] + force;
            }
Пример #7
0
        protected override void _SimulationStep(float timestep)
        {
            // TODO: Damping
            Matrix4x4 matrix        = this.transform.localToWorldMatrix;
            Matrix4x4 invPrevMatrix = this.simulation.prevFrameMatrix.inverse;

            // Read vertices and strands
            NativeArray <HairStrand> strands    = this.instance.strands.CpuReference;
            NativeArray <float3>     vertices   = this.instance.vertices.CpuReference;
            NativeArray <uint>       movability = this.instance.movability.CpuReference;

            Vector3    gravity = Physics.gravity * this.gravityStrength;
            HairStrand strand;
            Vector3    lastFramePosWS, lastFramePosOS, posWS, newPos;

            lastFramePosOS = lastFramePosWS = posWS = newPos = new Vector3();
            float timestepSqr = timestep * timestep;

            for (int j = 0; j < strands.Length; j++)
            {
                strand = strands[j];

                // First vertex is immovable
                vertices[strand.firstVertex] = matrix.MultiplyPoint3x4(this.simulation.initialVertices[strand.firstVertex]);

                for (int i = strand.firstVertex; i <= strand.lastVertex; i++)
                {
                    if (!HairMovability.IsMovable(i, movability))
                    {
                        continue;
                    }

                    lastFramePosWS = vertices[i];
                    lastFramePosOS = invPrevMatrix.MultiplyPoint3x4(lastFramePosWS);

                    posWS = matrix.MultiplyPoint3x4(lastFramePosOS);

                    // Unoptimized:
                    // newPos = posWS + (lastFramePosWS - posWS) + (gravity * (timestep * timestep));

                    // Optimized version:
                    newPos.x = posWS.x + (lastFramePosWS.x - posWS.x) + (gravity.x * timestepSqr);
                    newPos.y = posWS.y + (lastFramePosWS.y - posWS.y) + (gravity.y * timestepSqr);
                    newPos.z = posWS.z + (lastFramePosWS.z - posWS.z) + (gravity.z * timestepSqr);

                    vertices[i] = newPos;
                }
            }

            // Set dirty
            this.instance.vertices.SetGPUDirty();
        }
Пример #8
0
        /// <summary>
        /// Initializes (reallocates and overwrites internal- ) movability data.
        /// </summary>
        /// <param name="movability">The mobility data to write, if null every vertex is marked as immovable.</param>
        public void InitializeMovability(uint[] movability = null)
        {
            this.movability = HairMovability.CreateData(vertices.Length);

            if (movability != null)
            {
                if (movability.Length != this.movability.Length)
                {
                    throw new System.ArgumentException("Incorrect movability array size, length should be ceil(vertexCount / 32f)");
                }
                movability.CopyTo(this.movability, 0);
            }
        }
Пример #9
0
        protected override void _SimulationStep(float timestep)
        {
            // TODO: Spherical wind zones
            Vector3[] vertices   = this.instance.vertices.cpuReference;
            uint[]    movability = this.instance.movability.cpuReference;
            Vector3   f          = this.windZone.transform.forward * Mathf.Abs(Mathf.Sin(Time.time) * this.windZone.windMain);

            for (int i = 0; i < vertices.Length; i++)
            {
                if (!HairMovability.IsMovable(i, movability))
                {
                    continue;
                }

                vertices[i] = vertices[i] + (f * timestep);
            }
        }
Пример #10
0
        protected override void _SimulationStep(float timestep)
        {
            float stiffness = .5f * Mathf.Min(this.stiffness * timestep, .95f);

            HairStrand[] strands    = this.instance.strands.cpuReference;
            Vector3[]    vertices   = this.instance.vertices.cpuReference;
            uint[]       movability = this.instance.movability.cpuReference;
            Quaternion   rotation   = this.transform.rotation;

            // Apply local shape constraint
            for (int i = 0; i < strands.Length; i++)
            {
                HairStrand strand    = strands[i];
                Quaternion rotGlobal = this.globalTransform[strand.firstVertex];

                realtimeDebug[strand.firstVertex] = rotGlobal;
                for (int j = strand.firstVertex + 1; j < strand.lastVertex - 1; j++)
                {
                    Quaternion rotGlobalWorld = rotation * rotGlobal;

                    Vector3 p1 = vertices[j], p2 = vertices[j + 1];
                    Vector3 orgP2 = rotGlobalWorld * this.referenceVectors[j + 1] + p1;
                    Vector3 delta = stiffness * (orgP2 - p2);

                    if (HairMovability.IsMovable(j, movability))
                    {
                        p1 -= delta;
                    }
                    if (HairMovability.IsMovable(j + 1, movability))
                    {
                        p2 += delta;
                    }

                    Vector3 vec = (p2 - p1);

                    rotGlobal        = rotGlobal * Quaternion.LookRotation((Quaternion.Inverse(rotGlobalWorld) * vec).normalized);
                    vertices[j]      = p1;
                    vertices[j + 1]  = p2;
                    realtimeDebug[j] = rotGlobal;
                }
                realtimeDebug[strand.lastVertex] = rotGlobal;
            }

            this.instance.vertices.SetGPUDirty();
        }
            public void Execute(int index)
            {
                HairStrand strand = this.strands[index];

                for (int j = strand.firstVertex + 1; j <= strand.lastVertex; j++)
                {
                    if (!HairMovability.IsMovable(j, movability))
                    {
                        continue;
                    }

                    float  nDist = this.lengths[j];
                    float3 p = vertices[j], pPrev = vertices[j - 1], pDir = (p - pPrev);
                    float  dist     = math.length(pDir);
                    float  distDiff = (nDist - dist);

                    vertices[j] = p + ((pDir / dist) * (distDiff * this.stiffness * timestep));
                }
            }
Пример #12
0
            public void Execute(int j)
            {
                HairStrand strand = strands[j];
                int        target = Mathf.Min(strand.firstVertex + this.vertexRange, strand.lastVertex);

                for (int i = strand.firstVertex; i <= target; i++)
                {
                    if (!HairMovability.IsMovable(i, movability))
                    {
                        continue;
                    }

                    float3 iV = initialVertices[i], v = vertices[i];
                    float4 iV4 = new float4(iV.x, iV.y, iV.z, 1);
                    iV = math.mul(matrix, iV4).xyz;

                    float3 delta = (iV - v);
                    vertices[i] = v + (delta * this.stiffness * timestep);
                }
            }
            public void Execute(int index)
            {
                HairStrand strand = this.strands[index];
                float3     lastFramePosWS, lastFramePosOS, posWS, newPos;

                lastFramePosOS = lastFramePosWS = posWS = newPos = new float3();

                // First vertex is immovable
                float3 initialPos = initialVertices[strand.firstVertex];

                vertices[strand.firstVertex] = math.mul(matrix, new float4(initialPos.x, initialPos.y, initialPos.z, 1)).xyz;

                for (int i = strand.firstVertex; i <= strand.lastVertex; i++)
                {
                    if (!HairMovability.IsMovable(i, movability))
                    {
                        continue;
                    }

                    lastFramePosWS = vertices[i];
                    float4 lastFramePosWS4 = new float4(lastFramePosWS.x, lastFramePosWS.y, lastFramePosWS.z, 1);
                    lastFramePosOS = math.mul(invPrevMatrix, lastFramePosWS4).xyz;
                    float4 lastFramePosOS4 = new float4(lastFramePosOS.x, lastFramePosOS.y, lastFramePosOS.z, 1);

                    posWS = math.mul(matrix, lastFramePosOS4).xyz;

                    // Unoptimized:
                    // newPos = posWS + (lastFramePosWS - posWS) + (gravity * (timestep * timestep));

                    // Optimized version:
                    newPos.x = posWS.x + (lastFramePosWS.x - posWS.x) + (gravity.x * timestepSqr);
                    newPos.y = posWS.y + (lastFramePosWS.y - posWS.y) + (gravity.y * timestepSqr);
                    newPos.z = posWS.z + (lastFramePosWS.z - posWS.z) + (gravity.z * timestepSqr);

                    vertices[i] = newPos;
                }
            }
Пример #14
0
            public void Execute(int i)
            {
                // Is hair movable?
                if (HairMovability.IsMovable(i, movability))
                {
                    bool   wasModified = false;
                    float3 v           = vertices[i];
                    for (int j = 0; j < colliderCount; j++)
                    {
                        // Read collider
                        var c = colliders[j];

                        // Test sphere 1
                        float3 dir   = (v - c.sphere1Pos);
                        float  sqMag = math.lengthsq(dir);
                        if (sqMag <= c.radiusSq)
                        {
                            // Intersection! push the vertex out
                            float d = math.sqrt(sqMag);
                            v          += (dir / d) * (c.radius - d);
                            wasModified = true;
                        }
                        else
                        {
                            // Test sphere 2
                            dir   = (v - c.sphere2Pos);
                            sqMag = math.lengthsq(dir);
                            if (sqMag <= c.radiusSq)
                            {
                                // Intersection! push the vertex out
                                float d = math.sqrt(sqMag);
                                v          += (dir / d) * (c.radius - d);
                                wasModified = true;
                            }
                            else
                            {
                                // Test cylinder
                                float3 d  = c.sphere2Pos - c.sphere1Pos;
                                float3 pd = v - c.sphere1Pos;

                                float dot = math.dot(d, pd);
                                if (dot >= 0 && dot <= c.lengthSq)
                                {
                                    float dist = math.lengthsq(pd) - (dot * dot / c.lengthSq);
                                    if (dist <= c.radiusSq)
                                    {
                                        // Get closest point to vertex on cylinder axis
                                        float3 dNorm     = d / c.length;
                                        float  dotP      = math.dot(v - c.sphere1Pos, dNorm);
                                        float3 axisPoint = c.sphere1Pos + dNorm * dotP;

                                        // Construct ray through vertex from axis point and get cylinder body exit point
                                        v           = axisPoint + (math.normalizesafe(v - axisPoint) * c.radius);
                                        wasModified = true;
                                    }
                                }
                            }
                        }
                    }

                    if (wasModified)
                    {
                        vertices[i] = v;                         // Sync
                    }
                }
            }