예제 #1
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;
        }
    }
예제 #2
0
        // TODO: Clean up this method, split in smaller parts, update it as more info is available
        private bool Read(BinaryReader br)
        {
            try
            {
                Header header = new Header();
                header.Read(br);
                NodesTree nodesTree = new NodesTree();
                nodesTree.Read(br);
                Name = nodesTree.name;
                br.BaseStream.Seek(header.ContentsTableOffset, SeekOrigin.Begin);
                ContentsTable contentsTable = new ContentsTable();
                contentsTable.Read(br);
                MaterialsHeader materialsHeader = new MaterialsHeader();
                materialsHeader.Read(br);
                ObjectsTable objectsTable = new ObjectsTable();
                objectsTable.SetCount(contentsTable.objectsCount);
                objectsTable.Read(br);
                SubObjectsTable subObjectsTable = new SubObjectsTable();
                subObjectsTable.SetCount(contentsTable.subObjectsCount);
                subObjectsTable.Read(br);

                // In theory, it could be read all the data from current stream position
                //      but it would be safer to read by using the already read offsets

                // Read the materials table
                MaterialsTable materialsTable = new MaterialsTable();
                materialsTable.SetCount(materialsHeader.materialsCount);
                br.BaseStream.Seek(materialsHeader.materialsTableOffset, SeekOrigin.Begin);
                materialsTable.Read(br);
                // Build the materials list
                for (int i = 0; i < materialsTable.GetCount(); i++)
                {
                    Material mat = materialsTable[i].GetMaterial(br);
                    Materials.Add(mat);
                }

                // TODO: Read data for all the subobjects


                // Read data for all the objects
                for (int i = 0; i < objectsTable.GetCount(); i++)
                {
                    Model model = new Model();
                    br.BaseStream.Seek(objectsTable[i].nameAddress, SeekOrigin.Begin);
                    model.name = Text.ReadText(br);
                    if (objectsTable[i].materialDefsAddress != null && objectsTable[i].materialDefsCount > 0)
                    {
                        br.BaseStream.Seek(objectsTable[i].materialDefsAddress.Value, SeekOrigin.Begin);
                        MaterialDef matDef = new MaterialDef();
                        matDef.Read(br);
                        model.materialIndices = matDef.materialIndices;
                    }
                    if (objectsTable[i].childDefsAddress != null && objectsTable[i].childsDefsCount > 0)
                    {
                        br.BaseStream.Seek(objectsTable[i].childDefsAddress.Value, SeekOrigin.Begin);
                        ChildsDef childsDef = new ChildsDef();
                        childsDef.SetCount(objectsTable[i].childsDefsCount);
                        childsDef.Read(br);
                        // TODO: Decide how to add it to the model
                    }
                    if (objectsTable[i].data1Address != null && objectsTable[i].data1Count > 0)
                    {
                        List <int> meshesAddress = new List <int>();
                        br.BaseStream.Seek(objectsTable[i].data1Address.Value, SeekOrigin.Begin);
                        for (int j = 0; j < objectsTable[i].data1Count; j++)
                        {
                            int address = (int)ReadRelativeOffset(br);
                            meshesAddress.Add(address);
                        }
                        for (int j = 0; j < objectsTable[i].data1Count; j++)
                        {
                            br.BaseStream.Seek(meshesAddress[j], SeekOrigin.Begin);
                            Def def = new Def();
                            if (!def.Read(br))
                            {
                                return(false);
                            }
                            if (def.nextChunk != null && def.nextChunk is MeshDef)
                            {
                                MeshDef md = (MeshDef)def.nextChunk;
                                for (int k = 0; k < md.meshesData.Count; k++)
                                {
                                    MeshData data = md.meshesData[k];
                                    Mesh     mesh = new Mesh(data.boundingBox, data.vertices, data.triangles, data.textureVertices);
                                    model.meshes.Add(mesh);
                                }
                            }
                        }
                    }
                    Models.Add(model);
                }
            }
            catch
            {
                // TODO: Handle here any error reading
                return(false);
            }
            return(true);
        }
