Exemple #1
0
        private static bool LoadSprites(ChunkReader chunkIO, ChunkId idOuter, Wad2 wad, ref Dictionary <long, WadSprite> outSprites)
        {
            if (idOuter != Wad2Chunks.Sprites)
            {
                return(false);
            }

            var  sprites       = new Dictionary <long, WadSprite>();
            long obsoleteIndex = 0; // Move this into each chunk once we got rid of old style *.wad2 files.

            chunkIO.ReadChunks((id, chunkSize) =>
            {
                if (id != Wad2Chunks.Sprite)
                {
                    return(false);
                }

                int width          = LEB128.ReadInt(chunkIO.Raw);
                int height         = LEB128.ReadInt(chunkIO.Raw);
                byte[] imageData   = null;
                RectangleInt2 rect = new RectangleInt2();

                chunkIO.ReadChunks((id2, chunkSize2) =>
                {
                    if (id2 == Wad2Chunks.SpriteIndex)
                    {
                        obsoleteIndex = chunkIO.ReadChunkLong(chunkSize2);
                    }
                    else if (id2 == Wad2Chunks.SpriteData)
                    {
                        imageData = chunkIO.ReadChunkArrayOfBytes(chunkSize2);
                    }
                    else if (id2 == Wad2Chunks.SpriteSides)
                    {
                        rect.X0 = chunkIO.Raw.ReadInt32();
                        rect.Y0 = chunkIO.Raw.ReadInt32();
                        rect.X1 = chunkIO.Raw.ReadInt32();
                        rect.Y1 = chunkIO.Raw.ReadInt32();
                    }
                    else
                    {
                        return(false);
                    }
                    return(true);
                });

                sprites.Add(obsoleteIndex++, new WadSprite {
                    Texture   = new WadTexture(ImageC.FromByteArray(imageData, width, height)),
                    Alignment = rect
                })
                ;
                return(true);
            });

            outSprites = sprites;
            return(true);
        }
Exemple #2
0
        private static bool LoadTextures(ChunkReader chunkIO, ChunkId idOuter, Wad2 wad, ref Dictionary <long, WadTexture> outTextures)
        {
            if (idOuter != Wad2Chunks.Textures)
            {
                return(false);
            }

            Dictionary <long, WadTexture> textures = new Dictionary <long, WadTexture>();
            long obsoleteIndex = 0; // Move this into each chunk once we got rid of old style *.wad2 files.

            chunkIO.ReadChunks((id, chunkSize) =>
            {
                if (id != Wad2Chunks.Texture)
                {
                    return(false);
                }

                var width          = LEB128.ReadInt(chunkIO.Raw);
                var height         = LEB128.ReadInt(chunkIO.Raw);
                byte[] textureData = null;
                chunkIO.ReadChunks((id2, chunkSize2) =>
                {
                    if (id2 == Wad2Chunks.TextureIndex)
                    {
                        obsoleteIndex = chunkIO.ReadChunkLong(chunkSize2);
                    }
                    if (id2 == Wad2Chunks.TextureData)
                    {
                        textureData = chunkIO.ReadChunkArrayOfBytes(chunkSize2);
                    }
                    else
                    {
                        return(false);
                    }
                    return(true);
                });

                var texture = ImageC.FromByteArray(textureData, width, height);
                texture.ReplaceColor(new ColorC(255, 0, 255, 255), new ColorC(0, 0, 0, 0));

                textures.Add(obsoleteIndex++, new WadTexture(texture));
                return(true);
            });

            outTextures = textures;
            return(true);
        }
