Exemple #1
0
        } // Pick

        /// <summary>
        /// Pick the object that is on the X Y coordinates.
        /// If no object was found the result is a null pointer.
        /// </summary>
        public List <GameObject> Pick(Rectangle region, Matrix viewMatrix, Matrix projectionMatrix, Viewport viewport)
        {
            List <GameObject> pickedObjects = new List <GameObject>();

            try
            {
                RenderObjectsToPickerTexture(viewMatrix, projectionMatrix, viewport);

                #region Get the pixel from the texture

                if (region.Width == 0)
                {
                    region.Width = 1;
                }
                if (region.Height == 0)
                {
                    region.Height = 1;
                }
                Color[] colors = new Color[region.Width * region.Height];
                pickerTexture.Resource.GetData(0, region, colors, 0, region.Width * region.Height);

                #endregion

                #region Search the object

                byte red = 0, green = 0, blue = 0;
                foreach (GameObject obj in GameObject.GameObjects)
                {
                    // Select the next color
                    NextColor(ref red, ref green, ref blue);
                    if (colors.Any(color => color == new Color(red, green, blue)))
                    {
                        pickedObjects.Add(obj);
                    }
                }
                // Maybe it is an icon
                foreach (GameObject obj in GameObject.GameObjects)
                {
                    // Select the next color
                    NextColor(ref red, ref green, ref blue);
                    if (colors.Any(color => color == new Color(red, green, blue)))
                    {
                        pickedObjects.Add(obj);
                    }
                }

                #endregion
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Picker: operation failed: ", e);
            }
            return(pickedObjects);
        } // Pick
        private void InitializeStandingFrame1()
        {
            //attempt to get standing frame 1. It will have non-black pixels if it exists.
            Texture2D frameTexture = _npcSheet.GetNPCTexture(NPC.Data.Graphic, NPCFrame.StandingFrame1, NPC.Direction);

            Color[] textureData = new Color[frameTexture.Width * frameTexture.Height];
            frameTexture.GetData(textureData);

            hasStandFrame1 = textureData.Any(_c => _c.R != 0 || _c.G != 0 || _c.B != 0);
        }
Exemple #3
0
        private bool GetHasStandingAnimation()
        {
            var data = _enfFileProvider.ENFFile[NPC.ID];

            var frameTexture = _npcSpriteSheet.GetNPCTexture(data.Graphic, NPCFrame.StandingFrame1, NPC.Direction);
            var textureData  = new Color[frameTexture.Width * frameTexture.Height];

            frameTexture.GetData(textureData);

            return(textureData.Any(color => (color.R > 0 || color.G > 0 || color.B > 0) && color.A > 0));
        }
Exemple #4
0
        public NPC(NPCData data)
            : base(EOGame.Instance)
        {
            Index     = data.Index;
            X         = data.X;
            Y         = data.Y;
            Direction = data.Direction;

            Data = (NPCRecord)World.Instance.ENF.Data[data.ID];
            HP   = Data.HP;

            bool success = true;

            npcSheet = new EONPCSpriteSheet(this);
            int tries = 0;

            do
            {
                try
                {
                    //attempt to get standing frame 1. It will have non-black pixels if it exists.
                    Frame = NPCFrame.StandingFrame1;
                    Texture2D tmp     = npcSheet.GetNPCTexture();
                    Color[]   tmpData = new Color[tmp.Width * tmp.Height];
                    tmp.GetData(tmpData);
                    hasStandFrame1 = tmpData.Any(_c => _c.R != 0 || _c.G != 0 || _c.B != 0);

                    //get the first non-transparent pixel to determine offsets for name labels and damage counters
                    Frame   = NPCFrame.Standing;
                    tmp     = npcSheet.GetNPCTexture();
                    tmpData = new Color[tmp.Width * tmp.Height];
                    tmp.GetData(tmpData);
                    int i = 0;
                    while (i < tmpData.Length && tmpData[i].A == 0)
                    {
                        i++;
                    }
                    TopPixel = i == tmpData.Length - 1 ? 0 : i / tmp.Height;
                }                 //this block throws errors sometimes..no idea why. Keep looping until it works.
                catch (InvalidOperationException)
                {
                    success = false;
                    tries++;
                }
            } while (!success && tries < 3);

            if (tries >= 3)
            {
                throw new InvalidOperationException("Something weird happened initializing this NPC.");
            }

            m_chatBubble    = new EOChatBubble(this);
            m_damageCounter = new DamageCounter(this, GetType());
        }
