Пример #1
0
        private void LoadEntitiesFromLump(EntityLump entityLump)
        {
            var childEntities = entityLump.GetChildEntityNames();

            foreach (var childEntityName in childEntities)
            {
                // TODO: Should be controlled in UI with world layers
                if (childEntityName.Contains("_destruction"))
                {
                    continue;
                }

                var newResource = guiContext.LoadFileByAnyMeansNecessary(childEntityName + "_c");

                if (newResource == null)
                {
                    continue;
                }

                LoadEntitiesFromLump(new EntityLump(newResource));
            }

            var worldEntities = entityLump.GetEntities();

            foreach (var entity in worldEntities)
            {
                var    scale     = string.Empty;
                var    position  = string.Empty;
                var    angles    = string.Empty;
                string model     = null;
                var    skin      = string.Empty;
                var    colour    = new byte[0];
                var    classname = string.Empty;
                string particle  = null;
                string animation = null;

                foreach (var property in entity.Properties)
                {
                    if (property.Key == EntityLumpKeyLookup.Get("model"))
                    {
                        model = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("origin"))
                    {
                        position = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("angles"))
                    {
                        angles = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("scales"))
                    {
                        scale = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("skin"))
                    {
                        skin = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("rendercolor"))
                    {
                        colour = property.Data as byte[];
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("classname"))
                    {
                        classname = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("effect_name"))
                    {
                        particle = property.Data as string;
                    }
                    else if (property.Key == EntityLumpKeyLookup.Get("defaultanim"))
                    {
                        animation = property.Data as string;
                    }
                }

                if (scale == string.Empty || position == string.Empty || angles == string.Empty)
                {
                    continue;
                }

                var isGlobalLight = classname == "env_global_light";
                var isCamera      =
                    classname == "info_player_start" ||
                    classname == "worldspawn" ||
                    classname == "sky_camera" ||
                    classname == "point_devshot_camera" ||
                    classname == "point_camera";

                var scaleMatrix = Matrix4.CreateScale(ParseCoordinates(scale));

                var positionVector = ParseCoordinates(position);
                var positionMatrix = Matrix4.CreateTranslation(positionVector);

                var pitchYawRoll = ParseCoordinates(angles);
                var rollMatrix   = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(pitchYawRoll.Z)); // Roll
                var pitchMatrix  = Matrix4.CreateRotationY(MathHelper.DegreesToRadians(pitchYawRoll.X)); // Pitch
                var yawMatrix    = Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(pitchYawRoll.Y)); // Yaw

                var rotationMatrix       = rollMatrix * pitchMatrix * yawMatrix;
                var transformationMatrix = scaleMatrix * rotationMatrix * positionMatrix;

                if (particle != null)
                {
                    var particleResource = guiContext.LoadFileByAnyMeansNecessary(particle + "_c");

                    if (particleResource != null)
                    {
                        var particleSystem = new ParticleSystem(particleResource);
                        var origin         = new System.Numerics.Vector3(positionVector.X, positionVector.Y, positionVector.Z);
                        //particleRenderers.Add(new ParticleRenderer.ParticleRenderer(particleSystem, guiContext, origin));
                    }

                    continue;
                }

                if (isCamera)
                {
                    if (classname == "worldspawn")
                    {
                        // TODO
                        //glRenderControl.SetDefaultWorldCamera(positionVector);
                    }
                    else
                    {
                        // TODO
                        //glRenderControl.AddCamera(name == string.Empty ? $"{classname} #{anonymousCameraCount++}" : name, transformationMatrix);
                    }

                    continue;
                }
                else if (isGlobalLight)
                {
                    // TODO
                    //glRenderControl.SetWorldGlobalLight(positionVector); // TODO: set light angle

                    continue;
                }
                else if (model == null)
                {
                    continue;
                }

                var objColor = Vector4.One;

                // Parse colour if present
                if (colour.Length == 4)
                {
                    for (var i = 0; i < 4; i++)
                    {
                        objColor[i] = colour[i] / 255.0f;
                    }
                }

                var newEntity = guiContext.LoadFileByAnyMeansNecessary(model + "_c");

                if (newEntity == null)
                {
                    continue;
                }

                var newModel      = new Model(newEntity);
                var modelRenderer = new ModelRenderer(newModel, guiContext, skin, false);
                modelRenderer.SetMeshTransform(transformationMatrix);
                modelRenderer.SetTint(objColor);

                if (animation != default)
                {
                    modelRenderer.LoadAnimation(animation); // Load only this animation
                    modelRenderer.SetAnimation(animation);
                }

                worldOctree.Insert(modelRenderer);
                modelRenderers.Add(modelRenderer);

                BoundingBox = BoundingBox.IsZero ? modelRenderer.BoundingBox : BoundingBox.Union(modelRenderer.BoundingBox);
            }
        }
