Esempio n. 1
0
        public async Task LoadAnims()
        {
            // Read anims.bin
            Reader reader = files_array[SMem.Anims].reader;

            loadingState = "Loading animations";
            await WaitIfNecessary();

            uint num_anims = reader.ReadUInt32();

            reader.ReadUInt32();
            reader.ReadUInt32();
            reader.ReadUInt32();
            Pointer eof = null;

            romAnims = new ROMAnimation[num_anims];
            for (uint i = 0; i < num_anims; i++)
            {
                uint offset = reader.ReadUInt32();
                romAnims[i] = new ROMAnimation()
                {
                    compressed = (offset & 0x80000000) == 0x80000000,
                    index      = i
                };
                romAnims[i].Init(new Pointer(offset & 0x7FFFFFFF, files_array[SMem.Anims]));
                if (i > 0)
                {
                    romAnims[i - 1].compressedSize = romAnims[i].Offset.offset - romAnims[i - 1].Offset.offset;
                }
            }
            eof = new Pointer(reader.ReadUInt32(), files_array[SMem.Anims]);             // EOF
            if (num_anims > 0)
            {
                romAnims[num_anims - 1].compressedSize = eof.offset - romAnims[num_anims - 1].Offset.offset;
            }
            for (uint i = 0; i < num_anims; i++)
            {
                romAnims[i].Read(reader);
            }

            // Read shAnims.bin
            reader = files_array[SMem.ShAnims].reader;
            List <ROMShAnimation> shAnimsList = new List <ROMShAnimation>();

            while (reader.BaseStream.Position < reader.BaseStream.Length)
            {
                ROMShAnimation shAnim = new ROMShAnimation();
                shAnim.Init(Pointer.Current(reader));
                shAnim.Read(reader, true);
                shAnimsList.Add(shAnim);
            }
            shAnims = shAnimsList.ToArray();

            // Read cuttable.bin
            reader   = files_array[SMem.CutTable].reader;
            cutTable = new ROMAnimationCutTable();
            cutTable.Init(Pointer.Current(reader));
            cutTable.length = (ushort)num_anims;
            cutTable.Read(reader, true);
        }