Exemple #5
0
        public override string ToString()
        {
            var engine_code = (EngineCode?.Any() ?? false) ? string.Join(",", EngineCode) : "";
            var version = (Version?.Any() ?? false) ? string.Join(",", Version) : "";
            var engine_capacity = (EngineCapacity?.Any() ?? false) ? string.Join(",", EngineCapacity) : "";
            var vin = (Vin?.Any() ?? false) ? string.Join(",", Vin) : "";
            var engine_power = (EnginePower?.Any() ?? false) ? string.Join(",", EnginePower) : "";
            var gearbox = (Gearbox?.Any() ?? false) ? string.Join(",", Gearbox) : "";
            var transmission = (Transmission?.Any() ?? false) ? string.Join(",", Transmission) : "";
            var door_count = (DoorCount?.Any() ?? false) ? string.Join(",", DoorCount) : "";
            var nr_seats = (NrSeats?.Any() ?? false) ? string.Join(",", NrSeats) : "";
            var color = (Color?.Any() ?? false) ? string.Join(",", Color) : "";
            var registration = (Registration?.Any() ?? false) ? string.Join(",", Registration) : "";
            //var features = (Features?.Any() ?? false) ? string.Join(",", Features) : "";

            return string.Format("ID: " + AdId +
                "\nCena: " + PriceRaw +
                "\nTytul: " + Title +
                "\nOferta od: " + PrivateBusiness +
                "\nKategoria: " + Category +
                "\nWojewodztwo: " + Region +
                "\nMiasto: " + City +
                "\nMarka pojazdu: " + Make +
                "\nModel pojazdu: " + Model +
                "\nKod silnika: " + engine_code +
                "\nWersja: " + version +
                "\nRok produkcji: " + Year +
                "\nPrzebieg: " + Mileage +
                "\nPojemnosc skokowa: " + engine_capacity +
                "\nVin: " + vin +
                "\nRodzaj paliwa: " + FuelType +
                "\nMoc: " + engine_power +
                "\nSkrzynia biegow: " + gearbox +
                "\nNaped: " + transmission +                
                "\nTyp: " + BodyType +
                "\nLiczba drzwi: " + door_count +
                "\nLiczba miejsc: " + nr_seats +
                "\nKolor: " + color +
                "\nNumer rejestracyjny pojazdu: " + registration //+
                //"\nWyposazenie: " + features
            );
        }       
Exemple #6
0
        public NPC(NPCData data)
            : base(EOGame.Instance)
        {
            ApplyData(data);
            bool success = true;
            npcSheet = new EONPCSpriteSheet(this);
            int tries = 0;
            do
            {
                try
                {
                    //attempt to get standing frame 1. It will have non-black pixels if it exists.
                    Frame = NPCFrame.StandingFrame1;
                    Texture2D tmp = npcSheet.GetNPCTexture();
                    Color[] tmpData = new Color[tmp.Width*tmp.Height];
                    tmp.GetData(tmpData);
                    hasStandFrame1 = tmpData.Any(_c => _c.R != 0 || _c.G != 0 || _c.B != 0);

                    //get the first non-transparent pixel to determine offsets for name labels and damage counters
                    Frame = NPCFrame.Standing;
                    tmp = npcSheet.GetNPCTexture();
                    tmpData = new Color[tmp.Width*tmp.Height];
                    tmp.GetData(tmpData);
                    int i = 0;
                    while (i < tmpData.Length && tmpData[i].A == 0) i++;
                    TopPixel = i == tmpData.Length - 1 ? 0 : i/tmp.Height;

                } //this block throws errors sometimes..no idea why. Keep looping until it works.
                catch (InvalidOperationException)
                {
                    success = false;
                    tries++;
                }
            } while (!success && tries < 3);

            if(tries >= 3)
                throw new InvalidOperationException("Something weird happened initializing this NPC.");

            m_chatBubble = new EOChatBubble(this);
            m_damageCounter = new DamageCounter(this, GetType());
        }
