예제 #1
0
        private static void CreateTouchElement(ElementsGroup Group, Vector3 Position, Vector3 Size, int ScreenIndex, int[] SoundIndices, TrainManager.CommandEntry[] CommandEntries)
        {
            Vertex       t0     = new Vertex(Size.X, Size.Y, -Size.Z);
            Vertex       t1     = new Vertex(Size.X, -Size.Y, -Size.Z);
            Vertex       t2     = new Vertex(-Size.X, -Size.Y, -Size.Z);
            Vertex       t3     = new Vertex(-Size.X, Size.Y, -Size.Z);
            Vertex       t4     = new Vertex(Size.X, Size.Y, Size.Z);
            Vertex       t5     = new Vertex(Size.X, -Size.Y, Size.Z);
            Vertex       t6     = new Vertex(-Size.X, -Size.Y, Size.Z);
            Vertex       t7     = new Vertex(-Size.X, Size.Y, Size.Z);
            StaticObject Object = new StaticObject(Program.CurrentHost);

            Object.Mesh.Vertices                      = new VertexTemplate[] { t0, t1, t2, t3, t4, t5, t6, t7 };
            Object.Mesh.Faces                         = new MeshFace[] { new MeshFace(new int[] { 0, 1, 2, 3 }), new MeshFace(new int[] { 0, 4, 5, 1 }), new MeshFace(new int[] { 0, 3, 7, 4 }), new MeshFace(new int[] { 6, 5, 4, 7 }), new MeshFace(new int[] { 6, 7, 3, 2 }), new MeshFace(new int[] { 6, 2, 1, 5 }) };
            Object.Mesh.Materials                     = new MeshMaterial[1];
            Object.Mesh.Materials[0].Flags            = 0;
            Object.Mesh.Materials[0].Color            = Color32.White;
            Object.Mesh.Materials[0].TransparentColor = Color24.Blue;
            Object.Mesh.Materials[0].DaytimeTexture   = null;
            Object.Mesh.Materials[0].NighttimeTexture = null;
            Object.Dynamic = true;
            if (Group.TouchElements == null)
            {
                Group.TouchElements = new TouchElement[0];
            }
            int n = Group.TouchElements.Length;

            Array.Resize(ref Group.TouchElements, n + 1);
            Group.TouchElements[n] = new TouchElement
            {
                Element         = new AnimatedObject(Program.CurrentHost),
                JumpScreenIndex = ScreenIndex,
                SoundIndices    = SoundIndices,
                ControlIndices  = new int[CommandEntries.Length]
            };
            Group.TouchElements[n].Element.States = new [] { new ObjectState() };
            Group.TouchElements[n].Element.States[0].Translation = Matrix4D.CreateTranslation(Position.X, Position.Y, -Position.Z);
            Group.TouchElements[n].Element.States[0].Prototype   = Object;
            Group.TouchElements[n].Element.CurrentState          = 0;
            Group.TouchElements[n].Element.internalObject        = new ObjectState {
                Prototype = Object
            };
            Program.CurrentHost.CreateDynamicObject(ref Group.TouchElements[n].Element.internalObject);
            int m = Interface.CurrentControls.Length;

            Array.Resize(ref Interface.CurrentControls, m + CommandEntries.Length);
            for (int i = 0; i < CommandEntries.Length; i++)
            {
                Interface.CurrentControls[m + i].Command = CommandEntries[i].Command;
                Interface.CurrentControls[m + i].Method  = Interface.ControlMethod.Touch;
                Interface.CurrentControls[m + i].Option  = CommandEntries[i].Option;
                Group.TouchElements[n].ControlIndices[i] = m + i;
            }
        }
예제 #2
0
        public static void Freeze(ModelMesh model, FreezeComponents flags)
        {
            bool freezePos = flags.HasFlag(FreezeComponents.Position);
            bool freezeRot = flags.HasFlag(FreezeComponents.Rotation);
            bool freezeSca = flags.HasFlag(FreezeComponents.Scale);

            Matrix4D mPosition = Matrix4D.CreateTranslation(model.Parent.Transform.ExtractTranslation());
            Matrix4D mRotation = Matrix4D.CreateFromQuaternion(model.Parent.Transform.ExtractRotation());
            Matrix4D mScale    = Matrix4D.CreateScale(model.Parent.Transform.ExtractScale());

            if (freezePos)
            {
                model.Parent.Transform = model.Parent.Transform.ClearTranslation();
            }
            if (freezeRot)
            {
                model.Parent.Transform = model.Parent.Transform.ClearRotation();
            }
            if (freezeSca)
            {
                model.Parent.Transform = model.Parent.Transform.ClearScale();
            }

            foreach (ModelMeshPart meshpart in model.MeshParts)
            {
                for (int i = 0; i < meshpart.VertexCount; i++)
                {
                    if (freezePos)
                    {
                        meshpart.VertexBuffer.ModifyVertexPosition(i, Vector3.TransformVector(meshpart.VertexBuffer.Data[i].Position, mPosition));
                    }

                    if (freezeRot)
                    {
                        meshpart.VertexBuffer.ModifyVertexPosition(i, Vector3.TransformVector(meshpart.VertexBuffer.Data[i].Position, mRotation));
                        meshpart.VertexBuffer.ModifyVertexNormal(i, Vector3.TransformNormal(meshpart.VertexBuffer.Data[i].Normal, mRotation));
                    }

                    if (freezeSca)
                    {
                        meshpart.VertexBuffer.ModifyVertexPosition(i, Vector3.TransformVector(meshpart.VertexBuffer.Data[i].Position, mScale));
                    }
                }

                meshpart.VertexBuffer.Initialise();
            }

            model.BoundingBox.Calculate(model);
        }
예제 #3
0
        public void Draw()
        {
            if (model == null)
            {
                model = new Model();

                Sphere sphere = new Sphere(0.025f, 7, 7);
                ModelManipulator.SetVertexColour(sphere, 0, 255, 0, 255);
                model.AddMesh(sphere);
                model.SetRenderStyle(RenderStyle.Wireframe);
            }

            Matrix4D parentTransform = LinkedBone.CombinedTransform;

            Transform = Matrix4D.Identity;

            Vector3 v = parentTransform.ExtractTranslation();

            parentTransform.Normalise();
            parentTransform.M41 = v.X;
            parentTransform.M42 = v.Y;
            parentTransform.M43 = v.Z;

            Transform *= Matrix4D.CreateFromQuaternion(parentTransform.ExtractRotation());
            Transform *= Matrix4D.CreateTranslation(parentTransform.ExtractTranslation());

            Matrix4D mS = SceneManager.Current.Transform;
            Matrix4D mT = Transform;

            SceneManager.Current.Renderer.PushMatrix();

            SceneManager.Current.Renderer.MultMatrix(ref mS);
            SceneManager.Current.Renderer.MultMatrix(ref mT);

            model.Draw();

            SceneManager.Current.Renderer.PopMatrix();
        }
예제 #4
0
        public static void ProcessLevelForCarmageddonMaxDamage()
        {
            if (SceneManager.Current.Models.Count == 0)
            {
                return;
            }

            ModelBoneCollection bones = SceneManager.Current.Models[0].Bones[0].AllChildren();

            SceneManager.Current.UpdateProgress("Applying Carmageddon: Max Damage scale");

            ModelManipulator.Scale(bones, Matrix4D.CreateScale(6.9f, 6.9f, -6.9f), true);
            ModelManipulator.FlipFaces(bones, true);

            SceneManager.Current.UpdateProgress("Fixing material names");

            foreach (Material material in SceneManager.Current.Materials)
            {
                if (material.Name.Contains("."))
                {
                    material.Name = material.Name.Substring(0, material.Name.IndexOf("."));
                }
                material.Name = material.Name.Replace("\\", "");

                MATMaterial m = (material.SupportingDocuments["Source"] as MATMaterial);
                if (!m.HasTexture)
                {
                    using (Bitmap bmp = new Bitmap(16, 16))
                        using (Graphics g = Graphics.FromImage(bmp))
                        {
                            g.FillRectangle(new SolidBrush(Color.FromArgb(m.DiffuseColour[3], m.DiffuseColour[0], m.DiffuseColour[1], m.DiffuseColour[2])), 0, 0, 16, 16);

                            Texture t = new Texture();
                            t.CreateFromBitmap(bmp, string.Format("{4}_R{0:x2}G{1:x2}B{2:x2}A{3:x2}", m.DiffuseColour[0], m.DiffuseColour[1], m.DiffuseColour[2], m.DiffuseColour[3], material.Name));
                            material.Texture = t;
                        }
                }
            }

            SceneManager.Current.UpdateProgress("Processing powerups and accessories");

            for (int i = bones.Count - 1; i >= 0; i--)
            {
                ModelBone bone = bones[i];

                if (bone.Name.StartsWith("&"))
                {
                    if (bone.Name.StartsWith("&£"))
                    {
                        C2Powerup pup     = Powerups.LookupID(int.Parse(bone.Name.Substring(2, 2)));
                        Powerup   powerup = new Powerup();

                        if (pup.InMD)
                        {
                            powerup.Name = $"pup_{pup.Name}";
                            powerup.Tag  = pup.Model;
                        }
                        else
                        {
                            powerup.Name = "pup_Credits";
                            powerup.Tag  = pup.Model;
                        }

                        powerup.Transform = bone.CombinedTransform;

                        SceneManager.Current.Entities.Add(powerup);
                    }
                    else
                    {
                        Accessory accessory = new Accessory
                        {
                            Name = $"C2_{bone.Mesh.Name.Substring(3)}"
                        };

                        SceneManager.Current.Entities.Add(accessory);
                    }

                    SceneManager.Current.Models[0].RemoveBone(bone.Index);
                }
            }

            if (SceneManager.Current.Models[0].SupportingDocuments.ContainsKey("TXT"))
            {
                Map map = SceneManager.Current.Models[0].GetSupportingDocument <Map>("TXT");

                StartingGrid grid = new StartingGrid
                {
                    Transform = Matrix4D.CreateTranslation(map.GridPosition.X * 6.9f, map.GridPosition.Y * 6.9f, map.GridPosition.Z * -6.9f)
                };

                SceneManager.Current.Entities.Add(grid);
            }

            SceneManager.Current.UpdateProgress("Processing complete!");

            SceneManager.Current.SetCoordinateSystem(CoordinateSystem.LeftHanded);

            SceneManager.Current.Change(ChangeType.Munge, ChangeContext.Model, -1);

            SceneManager.Current.SetContext("Carmageddon Max Damage", ContextMode.Level);
        }
