public int ReadFrom(byte[] Buffer, int StartIndex = 0) { int cursor = StartIndex; ServerID = BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; FloorTexture = BitConverter.ToUInt16(Buffer, cursor); cursor += TypeSizes.SHORT; CeilingTexture = BitConverter.ToUInt16(Buffer, cursor); cursor += TypeSizes.SHORT; TextureX = BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; TextureY = BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; FloorHeight = (Real)BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; CeilingHeight = (Real)BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; Light1 = Buffer[cursor]; cursor++; Flags = new RooSectorFlags(BitConverter.ToUInt32(Buffer, cursor)); cursor += TypeSizes.INT; if (HasSpeed) { Speed = Buffer[cursor]; cursor++; } // Check for attached subinfo if (Flags.IsSlopedFloor) { SlopeInfoFloor = new RooSectorSlopeInfo(RooVersion, Buffer, cursor); cursor += SlopeInfoFloor.ByteLength; } if (Flags.IsSlopedCeiling) { SlopeInfoCeiling = new RooSectorSlopeInfo(RooVersion, Buffer, cursor); cursor += SlopeInfoCeiling.ByteLength; } return(cursor - StartIndex); }
public unsafe void ReadFrom(ref byte *Buffer) { ServerID = *((short *)Buffer); Buffer += TypeSizes.SHORT; FloorTexture = *((ushort *)Buffer); Buffer += TypeSizes.SHORT; CeilingTexture = *((ushort *)Buffer); Buffer += TypeSizes.SHORT; TextureX = *((short *)Buffer); Buffer += TypeSizes.SHORT; TextureY = *((short *)Buffer); Buffer += TypeSizes.SHORT; FloorHeight = (Real)(*((short *)Buffer)); Buffer += TypeSizes.SHORT; CeilingHeight = (Real)(*((short *)Buffer)); Buffer += TypeSizes.SHORT; Light1 = Buffer[0]; Buffer++; Flags = new RooSectorFlags(*((uint *)Buffer)); Buffer += TypeSizes.INT; if (HasSpeed) { Speed = Buffer[0]; Buffer++; } // Check for attached subinfo if (Flags.IsSlopedFloor) { SlopeInfoFloor = new RooSectorSlopeInfo(RooVersion, ref Buffer); } if (Flags.IsSlopedCeiling) { SlopeInfoCeiling = new RooSectorSlopeInfo(RooVersion, ref Buffer); } }
/// <summary> /// Calculates the z coordinate of a point given by it's x,y components and /// a plane equation in slopeinfo. /// </summary> /// <param name="SlopeInfo"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns>Height of the point in legacy client FINENESS (1:1024)</returns> public static Real CalculateSlopeHeight(RooSectorSlopeInfo SlopeInfo, Real x, Real y) { return((-SlopeInfo.A * x - SlopeInfo.B * y - SlopeInfo.D) / SlopeInfo.C); }
/// <summary> /// Creates RenderInfo data (containing points and uv coordinates). /// Note: Z component is the height. /// </summary> /// <param name="IsFloor">Whether to create for floor or ceiling</param> /// <param name="Scale">Optional additional scale to apply.</param> /// <returns></returns> public RenderInfo GetRenderInfo(bool IsFloor, Real Scale = 1.0f) { // get possible slopeinfo either for floor or ceiling RooSectorSlopeInfo slopeInfo = null; if (IsFloor) { slopeInfo = Sector.SlopeInfoFloor; } if (!IsFloor) { slopeInfo = Sector.SlopeInfoCeiling; } // initialize renderinfo keeping points and uv coordinates RenderInfo RI = new RenderInfo(Vertices.Count); V3[] P = RI.P; V2[] UV = RI.UV; // initialize some more vars V3 intersectTop = new V3(0, 0, 0); V3 intersectLeft = new V3(0, 0, 0); int left = 0; int top = 0; Real inv64 = 1.0f / (Real)(64 << 4); Real oneOverC = 0.0f; // find most top left vertex and get its coordinates if (slopeInfo != null) { left = (int)slopeInfo.X0; top = (int)slopeInfo.Y0; oneOverC = 1.0f / slopeInfo.C; } else { for (int i = 0; i < Vertices.Count; i++) { if (Vertices[i].X < left) { left = Vertices[i].X; } if (Vertices[i].Y < top) { top = Vertices[i].Y; } } } // Start UV calculation for (int count = 0; count < Vertices.Count; count++) { // fill in point coordinates // this time we use the z as z and flip y/z (mogre!) when triangulating // instead of changing all the following ported code if (slopeInfo != null) { P[count].X = (Real)Vertices[count].X; P[count].Y = (Real)Vertices[count].Y; P[count].Z = (-slopeInfo.A * P[count].X - slopeInfo.B * P[count].Y - slopeInfo.D) * oneOverC; } else { P[count].X = (Real)Vertices[count].X; P[count].Y = (Real)Vertices[count].Y; if (IsFloor) { P[count].Z = (Real)(Sector.FloorHeight * 16.0f); } else { P[count].Z = (Real)(Sector.CeilingHeight * 16.0f); } } Real U, temp; // start uv if (slopeInfo != null) { V3 vectorU = new V3(0, 0, 0); V3 vectorV = new V3(0, 0, 0); V3 vector = new V3(0, 0, 0); Real distance; // calc distance from top line (vector u) U = ((P[count].X - slopeInfo.P0.X) * (slopeInfo.P1.X - slopeInfo.P0.X)) + ((P[count].Z - slopeInfo.P0.Z) * (slopeInfo.P1.Z - slopeInfo.P0.Z)) + ((P[count].Y - slopeInfo.P0.Y) * (slopeInfo.P1.Y - slopeInfo.P0.Y)); temp = ((slopeInfo.P1.X - slopeInfo.P0.X) * (slopeInfo.P1.X - slopeInfo.P0.X)) + ((slopeInfo.P1.Z - slopeInfo.P0.Z) * (slopeInfo.P1.Z - slopeInfo.P0.Z)) + ((slopeInfo.P1.Y - slopeInfo.P0.Y) * (slopeInfo.P1.Y - slopeInfo.P0.Y)); if (temp == 0) { temp = 1.0f; } U /= temp; intersectTop.X = slopeInfo.P0.X + U * (slopeInfo.P1.X - slopeInfo.P0.X); intersectTop.Z = slopeInfo.P0.Z + U * (slopeInfo.P1.Z - slopeInfo.P0.Z); intersectTop.Y = slopeInfo.P0.Y + U * (slopeInfo.P1.Y - slopeInfo.P0.Y); UV[count].X = (Real)System.Math.Sqrt( (P[count].X - intersectTop.X) * (P[count].X - intersectTop.X) + (P[count].Z - intersectTop.Z) * (P[count].Z - intersectTop.Z) + (P[count].Y - intersectTop.Y) * (P[count].Y - intersectTop.Y)); // calc distance from left line (vector v) U = ((P[count].X - slopeInfo.P0.X) * (slopeInfo.P2.X - slopeInfo.P0.X)) + ((P[count].Z - slopeInfo.P0.Z) * (slopeInfo.P2.Z - slopeInfo.P0.Z)) + ((P[count].Y - slopeInfo.P0.Y) * (slopeInfo.P2.Y - slopeInfo.P0.Y)); temp = ((slopeInfo.P2.X - slopeInfo.P0.X) * (slopeInfo.P2.X - slopeInfo.P0.X)) + ((slopeInfo.P2.Z - slopeInfo.P0.Z) * (slopeInfo.P2.Z - slopeInfo.P0.Z)) + ((slopeInfo.P2.Y - slopeInfo.P0.Y) * (slopeInfo.P2.Y - slopeInfo.P0.Y)); if (temp == 0) { temp = 1.0f; } U /= temp; intersectLeft.X = slopeInfo.P0.X + U * (slopeInfo.P2.X - slopeInfo.P0.X); intersectLeft.Z = slopeInfo.P0.Z + U * (slopeInfo.P2.Z - slopeInfo.P0.Z); intersectLeft.Y = slopeInfo.P0.Y + U * (slopeInfo.P2.Y - slopeInfo.P0.Y); UV[count].Y = (Real)System.Math.Sqrt( (P[count].X - intersectLeft.X) * (P[count].X - intersectLeft.X) + (P[count].Z - intersectLeft.Z) * (P[count].Z - intersectLeft.Z) + (P[count].Y - intersectLeft.Y) * (P[count].Y - intersectLeft.Y)); UV[count].X += (Sector.TextureY << 4) / 2.0f; UV[count].Y += (Sector.TextureX << 4) / 2.0f; vectorU.X = slopeInfo.P1.X - slopeInfo.P0.X; vectorU.Z = slopeInfo.P1.Z - slopeInfo.P0.Z; vectorU.Y = slopeInfo.P1.Y - slopeInfo.P0.Y; distance = (Real)System.Math.Sqrt((vectorU.X * vectorU.X) + (vectorU.Y * vectorU.Y)); if (distance == 0) { distance = 1.0f; } vectorU.X /= distance; vectorU.Z /= distance; vectorU.Y /= distance; vectorV.X = slopeInfo.P2.X - slopeInfo.P0.X; vectorV.Z = slopeInfo.P2.Z - slopeInfo.P0.Z; vectorV.Y = slopeInfo.P2.Y - slopeInfo.P0.Y; distance = (Real)System.Math.Sqrt((vectorV.X * vectorV.X) + (vectorV.Y * vectorV.Y)); if (distance == 0) { distance = 1.0f; } vectorV.X /= distance; vectorV.Z /= distance; vectorV.Y /= distance; vector.X = P[count].X - slopeInfo.P0.X; vector.Y = P[count].Y - slopeInfo.P0.Y; distance = (Real)System.Math.Sqrt((vector.X * vector.X) + (vector.Y * vector.Y)); if (distance == 0) { distance = 1.0f; } vector.X /= distance; vector.Y /= distance; if (((vector.X * vectorU.X) + (vector.Y * vectorU.Y)) <= 0) { UV[count].Y = -UV[count].Y; } if (((vector.X * vectorV.X) + (vector.Y * vectorV.Y)) > 0) { UV[count].X = -UV[count].X; } } else { UV[count].X = (Real)System.Math.Abs(Vertices[count].Y - top) - (Sector.TextureY << 4); UV[count].Y = (Real)System.Math.Abs(Vertices[count].X - left) - (Sector.TextureX << 4); } UV[count].X *= inv64; UV[count].Y *= inv64; // apply additional userscale P[count] *= Scale; } // Calculate the normal if (slopeInfo != null) { // if the sector is sloped, we get the normal from slopeinfo RI.Normal.X = slopeInfo.A; RI.Normal.Y = slopeInfo.B; RI.Normal.Z = slopeInfo.C; RI.Normal.Normalize(); } else if (IsFloor) { // default normal for non sloped floor RI.Normal.X = 0.0f; RI.Normal.Y = 0.0f; RI.Normal.Z = 1.0f; } else { // default normal for non sloped ceilings RI.Normal.X = 0.0f; RI.Normal.Y = 0.0f; RI.Normal.Z = -1.0f; } return(RI); }
/// <summary> /// Updates the P, UV and Normal properties for either floor or ceiling. /// Fills in current 3D data for the subsector vertices. /// Note: Z component is the height here. /// </summary> /// <param name="IsFloor">Whether to create for floor or ceiling</param> /// <param name="Scale">Optional additional scale to apply.</param> public void UpdateVertexData(bool IsFloor, Real Scale = 1.0f) { const Real INV64 = 1.0f / (Real)(64 << 4); // from old code.. V3 normal; V3[] p = new V3[Vertices.Count]; V2[] uv = new V2[Vertices.Count]; Real left = 0; Real top = 0; Real oneOverC = 0.0f; RooSectorSlopeInfo slopeInfo = (IsFloor) ? Sector.SlopeInfoFloor : Sector.SlopeInfoCeiling; /*****************************************************************/ // find most top left vertex and get its coordinates if (slopeInfo != null) { left = (int)slopeInfo.X0; top = (int)slopeInfo.Y0; oneOverC = 1.0f / slopeInfo.C; } else { for (int i = 0; i < Vertices.Count; i++) { if (Vertices[i].X < left) { left = Vertices[i].X; } if (Vertices[i].Y < top) { top = Vertices[i].Y; } } } /*****************************************************************/ for (int count = 0; count < Vertices.Count; count++) { // 1: Fill in vertex coordinates if (slopeInfo != null) { p[count].X = Vertices[count].X; p[count].Y = Vertices[count].Y; p[count].Z = (-slopeInfo.A * p[count].X - slopeInfo.B * p[count].Y - slopeInfo.D) * oneOverC; } else { p[count].X = Vertices[count].X; p[count].Y = Vertices[count].Y; p[count].Z = (IsFloor) ? (Sector.FloorHeight * 16.0f) : (Sector.CeilingHeight * 16.0f); } // 2.1: UV with slope if (slopeInfo != null) { V3 intersectTop; V3 intersectLeft; V3 vectorU; V3 vectorV; V3 vector; Real distance; Real U, temp; // calc distance from top line (vector u) U = ((p[count].X - slopeInfo.P0.X) * (slopeInfo.P1.X - slopeInfo.P0.X)) + ((p[count].Z - slopeInfo.P0.Z) * (slopeInfo.P1.Z - slopeInfo.P0.Z)) + ((p[count].Y - slopeInfo.P0.Y) * (slopeInfo.P1.Y - slopeInfo.P0.Y)); temp = ((slopeInfo.P1.X - slopeInfo.P0.X) * (slopeInfo.P1.X - slopeInfo.P0.X)) + ((slopeInfo.P1.Z - slopeInfo.P0.Z) * (slopeInfo.P1.Z - slopeInfo.P0.Z)) + ((slopeInfo.P1.Y - slopeInfo.P0.Y) * (slopeInfo.P1.Y - slopeInfo.P0.Y)); if (temp == 0.0f) { temp = 1.0f; } U /= temp; intersectTop.X = slopeInfo.P0.X + U * (slopeInfo.P1.X - slopeInfo.P0.X); intersectTop.Z = slopeInfo.P0.Z + U * (slopeInfo.P1.Z - slopeInfo.P0.Z); intersectTop.Y = slopeInfo.P0.Y + U * (slopeInfo.P1.Y - slopeInfo.P0.Y); uv[count].X = (Real)System.Math.Sqrt( (p[count].X - intersectTop.X) * (p[count].X - intersectTop.X) + (p[count].Z - intersectTop.Z) * (p[count].Z - intersectTop.Z) + (p[count].Y - intersectTop.Y) * (p[count].Y - intersectTop.Y)); // calc distance from left line (vector v) U = ((p[count].X - slopeInfo.P0.X) * (slopeInfo.P2.X - slopeInfo.P0.X)) + ((p[count].Z - slopeInfo.P0.Z) * (slopeInfo.P2.Z - slopeInfo.P0.Z)) + ((p[count].Y - slopeInfo.P0.Y) * (slopeInfo.P2.Y - slopeInfo.P0.Y)); temp = ((slopeInfo.P2.X - slopeInfo.P0.X) * (slopeInfo.P2.X - slopeInfo.P0.X)) + ((slopeInfo.P2.Z - slopeInfo.P0.Z) * (slopeInfo.P2.Z - slopeInfo.P0.Z)) + ((slopeInfo.P2.Y - slopeInfo.P0.Y) * (slopeInfo.P2.Y - slopeInfo.P0.Y)); if (temp == 0.0f) { temp = 1.0f; } U /= temp; intersectLeft.X = slopeInfo.P0.X + U * (slopeInfo.P2.X - slopeInfo.P0.X); intersectLeft.Z = slopeInfo.P0.Z + U * (slopeInfo.P2.Z - slopeInfo.P0.Z); intersectLeft.Y = slopeInfo.P0.Y + U * (slopeInfo.P2.Y - slopeInfo.P0.Y); uv[count].Y = (Real)System.Math.Sqrt( (p[count].X - intersectLeft.X) * (p[count].X - intersectLeft.X) + (p[count].Z - intersectLeft.Z) * (p[count].Z - intersectLeft.Z) + (p[count].Y - intersectLeft.Y) * (p[count].Y - intersectLeft.Y)); uv[count].X += (Sector.TextureY << 4) / 2.0f; uv[count].Y += (Sector.TextureX << 4) / 2.0f; vectorU.X = slopeInfo.P1.X - slopeInfo.P0.X; vectorU.Z = slopeInfo.P1.Z - slopeInfo.P0.Z; vectorU.Y = slopeInfo.P1.Y - slopeInfo.P0.Y; distance = (Real)System.Math.Sqrt((vectorU.X * vectorU.X) + (vectorU.Y * vectorU.Y)); if (distance == 0.0f) { distance = 1.0f; } vectorU.X /= distance; vectorU.Z /= distance; vectorU.Y /= distance; vectorV.X = slopeInfo.P2.X - slopeInfo.P0.X; vectorV.Z = slopeInfo.P2.Z - slopeInfo.P0.Z; vectorV.Y = slopeInfo.P2.Y - slopeInfo.P0.Y; distance = (Real)System.Math.Sqrt((vectorV.X * vectorV.X) + (vectorV.Y * vectorV.Y)); if (distance == 0.0f) { distance = 1.0f; } vectorV.X /= distance; vectorV.Z /= distance; vectorV.Y /= distance; vector.X = p[count].X - slopeInfo.P0.X; vector.Y = p[count].Y - slopeInfo.P0.Y; distance = (Real)System.Math.Sqrt((vector.X * vector.X) + (vector.Y * vector.Y)); if (distance == 0) { distance = 1.0f; } vector.X /= distance; vector.Y /= distance; if (((vector.X * vectorU.X) + (vector.Y * vectorU.Y)) <= 0) { uv[count].Y = -uv[count].Y; } if (((vector.X * vectorV.X) + (vector.Y * vectorV.Y)) > 0) { uv[count].X = -uv[count].X; } } // 2.2: UV without slope else { uv[count].X = System.Math.Abs(Vertices[count].Y - top) - (Sector.TextureY << 4); uv[count].Y = System.Math.Abs(Vertices[count].X - left) - (Sector.TextureX << 4); } uv[count].X *= INV64; uv[count].Y *= INV64; // apply additional userscale p[count] *= Scale; } /*****************************************************************/ // Calculate the normal if (slopeInfo != null) { // if the sector is sloped, we get the normal from slopeinfo normal.X = slopeInfo.A; normal.Y = slopeInfo.B; normal.Z = slopeInfo.C; normal.Normalize(); } else if (IsFloor) { // default normal for non sloped floor normal.X = 0.0f; normal.Y = 0.0f; normal.Z = 1.0f; } else { // default normal for non sloped ceilings normal.X = 0.0f; normal.Y = 0.0f; normal.Z = -1.0f; } /*****************************************************************/ // save in class properties depending on floor/ceiling if (IsFloor) { FloorP = p; FloorUV = uv; FloorNormal = normal; } else { CeilingP = p; CeilingUV = uv; CeilingNormal = normal; } }
/// <summary> /// Calculates the z coordinate of a point given by it's x,y components and /// a plane equation in slopeinfo. /// </summary> /// <param name="SlopeInfo"></param> /// <param name="x"></param> /// <param name="y"></param> /// <returns>Height of the point in legacy client FINENESS (1:1024)</returns> public static Real CalculateSlopeHeight(RooSectorSlopeInfo SlopeInfo, Real x, Real y) { return (-SlopeInfo.A * x - SlopeInfo.B * y - SlopeInfo.D) / SlopeInfo.C; }
public unsafe void ReadFrom(ref byte* Buffer) { ServerID = *((short*)Buffer); Buffer += TypeSizes.SHORT; FloorTexture = *((ushort*)Buffer); Buffer += TypeSizes.SHORT; CeilingTexture = *((ushort*)Buffer); Buffer += TypeSizes.SHORT; TextureX = *((short*)Buffer); Buffer += TypeSizes.SHORT; TextureY = *((short*)Buffer); Buffer += TypeSizes.SHORT; FloorHeight = (Real)(*((short*)Buffer)); Buffer += TypeSizes.SHORT; CeilingHeight = (Real)(*((short*)Buffer)); Buffer += TypeSizes.SHORT; Light1 = Buffer[0]; Buffer++; Flags = new RooSectorFlags(*((uint*)Buffer)); Buffer += TypeSizes.INT; if (HasSpeed) { Speed = Buffer[0]; Buffer++; } // Check for attached subinfo if (Flags.IsSlopedFloor) SlopeInfoFloor = new RooSectorSlopeInfo(RooVersion, ref Buffer); if (Flags.IsSlopedCeiling) SlopeInfoCeiling = new RooSectorSlopeInfo(RooVersion, ref Buffer); }
public int ReadFrom(byte[] Buffer, int StartIndex = 0) { int cursor = StartIndex; ServerID = BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; FloorTexture = BitConverter.ToUInt16(Buffer, cursor); cursor += TypeSizes.SHORT; CeilingTexture = BitConverter.ToUInt16(Buffer, cursor); cursor += TypeSizes.SHORT; TextureX = BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; TextureY = BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; FloorHeight = (Real)BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; CeilingHeight = (Real)BitConverter.ToInt16(Buffer, cursor); cursor += TypeSizes.SHORT; Light1 = Buffer[cursor]; cursor++ ; Flags = new RooSectorFlags(BitConverter.ToUInt32(Buffer, cursor)); cursor += TypeSizes.INT; if (HasSpeed) { Speed = Buffer[cursor]; cursor++; } // Check for attached subinfo if (Flags.IsSlopedFloor) { SlopeInfoFloor = new RooSectorSlopeInfo(RooVersion, Buffer, cursor); cursor += SlopeInfoFloor.ByteLength; } if (Flags.IsSlopedCeiling) { SlopeInfoCeiling = new RooSectorSlopeInfo(RooVersion, Buffer, cursor); cursor += SlopeInfoCeiling.ByteLength; } return cursor - StartIndex; }