Esempio n. 1
0
    public static TressFXTransform Multiply(TressFXTransform t1, TressFXTransform t2)
    {
        TressFXTransform ret = new TressFXTransform();

        ret.translation = t1.rotation * t2.translation + t1.translation;
        ret.rotation    = t1.rotation * t2.rotation;

        return(ret);
    }
Esempio n. 2
0
    /// <summary>
    /// This initializes tressfx and all of it's components.
    /// This function gets called from the TressFX Loader.
    /// </summary>
    /// <param name="vertices">Vertices.</param>
    /// <param name="strandIndices">Strand indices.</param>
    public void Initialize(TressFXStrand[] strands, int numVertices, int hairCount)
    {
        // Initialize data
        this.vertexCount = numVertices;
        this.strandCount = strands.Length;
        this.strands     = strands;
        this.hairCount   = hairCount;
        this.globalToLocalVertexIndexMappings = new Dictionary <int, int> ();
        this.hairData = this.GetComponent <TressFXLoader> ().hairs;

        // Buffer resources
        positionVectors = new Vector4[numVertices];
        Vector4[] initialPositionVectors = new Vector4[numVertices];
        referenceVectors = new Vector3[numVertices];
        vectorTangents   = new Vector3[numVertices];
        hairRestLengths  = new float[numVertices];
        strandIndices    = new int[numVertices];
        offsets          = new int[strands.Length];
        hairIndices      = new int[strands.Length];

        // Rotations
        localRotations  = new Quaternion[numVertices];
        globalRotations = new Quaternion[numVertices];

        // Transforms
        localTransforms  = new TressFXTransform[numVertices];
        globalTransforms = new TressFXTransform[numVertices];

        List <int> triangleIndicesList = new List <int> ();

        thicknessCoeffs = new float[numVertices];

        // Initialize transforms and fill hair and strand indices, hair rest lengths and position vectors
        int index = 0;

        this.ComputeDistanceToRoot();

        for (int i = 0; i < strands.Length; i++)
        {
            hairIndices[i] = strands[i].hairId;

            for (int j = 0; j < strands[i].vertices.Length; j++)
            {
                this.globalToLocalVertexIndexMappings.Add(index, j);

                Vector4 pos  = strands[i].GetTressFXVector(j);
                Vector3 pos3 = new Vector3(pos.x, pos.y, pos.z);
                pos3 = this.transform.position + pos3;
                Vector4 position = new Vector4(pos3.x, pos3.y, pos3.z, pos.w);

                // Load position of the strand
                positionVectors[index]        = position;
                initialPositionVectors[index] = strands[i].GetTressFXVector(j);

                // Get rest length
                if (j < strands[i].vertices.Length - 1)
                {
                    hairRestLengths[index] = (strands[i].vertices[j].pos - strands[i].vertices[j + 1].pos).magnitude;
                }
                else
                {
                    hairRestLengths[index] = 0;
                }

                // Init transforms
                globalTransforms[index]        = new TressFXTransform();
                localTransforms[index]         = new TressFXTransform();
                strands[i].localTransforms[j]  = localTransforms[index];
                strands[i].globalTransforms[j] = globalTransforms[index];

                // Set triangle indices
                if (j < strands[i].vertices.Length - 1)
                {
                    triangleIndicesList.Add(2 * index);
                    triangleIndicesList.Add(2 * index + 1);
                    triangleIndicesList.Add(2 * index + 2);
                    triangleIndicesList.Add(2 * index + 2);
                    triangleIndicesList.Add(2 * index + 1);
                    triangleIndicesList.Add(2 * index + 3);
                }

                float tVal = strands[i].vertices[j].texcoords.z;
                thicknessCoeffs[index] = Mathf.Sqrt(1.0f - tVal * tVal);

                // Set strand indices currently used for cutting linestrips by a geometry shader
                strandIndices[index] = j;
                index++;
            }

            // Set strand offsets
            offsets[i] = index;
        }

        this.ThicknessCoeffsBuffer = new ComputeBuffer(numVertices, 4);
        this.ThicknessCoeffsBuffer.SetData(thicknessCoeffs);

        this.triangleIndices       = triangleIndicesList.ToArray();
        this.TriangleIndicesBuffer = new ComputeBuffer(this.triangleIndices.Length, 4);
        this.TriangleIndicesBuffer.SetData(this.triangleIndices);

        // Initialize frames
        this.InitializeLocalGlobalFrame();

        // Compute strand tangents
        this.ComputeStrandTangents();
        this.TangentsBuffer = new ComputeBuffer(this.vectorTangents.Length, 12);
        this.TangentsBuffer.SetData(this.vectorTangents);

        // Initialize compute buffers
        this.InitialVertexPositionBuffer = new ComputeBuffer(numVertices, 16);
        this.LastVertexPositionBuffer    = new ComputeBuffer(numVertices, 16);
        this.VertexPositionBuffer        = new ComputeBuffer(numVertices, 16);
        this.StrandIndicesBuffer         = new ComputeBuffer(numVertices, 4);
        this.HairIndicesBuffer           = new ComputeBuffer(strands.Length, 4);

        this.InitialVertexPositionBuffer.SetData(initialPositionVectors);
        this.StrandIndicesBuffer.SetData(strandIndices);
        this.HairIndicesBuffer.SetData(hairIndices);

        // Initialize simulation if existing
        TressFXSimulation simulation = this.gameObject.GetComponent <TressFXSimulation>();

        if (simulation != null)
        {
            simulation.Initialize(hairRestLengths, referenceVectors, offsets, localRotations, globalRotations);
        }

        // Initialize Rendering if existing
        ATressFXRender render = this.gameObject.GetComponent <ATressFXRender>();

        if (render != null)
        {
            render.Initialize();
        }

        this.LastVertexPositionBuffer.SetData(positionVectors);
        this.VertexPositionBuffer.SetData(positionVectors);

        Debug.Log("TressFX Loaded! Hair vertices: " + this.vertexCount);
    }
