Exemplo n.º 1
0
    private int GetNextGoodFrameIndex(int channel, int curFrame)
    {
        PS1AnimationChannel  ch    = anim.channels[channel];
        PS1AnimationKeyframe frame = ch.frames[curFrame];
        int skipFrames             = 0;

        while (frame.ntto < 0)
        {
            skipFrames++;
            if (skipFrames >= ch.frames.Length)
            {
                break;
            }
            frame = ch.frames[(curFrame + skipFrames) % ch.frames.Length];
        }
        if (skipFrames == ch.frames.Length)
        {
            return(-1);
        }
        return(skipFrames);
    }
Exemplo n.º 2
0
    public void UpdateAnimation()
    {
        if (IsLoaded && anim != null && channelObjects != null && subObjects != null && anim.num_frames != 0)
        {
            if (currentFrame >= anim.num_frames)
            {
                currentFrame %= anim.num_frames;
            }
            // First pass: reset TRS for all sub objects
            for (int i = 0; i < channelParents.Length; i++)
            {
                channelParents[i] = false;
            }
            // Create hierarchy for this frame
            for (int i = 0; i < anim.hierarchies.Length; i++)
            {
                PS1AnimationHierarchy h = anim.hierarchies[i];

                if (h.child > anim.channels.Length || h.parent > anim.channels.Length ||
                    h.child < 1 || h.parent < 1)
                {
                    continue;
                }
                int ch_child  = h.child - 1;
                int ch_parent = h.parent - 1;
                channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform);
                channelObjects[ch_child].transform.localPosition = Vector3.zero;
                channelObjects[ch_child].transform.localRotation = Quaternion.identity;
                channelObjects[ch_child].transform.localScale    = Vector3.one;
                channelParents[ch_child] = true;
            }
            PS1AnimationVector[]     animPositions = h.animPositions;
            PS1AnimationQuaternion[] animRotations = h.animRotations;
            PS1AnimationVector[]     animScales    = h.animScales;
            switch (anim.file_index)
            {
            case 1:
                animPositions = a1h?.animPositions;
                animRotations = a1h?.animRotations;
                animScales    = a1h?.animScales;
                break;

            case 2:
                animPositions = a2h?.animPositions;
                animRotations = a2h?.animRotations;
                animScales    = a2h?.animScales;
                break;
            }
            int[] channelNttoChanges = new int[anim.channels.Length];
            for (int i = 0; i < anim.channels.Length; i++)
            {
                PS1AnimationChannel ch = anim.channels[i];
                if (ch.frames.Length < 1)
                {
                    continue;
                }
                PS1AnimationKeyframe frame  = ch.frames[0];
                PS1AnimationKeyframe nextKF = null;

                int?posInd           = null;
                int?rotInd           = null;
                int?sclInd           = null;
                int curChannelFrame  = 0;
                int nextChannelFrame = 0;
                int curFrameIndex    = 0;

                channelNttoChanges[i] = -1;
                int?previousNtto = null;
                for (int f = 0; f < ch.frames.Length; f++)
                {
                    if (!ch.frames[f].ntto.HasValue || ch.frames[f].ntto >= 0 || ch.frames[f].ntto == -20)
                    {
                        if (!previousNtto.HasValue || previousNtto.Value != ch.frames[f].ntto)
                        {
                            channelNttoChanges[i]++;
                            previousNtto = ch.frames[f].ntto;
                        }
                        frame           = ch.frames[f];
                        curChannelFrame = nextChannelFrame;
                        curFrameIndex   = f;
                        if (frame.pos.HasValue)
                        {
                            posInd = frame.pos.Value;
                        }
                        if (frame.rot.HasValue)
                        {
                            rotInd = frame.rot.Value;
                        }
                        if (frame.scl.HasValue)
                        {
                            sclInd = frame.scl.Value;
                        }
                        nextChannelFrame++;
                        if (frame.extraDuration.HasValue && frame.extraDuration.Value > 0)
                        {
                            nextChannelFrame += frame.extraDuration.Value;
                        }
                        if (currentFrame < nextChannelFrame)
                        {
                            break;
                        }
                    }
                }
                if (frame.extraDuration.HasValue && frame.extraDuration.Value > 0 && curFrameIndex + 1 < ch.frames.Length)
                {
                    nextKF = ch.frames[curFrameIndex + 1];
                    //print(ch.frames[0].Offset);
                    if (nextKF.ntto.HasValue && (nextKF.ntto.Value < 0 && nextKF.ntto.Value != -20))
                    {
                        nextKF = ch.frames[curFrameIndex + 2];
                    }
                }
                float interpolation = 0f;

                if (nextKF != null)
                {
                    interpolation = (currentFrame - curChannelFrame) / (float)(nextChannelFrame - curChannelFrame);
                }

                if (currentActivePO[i] == -2)
                {
                    for (int j = 0; j < subObjectMorph[i].Length; j++)
                    {
                        GameObject morphGao = subObjectMorph[i][j];
                        if (morphGao != null && morphGao.activeSelf)
                        {
                            morphGao.SetActive(false);
                        }
                    }
                }

                if (!frame.ntto.HasValue || frame.ntto.Value >= 0 || frame.ntto.Value == -20)
                {
                    GameObject physicalObject = null;
                    short      poNum;
                    if (subObjectMorph?[i]?[currentFrame] != null)
                    {
                        physicalObject = subObjectMorph[i][currentFrame];
                        poNum          = -2;
                        physicalObject.SetActive(true);
                    }
                    else
                    {
                        poNum = (frame.ntto.HasValue && frame.ntto.Value != -20) ? frame.ntto.Value : (short)-1;
                        poNum = (short)Array.IndexOf(channelNTTO[i], poNum);

                        physicalObject = poNum >= 0 ? subObjects[i][poNum] : null;
                    }
                    if (poNum != currentActivePO[i])
                    {
                        if (currentActivePO[i] >= 0 && subObjects[i][currentActivePO[i]] != null)
                        {
                            subObjects[i][currentActivePO[i]].SetActive(false);
                        }
                        currentActivePO[i] = poNum;
                        if (physicalObject != null)
                        {
                            physicalObject.SetActive(true);
                        }
                    }
                    if (physicalObject != null)
                    {
                        if (frame.HasFlag(PS1AnimationKeyframe.AnimationFlags.FlipX))
                        {
                            physicalObject.transform.localScale = new Vector3(-1, 1, 1);
                        }
                        else
                        {
                            physicalObject.transform.localScale = Vector3.one;
                        }
                    }
                    if (!channelParents[i])
                    {
                        channelObjects[i].transform.SetParent(transform);
                    }


                    if (posInd.HasValue)
                    {
                        Vector3 pos = animPositions[posInd.Value].vector;
                        if (interpolation > 0f && nextKF.pos.HasValue)
                        {
                            pos = Vector3.Lerp(pos, animPositions[nextKF.pos.Value].vector, interpolation);
                        }
                        channelObjects[i].transform.localPosition = pos;
                    }
                    if (rotInd.HasValue)
                    {
                        Quaternion rot = animRotations[rotInd.Value].quaternion;
                        if (interpolation > 0f && nextKF.rot.HasValue)
                        {
                            rot = Quaternion.Lerp(rot, animRotations[nextKF.rot.Value].quaternion, interpolation);
                        }
                        channelObjects[i].transform.localRotation = rot;
                    }
                    if (sclInd.HasValue)
                    {
                        Vector3 scl = animScales[sclInd.Value].GetVector(factor: 256f * 16f);
                        if (interpolation > 0f && nextKF.scl.HasValue)
                        {
                            scl = Vector3.Lerp(scl, animScales[nextKF.scl.Value].GetVector(factor: 256f * 16f), interpolation);
                        }


                        /*scl = new Vector3(
                         *      1f / (scl.x != 0f ? scl.x : 256f),
                         *      1f / (scl.y != 0f ? scl.y : 256f),
                         *      1f / (scl.z != 0f ? scl.z : 256f));*/
                        channelObjects[i].transform.localScale = scl;
                    }
                }
                else
                {
                    switch (frame.ntto.Value)
                    {
                    case -13:
                        // morph
                        break;

                    case -9:
                        // 6
                        break;

                    case -8:
                        break;

                    case -7:
                        // 5
                        break;

                    case -6:
                        // 4
                        break;

                    case -5:
                        // 3
                        break;

                    case -4:
                        // 2
                        break;

                    case -3:
                        // sound event related. extraDuration is sound bank
                        break;

                    case -2:
                        // 1
                        break;

                    case -1:
                        break;
                    }
                }

                /*if (frame.pos.HasValue) {
                 *      channelObjects[i].transform.localPosition = h.animPositions[frame.pos.Value].vector;
                 * }
                 * if (frame.rot.HasValue) {
                 *      channelObjects[i].transform.localRotation = h.quaternions[frame.rot.Value].quaternion;
                 * }
                 * if (frame.scl.HasValue) {
                 *      Vector3 v = h.animScales[frame.scl.Value].vector;
                 *      v = new Vector3(
                 *              (1 / 256f) * (v.x != 0f ? v.x : 256f),
                 *              (1 / 256f) * (v.y != 0f ? v.y : 256f),
                 *              (1 / 256f) * (v.z != 0f ? v.z : 256f));
                 *      channelObjects[i].transform.localScale = v;
                 * }*/
            }

            if (hasBones && anim.bones?.Length > 0)
            {
                for (int i = 0; i < anim.channels.Length; i++)
                {
                    if (currentActivePO[i] >= 0 && subObjectBones[i][currentActivePO[i]] != null)
                    {
                        GameObject[] bones      = subObjectBones[i][currentActivePO[i]];
                        int          bonesIndex = Array.FindIndex(anim.bones, b => b.ind_ntto_channel == i);
                        if (bonesIndex != -1)
                        {
                            int curFrameIndex = bonesIndex + (channelNttoChanges[i] >= 0 ? channelNttoChanges[i] : 0);
                            PS1AnimationBoneChannelLinks b = anim.bones[curFrameIndex];
                            if (b.ind_ntto_channel != i)
                            {
                                print("Channel did not match!");
                            }
                            ushort[] indices = b.indices;
                            for (int j = 1; j < bones.Length; j++)
                            {
                                bones[j].transform.SetParent(channelObjects[indices[j - 1]].transform);
                                bones[j].transform.localPosition = Vector3.zero;
                                bones[j].transform.localRotation = Quaternion.identity;
                                bones[j].transform.localScale    = Vector3.one;
                            }
                        }
                    }
                }
            }
        }
    }