Пример #2
0
 public T GetProperty <T>(string name)
 => GetProperty <T>(EntityLumpKeyLookup.Get(name));
Пример #3
0
        private void LoadEntitiesFromLump(Scene scene, LoadResult result, EntityLump entityLump, string layerName = null)
        {
            var childEntities = entityLump.GetChildEntityNames();

            foreach (var childEntityName in childEntities)
            {
                var newResource = guiContext.LoadFileByAnyMeansNecessary(childEntityName + "_c");

                if (newResource == null)
                {
                    continue;
                }

                var childLump = (EntityLump)newResource.DataBlock;
                var childName = childLump.Data.GetProperty <string>("m_name");

                LoadEntitiesFromLump(scene, result, childLump, childName);
            }

            var worldEntities = entityLump.GetEntities();

            foreach (var entity in worldEntities)
            {
                var classname = entity.GetProperty <string>("classname");

                if (classname == "info_world_layer")
                {
                    var spawnflags = entity.GetProperty <uint>("spawnflags");
                    var layername  = entity.GetProperty <string>("layername");

                    // Visible on spawn flag
                    if ((spawnflags & 1) == 1)
                    {
                        result.DefaultEnabledLayers.Add(layername);
                    }

                    continue;
                }
                else if (classname == "skybox_reference")
                {
                    var worldgroupid  = entity.GetProperty <string>("worldgroupid");
                    var targetmapname = entity.GetProperty <string>("targetmapname");

                    var skyboxWorldPath = $"maps/{Path.GetFileNameWithoutExtension(targetmapname)}/world.vwrld_c";
                    var skyboxPackage   = guiContext.LoadFileByAnyMeansNecessary(skyboxWorldPath);

                    if (skyboxPackage != null)
                    {
                        result.Skybox = (World)skyboxPackage.DataBlock;
                    }
                }

                var scale    = entity.GetProperty <string>("scales");
                var position = entity.GetProperty <string>("origin");
                var angles   = entity.GetProperty <string>("angles");
                var model    = entity.GetProperty <string>("model");
                var skin     = entity.GetProperty <string>("skin");
                var particle = entity.GetProperty <string>("effect_name");
                //var animation = entity.GetProperty<string>("defaultanim");
                string animation = null;

                if (scale == null || position == null || angles == null)
                {
                    continue;
                }

                var isGlobalLight = classname == "env_global_light";
                var isCamera      =
                    classname == "sky_camera" ||
                    classname == "point_devshot_camera" ||
                    classname == "point_camera";

                var scaleMatrix = Matrix4x4.CreateScale(VectorExtensions.ParseVector(scale));

                var positionVector = VectorExtensions.ParseVector(position);
                var positionMatrix = Matrix4x4.CreateTranslation(positionVector);

                var pitchYawRoll = VectorExtensions.ParseVector(angles);
                var rollMatrix   = Matrix4x4.CreateRotationX(OpenTK.MathHelper.DegreesToRadians(pitchYawRoll.Z)); // Roll
                var pitchMatrix  = Matrix4x4.CreateRotationY(OpenTK.MathHelper.DegreesToRadians(pitchYawRoll.X)); // Pitch
                var yawMatrix    = Matrix4x4.CreateRotationZ(OpenTK.MathHelper.DegreesToRadians(pitchYawRoll.Y)); // Yaw

                var rotationMatrix       = rollMatrix * pitchMatrix * yawMatrix;
                var transformationMatrix = scaleMatrix * rotationMatrix * positionMatrix;

                if (classname == "sky_camera")
                {
                    result.SkyboxScale  = entity.GetProperty <ulong>("scale");
                    result.SkyboxOrigin = positionVector;
                }

                if (particle != null)
                {
                    var particleResource = guiContext.LoadFileByAnyMeansNecessary(particle + "_c");

                    if (particleResource != null)
                    {
                        var particleSystem = (ParticleSystem)particleResource.DataBlock;
                        var origin         = new Vector3(positionVector.X, positionVector.Y, positionVector.Z);

                        try
                        {
                            var particleNode = new ParticleSceneNode(scene, particleSystem)
                            {
                                Transform = Matrix4x4.CreateTranslation(origin),
                                LayerName = layerName,
                            };
                            scene.Add(particleNode, true);
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine($"Failed to setup particle '{particle}': {e.Message}");
                        }
                    }

                    continue;
                }

                if (isCamera)
                {
                    var name       = entity.GetProperty <string>("targetname") ?? string.Empty;
                    var cameraName = string.IsNullOrEmpty(name)
                        ? classname
                        : name;

                    result.CameraMatrices.Add(cameraName, transformationMatrix);

                    continue;
                }
                else if (isGlobalLight)
                {
                    result.GlobalLightPosition = positionVector;

                    continue;
                }
                else if (model == null)
                {
                    continue;
                }

                var objColor = Vector4.One;

                // Parse colour if present
                var colour = entity.GetProperty("rendercolor");

                // HL Alyx has an entity that puts rendercolor as a string instead of color255
                // TODO: Make an enum for these types
                if (colour != default && colour.Type == 0x09)
                {
                    var colourBytes = (byte[])colour.Data;
                    objColor.X = colourBytes[0] / 255.0f;
                    objColor.Y = colourBytes[1] / 255.0f;
                    objColor.Z = colourBytes[2] / 255.0f;
                    objColor.W = colourBytes[3] / 255.0f;
                }

                var newEntity = guiContext.LoadFileByAnyMeansNecessary(model + "_c");

                if (newEntity == null)
                {
                    var errorModelResource = guiContext.LoadFileByAnyMeansNecessary("models/dev/error.vmdl_c");

                    if (errorModelResource != null)
                    {
                        var errorModel = new ModelSceneNode(scene, (Model)errorModelResource.DataBlock, skin, false)
                        {
                            Transform = transformationMatrix,
                            LayerName = layerName,
                        };
                        scene.Add(errorModel, false);
                    }
                    else
                    {
                        Console.WriteLine("Unable to load error.vmdl_c. Did you add \"core/pak_001.dir\" to your game paths?");
                    }

                    continue;
                }

                var newModel = (Model)newEntity.DataBlock;

                var modelNode = new ModelSceneNode(scene, newModel, skin, false)
                {
                    Transform = transformationMatrix,
                    Tint      = objColor,
                    LayerName = layerName,
                };

                if (animation != default)
                {
                    modelNode.LoadAnimation(animation); // Load only this animation
                    modelNode.SetAnimation(animation);
                }

                var bodyHash = EntityLumpKeyLookup.Get("body");
                if (entity.Properties.ContainsKey(bodyHash))
                {
                    var groups    = modelNode.GetMeshGroups();
                    var body      = entity.Properties[bodyHash].Data;
                    int bodyGroup = -1;

                    if (body is ulong bodyGroupLong)
                    {
                        bodyGroup = (int)bodyGroupLong;
                    }
                    else if (body is string bodyGroupString)
                    {
                        if (!int.TryParse(bodyGroupString, out bodyGroup))
                        {
                            bodyGroup = -1;
                        }
                    }

                    modelNode.SetActiveMeshGroups(groups.Skip(bodyGroup).Take(1));
                }

                scene.Add(modelNode, false);
            }
        }