Example #1
0
 public static void ExtractBoneAnimMatrix(GPUSkinning gpuSkinning, GPUSkinning_BoneAnimation boneAnimation, System.Action <Matrix4x4, Matrix4x4> boneAnimMatrixCB, System.Action <int> frameCB)
 {
     for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex)
     {
         float second = (float)(frameIndex) / (float)boneAnimation.fps;
         gpuSkinning.matrixArray.UpdateBoneAnimationMatrix(null, second);
         int numBones = gpuSkinning.model.bones.Length;
         for (int i = 0; i < numBones; ++i)
         {
             boneAnimMatrixCB(gpuSkinning.model.bones[i].animationMatrix, gpuSkinning.model.bones[i].hierarchyMatrix);
         }
         frameCB(frameIndex);
     }
 }
Example #2
0
    private void UpdateBoneAnimationMatrix(string animName, float time)
    {
        GPUSkinning_BoneAnimation boneAnimation = boneAnimations[0];//GetBoneAnimation(animName);
        int frameIndex = (int)((time * boneAnimation.fps) % (boneAnimation.length * boneAnimation.fps));

        if (currFrameIndex != frameIndex)
        {
            currFrameIndex          = frameIndex;
            isCurrFrameIndexChanged = true;

            GPUSkinning_BoneAnimationFrame frame = boneAnimation.frames[frameIndex];

            UpdateBoneTransformMatrix(bones[rootBoneIndex], Matrix4x4.identity, frame);
        }
    }