Exemple #7
0
        private bool CollidesWithTrack(int moveInc)
        {
            var xPos = (float)(-Size.Width / 2 + Position.X + moveInc * Math.Cos(Rotation));
            var yPos = (float)(-Size.Height / 2 + Position.Y + moveInc * Math.Sin(Rotation));

            var collisionCheckTexture = CreateTrackCollisionTexture(xPos, yPos);

            var carPixels = Size.Width * Size.Height;

            var myColors = new Color[carPixels];

            collisionCheckTexture.GetData <Color>(0,
                                                  new Rectangle(collisionCheckTexture.Width / 2 - Size.Width / 2,
                                                                collisionCheckTexture.Height / 2 - Size.Height / 2,
                                                                Size.Width,
                                                                Size.Height),
                                                  myColors,
                                                  0, carPixels);

            return(myColors.Any(color => color != Color.Gray));
        }
Exemple #8
0
        public static Display ByPointsColors([KeepReferenceAttribute]Point[] points, Color[] colors)
        {
            if(points == null)
            {
                throw new ArgumentNullException("points");
            }

            if (!points.Any())
            {
                throw new ArgumentException(Resources.NoVertexExceptionMessage, "points");
            }

            if (points.Count() %3 != 0)
            {
                throw new ArgumentException(Resources.VerticesDivisibleByThreeExceptionMessage);
            }

            if(colors == null)
            {
                throw new ArgumentNullException("colors");
            }

            if (!colors.Any())
            {
                throw new ArgumentException(Resources.NoColorsExceptionMessage, "colors");
            }

            if (colors.Count() != points.Count())
            {
                throw new ArgumentException(Resources.VertexColorCountMismatchExceptionMessage, "colors");
            }

            return new Display(points, colors);
        }
Exemple #9
0
        /// <summary>
        /// Display color values on a surface.
        /// </summary>
        /// <param name="surface">The surface on which to apply the colors.</param>
        /// <param name="colors">A two dimensional list of Colors.</param>
        /// <returns>A Display object.</returns>
        public static Display BySurfaceColors(Surface surface, Color[][] colors)
        {
            if (surface == null)
            {
                throw new ArgumentNullException("surface");
            }

            if (colors == null)
            {
                throw new ArgumentNullException("colors");
            }

            if (!colors.Any())
            {
                throw new ArgumentException("You must supply some colors");
            }

            if (colors.Length == 1)
            {
                throw new ArgumentException("You must supply a two dimensional list of Colors.");
            }

            var size = colors[0].Count();
            foreach (var list in colors)
            {
                if (list.Count() != size)
                {
                    throw new ArgumentException("The list of colors must not be a jagged list.");
                }
            }

            return new Display(surface, colors);
        }
		private void InitializeStandingFrame1()
		{
			//attempt to get standing frame 1. It will have non-black pixels if it exists.
			Frame = NPCFrame.StandingFrame1;

			Texture2D frameTexture = _npcSheet.GetNPCTexture();
			Color[] textureData = new Color[frameTexture.Width * frameTexture.Height];
			frameTexture.GetData(textureData);

			hasStandFrame1 = textureData.Any(_c => _c.R != 0 || _c.G != 0 || _c.B != 0);
		}