예제 #3
0
    // Update is called once per frame
    void Update()
    {
        if (IsLoaded)
        {
            if (hasStates)
            {
                if (stateIndex != currentState)
                {
                    currentState = stateIndex;
                    SetState(currentState);
                }
            }
            MapLoader l = MapLoader.Loader;
            if (poListIndex != currentPOList && perso.p3dData != null)
            {
                if (poListIndex > 0 && poListIndex < poListNames.Length + 1)
                {
                    currentPOList = poListIndex;
                    ObjectsTable newOT = ROMStruct.Loader.objectsTables[currentPOList - 1];
                    perso.p3dData.Value.objectsTable = new Reference <ObjectsTable>(newOT.Index, newOT);
                }
                else
                {
                    poListIndex   = 0;
                    currentPOList = 0;
                    perso.p3dData.Value.objectsTable = new Reference <ObjectsTable>();
                }
                forceAnimUpdate = true;
                SetState(currentState);
            }
        }
        if (!IsLoaded || !(controller.LoadState == Controller.State.Finished || controller.LoadState == Controller.State.Error))
        {
            return;
        }
        bool sectorActive = false, insideSectors = false;

        if (sector == null || IsAlways || AlwaysPlayAnimation || sector.Loaded)
        {
            sectorActive = true;
        }
        if (sector == null || IsAlways || AlwaysPlayAnimation || controller.sectorManager.activeSector != null)
        {
            insideSectors = true;
        }
        if (controller.playAnimations && playAnimation && sectorActive)
        {
            updateCounter += Time.deltaTime * animationSpeed;
            // If the camera is not inside a sector, animations will only update 1 out of 2 times (w/ frameskip) to avoid lag
            if ((!insideSectors && updateCounter >= 2f) || (insideSectors && updateCounter >= 1f))
            {
                uint passedFrames = (uint)Mathf.FloorToInt(updateCounter);
                updateCounter %= 1;
                currentFrame  += passedFrames;
                if (shAnim != null && currentFrame >= shAnim.num_frames)
                {
                    if (autoNextState)
                    {
                        ROMShAnimation prevshAnim = shAnim;
                        GotoAutoNextState();
                        if (shAnim == prevshAnim)
                        {
                            currentFrame = currentFrame % shAnim.num_frames;
                            UpdateAnimation();
                        }
                    }
                    else
                    {
                        currentFrame = currentFrame % shAnim.num_frames;
                        UpdateAnimation();
                    }
                }
                else
                {
                    UpdateAnimation();
                }
            }
        }
    }
예제 #4
0
        public async Task LoadData()
        {
            Reader reader = files_array[SMem.Data].reader;

            if (exportTextures)
            {
                string state = loadingState;
                loadingState = "Exporting textures";
                await WaitIfNecessary();

                ExportTextures(reader);
                loadingState = state;
                await WaitIfNecessary();

                return;
            }

            // Load current level data
            loadingState = "Loading level data";
            await WaitIfNecessary();

            LevelHeader lh = GetOrRead <LevelHeader>(reader, (ushort)(CurrentLevel | (ushort)FATEntry.Flag.Fix));

            level        = lh;
            loadingState = "Loading additional object lists";
            await WaitIfNecessary();

            for (ushort i = 0; i < 0x7FFF; i++)
            {
                // Only do it a few times because we're trying to load way more than there is,
                // so it takes really long if we yield for everything
                if (i % 4096 == 0)
                {
                    loadingState = "Loading additional object lists: " + (i + 1);
                    await WaitIfNecessary();
                }
                ObjectsTable ot = GetOrRead <ObjectsTable>(reader, (ushort)(i | (ushort)FATEntry.Flag.Fix));
                if (ot != null)
                {
                    objectsTables.Add(ot);
                }
            }
            for (ushort i = 0; i < 0x8000; i++)
            {
                // Only do it a few times because we're trying to load way more than there is,
                // so it takes really long if we yield for everything
                if (i % 4096 == 0)
                {
                    loadingState = "Loading additional object lists: " + (i + 1);
                    await WaitIfNecessary();
                }
                ObjectsTable ot = GetOrRead <ObjectsTable>(reader, i);
                if (ot != null)
                {
                    objectsTables.Add(ot);
                }
            }

            for (ushort i = 0; i < 0x7FFF; i++)
            {
                // Only do it a few times because we're trying to load way more than there is,
                // so it takes really long if we yield for everything
                if (i % 4096 == 0)
                {
                    loadingState = "Loading waypoints: " + (i + 1);
                    await WaitIfNecessary();
                }
                WayPoint wp = GetOrRead <WayPoint>(reader, (ushort)(i | (ushort)FATEntry.Flag.Fix));
            }
            for (ushort i = 0; i < 0x8000; i++)
            {
                // Only do it a few times because we're trying to load way more than there is,
                // so it takes really long if we yield for everything
                if (i % 4096 == 0)
                {
                    loadingState = "Loading waypoints: " + (i + 1);
                    await WaitIfNecessary();
                }
                WayPoint wp = GetOrRead <WayPoint>(reader, i);
            }
            for (ushort i = 0; i < 0x7FFF; i++)
            {
                // Only do it a few times because we're trying to load way more than there is,
                // so it takes really long if we yield for everything
                if (i % 4096 == 0)
                {
                    loadingState = "Loading graphs: " + (i + 1);
                    await WaitIfNecessary();
                }
                Graph g = GetOrRead <Graph>(reader, (ushort)(i | (ushort)FATEntry.Flag.Fix));
            }
            for (ushort i = 0; i < 0x8000; i++)
            {
                // Only do it a few times because we're trying to load way more than there is,
                // so it takes really long if we yield for everything
                if (i % 4096 == 0)
                {
                    loadingState = "Loading graphs: " + (i + 1);
                    await WaitIfNecessary();
                }
                Graph g = GetOrRead <Graph>(reader, i);
            }
            loadingState = "Initializing hierarchy";
            await WaitIfNecessary();

            if (lh != null)
            {
                if (lh.hierarchyRoot.Value != null)
                {
                    lh.hierarchyRoot.Value.GetGameObject();
                }
            }
        }