Esempio n. 2
0
    public void UpdateAnimation()
    {
        if (IsLoaded && shAnim != null && animCuts != null && animCuts.Length > 0 && channelObjects != null && subObjects != null)
        {
            if (currentFrame >= shAnim.num_frames)
            {
                currentFrame %= shAnim.num_frames;
            }
            UpdateAnimationCut();
            // First pass: reset TRS for all sub objects
            for (int i = 0; i < channelParents[currentAnimCut].Length; i++)
            {
                channelParents[currentAnimCut][i] = false;
            }
            ROMAnimation  anim = ROMStruct.Loader.romAnims[animCuts[currentAnimCut].index];
            uint          currentRelativeFrame = currentFrame - anim.a3d.this_start_onlyFrames;
            AnimOnlyFrame of = anim.onlyFrames[currentRelativeFrame];
            // Create hierarchy for this frame
            for (int i = of.start_hierarchies_for_frame;
                 i < of.start_hierarchies_for_frame + of.num_hierarchies_for_frame; i++)
            {
                AnimHierarchy h = anim.hierarchies[i];

                if (!channelIDDictionary[currentAnimCut].ContainsKey(h.childChannelID) || !channelIDDictionary[currentAnimCut].ContainsKey(h.parentChannelID))
                {
                    continue;
                }
                List <int> ch_child_list  = GetChannelByID(h.childChannelID);
                List <int> ch_parent_list = GetChannelByID(h.parentChannelID);
                foreach (int ch_child in ch_child_list)
                {
                    foreach (int ch_parent in ch_parent_list)
                    {
                        channelObjects[currentAnimCut][ch_child].transform.SetParent(channelObjects[currentAnimCut][ch_parent].transform);
                        channelParents[currentAnimCut][ch_child] = true;
                    }
                }

                //channelObjects[ch_child].transform.SetParent(channelObjects[ch_parent].transform);
            }

            // Final pass
            int currentKFIndex = 0;
            for (int i = 0; i < anim.channels.Length; i++)
            {
                AnimChannel ch = anim.channels[i];

                // Select keyframe
                AnimKeyframe kf = null;
                int          selectedKFindex = 0;
                for (int k = 0; k < ch.num_keyframes; k++)
                {
                    if (anim.keyframes[currentKFIndex + k].frame <= currentFrame)
                    {
                        kf = anim.keyframes[currentKFIndex + k];
                        selectedKFindex = k;
                    }
                    else
                    {
                        break;
                    }
                }
                AnimVector     pos            = anim.vectors[kf.positionVector];
                AnimQuaternion qua            = anim.quaternions[kf.quaternion];
                AnimVector     scl            = anim.vectors[kf.scaleVector];
                AnimNumOfNTTO  numOfNTTO      = anim.numOfNTTO[(i * anim.a3d.num_numNTTO) + of.numOfNTTO];
                AnimNTTO       ntto           = null;
                int            poNum          = -1;
                GameObject     physicalObject = null;
                if (numOfNTTO.numOfNTTO != 0xFFFF)
                {
                    poNum          = numOfNTTO.numOfNTTO;
                    ntto           = anim.ntto[poNum];
                    physicalObject = subObjects[currentAnimCut][i][poNum];
                }
                Vector3      vector        = pos.vector;
                Quaternion   quaternion    = qua.quaternion;
                Vector3      scale         = scl.vector;
                int          framesSinceKF = (int)currentFrame - (int)kf.frame;
                AnimKeyframe nextKF        = null;
                int          framesDifference;
                float        interpolation;
                if (selectedKFindex == ch.num_keyframes - 1)
                {
                    nextKF           = anim.keyframes[currentKFIndex];
                    framesDifference = anim.a3d.total_num_onlyFrames - 1 + (int)nextKF.frame - (int)kf.frame;
                    if (framesDifference == 0)
                    {
                        interpolation = 0;
                    }
                    else
                    {
                        //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor);
                        interpolation = framesSinceKF / (float)framesDifference;
                    }
                }
                else
                {
                    nextKF           = anim.keyframes[currentKFIndex + selectedKFindex + 1];
                    framesDifference = (int)nextKF.frame - (int)kf.frame;
                    //interpolation = (float)(nextKF.interpolationFactor * (framesSinceKF / (float)framesDifference) + 1.0 * nextKF.interpolationFactor);
                    interpolation = framesSinceKF / (float)framesDifference;
                }

                currentKFIndex += ch.num_keyframes;


                //print(interpolation);
                //print(a3d.vectors.Length + " - " + nextKF.positionVector);
                //print(perso.p3dData.family.animBank);
                AnimVector     pos2 = anim.vectors[nextKF.positionVector];
                AnimQuaternion qua2 = anim.quaternions[nextKF.quaternion];
                AnimVector     scl2 = anim.vectors[nextKF.scaleVector];
                vector     = Vector3.Lerp(pos.vector, pos2.vector, interpolation);
                quaternion = Quaternion.Lerp(qua.quaternion, qua2.quaternion, interpolation);
                scale      = Vector3.Lerp(scl.vector, scl2.vector, interpolation);
                //float positionMultiplier = Mathf.Lerp(kf.positionMultiplier, nextKF.positionMultiplier, interpolation);

                if (poNum != currentActivePO[currentAnimCut][i])
                {
                    if (currentActivePO[currentAnimCut][i] == -2 && fullMorphPOs[currentAnimCut] != null && fullMorphPOs[currentAnimCut][i] != null)
                    {
                        foreach (GameObject morphPO in fullMorphPOs[currentAnimCut][i].Values)
                        {
                            if (morphPO.activeSelf)
                            {
                                morphPO.SetActive(false);
                            }
                        }
                    }
                    if (currentActivePO[currentAnimCut][i] >= 0 && subObjects[currentAnimCut][i][currentActivePO[currentAnimCut][i]] != null)
                    {
                        subObjects[currentAnimCut][i][currentActivePO[currentAnimCut][i]].SetActive(false);
                    }
                    currentActivePO[currentAnimCut][i] = poNum;
                    if (physicalObject != null)
                    {
                        physicalObject.SetActive(true);
                    }
                }
                if (!channelParents[currentAnimCut][i])
                {
                    channelObjects[currentAnimCut][i].transform.SetParent(transform);
                }
                channelObjects[currentAnimCut][i].transform.localPosition = vector;                // * positionMultiplier;
                channelObjects[currentAnimCut][i].transform.localRotation = quaternion;
                channelObjects[currentAnimCut][i].transform.localScale    = scale;

                if (physicalObject != null &&
                    anim.a3d.num_morphData > 0 &&
                    morphDataArray[currentAnimCut] != null &&
                    i < morphDataArray[currentAnimCut].GetLength(0) &&
                    currentRelativeFrame < morphDataArray[currentAnimCut].GetLength(1))
                {
                    AnimMorphData   morphData = morphDataArray[currentAnimCut][i, currentRelativeFrame];
                    GeometricObject ogPO      = perso.p3dData.Value.objectsTable.Value.data.Value.entries[anim.ntto[poNum].object_index].obj.Value.visual.Value;
                    if (morphData != null && morphData.morphProgress != 0 && morphData.morphProgress != 100)
                    {
                        //print("morphing " + physicalObject.name);
                        GeometricObject morphToPO = perso.p3dData.Value.objectsTable.Value.data.Value.entries[morphData.objectIndexTo].obj.Value.visual.Value;
                        ogPO.MorphVertices(physicalObject, morphToPO, morphData.morphProgress / 100f);
                    }
                    else if (morphData != null && morphData.morphProgress == 100)
                    {
                        physicalObject.SetActive(false);
                        GameObject c = fullMorphPOs[currentAnimCut][i][morphData.objectIndexTo];
                        c.transform.localScale    = objectIndexScales.ContainsKey(morphData.objectIndexTo) ? objectIndexScales[morphData.objectIndexTo] : Vector3.one;
                        c.transform.localPosition = Vector3.zero;
                        c.transform.localRotation = Quaternion.identity;
                        c.SetActive(true);
                        currentActivePO[currentAnimCut][i] = -2;
                    }
                    else
                    {
                        ogPO.ResetMorph(physicalObject);
                    }
                }
            }
        }
    }