Exemple #11
0
        /// <summary>
        /// Converts a buffer model to the GC format
        /// </summary>
        /// <param name="model">The model to converter</param>
        /// <param name="optimize">Whether to optimize the attaches</param>
        /// <param name="ignoreWeights">If conversion should still happen, despite weights existing</param>
        /// <param name="forceUpdate">Whether to convert, regardless of whether the attaches are already GC</param>
        public static void ConvertModelToGC(NJObject model, bool optimize = true, bool ignoreWeights = false, bool forceUpdate = false)
        {
            if (model.Parent != null)
            {
                throw new FormatException($"Model {model.Name} is not hierarchy root!");
            }

            if (model.AttachFormat == AttachFormat.GC && !forceUpdate)
            {
                return;
            }

            if (model.HasWeight && !ignoreWeights)
            {
                throw new FormatException("Model is weighted, cannot convert to basic format!");
            }

            AttachHelper.ProcessWeightlessModel(model, (cacheAtc, ogAtc) =>
            {
                // getting the vertex information
                Vector3[] positions = new Vector3[cacheAtc.vertices.Length];
                Vector3[] normals   = new Vector3[positions.Length];

                for (int i = 0; i < positions.Length; i++)
                {
                    var vtx      = cacheAtc.vertices[i];
                    positions[i] = vtx.Position;
                    normals[i]   = vtx.Normal;
                }

                // getting the corner information
                int cornerCount = 0;
                for (int i = 0; i < cacheAtc.corners.Length; i++)
                {
                    cornerCount += cacheAtc.corners[i].Length;
                }

                Vector2[] texcoords = new Vector2[cornerCount];
                Color[] colors      = new Color[cornerCount];
                Corner[][] corners  = new Corner[cacheAtc.corners.Length][];

                ushort cornerIndex = 0;
                for (int i = 0; i < corners.Length; i++)
                {
                    BufferCorner[] bufferCorners = cacheAtc.corners[i];
                    Corner[] meshCorners         = new Corner[bufferCorners.Length];
                    for (int j = 0; j < bufferCorners.Length; j++)
                    {
                        BufferCorner bcorner = bufferCorners[j];

                        texcoords[cornerIndex] = bcorner.Texcoord;
                        colors[cornerIndex]    = bcorner.Color;

                        meshCorners[j] = new Corner()
                        {
                            PositionIndex = bcorner.VertexIndex,
                            NormalIndex   = bcorner.VertexIndex,
                            UV0Index      = cornerIndex,
                            Color0Index   = cornerIndex
                        };

                        cornerIndex++;
                    }
                    corners[i] = meshCorners;
                }

                bool hasUVs = texcoords.Any(x => x != default);
                // if it has no normals, always use colors (even if they are all white)
                bool hasColors = colors.Any(x => x != Color.White) || !normals.Any(x => x != Vector3.UnitY);

                // Puttin together the vertex sets
                VertexSet[] vertexData = new VertexSet[2 + (hasUVs ? 1 : 0)];

                IndexAttributeParameter iaParam = new() { IndexAttributes = IndexAttributes.HasPosition };
                if (positions.Length > 256)
                {
                    iaParam.IndexAttributes |= IndexAttributes.Position16BitIndex;
                }
                vertexData[0] = new VertexSet(positions, false);

                if (hasColors)
                {
                    iaParam.IndexAttributes |= IndexAttributes.HasColor;
                    if (colors.Length > 256)
                    {
                        iaParam.IndexAttributes |= IndexAttributes.Color16BitIndex;
                    }

                    vertexData[1] = new VertexSet(colors);
                }
                else
                {
                    iaParam.IndexAttributes |= IndexAttributes.HasNormal;
                    if (normals.Length > 256)
                    {
                        iaParam.IndexAttributes |= IndexAttributes.Normal16BitIndex;
                    }

                    vertexData[1] = new VertexSet(normals, true);
                }

                if (hasUVs)
                {
                    iaParam.IndexAttributes |= IndexAttributes.HasUV;
                    if (texcoords.Length > 256)
                    {
                        iaParam.IndexAttributes |= IndexAttributes.UV16BitIndex;
                    }
                    vertexData[2] = new VertexSet(texcoords);
                }

                // stitching polygons together
                BufferMaterial currentMaterial = null;
                Mesh ProcessBufferMesh(int index)
                {
                    // generating parameter info
                    List <IParameter> parameters = new();

                    BufferMaterial cacheMaterial = cacheAtc.materials[index];
                    if (currentMaterial == null)
                    {
                        parameters.Add(new VtxAttrFmtParameter(VertexAttribute.Position));
                        parameters.Add(new VtxAttrFmtParameter(hasColors ? VertexAttribute.Color0 : VertexAttribute.Normal));
                        if (hasUVs)
                        {
                            parameters.Add(new VtxAttrFmtParameter(VertexAttribute.Tex0));
                        }
                        parameters.Add(iaParam);

                        if (cacheMaterial == null)
                        {
                            currentMaterial = new BufferMaterial()
                            {
                                MaterialAttributes = MaterialAttributes.noSpecular
                            };
                        }
                        else
                        {
                            currentMaterial = cacheMaterial;
                        }

                        parameters.Add(new LightingParameter()
                        {
                            LightingAttributes = LightingParameter.DefaultLighting.LightingAttributes,
                            ShadowStencil      = currentMaterial.ShadowStencil
                        });

                        parameters.Add(new BlendAlphaParameter()
                        {
                            SourceAlpha = currentMaterial.SourceBlendMode,
                            DestAlpha   = currentMaterial.DestinationBlendmode
                        });

                        parameters.Add(new AmbientColorParameter()
                        {
                            AmbientColor = currentMaterial.Ambient
                        });

                        TextureParameter texParam = new();
                        texParam.TextureID        = (ushort)currentMaterial.TextureIndex;

                        if (!currentMaterial.ClampU)
                        {
                            texParam.Tiling |= GCTileMode.RepeatU;
                        }

                        if (!currentMaterial.ClampV)
                        {
                            texParam.Tiling |= GCTileMode.RepeatV;
                        }

                        if (currentMaterial.MirrorU)
                        {
                            texParam.Tiling |= GCTileMode.MirrorU;
                        }

                        if (currentMaterial.MirrorV)
                        {
                            texParam.Tiling |= GCTileMode.MirrorV;
                        }

                        parameters.Add(texParam);

                        parameters.Add(Unknown9Parameter.DefaultValues);
                        parameters.Add(new TexCoordGenParameter()
                        {
                            TexCoordID = currentMaterial.TexCoordID,
                            TexGenType = currentMaterial.TexGenType,
                            TexGenSrc  = currentMaterial.TexGenSrc,
                            MatrixID   = currentMaterial.MatrixID
                        });
                    }
                    else
                    {
                        if (currentMaterial.ShadowStencil != cacheMaterial.ShadowStencil)
                        {
                            parameters.Add(new LightingParameter()
                            {
                                ShadowStencil = cacheMaterial.ShadowStencil
                            });
                        }

                        if (currentMaterial.SourceBlendMode != cacheMaterial.SourceBlendMode ||
                            currentMaterial.DestinationBlendmode != cacheMaterial.DestinationBlendmode)
                        {
                            parameters.Add(new BlendAlphaParameter()
                            {
                                SourceAlpha = cacheMaterial.SourceBlendMode,
                                DestAlpha   = cacheMaterial.DestinationBlendmode
                            });
                        }

                        if (currentMaterial.Ambient != cacheMaterial.Ambient)
                        {
                            parameters.Add(new AmbientColorParameter()
                            {
                                AmbientColor = cacheMaterial.Ambient
                            });
                        }

                        if (currentMaterial.TextureIndex != cacheMaterial.TextureIndex ||
                            currentMaterial.MirrorU != cacheMaterial.MirrorU ||
                            currentMaterial.MirrorV != cacheMaterial.MirrorV ||
                            currentMaterial.ClampU != cacheMaterial.ClampU ||
                            currentMaterial.ClampV != cacheMaterial.ClampV)
                        {
                            TextureParameter texParam = new();
                            texParam.TextureID        = (ushort)cacheMaterial.TextureIndex;

                            if (!cacheMaterial.ClampU)
                            {
                                texParam.Tiling |= GCTileMode.RepeatU;
                            }

                            if (!cacheMaterial.ClampV)
                            {
                                texParam.Tiling |= GCTileMode.RepeatV;
                            }

                            if (cacheMaterial.MirrorU)
                            {
                                texParam.Tiling |= GCTileMode.MirrorU;
                            }

                            if (cacheMaterial.MirrorV)
                            {
                                texParam.Tiling |= GCTileMode.MirrorV;
                            }

                            parameters.Add(texParam);
                        }

                        if (currentMaterial.TexCoordID != cacheMaterial.TexCoordID ||
                            currentMaterial.TexGenType != cacheMaterial.TexGenType ||
                            currentMaterial.TexGenSrc != cacheMaterial.TexGenSrc ||
                            currentMaterial.MatrixID != cacheMaterial.MatrixID)
                        {
                            parameters.Add(new TexCoordGenParameter()
                            {
                                TexCoordID = cacheMaterial.TexCoordID,
                                TexGenType = cacheMaterial.TexGenType,
                                TexGenSrc  = cacheMaterial.HasAttribute(MaterialAttributes.normalMapping) ? TexGenSrc.Normal : cacheMaterial.TexGenSrc,
                                MatrixID   = cacheMaterial.MatrixID
                            });
                        }

                        currentMaterial = cacheMaterial;
                    }

                    // note: a single triangle polygon can only carry 0xFFFF corners, so about 22k tris
                    Corner[] triangleCorners = corners[index];

                    List <Poly> polygons = new();
                    if (triangleCorners.Length > 0xFFFF)
                    {
                        int remainingLength = triangleCorners.Length;
                        int offset          = 0;
                        while (remainingLength > 0)
                        {
                            Corner[] finalCorners = new Corner[Math.Max(0xFFFF, remainingLength)];
                            Array.Copy(triangleCorners, offset, finalCorners, 0, finalCorners.Length);
                            offset          += finalCorners.Length;
                            remainingLength -= finalCorners.Length;

                            Poly triangle = new(PolyType.Triangles, finalCorners);
                            polygons.Add(triangle);
                        }
Exemple #12
0
		public NPC(NPCData data)
			: base(EOGame.Instance)
		{
			ApplyData(data);
			bool success = true;
			npcSheet = new EONPCSpriteSheet(((EOGame)Game).GFXManager, this);
			int tries = 0;
			do
			{
				try
				{
					//attempt to get standing frame 1. It will have non-black pixels if it exists.
					Frame = NPCFrame.StandingFrame1;
					Texture2D tmp = npcSheet.GetNPCTexture();
					Color[] tmpData = new Color[tmp.Width*tmp.Height];
					tmp.GetData(tmpData);
					hasStandFrame1 = tmpData.Any(_c => _c.R != 0 || _c.G != 0 || _c.B != 0);

					//get the first non-transparent pixel to determine offsets for name labels and damage counters
					Frame = NPCFrame.Standing;
					tmp = npcSheet.GetNPCTexture();
					tmpData = new Color[tmp.Width*tmp.Height];
					tmp.GetData(tmpData);
					int i = 0;
					while (i < tmpData.Length && tmpData[i].A == 0) i++;
					TopPixel = i == tmpData.Length - 1 ? 0 : i/tmp.Height;

				} //this block throws errors sometimes..no idea why. Keep looping until it works.
				catch (InvalidOperationException)
				{
					success = false;
					tries++;
				}
			} while (!success && tries < 3);

			if(tries >= 3)
				throw new InvalidOperationException("Something weird happened initializing this NPC.");

			m_chatBubble = new EOChatBubble(this);
			m_damageCounter = new DamageCounter(this);
			_mouseoverName = new XNALabel(new Rectangle(1, 1, 1, 1), Constants.FontSize08pt75)
			{
				Visible = false,
				Text = Data.Name,
				ForeColor = Color.White,
				AutoSize = false,
				DrawOrder = (int) ControlDrawLayer.BaseLayer + 3
			};
			_mouseoverName.DrawLocation = new Vector2(
				DrawArea.X + (DrawArea.Width - _mouseoverName.ActualWidth)/2f,
				DrawArea.Y + TopPixel - _mouseoverName.ActualHeight - 4);
			_mouseoverName.ResizeBasedOnText();
		}
Exemple #13
0
        /// <summary>
        /// Converts the buffer data of a model to BASIC attaches
        /// </summary>
        /// <param name="model">The tip of the model hierarchy to convert</param>
        /// <param name="optimize">Whether to optimize the data</param>
        /// <param name="ignoreWeights">Convert regardless of weight information being lost</param>
        /// <param name="forceUpdate">Still convert, even if the attaches are Basic already</param>
        public static void ConvertModelToBasic(NJObject model, bool optimize = true, bool ignoreWeights = false, bool forceUpdate = false)
        {
            if (model.Parent != null)
            {
                throw new FormatException($"Model {model.Name} is not hierarchy root!");
            }

            if (model.AttachFormat == AttachFormat.BASIC && !forceUpdate)
            {
                return;
            }

            if (model.HasWeight && !ignoreWeights)
            {
                throw new FormatException("Model is weighted, cannot convert to basic format!");
            }

            AttachHelper.ProcessWeightlessModel(model, (cacheAtc, ogAtc) =>
            {
                // getting the vertex information
                Vector3[] positions = new Vector3[cacheAtc.vertices.Length];
                Vector3[] normals   = new Vector3[positions.Length];
                bool hasNormals     = false;

                for (int i = 0; i < positions.Length; i++)
                {
                    var vtx      = cacheAtc.vertices[i];
                    positions[i] = vtx.Position;
                    normals[i]   = vtx.Normal;
                    if (vtx.Normal != Vector3.UnitY)
                    {
                        hasNormals = true;
                    }
                }

                if (!hasNormals)
                {
                    normals = null;
                }

                // putting together polygons
                Mesh[] meshes        = new Mesh[cacheAtc.corners.Length];
                Material[] materials = new Material[cacheAtc.corners.Length];

                for (int i = 0; i < cacheAtc.corners.Length; i++)
                {
                    // creating the material
                    Material mat        = new();
                    BufferMaterial bmat = cacheAtc.materials[i];
                    if (bmat != null)
                    {
                        mat.DiffuseColor     = bmat.Diffuse;
                        mat.SpecularColor    = bmat.Specular;
                        mat.Exponent         = bmat.SpecularExponent;
                        mat.TextureID        = bmat.TextureIndex;
                        mat.FilterMode       = bmat.TextureFiltering;
                        mat.MipmapDAdjust    = bmat.MipmapDistanceAdjust;
                        mat.SuperSample      = bmat.AnisotropicFiltering;
                        mat.ClampU           = bmat.ClampU;
                        mat.ClampV           = bmat.ClampV;
                        mat.MirrorU          = bmat.MirrorU;
                        mat.MirrorV          = bmat.MirrorV;
                        mat.UseAlpha         = bmat.UseAlpha;
                        mat.SourceAlpha      = bmat.SourceBlendMode;
                        mat.DestinationAlpha = bmat.DestinationBlendmode;
                        mat.DoubleSided      = !bmat.Culling;

                        mat.IgnoreLighting = bmat.HasAttribute(MaterialAttributes.noDiffuse);
                        mat.IgnoreSpecular = bmat.HasAttribute(MaterialAttributes.noSpecular);
                        mat.UseTexture     = bmat.HasAttribute(MaterialAttributes.useTexture);
                        mat.EnvironmentMap = bmat.HasAttribute(MaterialAttributes.normalMapping);
                    }
                    materials[i] = mat;

                    // creating the polygons

                    BufferCorner[] bCorners = cacheAtc.corners[i];
                    IPoly[] triangles       = new IPoly[bCorners.Length / 3];
                    Vector2[] texcoords     = new Vector2[bCorners.Length];
                    Color[] colors          = new Color[bCorners.Length];

                    Triangle current = new();
                    for (int j = 0; j < bCorners.Length; j++)
                    {
                        BufferCorner corner = bCorners[j];

                        int vIndex = j % 3;
                        current.Indices[vIndex] = corner.VertexIndex;
                        if (vIndex == 2)
                        {
                            triangles[(j - 2) / 3] = current;
                            current = new Triangle();
                        }

                        texcoords[j] = corner.Texcoord;
                        colors[j]    = corner.Color;
                    }

                    bool hasTexcoords = texcoords.Any(x => x != default);
                    bool hasColors    = colors.Any(x => x != Color.White);

                    Mesh basicmesh = new (BASICPolyType.Triangles, triangles, false, hasColors, hasTexcoords, (ushort)i);
                    if (hasColors)
                    {
                        basicmesh.Colors = colors;
                    }
                    if (hasTexcoords)
                    {
                        basicmesh.Texcoords = texcoords;
                    }

                    meshes[i] = basicmesh;
                }