Ejemplo n.º 1
0
    /// <summary>
    /// Instantiates a mesh object inside cpp plugin and stores
    /// a reference to it in this class
    /// </summary>
    private void SendSkinnedMesh()
    {
        // The plugin will want to modify the vertex buffer -- on many platforms
        // for that to work we have to mark mesh as "dynamic" (which makes the buffers CPU writable --
        // by default they are immutable and only GPU-readable).
        mesh.MarkDynamic();

        var vertices      = mesh.vertices;                      // Vector3[]
        var faces         = mesh.triangles.Clone() as int[];    // int[]
        var nativeWeights = mesh.GetAllBoneWeights();           // NativeArray<BoneWeight1>
        var boneCounts    = mesh.GetBonesPerVertex().ToArray(); // byte[]

        Debug.Assert(boneCounts.Length == vertices.Length, "Bone per vertex array has different length from vertex array");

        // copy because original struct is not interop-friendly
        int largestBoneIndex = 0;

        Bone[] weights = new Bone[nativeWeights.Length];
        for (int i = 0; i < weights.Length; i++)
        {
            var native = nativeWeights[i];
            weights[i] = new Bone(native.boneIndex, native.weight);

            largestBoneIndex = native.boneIndex > largestBoneIndex
                ? native.boneIndex : largestBoneIndex;
        }
        Debug.Log($"Largest bone index in mesh {mesh.name}: {largestBoneIndex}");

        GCHandle gcVertices   = GCHandle.Alloc(vertices, GCHandleType.Pinned);
        GCHandle gcFaces      = GCHandle.Alloc(faces, GCHandleType.Pinned);
        GCHandle gcWeights    = GCHandle.Alloc(weights, GCHandleType.Pinned);
        GCHandle gcBoneCounts = GCHandle.Alloc(boneCounts, GCHandleType.Pinned);

        var cppMesh = NativeInterface.CreateMesh(gcVertices.AddrOfPinnedObject(), mesh.vertexCount,
                                                 gcFaces.AddrOfPinnedObject(), faces.Length / 3,
                                                 gcWeights.AddrOfPinnedObject(), gcBoneCounts.AddrOfPinnedObject(),
                                                 largestBoneIndex + 1);

        gcVertices.Free();
        gcFaces.Free();
        gcWeights.Free();
        gcBoneCounts.Free();

        string errorMessage = ExtractFailureMessage(NativeInterface.HasFailedMeshConstruction(cppMesh));

        if (errorMessage.Equals(""))
        {
            this._cppMesh = cppMesh;
        }
        else
        {
            NativeInterface.DestroyMesh(cppMesh);
            throw new Exception(errorMessage);
        }

        // send pointer to the mesh buffer
        // if (mesh.vertexBufferCount > 1)
        //     Debug.LogWarning("There are more than one vertex buffer: " + mesh.vertexBufferCount);
        // NativeInterface.SetMeshVertexBuffer(this._cppMesh, mesh.GetNativeVertexBufferPtr(0));
    }
Ejemplo n.º 2
0
    /// <summary>
    /// To be called on FixedUpdate every frame
    /// </summary>
    public void Animate(Vector4[] rotations, Vector3[] translations)
    {
        GCHandle gcRotations    = GCHandle.Alloc(rotations, GCHandleType.Pinned);
        GCHandle gcTranslations = GCHandle.Alloc(translations, GCHandleType.Pinned);

        // results
        var deformed = new Vector3[this.GetRestVertexCount()];

        deformed.Initialize();
        GCHandle gcDeformed = GCHandle.Alloc(deformed, GCHandleType.Pinned);

        NativeInterface.Animate(this._cppMesh, gcRotations.AddrOfPinnedObject(),
                                gcTranslations.AddrOfPinnedObject(), gcDeformed.AddrOfPinnedObject());

        gcRotations.Free();
        gcTranslations.Free();
        gcDeformed.Free();

        string errorMessage = ExtractFailureMessage(NativeInterface.AnimationError(this._cppMesh));

        if (!errorMessage.Equals(""))
        {
            NativeInterface.DestroyMesh(this._cppMesh);
            throw new Exception(errorMessage);
        }

        this.mesh.SetVertices(deformed);
    }
Ejemplo n.º 3
0
    /// <summary>
    /// Serialize the entire mesh on disk, including vertices,
    /// faces, weights and centers of rotation (if available)
    /// </summary>
    /// <param name="path">A folder for where to store the files</param>
    public void Serialize(string path)
    {
        NativeInterface.SerializeMesh(this._cppMesh, Path.Combine(path, this.mesh.name));

        var error = ExtractFailureMessage(NativeInterface.SerializationError(this._cppMesh));

        if (!error.Equals(""))
        {
            NativeInterface.DestroyMesh(this._cppMesh);
            throw new Exception(error);
        }
    }
Ejemplo n.º 4
0
    /// <summary>
    /// Read a previously serialized file with centers of rotation
    /// </summary>
    /// <param name="path"></param>
    public void ReadCenters(string path)
    {
        NativeInterface.ReadCenters(this._cppMesh, path);

        var error = ExtractFailureMessage(NativeInterface.SerializationError(this._cppMesh));

        if (!error.Equals(""))
        {
            NativeInterface.DestroyMesh(this._cppMesh);
            throw new Exception(error);
        }
    }
Ejemplo n.º 5
0
    // public int GetSubdividedFaceCount() => NativeInterface.GetSubdividedFaceCount(this._cppMesh);
    // public int GetSubdividedVertexCount() => NativeInterface.GetSubdividedVertexCount(this._cppMesh);

    /// <summary>
    /// Get the number of center of rotations in the mesh.
    /// It will computed it if the number is not defined.
    /// </summary>
    /// <returns></returns>
    public int GetCenterCount()
    {
        var count = NativeInterface.GetCenterCount(this._cppMesh);
        var error = ExtractFailureMessage(NativeInterface.HasFailedGettingCentersOfRotation(_cppMesh));

        if (error.Equals(""))
        {
            return(count);
        }
        else
        {
            NativeInterface.DestroyMesh(this._cppMesh);
            throw new Exception(error);
        }
    }