Exemplo n.º 3
0
    void InitAnimation()
    {
        if (forceAnimUpdate)
        {
            forceAnimUpdate = false;
            DeinitAnimation();
            // Init animation
            if (anim != null)
            {
                //animationSpeed = a3d.speed;
                // Init channels & subobjects
                subObjects     = new GameObject[anim.num_channels][];
                channelObjects = new GameObject[anim.num_channels];
                subObjectBones = new GameObject[anim.num_channels][][];
                subObjectMorph = new GameObject[anim.num_channels][];
                //if (anim.a3d.num_morphData > 0) fullMorphPOs = new Dictionary<ushort, GameObject>[anim.a3d.num_channels];
                currentActivePO = new int[anim.num_channels];
                channelParents  = new bool[anim.num_channels];
                channelNTTO     = new short[anim.num_channels][];
                for (int i = 0; i < anim.num_channels; i++)
                {
                    PS1AnimationChannel ch = anim.channels[i];
                    short id = ch.id;
                    channelObjects[i] = new GameObject("Channel " + id + " - " + ch.Offset);
                    channelObjects[i].transform.SetParent(transform);
                    channelObjects[i].transform.localPosition = Vector3.zero;

                    currentActivePO[i] = -1;
                    AddChannelID(id, i);
                    channelNTTO[i]    = ch.frames?.SelectMany(f => (f.ntto != null && f.ntto >= 1) ? new short[] { f.ntto.Value } : new short[0]).Distinct().ToArray();
                    subObjects[i]     = new GameObject[channelNTTO[i] != null ? channelNTTO[i].Length : 0];
                    subObjectBones[i] = new GameObject[subObjects[i].Length][];
                    subObjectMorph[i] = new GameObject[anim.num_frames];
                    ObjectsTable geometricObjectsDynamic = h.geometricObjectsDynamic;
                    switch (anim.file_index)
                    {
                    case 1: geometricObjectsDynamic = a1h?.geometricObjectsDynamic; break;

                    case 2: geometricObjectsDynamic = a2h?.geometricObjectsDynamic; break;
                    }
                    for (int k = 0; k < subObjects[i].Length; k++)
                    {
                        int j = (int)channelNTTO[i][k] - 1;
                        if (j == 0xFFFF || j < 0 || j > geometricObjectsDynamic.length.Value)
                        {
                            subObjects[i][k] = new GameObject();
                            subObjects[i][k].transform.parent = channelObjects[i].transform;
                            subObjects[i][k].name             = "[" + j + "] Invisible NTTO";
                            subObjects[i][k].SetActive(false);
                        }
                        else
                        {
                            GameObject[] bones = null;
                            GameObject   c     = geometricObjectsDynamic.GetGameObject(j, perso.p3dData?.collisionMapping, out bones);
                            if (c != null)
                            {
                                //GeometricObject geo = geometricObjectsDynamic.entries[j].geo;
                                if (Settings.s.hasDeformations && bones != null)
                                {
                                    subObjectBones[i][k] = bones;
                                    hasBones             = true;
                                }
                            }
                            subObjects[i][k] = c;

                            /*if (entry.scale.HasValue) {
                             *      objectIndexScales[ntto.object_index] = new Vector3(entry.scale.Value.x, entry.scale.Value.z, entry.scale.Value.y);
                             *      subObjects[i][j].transform.localScale = objectIndexScales[ntto.object_index];
                             * }*/
                            c.transform.parent = channelObjects[i].transform;
                            c.name             = "[" + j + "] " + c.name;
                            c.SetActive(false);
                        }
                        subObjects[i][k].transform.localPosition = Vector3.zero;
                        subObjects[i][k].transform.localRotation = Quaternion.identity;
                        subObjects[i][k].transform.localScale    = Vector3.one;
                    }

                    // Calculate morph objects
                    int nextChannelFrame = 0;
                    int curChannelFrame  = 0;
                    for (int f = 0; f < ch.frames.Length; f++)
                    {
                        if (!ch.frames[f].ntto.HasValue || ch.frames[f].ntto >= 0 || ch.frames[f].ntto == -20)
                        {
                            PS1AnimationKeyframe frame = ch.frames[f];
                            curChannelFrame = nextChannelFrame;
                            nextChannelFrame++;
                            if (frame.extraDuration.HasValue && frame.extraDuration.Value > 0)
                            {
                                nextChannelFrame += frame.extraDuration.Value;
                            }
                            int curFrameIndex           = f;
                            PS1AnimationKeyframe nextKF = null;
                            if (frame.extraDuration.HasValue && frame.extraDuration.Value > 0 && curFrameIndex + 1 < ch.frames.Length)
                            {
                                nextKF = ch.frames[curFrameIndex + 1];
                                //print(ch.frames[0].Offset);
                                if (nextKF.ntto.HasValue && (nextKF.ntto.Value < 0 && nextKF.ntto.Value != -20))
                                {
                                    nextKF = ch.frames[curFrameIndex + 2];
                                }
                            }
                            if (ch.frames[f].HasFlag(PS1AnimationKeyframe.AnimationFlags.Morph) && ch.frames[f].HasFlag(PS1AnimationKeyframe.AnimationFlags.NTTO))
                            {
                                int j      = ch.frames[f].ntto.Value - 1;
                                int morphJ = ch.frames[f].morphNTTO.Value - 1;
                                if (j < 0 || j > geometricObjectsDynamic.length.Value || morphJ < 0 || morphJ > geometricObjectsDynamic.length.Value)
                                {
                                }
                                else
                                {
                                    int duration = nextChannelFrame - curChannelFrame;
                                    if (duration < 2 || nextKF == null || nextKF.ntto != frame.ntto || nextKF.morphNTTO != frame.morphNTTO || nextKF.morphProgress == frame.morphProgress)
                                    {
                                        if (frame.morphProgress.Value == 0)
                                        {
                                            continue;
                                        }
                                        float      morphProgress = frame.morphProgress.Value / 100f;
                                        GameObject c             = geometricObjectsDynamic.GetGameObject(j, perso.p3dData?.collisionMapping, out _, morphI: morphJ, morphProgress: morphProgress);
                                        for (int d = 0; d < duration; d++)
                                        {
                                            subObjectMorph[i][curChannelFrame + d] = c;
                                        }
                                        c.transform.parent = channelObjects[i].transform;
                                        c.name             = "[" + j + "] " + c.name + " - " + morphJ;
                                        c.SetActive(false);
                                        c.transform.localPosition = Vector3.zero;
                                        c.transform.localRotation = Quaternion.identity;
                                        c.transform.localScale    = Vector3.one;
                                    }
                                    else
                                    {
                                        for (int d = 0; d < duration; d++)
                                        {
                                            float      interpolation = d / (float)duration;
                                            float      morphProgress = Mathf.Lerp(frame.morphProgress.Value / 100f, nextKF.morphProgress.Value / 100f, interpolation);
                                            GameObject c             = geometricObjectsDynamic.GetGameObject(j, perso.p3dData?.collisionMapping, out _, morphI: morphJ, morphProgress: morphProgress);
                                            subObjectMorph[i][curChannelFrame + d] = c;
                                            c.transform.parent = channelObjects[i].transform;
                                            c.SetActive(false);
                                            c.transform.localPosition = Vector3.zero;
                                            c.transform.localRotation = Quaternion.identity;
                                            c.transform.localScale    = Vector3.one;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }


                // Keep lighting last so that it is applied to all new sub objects

                /*if (!isAlways) {
                 *      controller.sectorManager.ApplySectorLighting(sector, gameObject, OpenSpace.Visual.LightInfo.ObjectLightedFlag.Perso);
                 * } else {
                 *      controller.sectorManager.ApplySectorLighting(sector, gameObject, OpenSpace.Visual.LightInfo.ObjectLightedFlag.None);
                 * }*/
            }
            IsLoaded = true;
        }
    }