예제 #5
0
        public int CreateStaticObject(StaticObject Prototype, Vector3 Position, Transformation BaseTransformation, Transformation AuxTransformation, bool AccurateObjectDisposal, double AccurateObjectDisposalZOffset, double StartingDistance, double EndingDistance, double BlockLength, double TrackPosition, double Brightness)
        {
            if (Prototype == null)
            {
                return(-1);
            }

            float startingDistance = float.MaxValue;
            float endingDistance   = float.MinValue;

            if (AccurateObjectDisposal)
            {
                foreach (VertexTemplate vertex in Prototype.Mesh.Vertices)
                {
                    Vector3 Coordinates = new Vector3(vertex.Coordinates);
                    Coordinates.Rotate(AuxTransformation);

                    if (Coordinates.Z < startingDistance)
                    {
                        startingDistance = (float)Coordinates.Z;
                    }

                    if (Coordinates.Z > endingDistance)
                    {
                        endingDistance = (float)Coordinates.Z;
                    }
                }

                startingDistance += (float)AccurateObjectDisposalZOffset;
                endingDistance   += (float)AccurateObjectDisposalZOffset;
            }

            const double minBlockLength = 20.0;

            if (BlockLength < minBlockLength)
            {
                BlockLength *= Math.Ceiling(minBlockLength / BlockLength);
            }

            if (AccurateObjectDisposal)
            {
                startingDistance += (float)TrackPosition;
                endingDistance   += (float)TrackPosition;
                double z = BlockLength * Math.Floor(TrackPosition / BlockLength);
                StartingDistance = Math.Min(z - BlockLength, startingDistance);
                EndingDistance   = Math.Max(z + 2.0 * BlockLength, endingDistance);
                startingDistance = (float)(BlockLength * Math.Floor(StartingDistance / BlockLength));
                endingDistance   = (float)(BlockLength * Math.Ceiling(EndingDistance / BlockLength));
            }
            else
            {
                startingDistance = (float)StartingDistance;
                endingDistance   = (float)EndingDistance;
            }

            StaticObjectStates.Add(new ObjectState
            {
                Prototype   = Prototype,
                Translation = Matrix4D.CreateTranslation(Position.X, Position.Y, -Position.Z),
                //FIXME: This seems to need to be the 'wrong' way around. Need to standardise on Matrices throughout?
                Rotate           = (Matrix4D) new Transformation(AuxTransformation, BaseTransformation),
                Brightness       = Brightness,
                StartingDistance = startingDistance,
                EndingDistance   = endingDistance
            });

            foreach (MeshFace face in Prototype.Mesh.Faces)
            {
                switch (face.Flags & MeshFace.FaceTypeMask)
                {
                case MeshFace.FaceTypeTriangles:
                    InfoTotalTriangles++;
                    break;

                case MeshFace.FaceTypeTriangleStrip:
                    InfoTotalTriangleStrip++;
                    break;

                case MeshFace.FaceTypeQuads:
                    InfoTotalQuads++;
                    break;

                case MeshFace.FaceTypeQuadStrip:
                    InfoTotalQuadStrip++;
                    break;

                case MeshFace.FaceTypePolygon:
                    InfoTotalPolygon++;
                    break;
                }
            }

            return(StaticObjectStates.Count - 1);
        }