Example #3
0
    private void ExtractBoneAnimMatrix(System.Action <Matrix4x4> boneAnimMatrixCB, System.Action <int> frameCB)
    {
        GPUSkinning_BoneAnimation boneAnimation = boneAnimations[0];

        for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex)
        {
            float second = (float)(frameIndex) / (float)boneAnimation.fps;
            UpdateBoneAnimationMatrix(null, second);
            int numBones = bones.Length;
            for (int i = 0; i < numBones; ++i)
            {
                Matrix4x4 animMat = bones[i].animationMatrix;
                boneAnimMatrixCB(animMat);
            }
            frameCB(frameIndex);
        }
    }
    public override void Init(GPUSkinning gpuSkinning)
    {
        base.Init(gpuSkinning);

        shaderPropID_Time = Shader.PropertyToID("_GameTime");

        smr  = gpuSkinning.GetComponentInChildren <SkinnedMeshRenderer>();
        mesh = smr.sharedMesh;

        // Init Bones
        int numBones = smr.bones.Length;

        bones = new GPUSkinning_Bone[numBones];
        for (int i = 0; i < numBones; ++i)
        {
            GPUSkinning_Bone bone = new GPUSkinning_Bone();
            bones[i]       = bone;
            bone.transform = smr.bones[i];
            bone.name      = bone.transform.gameObject.name;
            bone.bindpose  = mesh.bindposes[i] /*smr to bone*/;
        }

        // Construct Hierarchy
        for (int i = 0; i < numBones; ++i)
        {
            if (bones[i].transform == smr.rootBone)
            {
                rootBoneIndex = i;
                break;
            }
        }
        System.Action <GPUSkinning_Bone> CollectChildren = null;
        CollectChildren = (currentBone) =>
        {
            List <GPUSkinning_Bone> children = new List <GPUSkinning_Bone>();
            for (int j = 0; j < currentBone.transform.childCount; ++j)
            {
                Transform        childTransform = currentBone.transform.GetChild(j);
                GPUSkinning_Bone childBone      = GetBoneByTransform(childTransform);
                if (childBone != null)
                {
                    childBone.parent = currentBone;
                    children.Add(childBone);
                    CollectChildren(childBone);
                }
            }
            currentBone.children = children.ToArray();
        };
        CollectChildren(bones[rootBoneIndex]);

        // New MeshFilter MeshRenderer
        mf = gpuSkinning.gameObject.AddComponent <MeshFilter>();
        mr = gpuSkinning.gameObject.AddComponent <MeshRenderer>();

        newMtrl = new Material(Shader.Find("Unlit/GPUSkinning"));
        newMtrl.CopyPropertiesFromMaterial(smr.sharedMaterial);
        mr.sharedMaterial = newMtrl;

        // New Mesh
        newMesh           = new Mesh();
        newMesh.vertices  = mesh.vertices;
        newMesh.tangents  = GPUSkinningUtil.ExtractBoneWeights(mesh);
        newMesh.uv        = mesh.uv;
        newMesh.triangles = mesh.triangles;
        mf.sharedMesh     = newMesh;

#if UNITY_EDITOR
        // Extract bone animation data
        int boneAnimationsCount = 0;
        boneAnimations = new GPUSkinning_BoneAnimation[gpuSkinning.GetComponent <Animator>().runtimeAnimatorController.animationClips.Length];
        foreach (AnimationClip animClip in gpuSkinning.GetComponent <Animator>().runtimeAnimatorController.animationClips)
        {
            GPUSkinning_BoneAnimation boneAnimation = ScriptableObject.CreateInstance <GPUSkinning_BoneAnimation>();
            boneAnimation.fps      = 60;
            boneAnimation.animName = animClip.name;
            boneAnimation.frames   = new GPUSkinning_BoneAnimationFrame[(int)(animClip.length * boneAnimation.fps)];
            boneAnimation.length   = animClip.length;
            boneAnimations[boneAnimationsCount++] = boneAnimation;

            for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex)
            {
                GPUSkinning_BoneAnimationFrame frame = new GPUSkinning_BoneAnimationFrame();
                boneAnimation.frames[frameIndex] = frame;
                float second = (float)(frameIndex) / (float)boneAnimation.fps;

                List <GPUSkinning_Bone> bones2              = new List <GPUSkinning_Bone>();
                List <Matrix4x4>        matrices            = new List <Matrix4x4>();
                List <string>           bonesHierarchyNames = null; if (boneAnimation.bonesHierarchyNames == null)
                {
                    bonesHierarchyNames = new List <string>();
                }
                EditorCurveBinding[] curvesBinding = AnimationUtility.GetCurveBindings(animClip);
                foreach (var curveBinding in curvesBinding)
                {
                    GPUSkinning_Bone bone = GetBoneByHierarchyName(curveBinding.path);

                    if (bones2.Contains(bone))
                    {
                        continue;
                    }
                    bones2.Add(bone);

                    if (bonesHierarchyNames != null)
                    {
                        bonesHierarchyNames.Add(GetBoneHierarchyName(bone));
                    }

                    AnimationCurve curveRX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.x");
                    AnimationCurve curveRY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.y");
                    AnimationCurve curveRZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.z");
                    AnimationCurve curveRW = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.w");

                    AnimationCurve curvePX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.x");
                    AnimationCurve curvePY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.y");
                    AnimationCurve curvePZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.z");

                    float curveRX_v = curveRX.Evaluate(second);
                    float curveRY_v = curveRY.Evaluate(second);
                    float curveRZ_v = curveRZ.Evaluate(second);
                    float curveRW_v = curveRW.Evaluate(second);

                    float curvePX_v = curvePX.Evaluate(second);
                    float curvePY_v = curvePY.Evaluate(second);
                    float curvePZ_v = curvePZ.Evaluate(second);

                    Vector3    translation = new Vector3(curvePX_v, curvePY_v, curvePZ_v);
                    Quaternion rotation    = new Quaternion(curveRX_v, curveRY_v, curveRZ_v, curveRW_v);
                    NormalizeQuaternion(ref rotation);
                    matrices.Add(
                        Matrix4x4.TRS(translation, rotation, Vector3.one)
                        );
                }

                frame.bones    = bones2.ToArray();
                frame.matrices = matrices.ToArray();
                if (boneAnimation.bonesHierarchyNames == null)
                {
                    boneAnimation.bonesHierarchyNames = bonesHierarchyNames.ToArray();
                }
            }
        }
        // Save as ScriptableObject
        AssetDatabase.CreateAsset(boneAnimations[0], "Assets/GPUSkinning/Resources/anim0.asset");
        AssetDatabase.Refresh();