Exemple #3
0
        private static bool LoadMoveables(ChunkReader chunkIO, ChunkId idOuter, Wad2 wad,
                                          Dictionary <long, WadSoundInfo> soundInfos,
                                          Dictionary <long, WadTexture> textures)
        {
            if (idOuter != Wad2Chunks.Moveables)
            {
                return(false);
            }

            chunkIO.ReadChunks((id, chunkSize) =>
            {
                if (id != Wad2Chunks.Moveable)
                {
                    return(false);
                }

                uint objTypeId = LEB128.ReadUInt(chunkIO.Raw);
                var mov        = new WadMoveable(new WadMoveableId(objTypeId));
                var meshes     = new List <WadMesh>();
                chunkIO.ReadChunks((id2, chunkSize2) =>
                {
                    if (id2 == Wad2Chunks.Mesh)
                    {
                        var mesh = LoadMesh(chunkIO, chunkSize2, textures);
                        meshes.Add(mesh);
                    }
                    else if (id2 == Wad2Chunks.MoveableBone)
                    {
                        var skeleton = LoadBone(chunkIO, mov, meshes);

                        // Now convert the skeleton in the new (?) format. Ugly system but this is required for
                        // setting exact hardcoded ID for some moveables (i.e. gun mesh of an enemy, the engine
                        // has hardcoded mesh indices for effects)
                        var bones = new List <WadBone>();

                        var root         = new WadBone();
                        root.Name        = skeleton.Name;
                        root.Translation = Vector3.Zero;
                        root.Mesh        = skeleton.Mesh;
                        bones.Add(root);

                        BuildNewMeshTree(skeleton, bones);
                        mov.Bones.AddRange(bones);
                    }
                    else if (id2 == Wad2Chunks.MoveableBoneNew)
                    {
                        var bone = new WadBone();

                        bone.OpCode = (WadLinkOpcode)LEB128.ReadByte(chunkIO.Raw);
                        bone.Name   = chunkIO.Raw.ReadStringUTF8();

                        chunkIO.ReadChunks((id3, chunkSize3) =>
                        {
                            if (id3 == Wad2Chunks.MoveableBoneTranslation)
                            {
                                bone.Translation = chunkIO.ReadChunkVector3(chunkSize);
                            }
                            else if (id3 == Wad2Chunks.MoveableBoneMeshPointer)
                            {
                                bone.Mesh = meshes[chunkIO.ReadChunkInt(chunkSize)];
                            }
                            else
                            {
                                return(false);
                            }
                            return(true);
                        });

                        mov.Bones.Add(bone);
                    }
                    else if (id2 == Wad2Chunks.AnimationObsolete ||
                             id2 == Wad2Chunks.Animation ||
                             id2 == Wad2Chunks.Animation2)
                    {
                        var animation = new WadAnimation();

                        animation.StateId   = LEB128.ReadUShort(chunkIO.Raw);
                        animation.EndFrame  = LEB128.ReadUShort(chunkIO.Raw);
                        animation.FrameRate = LEB128.ReadByte(chunkIO.Raw);

                        if (id2 == Wad2Chunks.AnimationObsolete)
                        {
                            LEB128.ReadUShort(chunkIO.Raw);
                            LEB128.ReadUShort(chunkIO.Raw);
                        }

                        int oldSpeed, oldAccel, oldLatSpeed, oldLatAccel;
                        oldSpeed = oldAccel = oldLatSpeed = oldLatAccel = 0;

                        if (id2 != Wad2Chunks.Animation2)
                        {
                            // Use old speeds/accels for legacy chunk versions
                            oldSpeed    = LEB128.ReadInt(chunkIO.Raw);
                            oldAccel    = LEB128.ReadInt(chunkIO.Raw);
                            oldLatSpeed = LEB128.ReadInt(chunkIO.Raw);
                            oldLatAccel = LEB128.ReadInt(chunkIO.Raw);

                            // Correct EndFrame for legacy chunk versions
                            if (animation.EndFrame > 0)
                            {
                                animation.EndFrame--;
                            }
                        }

                        // Fix possibly corrupted EndFrame value which was caused by bug introduced in 1.2.9
                        if (animation.EndFrame == ushort.MaxValue)
                        {
                            animation.EndFrame = 0;
                        }

                        animation.NextAnimation = LEB128.ReadUShort(chunkIO.Raw);
                        animation.NextFrame     = LEB128.ReadUShort(chunkIO.Raw);

                        bool foundNewVelocitiesChunk = false;
                        chunkIO.ReadChunks((id3, chunkSize3) =>
                        {
                            if (id3 == Wad2Chunks.AnimationName)
                            {
                                animation.Name = chunkIO.ReadChunkString(chunkSize3);
                            }
                            else if (id3 == Wad2Chunks.AnimationVelocities)
                            {
                                foundNewVelocitiesChunk        = true;
                                var velocities                 = chunkIO.ReadChunkVector4(chunkSize);
                                animation.StartVelocity        = velocities.X;
                                animation.EndVelocity          = velocities.Y;
                                animation.StartLateralVelocity = velocities.Z;
                                animation.EndLateralVelocity   = velocities.W;
                            }
                            else if (id3 == Wad2Chunks.KeyFrame)
                            {
                                var keyframe = new WadKeyFrame();
                                chunkIO.ReadChunks((id4, chunkSize4) =>
                                {
                                    if (id4 == Wad2Chunks.KeyFrameOffset)
                                    {
                                        keyframe.Offset = chunkIO.ReadChunkVector3(chunkSize4);
                                    }
                                    else if (id4 == Wad2Chunks.KeyFrameBoundingBox)
                                    {
                                        var kfMin = Vector3.Zero;
                                        var kfMax = Vector3.Zero;
                                        chunkIO.ReadChunks((id5, chunkSize5) =>
                                        {
                                            if (id5 == Wad2Chunks.MeshBoundingBoxMin)
                                            {
                                                kfMin = chunkIO.ReadChunkVector3(chunkSize5);
                                            }
                                            else if (id5 == Wad2Chunks.MeshBoundingBoxMax)
                                            {
                                                kfMax = chunkIO.ReadChunkVector3(chunkSize5);
                                            }
                                            else
                                            {
                                                return(false);
                                            }
                                            return(true);
                                        });
                                        keyframe.BoundingBox = new BoundingBox(kfMin, kfMax);
                                    }
                                    else if (id4 == Wad2Chunks.KeyFrameAngle)
                                    {
                                        var angle       = new WadKeyFrameRotation();
                                        angle.Rotations = chunkIO.ReadChunkVector3(chunkSize4);
                                        keyframe.Angles.Add(angle);
                                    }
                                    else
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                                animation.KeyFrames.Add(keyframe);
                            }
                            else if (id3 == Wad2Chunks.StateChange)
                            {
                                var stateChange     = new WadStateChange();
                                stateChange.StateId = LEB128.ReadUShort(chunkIO.Raw);
                                chunkIO.ReadChunks((id4, chunkSize4) =>
                                {
                                    if (id4 == Wad2Chunks.Dispatch)
                                    {
                                        var dispatch           = new WadAnimDispatch();
                                        dispatch.InFrame       = LEB128.ReadUShort(chunkIO.Raw);
                                        dispatch.OutFrame      = LEB128.ReadUShort(chunkIO.Raw);
                                        dispatch.NextAnimation = LEB128.ReadUShort(chunkIO.Raw);
                                        dispatch.NextFrame     = LEB128.ReadUShort(chunkIO.Raw);
                                        stateChange.Dispatches.Add(dispatch);
                                    }
                                    else
                                    {
                                        return(false);
                                    }
                                    return(true);
                                });
                                animation.StateChanges.Add(stateChange);
                            }
                            else if (id3 == Wad2Chunks.AnimCommand)
                            {
                                var command        = new WadAnimCommand();
                                long offset        = chunkIO.Raw.BaseStream.Position;
                                command.Type       = (WadAnimCommandType)LEB128.ReadUShort(chunkIO.Raw);
                                command.Parameter1 = LEB128.ReadShort(chunkIO.Raw);
                                command.Parameter2 = LEB128.ReadShort(chunkIO.Raw);
                                command.Parameter3 = LEB128.ReadShort(chunkIO.Raw);

                                chunkIO.ReadChunks((id4, chunkSize4) =>
                                {
                                    if (id4 == Wad2Chunks.AnimCommandSoundInfo)
                                    {
                                        var info = chunkIO.ReadChunkInt(chunkSize4);
                                        if (info != -1)
                                        {
                                            command.SoundInfoObsolete = soundInfos[info];
                                        }
                                        return(true);
                                    }
                                    else
                                    {
                                        return(false);
                                    }
                                });

                                animation.AnimCommands.Add(command);
                            }
                            else
                            {
                                return(false);
                            }
                            return(true);
                        });

                        // Legacy code for calculating start and end velocities
                        if (!foundNewVelocitiesChunk)
                        {
                            float acceleration      = oldAccel / 65536.0f;
                            animation.StartVelocity = oldSpeed / 65536.0f;
                            animation.EndVelocity   = animation.StartVelocity + acceleration *
                                                      (animation.KeyFrames.Count - 1) * animation.FrameRate;

                            float lateralAcceleration      = oldLatAccel / 65536.0f;
                            animation.StartLateralVelocity = oldLatSpeed / 65536.0f;
                            animation.EndLateralVelocity   = animation.StartLateralVelocity + lateralAcceleration *
                                                             (animation.KeyFrames.Count - 1) * animation.FrameRate;
                        }

                        mov.Animations.Add(animation);
                    }
                    else
                    {
                        return(false);
                    }
                    return(true);
                });

                wad.Moveables.Add(mov.Id, mov);

                return(true);
            });

            return(true);
        }
Exemple #4
0
        private static WadMesh LoadMesh(ChunkReader chunkIO, long chunkSize, Dictionary <long, WadTexture> textures)
        {
            var  mesh          = new WadMesh();
            long obsoleteIndex = 0;

            chunkIO.ReadChunks((id2, chunkSize2) =>
            {
                if (id2 == Wad2Chunks.MeshIndex)
                {
                    obsoleteIndex = chunkIO.ReadChunkLong(chunkSize2);
                }
                else if (id2 == Wad2Chunks.MeshName)
                {
                    mesh.Name = chunkIO.ReadChunkString(chunkSize2);
                }
                else if (id2 == Wad2Chunks.MeshSphere)
                {
                    // Read bounding sphere
                    float radius   = 0;
                    Vector3 center = Vector3.Zero;
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshSphereCenter)
                        {
                            center = chunkIO.ReadChunkVector3(chunkSize3);
                        }
                        else if (id3 == Wad2Chunks.MeshSphereRadius)
                        {
                            radius = chunkIO.ReadChunkFloat(chunkSize3);
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                    mesh.BoundingSphere = new BoundingSphere(center, radius);
                }
                else if (id2 == Wad2Chunks.MeshBoundingBox)
                {
                    // Read bounding box
                    Vector3 min = Vector3.Zero;
                    Vector3 max = Vector3.Zero;
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshBoundingBoxMin)
                        {
                            min = chunkIO.ReadChunkVector3(chunkSize3);
                        }
                        else if (id3 == Wad2Chunks.MeshBoundingBoxMax)
                        {
                            max = chunkIO.ReadChunkVector3(chunkSize3);
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                    mesh.BoundingBox = new BoundingBox(min, max);
                }
                else if (id2 == Wad2Chunks.MeshVertexPositions)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshVertexPosition)
                        {
                            mesh.VerticesPositions.Add(chunkIO.ReadChunkVector3(chunkSize3));
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else if (id2 == Wad2Chunks.MeshVertexNormals)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshVertexNormal)
                        {
                            mesh.VerticesNormals.Add(chunkIO.ReadChunkVector3(chunkSize3));
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else if (id2 == Wad2Chunks.MeshVertexShades)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshVertexShade)
                        {
                            mesh.VerticesShades.Add(chunkIO.ReadChunkShort(chunkSize3));
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else if (id2 == Wad2Chunks.MeshPolygons)
                {
                    chunkIO.ReadChunks((id3, chunkSize3) =>
                    {
                        if (id3 == Wad2Chunks.MeshQuad ||
                            id3 == Wad2Chunks.MeshTriangle)
                        {
                            var polygon    = new WadPolygon();
                            polygon.Shape  = id3 == Wad2Chunks.MeshQuad ? WadPolygonShape.Quad : WadPolygonShape.Triangle;
                            polygon.Index0 = LEB128.ReadInt(chunkIO.Raw);
                            polygon.Index1 = LEB128.ReadInt(chunkIO.Raw);
                            polygon.Index2 = LEB128.ReadInt(chunkIO.Raw);
                            if (id3 == Wad2Chunks.MeshQuad)
                            {
                                polygon.Index3 = LEB128.ReadInt(chunkIO.Raw);
                            }
                            polygon.ShineStrength = LEB128.ReadByte(chunkIO.Raw);

                            TextureArea textureArea = new TextureArea();
                            textureArea.Texture     = textures[LEB128.ReadInt(chunkIO.Raw)];
                            textureArea.TexCoord0   = chunkIO.Raw.ReadVector2();
                            textureArea.TexCoord1   = chunkIO.Raw.ReadVector2();
                            textureArea.TexCoord2   = chunkIO.Raw.ReadVector2();
                            if (id3 == Wad2Chunks.MeshQuad)
                            {
                                textureArea.TexCoord3 = chunkIO.Raw.ReadVector2();
                            }
                            else
                            {
                                textureArea.TexCoord3 = textureArea.TexCoord2;
                            }
                            textureArea.BlendMode   = (BlendMode)LEB128.ReadLong(chunkIO.Raw);
                            textureArea.DoubleSided = chunkIO.Raw.ReadBoolean();
                            polygon.Texture         = textureArea;

                            chunkIO.ReadChunks((id4, chunkSize4) =>
                            {
                                return(false);
                            });

                            mesh.Polys.Add(polygon);
                        }
                        else
                        {
                            return(false);
                        }
                        return(true);
                    });
                }
                else
                {
                    return(false);
                }

                return(true);
            });

            return(mesh);
        }