예제 #6
0
파일: Icon.cs 프로젝트: q4a/Flummery
        public void Draw()
        {
            if (asset == null)
            {
                ModelMeshPart sprite = new ModelMeshPart();
                sprite.AddVertex(new Vector3(-0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 1));
                sprite.AddVertex(new Vector3(-0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 0));
                sprite.AddVertex(new Vector3(0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 0));
                sprite.AddVertex(new Vector3(0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 1));

                sprite.AddVertex(new Vector3(0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 1));
                sprite.AddVertex(new Vector3(0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(0, 0));
                sprite.AddVertex(new Vector3(-0.25f, 0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 0));
                sprite.AddVertex(new Vector3(-0.25f, -0.25f, 0.0f), Vector3.UnitY, new Vector2(1, 1));
                sprite.IndexBuffer.Initialise();
                sprite.VertexBuffer.Initialise();
                sprite.Material = new Material {
                    Name = "Entity.Asset", Texture = SceneManager.Current.Content.Load <Texture, PNGImporter>(IconFilename)
                };
                sprite.PrimitiveType = PrimitiveType.Quads;

                ModelMesh spritemesh = new ModelMesh();
                spritemesh.AddModelMeshPart(sprite);

                Model spritemodel = new Model();
                spritemodel.AddMesh(spritemesh);
                asset = spritemodel;
            }

            if (Linked)
            {
                Matrix4D parentTransform = ((ModelBone)Link).CombinedTransform;

                if (LinkType == LinkType.All)
                {
                    Transform = parentTransform;
                }
                else
                {
                    Transform = Matrix4D.Identity;

                    Vector3 v = parentTransform.ExtractTranslation();
                    parentTransform.Normalise();
                    parentTransform.M41 = v.X;
                    parentTransform.M42 = v.Y;
                    parentTransform.M43 = v.Z;

                    if (LinkType.HasFlag(LinkType.Rotation))
                    {
                        Transform *= Matrix4D.CreateFromQuaternion(parentTransform.ExtractRotation());
                    }
                    if (LinkType.HasFlag(LinkType.Scale))
                    {
                        Transform *= Matrix4D.CreateScale(parentTransform.ExtractScale());
                    }
                    if (LinkType.HasFlag(LinkType.Position))
                    {
                        Transform *= Matrix4D.CreateTranslation(parentTransform.ExtractTranslation());
                    }
                }
            }

            Matrix4D mS = SceneManager.Current.Transform;
            Matrix4D mT = Transform;

            SceneManager.Current.Renderer.PushMatrix();

            Matrix4D position = Matrix4D.CreateTranslation(mT.ExtractTranslation());

            SceneManager.Current.Renderer.MultMatrix(ref mS);
            SceneManager.Current.Renderer.MultMatrix(ref position);

            if (Lollipop)
            {
                Matrix4D rotation = ViewportManager.Current.Active.Camera.Rotation;
                Matrix4D scale    = Matrix4D.CreateScale(0.1f);

                SceneManager.Current.Renderer.MultMatrix(ref rotation);
                SceneManager.Current.Renderer.MultMatrix(ref scale);
            }

            SceneManager.Current.Renderer.Enable("Blend");
            SceneManager.Current.Renderer.BlendFunc("SrcAlpha", "OneMinusSrcAlpha");
            ((Model)asset).Draw();
            SceneManager.Current.Renderer.Disable("Blend");

            SceneManager.Current.Renderer.PopMatrix();
        }
예제 #7
0
        /// <summary> Updates the position and state of the animated object</summary>
        /// <param name="IsPartOfTrain">Whether this object forms part of a train</param>
        /// <param name="Train">The train, or a null reference otherwise</param>
        /// <param name="CarIndex">If this object forms part of a train, the car index it refers to</param>
        /// <param name="SectionIndex">If this object has been placed via Track.Sig, the index of the section it is attached to</param>
        /// <param name="TrackPosition"></param>
        /// <param name="Position"></param>
        /// <param name="Direction"></param>
        /// <param name="Up"></param>
        /// <param name="Side"></param>
        /// <param name="UpdateFunctions">Whether the functions associated with this object should be re-evaluated</param>
        /// <param name="Show"></param>
        /// <param name="TimeElapsed">The time elapsed since this object was last updated</param>
        /// <param name="EnableDamping">Whether damping is to be applied for this call</param>
        /// <param name="IsTouch">Whether Animated Object belonging to TouchElement class.</param>
        /// <param name="Camera"></param>
        public void Update(bool IsPartOfTrain, AbstractTrain Train, int CarIndex, int SectionIndex, double TrackPosition, Vector3 Position, Vector3 Direction, Vector3 Up, Vector3 Side, bool UpdateFunctions, bool Show, double TimeElapsed, bool EnableDamping, bool IsTouch = false, dynamic Camera = null)
        {
            // state change
            if (StateFunction != null & UpdateFunctions)
            {
                double sd = StateFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                int    si = (int)System.Math.Round(sd);
                if (si < 0 | si >= States.Length)
                {
                    si = -1;
                }
                if (CurrentState != si)
                {
                    ObjectType type = ObjectType.Dynamic;
                    if (Camera != null)
                    {
                        type = ObjectType.Overlay;
                    }
                    Initialize(si, type, Show);
                    CurrentState = si;
                }
            }

            if (CurrentState == -1)
            {
                return;                                 //not visible state, so don't bother updating
            }
            // translation
            if (TranslateXFunction != null)
            {
                double x = TranslateXFunction.LastResult;
                if (UpdateFunctions)
                {
                    x = TranslateXFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }

                Vector3 translationVector = new Vector3(TranslateXDirection);                 //Must clone
                translationVector.Rotate(Direction, Up, Side);
                translationVector *= x;
                Position          += translationVector;
            }
            else if (TranslateXScriptFile != null)
            {
                //Translate X Script
                if (TranslateXAnimationScript == null)
                {
                    //Load the script if required
                    try
                    {
                        CSScript.GlobalSettings.TargetFramework = "v4.0";
                        TranslateXAnimationScript = CSScript.LoadCode(File.ReadAllText(TranslateXScriptFile))
                                                    .CreateObject("OpenBVEScript")
                                                    .AlignToInterface <AnimationScript>(true);
                    }
                    catch
                    {
                        currentHost.AddMessage(MessageType.Error, false,
                                               "An error occcured whilst parsing script " + TranslateXScriptFile);
                        TranslateXScriptFile = null;
                        return;
                    }
                }

                double x = TranslateXAnimationScript.ExecuteScript(Train, Position, TrackPosition, SectionIndex,
                                                                   IsPartOfTrain, TimeElapsed);
                Vector3 translationVector = new Vector3(TranslateXDirection);                 //Must clone
                translationVector.Rotate(Direction, Up, Side);
                translationVector *= x;
                Position          += translationVector;
            }


            if (TranslateYFunction != null)
            {
                double y = TranslateYFunction.LastResult;
                if (UpdateFunctions)
                {
                    y = TranslateYFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }

                Vector3 translationVector = new Vector3(TranslateYDirection);                 //Must clone
                translationVector.Rotate(Direction, Up, Side);
                translationVector *= y;
                Position          += translationVector;
            }
            else if (TranslateYScriptFile != null)
            {
                //Translate X Script
                if (TranslateYAnimationScript == null)
                {
                    //Load the script if required
                    try
                    {
                        CSScript.GlobalSettings.TargetFramework = "v4.0";
                        TranslateYAnimationScript = CSScript.LoadCode(File.ReadAllText(TranslateYScriptFile))
                                                    .CreateObject("OpenBVEScript")
                                                    .AlignToInterface <AnimationScript>(true);
                    }
                    catch
                    {
                        currentHost.AddMessage(MessageType.Error, false,
                                               "An error occcured whilst parsing script " + TranslateYScriptFile);
                        TranslateYScriptFile = null;
                        return;
                    }
                }

                double y = TranslateYAnimationScript.ExecuteScript(Train, Position, TrackPosition, SectionIndex,
                                                                   IsPartOfTrain, TimeElapsed);
                Vector3 translationVector = new Vector3(TranslateYDirection);                 //Must clone
                translationVector.Rotate(Direction, Up, Side);
                translationVector *= y;
                Position          += translationVector;
            }

            if (TranslateZFunction != null)
            {
                double z = TranslateZFunction.LastResult;
                if (UpdateFunctions)
                {
                    z = TranslateZFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }

                Vector3 translationVector = new Vector3(TranslateZDirection);                 //Must clone
                translationVector.Rotate(Direction, Up, Side);
                translationVector *= z;
                Position          += translationVector;
            }
            else if (TranslateZScriptFile != null)
            {
                //Translate X Script
                if (TranslateZAnimationScript == null)
                {
                    //Load the script if required
                    try
                    {
                        CSScript.GlobalSettings.TargetFramework = "v4.0";
                        TranslateZAnimationScript = CSScript.LoadCode(File.ReadAllText(TranslateZScriptFile))
                                                    .CreateObject("OpenBVEScript")
                                                    .AlignToInterface <AnimationScript>(true);
                    }
                    catch
                    {
                        currentHost.AddMessage(MessageType.Error, false,
                                               "An error occcured whilst parsing script " + TranslateZScriptFile);
                        TranslateZScriptFile = null;
                        return;
                    }
                }

                double z = TranslateZAnimationScript.ExecuteScript(Train, Position, TrackPosition, SectionIndex,
                                                                   IsPartOfTrain, TimeElapsed);
                Vector3 translationVector = new Vector3(TranslateZDirection);                 //Must clone
                translationVector.Rotate(Direction, Up, Side);
                translationVector *= z;
                Position          += translationVector;
            }

            // rotation
            bool   rotateX = RotateXFunction != null;
            bool   rotateY = RotateYFunction != null;
            bool   rotateZ = RotateZFunction != null;
            double radianX = 0.0;

            if (rotateX)
            {
                radianX = RotateXFunction.LastResult;
                if (UpdateFunctions)
                {
                    radianX = RotateXFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }

                if (RotateXDamping != null)
                {
                    RotateXDamping.Update(TimeElapsed, ref radianX, EnableDamping);
                }
            }

            double radianY = 0.0;

            if (rotateY)
            {
                radianY = RotateYFunction.LastResult;
                if (UpdateFunctions)
                {
                    radianY = RotateYFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }

                if (RotateYDamping != null)
                {
                    RotateYDamping.Update(TimeElapsed, ref radianY, EnableDamping);
                }
            }

            double radianZ = 0.0;

            if (rotateZ)
            {
                radianZ = RotateZFunction.LastResult;
                if (UpdateFunctions)
                {
                    radianZ = RotateZFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }

                if (RotateZDamping != null)
                {
                    RotateZDamping.Update(TimeElapsed, ref radianZ, EnableDamping);
                }
            }

            // texture shift
            bool shiftx = TextureShiftXFunction != null;
            bool shifty = TextureShiftYFunction != null;

            internalObject.TextureTranslation = Matrix4D.Identity;

            if (shiftx | shifty)
            {
                if (shiftx)
                {
                    double x = TextureShiftXFunction.LastResult;
                    if (UpdateFunctions)
                    {
                        x = TextureShiftXFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                    }

                    x -= System.Math.Floor(x);
                    internalObject.TextureTranslation *= Matrix4D.CreateTranslation(x * TextureShiftXDirection.X, x * TextureShiftXDirection.Y, 1.0);
                }

                if (shifty)
                {
                    double y = TextureShiftYFunction.LastResult;
                    if (UpdateFunctions)
                    {
                        y = TextureShiftYFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                    }

                    y -= System.Math.Floor(y);
                    internalObject.TextureTranslation *= Matrix4D.CreateTranslation(y * TextureShiftYDirection.X, y * TextureShiftYDirection.Y, 1.0);
                }
            }

            // led
            bool   led      = LEDFunction != null;
            double ledangle = 0.0;

            if (led)
            {
                ledangle = LEDFunction.LastResult;
                if (UpdateFunctions)
                {
                    ledangle = LEDFunction.Perform(Train, CarIndex, Position, TrackPosition, SectionIndex, IsPartOfTrain, TimeElapsed, CurrentState);
                }
            }

            // null object
            if (States[CurrentState].Prototype == null)
            {
                return;
            }

            // led
            if (led)
            {
                /*
                 * Edges:         Vertices:
                 * 0 - bottom     0 - bottom-left
                 * 1 - left       1 - top-left
                 * 2 - top        2 - top-right
                 * 3 - right      3 - bottom-right
                 *                4 - center
                 * */
                int v = 1;
                if (LEDClockwiseWinding)
                {
                    /* winding is clockwise*/
                    if (ledangle < LEDInitialAngle)
                    {
                        ledangle = LEDInitialAngle;
                    }

                    if (ledangle < LEDLastAngle)
                    {
                        double currentEdgeFloat = System.Math.Floor(0.636619772367582 * (ledangle + 0.785398163397449));
                        int    currentEdge      = ((int)currentEdgeFloat % 4 + 4) % 4;
                        double lastEdgeFloat    = System.Math.Floor(0.636619772367582 * (LEDLastAngle + 0.785398163397449));
                        int    lastEdge         = ((int)lastEdgeFloat % 4 + 4) % 4;
                        if (lastEdge < currentEdge | lastEdge == currentEdge & System.Math.Abs(currentEdgeFloat - lastEdgeFloat) > 2.0)
                        {
                            lastEdge += 4;
                        }

                        if (currentEdge == lastEdge)
                        {
                            /* current angle to last angle */
                            {
                                double t = 0.5 + 0.636619772367582 * ledangle - currentEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge].X;
                                double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge].Y;
                                double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v].Coordinates = new Vector3(cx, cy, cz);
                                v++;
                            }
                            {
                                double t = 0.5 + 0.636619772367582 * LEDLastAngle - lastEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge].X;
                                double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge].Y;
                                double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v].Coordinates = new Vector3(lx, ly, lz);
                                v++;
                            }
                        }
                        else
                        {
                            {
                                /* current angle to square vertex */
                                double t = 0.5 + 0.636619772367582 * ledangle - currentEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge].X;
                                double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge].Y;
                                double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v + 0].Coordinates = new Vector3(cx, cy, cz);
                                States[CurrentState].Prototype.Mesh.Vertices[v + 1].Coordinates = LEDVectors[currentEdge];
                                v += 2;
                            }
                            for (int j = currentEdge + 1; j < lastEdge; j++)
                            {
                                /* square-vertex to square-vertex */
                                States[CurrentState].Prototype.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(j + 3) % 4];
                                States[CurrentState].Prototype.Mesh.Vertices[v + 1].Coordinates = LEDVectors[j % 4];
                                v += 2;
                            }

                            {
                                /* square vertex to last angle */
                                double t = 0.5 + 0.636619772367582 * LEDLastAngle - lastEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge % 4].X;
                                double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge % 4].Y;
                                double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge % 4].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(lastEdge + 3) % 4];
                                States[CurrentState].Prototype.Mesh.Vertices[v + 1].Coordinates = new Vector3(lx, ly, lz);
                                v += 2;
                            }
                        }
                    }
                }
                else
                {
                    /* winding is counter-clockwise*/
                    if (ledangle > LEDInitialAngle)
                    {
                        ledangle = LEDInitialAngle;
                    }

                    if (ledangle > LEDLastAngle)
                    {
                        double currentEdgeFloat = System.Math.Floor(0.636619772367582 * (ledangle + 0.785398163397449));
                        int    currentEdge      = ((int)currentEdgeFloat % 4 + 4) % 4;
                        double lastEdgeFloat    = System.Math.Floor(0.636619772367582 * (LEDLastAngle + 0.785398163397449));
                        int    lastEdge         = ((int)lastEdgeFloat % 4 + 4) % 4;
                        if (currentEdge < lastEdge | lastEdge == currentEdge & System.Math.Abs(currentEdgeFloat - lastEdgeFloat) > 2.0)
                        {
                            currentEdge += 4;
                        }

                        if (currentEdge == lastEdge)
                        {
                            /* current angle to last angle */
                            {
                                double t = 0.5 + 0.636619772367582 * LEDLastAngle - lastEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge].X;
                                double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge].Y;
                                double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v].Coordinates = new Vector3(lx, ly, lz);
                                v++;
                            }
                            {
                                double t = 0.5 + 0.636619772367582 * ledangle - currentEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = t - System.Math.Floor(t);
                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge].X;
                                double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge].Y;
                                double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v].Coordinates = new Vector3(cx, cy, cz);
                                v++;
                            }
                        }
                        else
                        {
                            {
                                /* current angle to square vertex */
                                double t = 0.5 + 0.636619772367582 * ledangle - currentEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double cx = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].X + t * LEDVectors[currentEdge % 4].X;
                                double cy = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Y + t * LEDVectors[currentEdge % 4].Y;
                                double cz = (1.0 - t) * LEDVectors[(currentEdge + 3) % 4].Z + t * LEDVectors[currentEdge % 4].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(currentEdge + 3) % 4];
                                States[CurrentState].Prototype.Mesh.Vertices[v + 1].Coordinates = new Vector3(cx, cy, cz);
                                v += 2;
                            }
                            for (int j = currentEdge - 1; j > lastEdge; j--)
                            {
                                /* square-vertex to square-vertex */
                                States[CurrentState].Prototype.Mesh.Vertices[v + 0].Coordinates = LEDVectors[(j + 3) % 4];
                                States[CurrentState].Prototype.Mesh.Vertices[v + 1].Coordinates = LEDVectors[j % 4];
                                v += 2;
                            }

                            {
                                /* square vertex to last angle */
                                double t = 0.5 + 0.636619772367582 * LEDLastAngle - lastEdgeFloat;
                                if (t < 0.0)
                                {
                                    t = 0.0;
                                }
                                else if (t > 1.0)
                                {
                                    t = 1.0;
                                }

                                t = 0.5 * (1.0 - System.Math.Tan(0.25 * (System.Math.PI - 2.0 * System.Math.PI * t)));
                                double lx = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].X + t * LEDVectors[lastEdge].X;
                                double ly = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Y + t * LEDVectors[lastEdge].Y;
                                double lz = (1.0 - t) * LEDVectors[(lastEdge + 3) % 4].Z + t * LEDVectors[lastEdge].Z;
                                States[CurrentState].Prototype.Mesh.Vertices[v + 0].Coordinates = new Vector3(lx, ly, lz);
                                States[CurrentState].Prototype.Mesh.Vertices[v + 1].Coordinates = LEDVectors[lastEdge % 4];
                                v += 2;
                            }
                        }
                    }
                }

                for (int j = v; v < 11; v++)
                {
                    States[CurrentState].Prototype.Mesh.Vertices[j].Coordinates = LEDVectors[4];
                }
            }

            // update prototype
            internalObject.Prototype = States[CurrentState].Prototype;

            // update VAO for led if required
            UpdateVAO = led;

            // update state
            // rotate
            internalObject.Rotate = Matrix4D.Identity;

            if (rotateX)
            {
                internalObject.Rotate *= Matrix4D.CreateFromAxisAngle(new Vector3(RotateXDirection.X, RotateXDirection.Y, -RotateXDirection.Z), 2.0 * System.Math.PI - radianX);
            }

            if (rotateY)
            {
                internalObject.Rotate *= Matrix4D.CreateFromAxisAngle(new Vector3(RotateYDirection.X, RotateYDirection.Y, -RotateYDirection.Z), 2.0 * System.Math.PI - radianY);
            }

            if (rotateZ)
            {
                internalObject.Rotate *= Matrix4D.CreateFromAxisAngle(new Vector3(RotateZDirection.X, RotateZDirection.Y, -RotateZDirection.Z), 2.0 * System.Math.PI - radianZ);
            }

            if (Camera != null && Camera.CurrentRestriction != CameraRestrictionMode.NotAvailable && Camera.CurrentRestriction != CameraRestrictionMode.Restricted3D)
            {
                internalObject.Rotate *= States[CurrentState].Translation * Matrix4D.CreateTranslation(-Position.X, -Position.Y, Position.Z);
                internalObject.Rotate *= (Matrix4D) new Transformation((Vector3)Camera.AbsoluteDirection, (Vector3)Camera.AbsoluteUp, (Vector3)Camera.AbsoluteSide);

                // translate
                double  dx  = -System.Math.Tan(Camera.Alignment.Yaw) - Camera.Alignment.Position.X;
                double  dy  = -System.Math.Tan(Camera.Alignment.Pitch) - Camera.Alignment.Position.Y;
                double  dz  = -Camera.Alignment.Position.Z;
                Vector3 add = Camera.AbsolutePosition + dx * Camera.AbsoluteSide + dy * Camera.AbsoluteUp + dz * Camera.AbsoluteDirection;
                internalObject.Translation = Matrix4D.CreateTranslation(add.X, add.Y, -add.Z);
            }
            else
            {
                internalObject.Rotate *= States[CurrentState].Translation;
                internalObject.Rotate *= (Matrix4D) new Transformation(Direction, Up, Side);

                // translate
                internalObject.Translation = Matrix4D.CreateTranslation(Position.X, Position.Y, -Position.Z);
            }

            // visibility changed
            // TouchElement is handled by another function.
            if (!IsTouch)
            {
                if (Show)
                {
                    if (Camera != null)
                    {
                        currentHost.ShowObject(internalObject, ObjectType.Overlay);
                    }
                    else
                    {
                        currentHost.ShowObject(internalObject, ObjectType.Dynamic);
                    }
                }
                else
                {
                    currentHost.HideObject(internalObject);
                }
            }
        }