#else
        // Read from ScriptableObject directly
        boneAnimations = new GPUSkinning_BoneAnimation[] { Resources.Load("anim0") as GPUSkinning_BoneAnimation };
        foreach (var boneAnimation in boneAnimations)
        {
            foreach (var frame in boneAnimation.frames)
            {
                int numBones2 = boneAnimation.bonesHierarchyNames.Length;
                frame.bones = new GPUSkinning_Bone[numBones2];
                for (int i = 0; i < numBones2; ++i)
                {
                    frame.bones[i] = GetBoneByHierarchyName(boneAnimation.bonesHierarchyNames[i]);
                }
            }
        }
#endif

        // Spawn many models
        if (spawnPoints != null)
        {
            List <GPUSkinning_SpawnObject> list = new List <GPUSkinning_SpawnObject>();
            for (int i = 0; i < spawnPoints.Length; ++i)
            {
                for (int j = 0; j < spawnPoints[i].childCount; ++j)
                {
                    GPUSkinning_SpawnObject spawnObject = new GPUSkinning_SpawnObject();
                    list.Add(spawnObject);
                    spawnObject.transform         = spawnPoints[i].GetChild(j);
                    spawnObject.mf                = spawnObject.transform.gameObject.AddComponent <MeshFilter>();
                    spawnObject.mr                = spawnObject.transform.gameObject.AddComponent <MeshRenderer>();
                    spawnObject.mr.sharedMaterial = newMtrl;
                    spawnObject.mf.sharedMesh     = newMesh;
                }
            }
            spawnObjects = list.ToArray();
        }
    }