Esempio n. 3
0
    /// <summary>
    /// Inititalizes the local and global frame.
    /// </summary>
    private void InitializeLocalGlobalFrame()
    {
        // Init global / local frame
        for (int i = 0; i < positionVectors.Length; i++)
        {
            // Calculate rotations for vertex 0
            if (i == 0)
            {
                Vector3 currentVector = new Vector3(positionVectors[i].x, positionVectors[i].y, positionVectors[i].z);
                Vector3 nextVector    = new Vector3(positionVectors[i + 1].x, positionVectors[i + 1].y, positionVectors[i + 1].z);

                Vector3 vec = nextVector - currentVector;
                // Rotations for vertex 0 local = global
                Vector3 vecX = vec.normalized;

                Vector3 vecZ = Vector3.Cross(vecX, new Vector3(1, 0, 0));

                if (vecZ.magnitude * vecZ.magnitude < 0.0001f)
                {
                    vecZ = Vector3.Cross(vecX, new Vector3(0, 1, 0));
                }

                vecZ.Normalize();

                Vector3 vecY = Vector3.Cross(vecZ, vecX).normalized;

                // Construct rotation matrix
                Matrix3x3 rotL2W = new Matrix3x3();
                rotL2W.matrixData[0, 0] = vecX.x; rotL2W.matrixData[0, 1] = vecY.x; rotL2W.matrixData[0, 2] = vecZ.x;
                rotL2W.matrixData[1, 0] = vecX.y; rotL2W.matrixData[1, 1] = vecY.y; rotL2W.matrixData[1, 2] = vecZ.y;
                rotL2W.matrixData[2, 0] = vecX.z; rotL2W.matrixData[2, 1] = vecY.z; rotL2W.matrixData[2, 2] = vecZ.z;

                localTransforms[i].translation = currentVector;
                localTransforms[i].rotation    = rotL2W.ToQuaternion();
                globalTransforms[i]            = localTransforms[i];
            }
            else
            {
                // Normal rotation calculation
                Vector3 lastVector    = new Vector3(positionVectors[i - 1].x, positionVectors[i - 1].y, positionVectors[i - 1].z);
                Vector3 currentVector = new Vector3(positionVectors[i].x, positionVectors[i].y, positionVectors[i].z);

                Vector3 vec = Quaternion.Inverse(globalRotations[i - 1]) * (currentVector - lastVector);

                Vector3 vecX = vec.normalized;

                Vector3 X       = new Vector3(1.0f, 0, 0);
                Vector3 rotAxis = Vector3.Cross(X, vecX);
                float   angle   = Mathf.Acos(Vector3.Dot(X, vecX));


                if (Mathf.Abs(angle) < 0.001 || rotAxis.magnitude < 0.001)
                {
                    localRotations[i] = Quaternion.identity;
                }
                else
                {
                    rotAxis.Normalize();
                    Quaternion rot = TressFXUtil.QuaternionFromAngleAxis(angle, rotAxis);
                    localRotations[i] = rot;
                }

                localTransforms[i].translation = vec;
                globalTransforms[i]            = TressFXTransform.Multiply(globalTransforms[i - 1], localTransforms[i]);
            }
        }

        // Generate rotations and reference vectors
        for (int i = 0; i < positionVectors.Length; i++)
        {
            referenceVectors[i] = localTransforms[i].translation;
            localRotations[i]   = localTransforms[i].rotation;
            globalRotations[i]  = localTransforms[i].rotation;
        }
    }