예제 #8
0
파일: FBXImporter.cs 프로젝트: q4a/Flummery
        public override Asset Import(string path)
        {
            FBX   fbx   = FBX.Load(path);
            Model model = new Model();
            Dictionary <long, object>   components = new Dictionary <long, object>();
            Dictionary <long, Matrix4D> transforms = new Dictionary <long, Matrix4D>();

            Dictionary <long, string> triangulationErrors = new Dictionary <long, string>();

            string name = Path.GetFileNameWithoutExtension(path);

            if (fbx == null)
            {
                SceneManager.Current.RaiseError($"File \"{name}\" could not be opened.  Please ensure this is a binary FBX file.");
                return(null);
            }

            FBXElem objects = fbx.Elements.Find(e => e.ID == "Objects");

            Matrix4D worldMatrix = createTransformFor(fbx.Elements.Find(e => e.ID == "GlobalSettings").Children[1], out Quaternion.RotationOrder order);

            foreach (FBXElem material in objects.Children.Where(e => e.ID == "Material"))
            {
                string matName = material.Properties[1].Value.ToString();
                matName = matName.Substring(0, matName.IndexOf("::"));
                Material m = new Material {
                    Name = matName
                };
                components.Add((long)material.Properties[0].Value, m);

                Console.WriteLine($"Added material \"{matName}\" ({material.Properties[0].Value})");
            }

            foreach (FBXElem video in objects.Children.Where(e => e.ID == "Video"))
            {
                FBXElem content = video.Children.Find(e => e.ID == "Content");

                if (content.Properties[0].Size > 4)
                {
                    components.Add((long)video.Properties[0].Value, (byte[])content.Properties[0].Value);
                }
            }

            IEnumerable <FBXElem> textures = objects.Children.Where(e => e.ID == "Texture");

            foreach (FBXElem texture in textures)
            {
                string fullFile = texture.Children.Find(e => e.ID == "FileName").Properties[0].Value.ToString();
                if (fullFile.IndexOf('.') == -1)
                {
                    continue;
                }
                string file = Path.GetFileName(fullFile);

                Texture t = new Texture();

                long videoKey = (long)fbx.Elements.Find(e => e.ID == "Connections").Children.Where(c => (long)c.Properties[2].Value == (long)texture.Properties[0].Value).First().Properties[1].Value;

                if (components.ContainsKey(videoKey))
                {
                    using (FileStream fs = new FileStream(Path.Combine(Path.GetDirectoryName(path), file), FileMode.Create))
                        using (BinaryWriter bw = new BinaryWriter(fs))
                        {
                            bw.Write((byte[])components[videoKey]);
                        }
                }

                t = SceneManager.Current.Content.Load(Path.GetFileName(file));

                switch (fbx.Elements.Find(e => e.ID == "Connections").Children.Where(c => (long)c.Properties[1].Value == (long)texture.Properties[0].Value).First().Properties.Last().Value.ToString())
                {
                case "NormalMap":
                    t.Type = Texture.TextureType.Normal;
                    break;

                case "SpecularColor":
                    t.Type = Texture.TextureType.Specular;
                    break;
                }

                if (!components.ContainsKey((long)texture.Properties[0].Value))
                {
                    components.Add((long)texture.Properties[0].Value, t);

                    Console.WriteLine($"Added texture \"{file}\" ({texture.Properties[0].Value})");
                }
            }

            foreach (FBXElem element in objects.Children.Where(e => e.ID == "Model"))
            {
                string modelName = element.Properties[1].Value.ToString();
                modelName = modelName.Substring(0, modelName.IndexOf("::"));

                components.Add((long)element.Properties[0].Value, new ModelMesh {
                    Name = modelName, Tag = (long)element.Properties[0].Value
                });

                Console.WriteLine("Added model \"{0}\" ({1})", modelName, element.Properties[0].Value);

                FBXElem  properties      = element.Children.Find(c => c.ID == "Properties70");
                Matrix4D m               = Matrix4D.Identity;
                bool     bRotationActive = false;

                Vector3    lclTranslation = Vector3.Zero;
                Quaternion lclRotation    = Quaternion.Identity;
                Quaternion preRotation    = Quaternion.Identity;
                Quaternion postRotation   = Quaternion.Identity;
                Vector3    rotationPivot  = Vector3.Zero;
                Vector3    rotationOffset = Vector3.Zero;
                Vector3    lclScaling     = Vector3.One;
                Vector3    scalingPivot   = Vector3.Zero;
                Vector3    scalingOffset  = Vector3.Zero;

                Vector3    geoPosition = Vector3.Zero;
                Quaternion geoRotation = Quaternion.Identity;
                Vector3    geoScale    = Vector3.One;

                FBXElem property;

                property = properties.Children.GetProperty("RotationActive");
                if (property != null)
                {
                    bRotationActive = ((int)property.Properties[4].Value == 1);
                }

                property = properties.Children.GetProperty("ScalingPivot");
                if (property != null)
                {
                    scalingPivot = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("Lcl Scaling");
                if (property != null)
                {
                    lclScaling = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("ScalingOffset");
                if (property != null)
                {
                    scalingOffset = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("RotationPivot");
                if (property != null)
                {
                    rotationPivot = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("PostRotation");
                if (property != null)
                {
                    postRotation = MakeQuaternion(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value),
                        order
                        );
                }

                property = properties.Children.GetProperty("Lcl Rotation");
                if (property != null)
                {
                    lclRotation = MakeQuaternion(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value),
                        order
                        );
                }

                property = properties.Children.GetProperty("PreRotation");
                if (property != null)
                {
                    preRotation = MakeQuaternion(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value),
                        order
                        );
                }

                property = properties.Children.GetProperty("RotationOffset");
                if (property != null)
                {
                    rotationOffset = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("Lcl Translation");
                if (property != null)
                {
                    lclTranslation = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("GeometricTranslation");
                if (property != null)
                {
                    geoPosition = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                property = properties.Children.GetProperty("GeometricRotation");
                if (property != null)
                {
                    geoRotation = MakeQuaternion(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value),
                        order
                        );
                }

                property = properties.Children.GetProperty("GeometricScaling");
                if (property != null)
                {
                    geoScale = new Vector3(
                        Convert.ToSingle(property.Properties[4].Value),
                        Convert.ToSingle(property.Properties[5].Value),
                        Convert.ToSingle(property.Properties[6].Value)
                        );
                }

                m =
                    Matrix4D.CreateTranslation(scalingPivot).Inverted() *
                    Matrix4D.CreateScale(lclScaling) *
                    Matrix4D.CreateTranslation(scalingPivot) *
                    Matrix4D.CreateTranslation(scalingOffset) *
                    Matrix4D.CreateTranslation(rotationPivot).Inverted() *
                    Matrix4D.CreateFromQuaternion(postRotation) *
                    Matrix4D.CreateFromQuaternion(lclRotation) *
                    Matrix4D.CreateFromQuaternion(preRotation) *
                    Matrix4D.CreateTranslation(rotationPivot) *
                    Matrix4D.CreateTranslation(rotationOffset) *
                    Matrix4D.CreateTranslation(lclTranslation);

                if (m != Matrix4D.Identity)
                {
                    transforms.Add((long)element.Properties[0].Value, m);
                }
            }

            foreach (FBXElem element in objects.Children.Where(e => e.ID == "Geometry"))
            {
                bool bUVs          = true;
                bool bNorms        = true;
                bool bColours      = true;
                bool bUseIndexNorm = false;

                bool bNeedsTriangulating = false;

                string geometryName = element.Properties[1].Value.ToString();
                geometryName = geometryName.Substring(0, geometryName.IndexOf("::"));

                List <Vector3> verts   = new List <Vector3>();
                List <Vector3> norms   = new List <Vector3>();
                List <Vector2> uvs     = new List <Vector2>();
                List <Colour>  colours = new List <Colour>();

                double[] vertParts = (double[])element.Children.Find(e => e.ID == "Vertices").Properties[0].Value;
                for (int i = 0; i < vertParts.Length; i += 3)
                {
                    verts.Add(new Vector3((float)vertParts[i + 0], (float)vertParts[i + 1], (float)vertParts[i + 2]));
                }

                SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Vertices");

                FBXElem normElem = element.Children.Find(e => e.ID == "LayerElementNormal");
                if (normElem != null)
                {
                    double[] normParts = (double[])normElem.Children.Find(e => e.ID == "Normals").Properties[0].Value;
                    for (int i = 0; i < normParts.Length; i += 3)
                    {
                        norms.Add(new Vector3((float)normParts[i + 0], (float)normParts[i + 1], (float)normParts[i + 2]));
                    }

                    bUseIndexNorm = (normElem.Children.Find(e => e.ID == "MappingInformationType").Properties[0].Value.ToString() == "ByVertice");

                    SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Normals");
                }
                else
                {
                    bNorms = false;
                }

                FBXElem colourElem = element.Children.Find(e => e.ID == "LayerElementColor");
                if (colourElem != null)
                {
                    double[] colourParts = (double[])colourElem.Children.Find(e => e.ID == "Colors").Properties[0].Value;

                    FBXElem colourReferenceType = colourElem.Children.Find(e => e.ID == "ReferenceInformationType");

                    switch (colourReferenceType.Properties[0].Value.ToString())
                    {
                    case "IndexToDirect":
                        int[] colourIndicies = (int[])colourElem.Children.Find(e => e.ID == "ColorIndex").Properties[0].Value;
                        for (int i = 0; i < colourIndicies.Length; i++)
                        {
                            int offset = colourIndicies[i] * 4;
                            colours.Add(new Colour(
                                            (float)colourParts[offset + 0],
                                            (float)colourParts[offset + 1],
                                            (float)colourParts[offset + 2],
                                            (float)colourParts[offset + 3])
                                        );
                        }
                        break;

                    case "Direct":
                        bColours = false;
                        break;

                    default:
                        throw new NotImplementedException($"Unsupported Colour Reference Type: {colourReferenceType.Properties[0].Value}");
                    }

                    SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Colours");
                }
                else
                {
                    bColours = false;
                }

                FBXElem uvElem = element.Children.Find(e => e.ID == "LayerElementUV");
                if (uvElem != null)
                {
                    double[] uvParts = (double[])uvElem.Children.Find(e => e.ID == "UV").Properties[0].Value;

                    FBXElem uvReferenceType = uvElem.Children.Find(e => e.ID == "ReferenceInformationType");
                    if (uvReferenceType.Properties[0].Value.ToString() == "IndexToDirect")
                    {
                        List <Vector2> luvs = new List <Vector2>();
                        for (int i = 0; i < uvParts.Length; i += 2)
                        {
                            luvs.Add(new Vector2((float)uvParts[i + 0], 1 - (float)uvParts[i + 1]));
                        }

                        int[] uvindicies = (int[])uvElem.Children.Find(e => e.ID == "UVIndex").Properties[0].Value;
                        for (int i = 0; i < uvindicies.Length; i++)
                        {
                            if (uvindicies[i] == -1)
                            {
                                uvs.Add(Vector2.Zero);
                            }
                            else
                            {
                                uvs.Add(luvs[uvindicies[i]]);
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < uvParts.Length; i += 2)
                        {
                            uvs.Add(new Vector2((float)uvParts[i + 0], (float)uvParts[i + 1]));
                        }
                    }

                    SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->UVs");
                }
                else
                {
                    bUVs = false;
                }

                int[]          indicies = (int[])element.Children.Find(e => e.ID == "PolygonVertexIndex").Properties[0].Value;
                List <FBXFace> faces    = new List <FBXFace>();
                FBXFace        face     = new FBXFace();
                int            j        = 0;

                for (int i = 0; i < indicies.Length; i++)
                {
                    bool bFace = false;
                    int  index = indicies[i];

                    if (index < 0)
                    {
                        bFace = true;
                        index = (index * -1) - 1;
                    }

                    j++;
                    face.AddVertex(verts[index], bNorms ? norms[bUseIndexNorm ? index : i] : Vector3.Zero, bUVs ? uvs[i] : Vector2.Zero, bColours ? colours[i] : Colour.White);

                    if (bFace)
                    {
                        if (j > 3)
                        {
                            triangulationErrors.Add((long)element.Properties[0].Value, geometryName);
                            bNeedsTriangulating = true;
                            break;
                        }

                        faces.Add(face);
                        face = new FBXFace();
                        j    = 0;
                    }
                }

                List <ModelMeshPart> parts = new List <ModelMeshPart>();

                if (!bNeedsTriangulating)
                {
                    SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Faces");

                    FBXElem elemMaterial = element.Children.Find(e => e.ID == "LayerElementMaterial");
                    if (elemMaterial != null)
                    {
                        int[] faceMaterials = (int[])elemMaterial.Children.Find(e => e.ID == "Materials").Properties[0].Value;
                        for (int i = 0; i < faceMaterials.Length; i++)
                        {
                            faces[i].MaterialID = faceMaterials[i];
                        }

                        SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->Materials");
                    }


                    IEnumerable <IGrouping <int, FBXFace> > materialGroups = faces.GroupBy(f => f.MaterialID);

                    int processedFaceCount  = 0,
                        processedGroupCount = 0;

                    foreach (IGrouping <int, FBXFace> materialGroup in materialGroups)
                    {
                        IEnumerable <IGrouping <int, FBXFace> > smoothingGroups = materialGroup.GroupBy(f => f.SmoothingGroup);

                        foreach (IGrouping <int, FBXFace> smoothingGroup in smoothingGroups)
                        {
                            ModelMeshPart meshpart = new ModelMeshPart {
                                PrimitiveType = Flummery.Core.PrimitiveType.Triangles
                            };
                            processedFaceCount = 0;

                            foreach (FBXFace groupface in smoothingGroup)
                            {
                                foreach (Vertex vert in groupface.Vertices)
                                {
                                    meshpart.AddVertex(vert.Position, vert.Normal, vert.UV, vert.Colour);
                                }

                                processedFaceCount++;

                                if (processedFaceCount % 250 == 0)
                                {
                                    SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->MeshPart[{processedGroupCount}]->Face[{processedFaceCount}]");
                                }
                            }

                            meshpart.Key = materialGroup.Key;

                            parts.Add(meshpart);
                            SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}->MeshPart");

                            processedGroupCount++;
                        }
                    }
                }

                components.Add((long)element.Properties[0].Value, parts);
                SceneManager.Current.UpdateProgress($"Processed {element.Properties[1].Value}");
            }

            Dictionary <long, BoneType> nodeAttributes  = new Dictionary <long, BoneType>();
            Dictionary <long, object>   nodeAttachments = new Dictionary <long, object>();

            foreach (FBXElem nodeAttribute in objects.Children.Where(e => e.ID == "NodeAttribute"))
            {
                FBXElem typeFlags = nodeAttribute.Children.Find(e => e.ID == "TypeFlags");
                if (typeFlags != null)
                {
                    switch (typeFlags.Properties[0].Value.ToString().ToLower())
                    {
                    case "light":
                        LIGHT light = new LIGHT();

                        FBXElem lightType = nodeAttribute.Children.Find(c => c.ID == "Properties70").Children.GetProperty("LightType");
                        light.Type = (LIGHT.LightType)(lightType == null ? 0 : lightType.Properties[4].Value);

                        nodeAttributes.Add((long)nodeAttribute.Properties[0].Value, BoneType.Light);
                        nodeAttachments.Add((long)nodeAttribute.Properties[0].Value, light);
                        break;

                    default:
                        // null node
                        break;
                    }
                }
            }

            string[] connectionOrder = new string[] { "System.Collections.Generic.List`1[Flummery.Core.ModelMeshPart]", "Flummery.Core.Texture", "Flummery.Core.Material", "Flummery.Core.ModelMesh" };
            FBXElem  connections     = fbx.Elements.Find(e => e.ID == "Connections");

            HashSet <long> loaded = new HashSet <long>();

            foreach (string connectionType in connectionOrder)
            {
                IEnumerable <FBXElem> connectionsOfType = connections.Children.Where(c => components.ContainsKey((long)c.Properties[1].Value) && components[(long)c.Properties[1].Value].GetType().ToString() == connectionType);

                foreach (FBXElem connection in connectionsOfType)
                {
                    long keyA = (long)connection.Properties[1].Value;
                    long keyB = (long)connection.Properties[2].Value;

                    Console.WriteLine("{0} is connected to {1} :: {2}", keyA, keyB, connectionType);

                    switch (connectionType)
                    {
                    case "Flummery.Core.ModelMesh":
                        int boneID;

                        if (keyB == 0)
                        {
                            boneID = model.AddMesh((ModelMesh)components[keyA]);
                            model.SetName(((ModelMesh)components[keyA]).Name, boneID);
                            if (transforms.ContainsKey(keyA))
                            {
                                model.SetTransform(transforms[keyA], boneID);
                            }

                            FBXElem attribute = connections.Children.FirstOrDefault(c => nodeAttributes.ContainsKey((long)c.Properties[1].Value) && (long)c.Properties[2].Value == keyA);
                            if (attribute != null)
                            {
                                keyA = (long)attribute.Properties[1].Value;

                                if (nodeAttributes.ContainsKey(keyA))
                                {
                                    model.Bones[boneID].Type = nodeAttributes[keyA];
                                }
                                if (nodeAttachments.ContainsKey(keyA))
                                {
                                    model.Bones[boneID].Attachment = nodeAttachments[keyA];
                                }
                            }
                        }
                        else
                        {
                            ModelMesh parent = model.FindMesh(keyB);
                            if (parent != null)
                            {
                                boneID = model.AddMesh((ModelMesh)components[keyA], parent.Parent.Index);
                                model.SetName(((ModelMesh)components[keyA]).Name, boneID);
                                if (transforms.ContainsKey(keyA))
                                {
                                    model.SetTransform(transforms[keyA], boneID);
                                }
                            }
                            else
                            {
                                if (!components.ContainsKey(keyB))
                                {
                                    Console.WriteLine("Components doesn't contain {0}", keyB);
                                }
                                else
                                {
                                    Console.WriteLine("Couldn't find {0}", ((ModelMesh)components[keyB]).Name);
                                }
                            }
                        }
                        break;

                    case "Flummery.Core.Texture":
                        if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Core.Material")
                        {
                            if (loaded.Add(keyA))
                            {
                                ((Material)components[keyB]).Texture = (Texture)components[keyA];
                                //SceneManager.Current.Add((Material)components[keyB]);
                            }
                        }
                        else
                        {
                            Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString());
                            Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString());
                        }
                        break;

                    case "System.Collections.Generic.List`1[Flummery.Core.ModelMeshPart]":
                        if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Core.ModelMesh")
                        {
                            if (triangulationErrors.ContainsKey(keyA))
                            {
                                triangulationErrors[keyA] += " (geometry of " + ((ModelMesh)components[keyB]).Name + ")";
                            }

                            foreach (ModelMeshPart part in (List <ModelMeshPart>)components[keyA])
                            {
                                ((ModelMesh)components[keyB]).AddModelMeshPart(part);
                            }
                        }
                        break;

                    case "Flummery.Core.Material":
                        if (components.ContainsKey(keyB) && components[keyB].GetType().ToString() == "Flummery.Core.ModelMesh")
                        {
                            List <FBXElem> materialLookup = connections.Children.Where(c => (long)c.Properties[2].Value == keyB).ToList();
                            for (int i = materialLookup.Count - 1; i > -1; i--)
                            {
                                if (!connectionsOfType.Any(c => (long)c.Properties[1].Value == (long)materialLookup[i].Properties[1].Value))
                                {
                                    materialLookup.RemoveAt(i);
                                }
                            }

                            foreach (ModelMeshPart part in ((ModelMesh)components[keyB]).MeshParts)
                            {
                                if ((long)materialLookup[(int)part.Key].Properties[1].Value == keyA)
                                {
                                    part.Material = (Material)components[keyA];
                                    SceneManager.Current.Add(part.Material);
                                }
                            }
                        }
                        break;

                    default:
                        Console.WriteLine("{0} is of unknown type {1}", keyA, components[keyA].GetType().ToString());
                        if (components.ContainsKey(keyB))
                        {
                            Console.WriteLine("{0} is of unknown type {1}", keyB, components[keyB].GetType().ToString());
                        }
                        Console.WriteLine("===");
                        break;
                    }
                }
            }

            if (triangulationErrors.Count > 0)
            {
                SceneManager.Current.UpdateProgress($"Failed to load {name}");

                string error = $"File \"{name}\" has part{(triangulationErrors.Count > 1 ? "s" : "")} that need been triangulating!  Please triangulate the following:";
                foreach (KeyValuePair <long, string> kvp in triangulationErrors)
                {
                    error += $"\r\n{kvp.Value}";
                }

                SceneManager.Current.RaiseError(error);

                return(null);
            }
            else
            {
                SceneManager.Current.UpdateProgress($"Loaded {name}");

                model.Santise();

                //if (worldMatrix != Matrix4D.Identity) { ModelManipulator.Freeze(model, worldMatrix); }
                ModelManipulator.FlipAxis(model, Axis.Z, true);

                return(model);
            }
        }
예제 #9
0
        public void RenderFace(Shader Shader, ObjectState State, MeshFace Face, Vector3 EyePosition, bool IsDebugTouchMode = false)
        {
            if (State.Prototype.Mesh.Vertices.Length < 1)
            {
                return;
            }

            VertexTemplate[]  vertices   = State.Prototype.Mesh.Vertices;
            MeshMaterial      material   = State.Prototype.Mesh.Materials[Face.Material];
            VertexArrayObject VAO        = (VertexArrayObject)State.Prototype.Mesh.VAO;
            VertexArrayObject NormalsVAO = (VertexArrayObject)State.Prototype.Mesh.NormalsVAO;

            if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0)
            {
                GL.Disable(EnableCap.CullFace);
            }
            else if (OptionBackFaceCulling)
            {
                if ((Face.Flags & MeshFace.Face2Mask) == 0)
                {
                    GL.Enable(EnableCap.CullFace);
                }
            }

            // matrix
            Matrix4D modelMatrix     = State.Scale * State.Rotate * State.Translation * Matrix4D.CreateTranslation(-EyePosition);
            Matrix4D modelViewMatrix = modelMatrix * CurrentViewMatrix;

            Shader.SetCurrentProjectionMatrix(CurrentProjectionMatrix);
            Shader.SetCurrentModelViewMatrix(modelViewMatrix);
            Shader.SetCurrentNormalMatrix(Matrix4D.Transpose(Matrix4D.Invert(modelViewMatrix)));
            Shader.SetCurrentTextureMatrix(State.TextureTranslation);

            if (OptionWireFrame || IsDebugTouchMode)
            {
                VAO.Bind();
                VAO.Draw(Shader.VertexLayout, PrimitiveType.LineLoop, Face.IboStartIndex, Face.Vertices.Length);
                VAO.UnBind();
                return;
            }

            // lighting
            if (material.NighttimeTexture == null)
            {
                if (OptionLighting)
                {
                    Shader.SetIsLight(true);
                    Shader.SetLightPosition(new Vector3(Lighting.OptionLightPosition.X, Lighting.OptionLightPosition.Y, -Lighting.OptionLightPosition.Z));
                    Shader.SetLightAmbient(new Color4(Lighting.OptionAmbientColor.R, Lighting.OptionAmbientColor.G, Lighting.OptionAmbientColor.B, 255));
                    Shader.SetLightDiffuse(new Color4(Lighting.OptionDiffuseColor.R, Lighting.OptionDiffuseColor.G, Lighting.OptionDiffuseColor.B, 255));
                    Shader.SetLightSpecular(new Color4(Lighting.OptionSpecularColor.R, Lighting.OptionSpecularColor.G, Lighting.OptionSpecularColor.B, 255));
                    Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A));                      // TODO
                    Shader.SetMaterialDiffuse(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A));
                    Shader.SetMaterialSpecular(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A));                     // TODO

                    if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0)
                    {
                        Shader.SetMaterialEmission(new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255));
                    }
                    else
                    {
                        Shader.SetMaterialEmission(new Color4(0.0f, 0.0f, 0.0f, 1.0f));
                    }

                    Shader.SetMaterialShininess(1.0f);

                    Lighting.OptionLightingResultingAmount = (Lighting.OptionAmbientColor.R + Lighting.OptionAmbientColor.G + Lighting.OptionAmbientColor.B) / 480.0f;

                    if (Lighting.OptionLightingResultingAmount > 1.0f)
                    {
                        Lighting.OptionLightingResultingAmount = 1.0f;
                    }
                }
                else
                {
                    Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A));                      // TODO
                }
            }
            else
            {
                Shader.SetMaterialAmbient(new Color4(material.Color.R, material.Color.G, material.Color.B, material.Color.A));                  // TODO
            }

            // fog
            if (OptionFog)
            {
                Shader.SetIsFog(true);
                Shader.SetFogStart(Fog.Start);
                Shader.SetFogEnd(Fog.End);
                Shader.SetFogColor(new Color4(Fog.Color.R, Fog.Color.G, Fog.Color.B, 255));
            }

            PrimitiveType DrawMode;

            switch (Face.Flags & MeshFace.FaceTypeMask)
            {
            case MeshFace.FaceTypeTriangles:
                DrawMode = PrimitiveType.Triangles;
                break;

            case MeshFace.FaceTypeTriangleStrip:
                DrawMode = PrimitiveType.TriangleStrip;
                break;

            case MeshFace.FaceTypeQuads:
                DrawMode = PrimitiveType.Quads;
                break;

            case MeshFace.FaceTypeQuadStrip:
                DrawMode = PrimitiveType.QuadStrip;
                break;

            default:
                DrawMode = PrimitiveType.Polygon;
                break;
            }

            // daytime polygon
            {
                // texture
                if (material.DaytimeTexture != null)
                {
                    if (currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
                    {
                        GL.Enable(EnableCap.Texture2D);
                        Shader.SetIsTexture(true);
                        Shader.SetTexture(0);
                        GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name);
                    }
                }

                // blend mode
                float factor;
                if (material.BlendMode == MeshMaterialBlendMode.Additive)
                {
                    factor = 1.0f;
                    GL.Enable(EnableCap.Blend);
                    GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One);
                    Shader.SetIsFog(false);
                }
                else if (material.NighttimeTexture == null)
                {
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;

                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    factor = 1.0f - 0.7f * blend;
                }
                else
                {
                    factor = 1.0f;
                }
                Shader.SetBrightness(factor);

                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData);
                }
                else
                {
                    alphaFactor = 1.0f;
                }
                Shader.SetOpacity(inv255 * material.Color.A * alphaFactor);

                // render polygon
                VAO.Bind();
                VAO.Draw(Shader.VertexLayout, DrawMode, Face.IboStartIndex, Face.Vertices.Length);
                VAO.UnBind();

                GL.BindTexture(TextureTarget.Texture2D, 0);
            }

            // nighttime polygon
            if (material.NighttimeTexture != null && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
            {
                // texture
                GL.Enable(EnableCap.Texture2D);
                Shader.SetIsTexture(true);
                Shader.SetTexture(0);
                GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name);

                GL.Enable(EnableCap.Blend);

                // alpha test
                GL.Enable(EnableCap.AlphaTest);
                GL.AlphaFunc(AlphaFunction.Greater, 0.0f);

                // blend mode
                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData);
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    alphaFactor *= blend;
                }
                else
                {
                    alphaFactor = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (alphaFactor > 1.0f)
                    {
                        alphaFactor = 1.0f;
                    }
                }

                Shader.SetOpacity(alphaFactor);

                // render polygon
                VAO.Bind();
                VAO.Draw(Shader.VertexLayout, DrawMode, Face.IboStartIndex, Face.Vertices.Length);
                VAO.UnBind();

                GL.BindTexture(TextureTarget.Texture2D, 0);

                RestoreBlendFunc();
                RestoreAlphaFunc();
            }

            GL.Disable(EnableCap.Texture2D);

            // normals
            if (OptionNormals)
            {
                Shader.SetIsTexture(false);
                Shader.SetBrightness(1.0f);
                Shader.SetOpacity(1.0f);

                NormalsVAO.Bind();
                NormalsVAO.Draw(Shader.VertexLayout, PrimitiveType.Lines, Face.NormalsIboStartIndex, Face.Vertices.Length * 2);
                NormalsVAO.UnBind();
            }

            // finalize
            if (material.BlendMode == MeshMaterialBlendMode.Additive)
            {
                RestoreBlendFunc();
            }
        }