Example #5
0
    private void Start()
    {
        shaderPropID_Matrices        = Shader.PropertyToID("_Matrices");
        shaderPropID_MatricesTex     = Shader.PropertyToID("_MatricesTex");
        shaderPropID_MatricesTexSize = Shader.PropertyToID("_MatricesTexSize");
        shaderPropID_AnimLength      = Shader.PropertyToID("_AnimLength");
        shaderPropID_AnimFPS         = Shader.PropertyToID("_AnimFPS");
        shaderPropID_TerrainTex      = Shader.PropertyToID("_TerrainTex");
        shaderPropID_TerrainSize     = Shader.PropertyToID("_TerrainSize");
        shaderPropID_TerrainPos      = Shader.PropertyToID("_TerrainPos");
        shaderPropID_mpb_time        = Shader.PropertyToID("_mpb_time");

        smr  = GetComponentInChildren <SkinnedMeshRenderer>();
        mesh = smr.sharedMesh;

        // 初始化骨骼对象
        int numBones = smr.bones.Length;

        bones = new GPUSkinning_Bone[numBones];
        for (int i = 0; i < numBones; ++i)
        {
            GPUSkinning_Bone bone = new GPUSkinning_Bone();
            bones[i]       = bone;
            bone.transform = smr.bones[i];
            bone.bindpose  = mesh.bindposes[i] /*smr to bone*/;
        }

        matricesUniformBlock = new Matrix4x4[numBones];

        // 构建骨骼的层级结构
        for (int i = 0; i < numBones; ++i)
        {
            if (bones[i].transform == smr.rootBone)
            {
                rootBoneIndex = i;
                break;
            }
        }
        System.Action <GPUSkinning_Bone> CollectChildren = null;
        CollectChildren = (currentBone) =>
        {
            List <GPUSkinning_Bone> children = new List <GPUSkinning_Bone>();
            for (int j = 0; j < currentBone.transform.childCount; ++j)
            {
                Transform        childTransform = currentBone.transform.GetChild(j);
                GPUSkinning_Bone childBone      = GetBoneByTransform(childTransform);
                if (childBone != null)
                {
                    childBone.parent = currentBone;
                    children.Add(childBone);
                    CollectChildren(childBone);
                }
            }
            currentBone.children = children.ToArray();
        };
        CollectChildren(bones[rootBoneIndex]);

        // New MeshFilter MeshRenderer
        mf = gameObject.AddComponent <MeshFilter>();
        mr = gameObject.AddComponent <MeshRenderer>();

        newMtrl = new Material(Shader.Find("Unlit/GPUSkinning"));
        newMtrl.CopyPropertiesFromMaterial(smr.sharedMaterial);
        mr.sharedMaterial = newMtrl;

        // 保存骨骼动画权重
        Vector4[] tangents = new Vector4[mesh.vertexCount];
        for (int i = 0; i < mesh.vertexCount; ++i)
        {
            BoneWeight boneWeight = mesh.boneWeights[i];
            tangents[i].x = boneWeight.boneIndex0;
            tangents[i].y = boneWeight.weight0;
            tangents[i].z = boneWeight.boneIndex1;
            tangents[i].w = boneWeight.weight1;
        }

        // New Mesh
        newMesh           = new Mesh();
        newMesh.vertices  = mesh.vertices;
        newMesh.tangents  = tangents;
        newMesh.uv        = mesh.uv;
        newMesh.triangles = mesh.triangles;
        mf.sharedMesh     = newMesh;

        // 为每个角色生成差异化数据
        if (IsMatricesTextureSupported())
        {
            additionalVertexStreames = new Mesh[50];
            for (int i = 0; i < additionalVertexStreames.Length; ++i)
            {
                Mesh      m   = new Mesh();
                float     rnd = Random.Range(0.0f, 10.0f);
                Vector2[] uv2 = new Vector2[mesh.vertexCount];
                for (int j = 0; j < mesh.vertexCount; ++j)
                {
                    Vector2 uv = Vector2.zero;
                    uv.x   = rnd;
                    uv2[j] = uv;
                }
                m.vertices = newMesh.vertices;
                m.uv2      = uv2;
                m.UploadMeshData(true);
                additionalVertexStreames[i] = m;
            }
            mr.additionalVertexStreams = additionalVertexStreames[0];
        }

#if UNITY_EDITOR
        // 从 Unity 的 Animation 中提取骨骼动画所需要的数据
        int boneAnimationsCount = 0;
        boneAnimations = new GPUSkinning_BoneAnimation[GetComponent <Animator>().runtimeAnimatorController.animationClips.Length];
        foreach (AnimationClip animClip in GetComponent <Animator>().runtimeAnimatorController.animationClips)
        {
            GPUSkinning_BoneAnimation boneAnimation = ScriptableObject.CreateInstance <GPUSkinning_BoneAnimation>();
            boneAnimation.fps      = 60;
            boneAnimation.animName = animClip.name;
            boneAnimation.frames   = new GPUSkinning_BoneAnimationFrame[(int)(animClip.length * boneAnimation.fps)];
            boneAnimation.length   = animClip.length;
            boneAnimations[boneAnimationsCount++] = boneAnimation;

            for (int frameIndex = 0; frameIndex < boneAnimation.frames.Length; ++frameIndex)
            {
                GPUSkinning_BoneAnimationFrame frame = new GPUSkinning_BoneAnimationFrame();
                boneAnimation.frames[frameIndex] = frame;
                float second = (float)(frameIndex) / (float)boneAnimation.fps;

                List <GPUSkinning_Bone> bones2              = new List <GPUSkinning_Bone>();
                List <Matrix4x4>        matrices            = new List <Matrix4x4>();
                List <string>           bonesHierarchyNames = null; if (boneAnimation.bonesHierarchyNames == null)
                {
                    bonesHierarchyNames = new List <string>();
                }
                EditorCurveBinding[] curvesBinding = AnimationUtility.GetCurveBindings(animClip);
                foreach (var curveBinding in curvesBinding)
                {
                    GPUSkinning_Bone bone = GetBoneByHierarchyName(curveBinding.path);

                    if (bones2.Contains(bone))
                    {
                        continue;
                    }
                    bones2.Add(bone);

                    if (bonesHierarchyNames != null)
                    {
                        bonesHierarchyNames.Add(GetBoneHierarchyName(bone));
                    }

                    AnimationCurve curveRX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.x");
                    AnimationCurve curveRY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.y");
                    AnimationCurve curveRZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.z");
                    AnimationCurve curveRW = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalRotation.w");

                    AnimationCurve curvePX = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.x");
                    AnimationCurve curvePY = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.y");
                    AnimationCurve curvePZ = AnimationUtility.GetEditorCurve(animClip, curveBinding.path, curveBinding.type, "m_LocalPosition.z");

                    float curveRX_v = curveRX.Evaluate(second);
                    float curveRY_v = curveRY.Evaluate(second);
                    float curveRZ_v = curveRZ.Evaluate(second);
                    float curveRW_v = curveRW.Evaluate(second);

                    float curvePX_v = curvePX.Evaluate(second);
                    float curvePY_v = curvePY.Evaluate(second);
                    float curvePZ_v = curvePZ.Evaluate(second);

                    Vector3    translation = new Vector3(curvePX_v, curvePY_v, curvePZ_v);
                    Quaternion rotation    = new Quaternion(curveRX_v, curveRY_v, curveRZ_v, curveRW_v);
                    NormalizeQuaternion(ref rotation);
                    matrices.Add(
                        Matrix4x4.TRS(translation, rotation, Vector3.one)
                        );
                }

                frame.bones    = bones2.ToArray();
                frame.matrices = matrices.ToArray();
                if (boneAnimation.bonesHierarchyNames == null)
                {
                    boneAnimation.bonesHierarchyNames = bonesHierarchyNames.ToArray();
                }
            }
        }
        AssetDatabase.CreateAsset(boneAnimations[0], "Assets/GPUSkinning/Resources/anim0.asset");
        AssetDatabase.Refresh();
#else
        // 直接读取序列化的骨骼动画数据
        boneAnimations = new GPUSkinning_BoneAnimation[] { Resources.Load("anim0") as GPUSkinning_BoneAnimation };
        foreach (var boneAnimation in boneAnimations)
        {
            foreach (var frame in boneAnimation.frames)
            {
                int numBones2 = boneAnimation.bonesHierarchyNames.Length;
                frame.bones = new GPUSkinning_Bone[numBones2];
                for (int i = 0; i < numBones2; ++i)
                {
                    frame.bones[i] = GetBoneByHierarchyName(boneAnimation.bonesHierarchyNames[i]);
                }
            }
        }
#endif

        // 创建出更多的角色模型
        if (spawnPoints != null)
        {
            List <GPUSkinning_SpawnObject> list = new List <GPUSkinning_SpawnObject>();
            for (int i = 0; i < spawnPoints.Length; ++i)
            {
                for (int j = 0; j < spawnPoints[i].childCount; ++j)
                {
                    GPUSkinning_SpawnObject spawnObject = new GPUSkinning_SpawnObject();
                    list.Add(spawnObject);
                    spawnObject.transform         = spawnPoints[i].GetChild(j);
                    spawnObject.mf                = spawnObject.transform.gameObject.AddComponent <MeshFilter>();
                    spawnObject.mr                = spawnObject.transform.gameObject.AddComponent <MeshRenderer>();
                    spawnObject.mr.sharedMaterial = newMtrl;
                    spawnObject.mf.sharedMesh     = newMesh;
                    if (additionalVertexStreames != null)
                    {
                        // 当开启 GPUInstancing 时,这个是不需要的,偷懒就直接设置了
                        spawnObject.mr.additionalVertexStreams = additionalVertexStreames[Random.Range(0, additionalVertexStreames.Length)];
                    }
                }
            }
            spawnObjects = list.ToArray();
        }

        // 销毁并暂停 Unity 的 Animator
        GameObject.Destroy(transform.FindChild("pelvis").gameObject);
        GameObject.Destroy(transform.FindChild("mutant_mesh").gameObject);
        Object.Destroy(gameObject.GetComponent <Animator>());

        smr.enabled = false;

        //PrintBones();

        CreateMatricesTexture();

        BakeAnimationsToTexture();

        SetPlayMode0();

        InitTerrain();

        SetTerrainHeightSwitch();

        InitGPUInstancing();

        InitComputeBuffer(newMesh);

        newMesh.UploadMeshData(true);
    }