Esempio n. 3
0
    void SwitchAnimationCut(int newAnimCut)
    {
        if (currentAnimCut != newAnimCut || forceAnimUpdate)
        {
            forceAnimUpdate = false;
            // Init animation
            this.currentAnimCut = newAnimCut;

            ROMAnimation anim   = ROMStruct.Loader.romAnims[animCuts[currentAnimCut].index];
            bool         newCut = subObjects[currentAnimCut] == null;
            if (anim != null && newCut)
            {
                //animationSpeed = a3d.speed;
                // Init channels & subobjects
                channelObjects[currentAnimCut]  = new GameObject[anim.a3d.num_channels];
                currentActivePO[currentAnimCut] = new int[anim.a3d.num_channels];
                channelParents[currentAnimCut]  = new bool[anim.a3d.num_channels];
                subObjects[currentAnimCut]      = new GameObject[anim.a3d.num_channels][];
                if (anim.a3d.num_morphData > 0)
                {
                    fullMorphPOs[currentAnimCut] = new Dictionary <ushort, GameObject> [anim.a3d.num_channels];
                }
                for (int i = 0; i < anim.a3d.num_channels; i++)
                {
                    short id = anim.channels[i].id;
                    channelObjects[currentAnimCut][i] = new GameObject($"[Cut {currentAnimCut}] Channel {id}");
                    channelObjects[currentAnimCut][i].transform.SetParent(transform);
                    currentActivePO[currentAnimCut][i] = -1;
                    AddChannelID(id, i);
                    if (newCut)
                    {
                        subObjects[currentAnimCut][i] = new GameObject[anim.a3d.num_NTTO];
                    }
                    AnimChannel   ch = anim.channels[i];
                    List <ushort> listOfNTTOforChannel = new List <ushort>();
                    for (int j = 0; j < anim.onlyFrames.Length; j++)
                    {
                        AnimOnlyFrame of = anim.onlyFrames[j];
                        //print(ch.numOfNTTO + " - " + of.numOfNTTO + " - " + a3d.numOfNTTO.Length);
                        AnimNumOfNTTO numOfNTTO = anim.numOfNTTO[(i * anim.a3d.num_numNTTO) + of.numOfNTTO];
                        if (!listOfNTTOforChannel.Contains(numOfNTTO.numOfNTTO) && numOfNTTO.numOfNTTO != 0xFFFF)
                        {
                            listOfNTTOforChannel.Add(numOfNTTO.numOfNTTO);
                        }
                    }
                    if (newCut)
                    {
                        for (int k = 0; k < listOfNTTOforChannel.Count; k++)
                        {
                            int      j    = listOfNTTOforChannel[k];
                            AnimNTTO ntto = anim.ntto[j];
                            if (ntto.IsInvisibleNTTO)
                            {
                                subObjects[currentAnimCut][i][j] = new GameObject();
                                subObjects[currentAnimCut][i][j].transform.parent = channelObjects[currentAnimCut][i].transform;
                                subObjects[currentAnimCut][i][j].name             = "[" + j + "] Invisible NTTO";
                                subObjects[currentAnimCut][i][j].SetActive(false);
                            }
                            else
                            {
                                if (perso.p3dData.Value.objectsTable.Value != null &&
                                    perso.p3dData.Value.objectsTable.Value.length > ntto.object_index)
                                {
                                    ObjectsTableData.Entry entry = perso.p3dData.Value.objectsTable.Value.data.Value.entries[ntto.object_index];
                                    PhysicalObject         o     = entry.obj.Value;
                                    if (o != null)
                                    {
                                        //if (o.visualSetType == 1) print(name);
                                        GameObject c = o.GetGameObject().gameObject;
                                        subObjects[currentAnimCut][i][j] = c;
                                        if (entry.scale.HasValue)
                                        {
                                            objectIndexScales[ntto.object_index] = new Vector3(entry.scale.Value.x, entry.scale.Value.z, entry.scale.Value.y);
                                            subObjects[currentAnimCut][i][j].transform.localScale = objectIndexScales[ntto.object_index];
                                        }
                                        c.transform.parent = channelObjects[currentAnimCut][i].transform;
                                        c.name             = "[" + j + "] " + c.name;
                                        c.SetActive(false);
                                    }
                                }
                            }
                        }
                    }
                }


                if (anim.a3d.num_morphData > 0 && anim.morphData != null)
                {
                    morphDataArray[currentAnimCut] = new AnimMorphData[anim.channels.Length, anim.onlyFrames.Length];
                    // Iterate over morph data to find the correct channel and keyframe
                    for (int i = 0; i < anim.a3d.num_morphData; i++)
                    {
                        AnimMorphData m = anim.morphData[i];
                        if (m != null)
                        {
                            /*print("F:" + a3d.num_onlyFrames + " - C:" + a3d.num_channels + " - CF" + (a3d.num_onlyFrames * a3d.num_channels) + " - " +
                             *      m.channel + " - " + m.frame + " - " + m.morphProgress + " - " + m.objectIndexTo + " - " + m.byte5 + " - " + m.byte6 + " - " + m.byte7);*/
                            int channelIndex = this.GetChannelByID(m.channel)[0];
                            if (channelIndex < morphDataArray[currentAnimCut].GetLength(0) && m.frame < morphDataArray[currentAnimCut].GetLength(1))
                            {
                                morphDataArray[currentAnimCut][channelIndex, m.frame] = m;
                                if (m.morphProgress == 100 && perso.p3dData.Value.objectsTable.Value != null &&
                                    perso.p3dData.Value.objectsTable.Value.length > m.objectIndexTo)
                                {
                                    if (fullMorphPOs[currentAnimCut][channelIndex] == null)
                                    {
                                        fullMorphPOs[currentAnimCut][channelIndex] = new Dictionary <ushort, GameObject>();
                                    }
                                    if (!fullMorphPOs[currentAnimCut][channelIndex].ContainsKey(m.objectIndexTo))
                                    {
                                        ObjectsTableData.Entry entry = perso.p3dData.Value.objectsTable.Value.data.Value.entries[m.objectIndexTo];
                                        PhysicalObject         o     = entry.obj.Value;
                                        if (o != null)
                                        {
                                            //if (o.visualSetType == 1) print(name);
                                            GameObject c = o.GetGameObject().gameObject;
                                            fullMorphPOs[currentAnimCut][channelIndex][m.objectIndexTo] = c;
                                            if (entry.scale.HasValue)
                                            {
                                                objectIndexScales[m.objectIndexTo] = new Vector3(entry.scale.Value.x, entry.scale.Value.z, entry.scale.Value.y);
                                                c.transform.localScale             = objectIndexScales[m.objectIndexTo];
                                            }

                                            /*subObjects[i][j].transform.localScale =
                                             *      subObjects[i][j].scaleMultiplier.HasValue ? subObjects[i][j].scaleMultiplier.Value : Vector3.one;*/
                                            c.transform.parent = channelObjects[currentAnimCut][channelIndex].transform;
                                            c.name             = "[Morph] " + c.name;
                                            c.SetActive(false);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    morphDataArray = null;
                }

                // 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);
                }
            }
            if (channelObjects != null)
            {
                for (int i = 0; i < animCuts.Length; i++)
                {
                    if (channelObjects[i] != null)
                    {
                        if (currentAnimCut == i)
                        {
                            foreach (GameObject g in channelObjects[i])
                            {
                                g.SetActive(true);
                            }
                        }
                        else
                        {
                            foreach (GameObject g in channelObjects[i])
                            {
                                g.SetActive(false);
                            }
                        }
                    }
                }
            }
            IsLoaded = true;
        }
    }