예제 #10
0
        public void RenderFaceImmediateMode(ObjectState State, MeshFace Face, Vector3 EyePosition, bool IsDebugTouchMode = false)
        {
            if (State.Prototype.Mesh.Vertices.Length < 1)
            {
                return;
            }

            VertexTemplate[] vertices = State.Prototype.Mesh.Vertices;
            MeshMaterial     material = State.Prototype.Mesh.Materials[Face.Material];

            if (!OptionBackFaceCulling || (Face.Flags & MeshFace.Face2Mask) != 0)
            {
                GL.Disable(EnableCap.CullFace);
            }
            else if (OptionBackFaceCulling)
            {
                if ((Face.Flags & MeshFace.Face2Mask) == 0)
                {
                    GL.Enable(EnableCap.CullFace);
                }
            }
            Matrix4D modelMatrix = State.Scale * State.Rotate * State.Translation * Matrix4D.CreateTranslation(-EyePosition);

            // matrix
            unsafe
            {
                GL.MatrixMode(MatrixMode.Projection);
                GL.PushMatrix();
                fixed(double *matrixPointer = &CurrentProjectionMatrix.Row0.X)
                {
                    GL.LoadMatrix(matrixPointer);
                }

                GL.MatrixMode(MatrixMode.Modelview);
                GL.PushMatrix();
                fixed(double *matrixPointer = &CurrentViewMatrix.Row0.X)
                {
                    GL.LoadMatrix(matrixPointer);
                }

                double *matrixPointer2 = &modelMatrix.Row0.X;
                {
                    GL.MultMatrix(matrixPointer2);
                }

                GL.MatrixMode(MatrixMode.Texture);
                GL.PushMatrix();
                fixed(double *matrixPointer = &State.TextureTranslation.Row0.X)
                {
                    GL.LoadMatrix(matrixPointer);
                }
            }


            if (OptionWireFrame)
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);
            }

            // lighting
            if (material.NighttimeTexture == null)
            {
                if (OptionLighting)
                {
                    GL.Enable(EnableCap.Lighting);

                    if ((material.Flags & MeshMaterial.EmissiveColorMask) != 0)
                    {
                        GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new Color4(material.EmissiveColor.R, material.EmissiveColor.G, material.EmissiveColor.B, 255));
                    }
                    else
                    {
                        GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, new Color4(0.0f, 0.0f, 0.0f, 1.0f));
                    }
                }
            }

            // fog
            if (OptionFog)
            {
                GL.Enable(EnableCap.Fog);
            }

            PrimitiveType DrawMode;

            switch (Face.Flags & MeshFace.FaceTypeMask)
            {
            case MeshFace.FaceTypeTriangles:
                DrawMode = PrimitiveType.Triangles;
                break;

            case MeshFace.FaceTypeTriangleStrip:
                DrawMode = PrimitiveType.TriangleStrip;
                break;

            case MeshFace.FaceTypeQuads:
                DrawMode = PrimitiveType.Quads;
                break;

            case MeshFace.FaceTypeQuadStrip:
                DrawMode = PrimitiveType.QuadStrip;
                break;

            default:
                DrawMode = PrimitiveType.Polygon;
                break;
            }

            // daytime polygon
            {
                // texture
                if (material.DaytimeTexture != null)
                {
                    if (currentHost.LoadTexture(material.DaytimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
                    {
                        GL.Enable(EnableCap.Texture2D);
                        GL.BindTexture(TextureTarget.Texture2D, material.DaytimeTexture.OpenGlTextures[(int)material.WrapMode].Name);
                    }
                }

                // blend mode
                float factor;
                if (material.BlendMode == MeshMaterialBlendMode.Additive)
                {
                    factor = 1.0f;
                    GL.Enable(EnableCap.Blend);
                    GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.One);
                    GL.Disable(EnableCap.Fog);
                }
                else if (material.NighttimeTexture == null)
                {
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;

                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    factor = 1.0f - 0.7f * blend;
                }
                else
                {
                    factor = 1.0f;
                }

                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData);
                }
                else
                {
                    alphaFactor = 1.0f;
                }

                GL.Begin(DrawMode);

                if (OptionWireFrame)
                {
                    GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * material.Color.R * factor, inv255 * material.Color.G * factor, inv255 * material.Color.B * factor, inv255 * material.Color.A * alphaFactor);
                }

                for (int i = 0; i < Face.Vertices.Length; i++)
                {
                    GL.Normal3(Face.Vertices[i].Normal.X, Face.Vertices[i].Normal.Y, -Face.Vertices[i].Normal.Z);
                    GL.TexCoord2(vertices[Face.Vertices[i].Index].TextureCoordinates.X, vertices[Face.Vertices[i].Index].TextureCoordinates.Y);

                    if (vertices[Face.Vertices[i].Index] is ColoredVertex)
                    {
                        ColoredVertex v = (ColoredVertex)vertices[Face.Vertices[i].Index];
                        GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                    }

                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z);
                }

                GL.End();

                GL.BindTexture(TextureTarget.Texture2D, 0);
            }

            // nighttime polygon
            if (material.NighttimeTexture != null && currentHost.LoadTexture(material.NighttimeTexture, (OpenGlTextureWrapMode)material.WrapMode))
            {
                // texture
                GL.Enable(EnableCap.Texture2D);
                GL.BindTexture(TextureTarget.Texture2D, material.NighttimeTexture.OpenGlTextures[(int)material.WrapMode].Name);

                GL.Enable(EnableCap.Blend);

                // alpha test
                GL.Enable(EnableCap.AlphaTest);
                GL.AlphaFunc(AlphaFunction.Greater, 0.0f);

                // blend mode
                float alphaFactor;
                if (material.GlowAttenuationData != 0)
                {
                    alphaFactor = (float)Glow.GetDistanceFactor(modelMatrix, vertices, ref Face, material.GlowAttenuationData);
                    float blend = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (blend > 1.0f)
                    {
                        blend = 1.0f;
                    }

                    alphaFactor *= blend;
                }
                else
                {
                    alphaFactor = inv255 * material.DaytimeNighttimeBlend + 1.0f - Lighting.OptionLightingResultingAmount;
                    if (alphaFactor > 1.0f)
                    {
                        alphaFactor = 1.0f;
                    }
                }

                GL.Begin(DrawMode);

                if (OptionWireFrame)
                {
                    GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, 1.0f);
                }
                else
                {
                    GL.Color4(inv255 * material.Color.R, inv255 * material.Color.G, inv255 * material.Color.B, inv255 * material.Color.A * alphaFactor);
                }

                for (int i = 0; i < Face.Vertices.Length; i++)
                {
                    GL.Normal3(Face.Vertices[i].Normal.X, Face.Vertices[i].Normal.Y, -Face.Vertices[i].Normal.Z);
                    GL.TexCoord2(vertices[Face.Vertices[i].Index].TextureCoordinates.X, vertices[Face.Vertices[i].Index].TextureCoordinates.Y);

                    if (vertices[Face.Vertices[i].Index] is ColoredVertex)
                    {
                        ColoredVertex v = (ColoredVertex)vertices[Face.Vertices[i].Index];
                        GL.Color3(v.Color.R, v.Color.G, v.Color.B);
                    }

                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z);
                }

                GL.End();

                GL.BindTexture(TextureTarget.Texture2D, 0);

                RestoreBlendFunc();
                RestoreAlphaFunc();
            }

            GL.Disable(EnableCap.Texture2D);

            // normals
            if (OptionNormals)
            {
                for (int i = 0; i < Face.Vertices.Length; i++)
                {
                    GL.Begin(PrimitiveType.Lines);
                    GL.Color4(new Color4(material.Color.R, material.Color.G, material.Color.B, 255));
                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X, vertices[Face.Vertices[i].Index].Coordinates.Y, -vertices[Face.Vertices[i].Index].Coordinates.Z);
                    GL.Vertex3(vertices[Face.Vertices[i].Index].Coordinates.X + Face.Vertices[i].Normal.X, vertices[Face.Vertices[i].Index].Coordinates.Y + +Face.Vertices[i].Normal.Z, -(vertices[Face.Vertices[i].Index].Coordinates.Z + Face.Vertices[i].Normal.Z));
                    GL.End();
                }
            }

            // finalize
            if (OptionWireFrame)
            {
                GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            }

            if (material.BlendMode == MeshMaterialBlendMode.Additive)
            {
                RestoreBlendFunc();
            }

            GL.PopMatrix();

            GL.MatrixMode(MatrixMode.Modelview);
            GL.PopMatrix();

            GL.MatrixMode(MatrixMode.Projection);
            GL.PopMatrix();
        }