/// <summary> /// Cuenta el numero de pixeles negros en la mitad indicada por <c>h</c>. /// </summary> /// <remarks> /// Si la imagen tiene un numero impar de pixeles se incluye la fila /// o columna central, segun el caso. /// </remarks> /// <param name="image">Imagen sobre la que se trabaja</param> /// <param name="h">Mitad a analizar</param> /// <returns>Numero de pixeles negros</returns> public static int NumBlackPixelsInHalf(FloatBitmap image, Half h) { int n=0; int width = image.Width; int height = image.Height; int halfWidth = width/2; int halfHeight = height/2; switch(h) { case(Half.Top): n=NumPixelsInArea(image,FloatBitmap.Black, 0,0, width,halfHeight); break; case(Half.Bottom): n=NumPixelsInArea(image,FloatBitmap.Black, 0,halfHeight, width,height); break; case(Half.Left): n=NumPixelsInArea(image,FloatBitmap.Black, 0,0, halfWidth,height); break; case(Half.Right): n=NumPixelsInArea(image,FloatBitmap.Black, halfWidth,0, width,height); break; } return n; }
public static bool TryConvertSingleToHalf(float value, out Half result) { result = (Half)value; return(BitConverter.SingleToInt32Bits((float)result) == BitConverter.SingleToInt32Bits(value)); }
public static bool IsNaN(Half half) { return ((half.value & 0x7fff) > 0x7c00); }
/// <summary> /// Converts the given object to the type of this converter, using the specified context and culture information. /// </summary> /// <param name="context">A <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context.</param> /// <param name="culture">A <see cref="T:System.Globalization.CultureInfo" />. If <c>null</c> is passed, the current culture is assumed.</param> /// <param name="value">The <see cref="T:System.Object" /> to convert.</param> /// <returns>An <see cref="T:System.Object" /> that represents the converted value.</returns> public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { if (culture == null) { culture = CultureInfo.CurrentCulture; } string @string = value as string; if (@string == null) { return base.ConvertFrom(context, culture, value); } @string = @string.Trim(); char[] separator = new char[] { culture.TextInfo.ListSeparator[0] }; string[] stringArray = @string.Split(separator); if (stringArray.Length != 1) { throw new ArgumentException("Invalid half format."); } float H = (float)TypeDescriptor.GetConverter(typeof(float)).ConvertFromString(context, culture, stringArray[0]); Half type = new Half(H); return type; }
internal extern static void VertexAttrib4hNV(UInt32 index, Half x, Half y, Half z, Half w);
internal extern static void Vertex3hNV(Half x, Half y, Half z);
internal extern static unsafe void TexCoord4hvNV(Half* v);
internal extern static void Color3hNV(Half red, Half green, Half blue);
public static bool IsNaN(Half half) { return((half.Value & 0x7fff) > 0x7c00); }
public static Half Abs(Half half) { return(Half.ToHalf((ushort)(half.Value & 0x7fff))); }
public static Half Negate(Half half) { return(Half.ToHalf((ushort)(half.Value ^ 0x8000))); }
public static unsafe float HalfToSingle(Half half) { uint result = MantissaTable[OffsetTable[half.Value >> 10] + (half.Value & 0x3ff)] + ExponentTable[half.Value >> 10]; return(*(float *)&result); }
public void ExportModelToDirectoryWithExportOptions(Model model, String directory, ExportOptions exportOptions) { //TODO: Figure out what to do with non-version 4 models. if (model != null && model.Version != 4) { return; } NumberFormatInfo format = new NumberFormatInfo(); format.NumberDecimalSeparator = "."; if (exportOptions.Package) { try { DirectoryInfo directoryInfo = Directory.CreateDirectory(directory + @"\" + Path.GetFileNameWithoutExtension(model.Name)); directory = directoryInfo.FullName; } catch (Exception) { } } if (exportOptions.Textures) { ImageImporter imageImporter = new ImageImporter(); ImageExporter imageExporter = new ImageExporter(); foreach (String textureString in model.TextureStrings) { MemoryStream textureMemoryStream = AssetManager.Instance.CreateAssetMemoryStreamByName(textureString); if (textureMemoryStream == null) { continue; } Image textureImage = imageImporter.LoadImageFromStream(textureMemoryStream); if (textureImage == null) { continue; } imageExporter.SaveImage(textureImage, exportOptions.TextureFormat.ImageType, directory + @"\" + Path.GetFileNameWithoutExtension(textureString) + @"." + exportOptions.TextureFormat.Extension); } } String path = directory + @"\" + Path.GetFileNameWithoutExtension(model.Name) + ".obj"; FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write); StreamWriter streamWriter = new StreamWriter(fileStream); for (Int32 i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; MaterialDefinition materialDefinition = MaterialDefinitionManager.Instance.MaterialDefinitions[model.Materials[(Int32)mesh.MaterialIndex].MaterialDefinitionHash]; VertexLayout vertexLayout = MaterialDefinitionManager.Instance.VertexLayouts[materialDefinition.DrawStyles[0].VertexLayoutNameHash]; //position VertexLayout.Entry.DataTypes positionDataType; Int32 positionOffset; Int32 positionStreamIndex; vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStreamIndex, out positionOffset); Mesh.VertexStream positionStream = mesh.VertexStreams[positionStreamIndex]; for (Int32 j = 0; j < mesh.VertexCount; ++j) { Vector3 position = readVector3(exportOptions, positionOffset, positionStream, j); position.X *= exportOptions.Scale.X; position.Y *= exportOptions.Scale.Y; position.Z *= exportOptions.Scale.Z; streamWriter.WriteLine("v " + position.X.ToString(format) + " " + position.Y.ToString(format) + " " + position.Z.ToString(format)); } //texture coordinates if (exportOptions.TextureCoordinates) { VertexLayout.Entry.DataTypes texCoord0DataType; Int32 texCoord0Offset = 0; Int32 texCoord0StreamIndex = 0; Boolean texCoord0Present = vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0StreamIndex, out texCoord0Offset); if (texCoord0Present) { Mesh.VertexStream texCoord0Stream = mesh.VertexStreams[texCoord0StreamIndex]; for (Int32 j = 0; j < mesh.VertexCount; ++j) { Vector2 texCoord; switch (texCoord0DataType) { case VertexLayout.Entry.DataTypes.Float2: texCoord.X = BitConverter.ToSingle(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + 0); texCoord.Y = 1.0f - BitConverter.ToSingle(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + 4); break; case VertexLayout.Entry.DataTypes.float16_2: texCoord.X = Half.FromBytes(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 0).ToSingle(); texCoord.Y = 1.0f - Half.FromBytes(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 2).ToSingle(); break; default: texCoord.X = 0; texCoord.Y = 0; break; } streamWriter.WriteLine("vt " + texCoord.X.ToString(format) + " " + texCoord.Y.ToString(format)); } } } } //faces UInt32 vertexCount = 0; for (Int32 i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; streamWriter.WriteLine("g Mesh" + i); for (Int32 j = 0; j < mesh.IndexCount; j += 3) { UInt32 index0, index1, index2; switch (mesh.IndexSize) { case 2: index0 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 0) + 1; index1 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 2) + 1; index2 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 4) + 1; break; case 4: index0 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 0) + 1; index1 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 4) + 1; index2 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 8) + 1; break; default: index0 = 0; index1 = 0; index2 = 0; break; } if (exportOptions.Normals && exportOptions.TextureCoordinates) { streamWriter.WriteLine("f " + index2 + "/" + index2 + "/" + index2 + " " + index1 + "/" + index1 + "/" + index1 + " " + index0 + "/" + index0 + "/" + index0); } else if (exportOptions.Normals) { streamWriter.WriteLine("f " + index2 + "//" + index2 + " " + index1 + "//" + index1 + " " + index0 + "//" + index0); } else if (exportOptions.TextureCoordinates) { streamWriter.WriteLine("f " + index2 + "/" + index2 + " " + index1 + "/" + index1 + " " + index0 + "/" + index0); } else { streamWriter.WriteLine("f " + index2 + " " + index1 + " " + index0); } } vertexCount += (UInt32)mesh.VertexCount; } streamWriter.Close(); }
public void WriteHalf(Half value) { InternalWriteHalf(value); }
private static void TransformRgba16161616F(byte[] buffer, BinaryReader br, uint width, uint height) { // I have no idea how this works. It's just converted straight from VTFLib. // I think the half format is slightly different to what it should be, which causes the result to be different to VTFLib. // Fortunately Sledge does not need to care about cubemaps, which is what this format seems to be used for... const int a = 6; const int r = 0; const int g = 2; const int b = 4; var bytes = br.ReadBytes((int)(width * height * 8)); var log = 0d; for (int i = 0, j = 0; i < bytes.Length; i += 8, j += 4) { var hb = Half.FromBytes(bytes, i + b).ToSingle(); var hg = Half.FromBytes(bytes, i + g).ToSingle(); var hr = Half.FromBytes(bytes, i + r).ToSingle(); var lum = hr * 0.299f + hg * 0.587f + hb * 0.114f; log += Math.Log(0.0000000001d + lum); } log = Math.Exp(log / (width * height)); for (int i = 0, j = 0; i < bytes.Length; i += 8, j += 4) { var hb = Half.FromBytes(bytes, i + b).ToSingle(); var hg = Half.FromBytes(bytes, i + g).ToSingle(); var hr = Half.FromBytes(bytes, i + r).ToSingle(); var ha = Half.FromBytes(bytes, i + a).ToSingle(); var y = hr * 0.299f + hg * 0.587f + hb * 0.114f; var u = (hb - y) * 0.565f; var v = (hr - y) * 0.713f; var mul = 4 * y / log; mul = mul / (1 + mul); mul /= y; hr = (float)Math.Pow((y + 1.403f * v) * mul, 2.25f); hg = (float)Math.Pow((y - 0.344f * u - 0.714f * v) * mul, 2.25f); hb = (float)Math.Pow((y + 1.770f * u) * mul, 2.25f); if (hr < 0) { hr = 0; } if (hr > 1) { hr = 1; } if (hg < 0) { hg = 0; } if (hg > 1) { hg = 1; } if (hb < 0) { hb = 0; } if (hb > 1) { hb = 1; } buffer[j + 0] = (byte)(hb * 255); // b buffer[j + 1] = (byte)(hg * 255); // g buffer[j + 2] = (byte)(hr * 255); // r buffer[j + 3] = (byte)(ha * 255); // a } }
internal extern static unsafe void Normal3hvNV(Half* v);
internal extern static unsafe void SecondaryColor3hvNV(Half* v);
public static bool IsInfinity(Half half) { return((half.Value & 0x7fff) == 0x7c00); }
internal extern static void TexCoord3hNV(Half s, Half t, Half r);
public static bool IsPositiveInfinity(Half half) { return(half.Value == 0x7c00); }
internal extern static unsafe void Color4hvNV(Half* v);
public static bool IsNegativeInfinity(Half half) { return(half.Value == 0xfc00); }
internal extern static unsafe void Vertex4hvNV(Half* v);
public Vector3Half(Half x, Half y, Half z) { this.x = x; this.y = y; this.z = z; } //constructor
internal extern static void VertexWeighthNV(Half weight);
public static Half ReadHalf(this BinaryReader reader) => Half.ToHalf(reader.ReadUInt16());
public static Half Negate(Half half) { return Half.ToHalf((ushort)(half.value ^ 0x8000)); }
public void SpanWrite() { Span <byte> span = new byte[8]; byte byteValue = 0x11; MemoryMarshal.Write <byte>(span, ref byteValue); TestHelpers.Validate <byte>(span, byteValue); Assert.True(MemoryMarshal.TryWrite <byte>(span, ref byteValue)); TestHelpers.Validate <byte>(span, byteValue); sbyte sbyteValue = 0x11; MemoryMarshal.Write <sbyte>(span, ref sbyteValue); TestHelpers.Validate <sbyte>(span, sbyteValue); Assert.True(MemoryMarshal.TryWrite <sbyte>(span, ref sbyteValue)); TestHelpers.Validate <sbyte>(span, sbyteValue); ushort ushortValue = 0x1122; MemoryMarshal.Write <ushort>(span, ref ushortValue); TestHelpers.Validate <ushort>(span, ushortValue); Assert.True(MemoryMarshal.TryWrite <ushort>(span, ref ushortValue)); TestHelpers.Validate <ushort>(span, ushortValue); uint uintValue = 0x11223344; MemoryMarshal.Write <uint>(span, ref uintValue); TestHelpers.Validate <uint>(span, uintValue); Assert.True(MemoryMarshal.TryWrite <uint>(span, ref uintValue)); TestHelpers.Validate <uint>(span, uintValue); ulong ulongValue = 0x1122334455667788; MemoryMarshal.Write <ulong>(span, ref ulongValue); TestHelpers.Validate <ulong>(span, ulongValue); Assert.True(MemoryMarshal.TryWrite <ulong>(span, ref ulongValue)); TestHelpers.Validate <ulong>(span, ulongValue); short shortValue = 0x1122; MemoryMarshal.Write <short>(span, ref shortValue); TestHelpers.Validate <short>(span, shortValue); Assert.True(MemoryMarshal.TryWrite <short>(span, ref shortValue)); TestHelpers.Validate <short>(span, shortValue); int intValue = 0x11223344; MemoryMarshal.Write <int>(span, ref intValue); TestHelpers.Validate <int>(span, intValue); Assert.True(MemoryMarshal.TryWrite <int>(span, ref intValue)); TestHelpers.Validate <int>(span, intValue); long longValue = 0x1122334455667788; MemoryMarshal.Write <long>(span, ref longValue); TestHelpers.Validate <long>(span, longValue); Assert.True(MemoryMarshal.TryWrite <long>(span, ref longValue)); TestHelpers.Validate <long>(span, longValue); Half halfValue = BitConverter.Int16BitsToHalf(0x1122); MemoryMarshal.Write <Half>(span, ref halfValue); TestHelpers.Validate <Half>(span, halfValue); Assert.True(MemoryMarshal.TryWrite <Half>(span, ref halfValue)); TestHelpers.Validate <Half>(span, halfValue); float floatValue = BitConverter.Int32BitsToSingle(0x11223344); MemoryMarshal.Write <float>(span, ref floatValue); TestHelpers.Validate <float>(span, floatValue); Assert.True(MemoryMarshal.TryWrite <float>(span, ref floatValue)); TestHelpers.Validate <float>(span, floatValue); double doubleValue = BitConverter.Int64BitsToDouble(0x1122334455667788); MemoryMarshal.Write <double>(span, ref doubleValue); TestHelpers.Validate <double>(span, doubleValue); Assert.True(MemoryMarshal.TryWrite <double>(span, ref doubleValue)); TestHelpers.Validate <double>(span, doubleValue); }
public static bool IsPositiveInfinity(Half half) { return (half.value == 0x7c00); }
public void SpanWriteFail() { byte byteValue = 1; sbyte sbyteValue = 1; short shortValue = 1; ushort ushortValue = 1; int intValue = 1; uint uintValue = 1; long longValue = 1; ulong ulongValue = 1; Half halfValue = (Half)1; float floatValue = 1; double doubleValue = 1; Span <byte> span = new byte[1]; MemoryMarshal.Write <byte>(span, ref byteValue); byte read = MemoryMarshal.Read <byte>(span); Assert.Equal <byte>(byteValue, read); span.Clear(); Assert.True(MemoryMarshal.TryWrite <byte>(span, ref byteValue)); read = MemoryMarshal.Read <byte>(span); Assert.Equal <byte>(byteValue, read); MemoryMarshal.Write <sbyte>(span, ref sbyteValue); sbyte readSbyte = MemoryMarshal.Read <sbyte>(span); Assert.Equal <sbyte>(sbyteValue, readSbyte); span.Clear(); Assert.True(MemoryMarshal.TryWrite <sbyte>(span, ref sbyteValue)); readSbyte = MemoryMarshal.Read <sbyte>(span); Assert.Equal <sbyte>(sbyteValue, readSbyte); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <short>(_span, ref shortValue)); Assert.False(MemoryMarshal.TryWrite <short>(span, ref shortValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <int>(_span, ref intValue)); Assert.False(MemoryMarshal.TryWrite <int>(span, ref intValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <long>(_span, ref longValue)); Assert.False(MemoryMarshal.TryWrite <long>(span, ref longValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <ushort>(_span, ref ushortValue)); Assert.False(MemoryMarshal.TryWrite <ushort>(span, ref ushortValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <uint>(_span, ref uintValue)); Assert.False(MemoryMarshal.TryWrite <uint>(span, ref uintValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <ulong>(_span, ref ulongValue)); Assert.False(MemoryMarshal.TryWrite <ulong>(span, ref ulongValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <Half>(_span, ref halfValue)); Assert.False(MemoryMarshal.TryWrite <Half>(span, ref halfValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <float>(_span, ref floatValue)); Assert.False(MemoryMarshal.TryWrite <float>(span, ref floatValue)); TestHelpers.AssertThrows <ArgumentOutOfRangeException, byte>(span, (_span) => MemoryMarshal.Write <double>(_span, ref doubleValue)); Assert.False(MemoryMarshal.TryWrite <double>(span, ref doubleValue)); var structValue = new TestHelpers.TestValueTypeWithReference { I = 1, S = "1" }; TestHelpers.AssertThrows <ArgumentException, byte>(span, (_span) => MemoryMarshal.Write <TestHelpers.TestValueTypeWithReference>(_span, ref structValue)); TestHelpers.AssertThrows <ArgumentException, byte>(span, (_span) => MemoryMarshal.TryWrite <TestHelpers.TestValueTypeWithReference>(_span, ref structValue)); }
internal extern static void Normal3hNV(Half nx, Half ny, Half nz);
public static unsafe ushort HalfToUInt16Bits(Half value) { return(*((ushort *)&value)); }
internal extern static void SecondaryColor3hNV(Half red, Half green, Half blue);
/// <summary> /// Creates bitmap from decompressed RGBAF texture data. /// </summary> /// <param name="textureData">The decompressed texture data.</param> /// <param name="width">The textures width.</param> /// <param name="height">The textures height.</param> /// <returns>The created bitmap.</returns> private static Bitmap ReadRGBAFImage(byte[] textureData, int width, int height) { Bitmap bmp = new Bitmap(width, height); using (MemoryStream ms = new MemoryStream(textureData)) { using (BinaryReader br = new BinaryReader(ms)) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { ushort red = BitConverter.ToUInt16(br.ReadBytes(2), 0); Half hRed = Half.ToHalf(red); ushort green = BitConverter.ToUInt16(br.ReadBytes(2), 0); Half hGreen = Half.ToHalf(green); ushort blue = BitConverter.ToUInt16(br.ReadBytes(2), 0); Half hBlue = Half.ToHalf(blue); ushort alpha = BitConverter.ToUInt16(br.ReadBytes(2), 0); Half hAlpha = Half.ToHalf(alpha); if (hRed > 1) { hRed = 1; } else if (hRed < 0) { hRed = 0; } if (hGreen > 1) { hGreen = 1; } else if (hGreen < 0) { hGreen = 0; } if (hBlue > 1) { hBlue = 1; } else if (hBlue < 0) { hBlue = 0; } if (hAlpha > 1) { hAlpha = 1; } else if (hAlpha < 0) { hAlpha = 0; } bmp.SetPixel(x, y, Color.FromArgb((int)(hAlpha * 255), (int)(hRed * 255), (int)(hGreen * 255), (int)(hBlue * 255))); } } } } return(bmp); }
internal extern static void TexCoord1hNV(Half s);
public void SpanRead() { Assert.True(BitConverter.IsLittleEndian); ulong value = 0x8877665544332211; // [11 22 33 44 55 66 77 88] Span <byte> span; unsafe { span = new Span <byte>(&value, 8); } Assert.Equal <byte>(0x11, MemoryMarshal.Read <byte>(span)); Assert.True(MemoryMarshal.TryRead(span, out byte byteValue)); Assert.Equal(0x11, byteValue); Assert.Equal <sbyte>(0x11, MemoryMarshal.Read <sbyte>(span)); Assert.True(MemoryMarshal.TryRead(span, out byte sbyteValue)); Assert.Equal(0x11, byteValue); Assert.Equal <ushort>(0x1122, ReadUInt16BigEndian(span)); Assert.True(TryReadUInt16BigEndian(span, out ushort ushortValue)); Assert.Equal(0x1122, ushortValue); Assert.Equal <ushort>(0x2211, ReadUInt16LittleEndian(span)); Assert.True(TryReadUInt16LittleEndian(span, out ushortValue)); Assert.Equal(0x2211, ushortValue); Assert.Equal <short>(0x1122, ReadInt16BigEndian(span)); Assert.True(TryReadInt16BigEndian(span, out short shortValue)); Assert.Equal(0x1122, shortValue); Assert.Equal <short>(0x2211, ReadInt16LittleEndian(span)); Assert.True(TryReadInt16LittleEndian(span, out shortValue)); Assert.Equal(0x2211, ushortValue); Assert.Equal <uint>(0x11223344, ReadUInt32BigEndian(span)); Assert.True(TryReadUInt32BigEndian(span, out uint uintValue)); Assert.Equal <uint>(0x11223344, uintValue); Assert.Equal <uint>(0x44332211, ReadUInt32LittleEndian(span)); Assert.True(TryReadUInt32LittleEndian(span, out uintValue)); Assert.Equal <uint>(0x44332211, uintValue); Assert.Equal <int>(0x11223344, ReadInt32BigEndian(span)); Assert.True(TryReadInt32BigEndian(span, out int intValue)); Assert.Equal <int>(0x11223344, intValue); Assert.Equal <int>(0x44332211, ReadInt32LittleEndian(span)); Assert.True(TryReadInt32LittleEndian(span, out intValue)); Assert.Equal <int>(0x44332211, intValue); Assert.Equal <ulong>(0x1122334455667788, ReadUInt64BigEndian(span)); Assert.True(TryReadUInt64BigEndian(span, out ulong ulongValue)); Assert.Equal <ulong>(0x1122334455667788, ulongValue); Assert.Equal <ulong>(0x8877665544332211, ReadUInt64LittleEndian(span)); Assert.True(TryReadUInt64LittleEndian(span, out ulongValue)); Assert.Equal <ulong>(0x8877665544332211, ulongValue); Assert.Equal <long>(0x1122334455667788, ReadInt64BigEndian(span)); Assert.True(TryReadInt64BigEndian(span, out long longValue)); Assert.Equal <long>(0x1122334455667788, longValue); Assert.Equal <long>(unchecked ((long)0x8877665544332211), ReadInt64LittleEndian(span)); Assert.True(TryReadInt64LittleEndian(span, out longValue)); Assert.Equal <long>(unchecked ((long)0x8877665544332211), longValue); Half expectedHalf = BitConverter.Int16BitsToHalf(0x1122); Assert.Equal <Half>(expectedHalf, ReadHalfBigEndian(span)); Assert.True(TryReadHalfBigEndian(span, out Half halfValue)); Assert.Equal <Half>(expectedHalf, halfValue); expectedHalf = BitConverter.Int16BitsToHalf(0x2211); Assert.Equal <Half>(expectedHalf, ReadHalfLittleEndian(span)); Assert.True(TryReadHalfLittleEndian(span, out halfValue)); Assert.Equal <Half>(expectedHalf, halfValue); float expectedFloat = BitConverter.Int32BitsToSingle(0x11223344); Assert.Equal <float>(expectedFloat, ReadSingleBigEndian(span)); Assert.True(TryReadSingleBigEndian(span, out float floatValue)); Assert.Equal <float>(expectedFloat, floatValue); expectedFloat = BitConverter.Int32BitsToSingle(0x44332211); Assert.Equal <float>(expectedFloat, ReadSingleLittleEndian(span)); Assert.True(TryReadSingleLittleEndian(span, out floatValue)); Assert.Equal <float>(expectedFloat, floatValue); double expectedDouble = BitConverter.Int64BitsToDouble(0x1122334455667788); Assert.Equal <double>(expectedDouble, ReadDoubleBigEndian(span)); Assert.True(TryReadDoubleBigEndian(span, out double doubleValue)); Assert.Equal <double>(expectedDouble, doubleValue); expectedDouble = BitConverter.Int64BitsToDouble(unchecked ((long)0x8877665544332211)); Assert.Equal <double>(expectedDouble, ReadDoubleLittleEndian(span)); Assert.True(TryReadDoubleLittleEndian(span, out doubleValue)); Assert.Equal <double>(expectedDouble, doubleValue); }
internal extern static void TexCoord2hNV(Half s, Half t);
public static void ParseValidSpanTest(string value, int offset, int count, NumberStyles style, IFormatProvider provider, Half expected) { bool isDefaultProvider = provider == null || provider == NumberFormatInfo.CurrentInfo; Half result; if ((style & ~(NumberStyles.Float | NumberStyles.AllowThousands)) == 0 && style != NumberStyles.None) { // Use Parse(string) or Parse(string, IFormatProvider) if (isDefaultProvider) { Assert.True(NumberHelper <Half> .TryParse(value.AsSpan(offset, count), null, out result)); Assert.Equal(expected, result); Assert.Equal(expected, NumberHelper <Half> .Parse(value.AsSpan(offset, count), null)); } Assert.Equal(expected, NumberHelper <Half> .Parse(value.AsSpan(offset, count), provider: provider)); } Assert.Equal(expected, NumberHelper <Half> .Parse(value.AsSpan(offset, count), style, provider)); Assert.True(NumberHelper <Half> .TryParse(value.AsSpan(offset, count), style, provider, out result)); Assert.Equal(expected, result); }
internal extern static void TexCoord4hNV(Half s, Half t, Half r, Half q);
public byte[] Write() { List <byte> bytes = new List <byte>(); int animCount = GetIndexedAnimationCount(); List <int> animNameOffsets = new List <int>(); //Header bytes.AddRange(BitConverter.GetBytes(EMA_SIGNATURE)); bytes.AddRange(BitConverter.GetBytes((ushort)65534)); bytes.AddRange(BitConverter.GetBytes((ushort)32)); bytes.AddRange(BitConverter.GetBytes((int)Version)); bytes.AddRange(new byte[4]); //Skeleton offset bytes.AddRange(BitConverter.GetBytes((ushort)animCount)); bytes.AddRange(BitConverter.GetBytes(I_18)); bytes.AddRange(BitConverter.GetBytes(I_20)); bytes.AddRange(BitConverter.GetBytes(I_24)); bytes.AddRange(BitConverter.GetBytes(I_28)); //Animation pointers bytes.AddRange(new byte[4 * animCount]); //Animations foreach (var anim in Animations) { int animStartOffset = bytes.Count; bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count), 32 + (anim.Index * 4)); List <float> values = anim.GetValues(); bytes.AddRange(BitConverter.GetBytes(anim.I_00)); bytes.AddRange(BitConverter.GetBytes((ushort)anim.CommandCount)); bytes.AddRange(BitConverter.GetBytes((int)values.Count)); bytes.AddRange(BitConverter.GetBytes((ushort)anim.I_08)); bytes.AddRange(BitConverter.GetBytes((ushort)anim.I_10)); animNameOffsets.Add(bytes.Count); bytes.AddRange(new byte[4]); //Name offset bytes.AddRange(new byte[4]); //value offset bytes.AddRange(new byte[4 * anim.CommandCount]); //Commands for (int i = 0; i < anim.CommandCount; i++) { int startCommandOffset = bytes.Count; bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - animStartOffset), animStartOffset + 20 + (i * 4)); anim.Commands[i].SetFlags(); //Calculate the known flags if (HasSkeleton) { bytes.AddRange(BitConverter.GetBytes((ushort)GetBoneIndex(anim.Commands[i].BoneName))); } else { bytes.AddRange(new byte[2]); } bytes.Add(anim.Commands[i].I_02); var bitArray_b = new BitArray(new bool[8] { anim.Commands[i].I_03_b1, anim.Commands[i].I_03_b2_Int16ForTime, anim.Commands[i].I_03_b3_Int16ForValueIndex, anim.Commands[i].I_03_b4, false, false, false, false }); var bitArray_a = new BitArray(new byte[1] { anim.Commands[i].I_03_a }); bitArray_a[3] = anim.Commands[i].I_03_a4; bytes.Add((byte)Int4Converter.GetByte(Utils.ConvertToByte(bitArray_a), Utils.ConvertToByte(bitArray_b))); bytes.AddRange(BitConverter.GetBytes((ushort)anim.Commands[i].KeyframeCount)); bytes.AddRange(new byte[2]); //Sort keyframes if (anim.Commands[i].KeyframeCount > 0) { anim.Commands[i].SortKeyframes(); } //Write Time for (int a = 0; a < anim.Commands[i].KeyframeCount; a++) { if (anim.Commands[i].I_03_b2_Int16ForTime) { bytes.AddRange(BitConverter.GetBytes(anim.Commands[i].Keyframes[a].Time)); } else { bytes.Add((byte)anim.Commands[i].Keyframes[a].Time); } } //Add padding bytes.AddRange(new byte[Utils.CalculatePadding(bytes.Count - startCommandOffset, 4)]); //Write value/index bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes((ushort)(bytes.Count - startCommandOffset)), startCommandOffset + 6); for (int a = 0; a < anim.Commands[i].KeyframeCount; a++) { if (anim.Commands[i].I_03_b3_Int16ForValueIndex) { bytes.AddRange(BitConverter.GetBytes((ushort)anim.Commands[i].Keyframes[a].index)); bytes.AddRange(BitConverter.GetBytes((ushort)anim.Commands[i].Keyframes[a].Flags)); } else { bytes.Add((byte)anim.Commands[i].Keyframes[a].index); bytes.Add((byte)anim.Commands[i].Keyframes[a].Flags); } } //Add padding bytes.AddRange(new byte[Utils.CalculatePadding(bytes.Count - startCommandOffset, 4)]); } //Values int valuesStartOffset = bytes.Count; bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - animStartOffset), animStartOffset + 16); foreach (var value in values) { if (anim.I_10 == ValueType.Float16) { bytes.AddRange(Half.GetBytes((Half)value)); } else if (anim.I_10 == ValueType.Float32 || anim.I_10 == ValueType.Float32_2) { bytes.AddRange(BitConverter.GetBytes(value)); } else { throw new InvalidDataException("Unknown ValueType. Cannot continue."); } } bytes.AddRange(new byte[Utils.CalculatePadding(bytes.Count - valuesStartOffset, 4)]); } //Skeleton if (HasSkeleton) { bytes.AddRange(new byte[Utils.CalculatePadding(bytes.Count, 16)]); bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count), 12); bytes.AddRange(skeleton.Write()); } //Strings (animations) for (int i = 0; i < Animations.Count; i++) { if (!String.IsNullOrWhiteSpace(Animations[i].Name)) { bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - animNameOffsets[i] + 12), animNameOffsets[i]); bytes.AddRange(new byte[10]); bytes.Add((byte)Animations[i].Name.Length); bytes.AddRange(Encoding.ASCII.GetBytes(Animations[i].Name)); bytes.Add(0); } } return(bytes.ToArray()); }
internal extern static void Color4hNV(Half red, Half green, Half blue, Half alpha);
public override void Read(BinaryReader b) { base.Read(b); this.Flags2 = b.ReadUInt32(); // another filler UInt32 tmpdataStreamType = b.ReadUInt32(); this.DataStreamType = (DataStreamTypeEnum)Enum.ToObject(typeof(DataStreamTypeEnum), tmpdataStreamType); this.NumElements = b.ReadUInt32(); // number of elements in this chunk if (this._model.FileVersion == FileVersionEnum.CryTek_3_5 || this._model.FileVersion == FileVersionEnum.CryTek_3_4) { this.BytesPerElement = b.ReadUInt32(); // bytes per element } if (this._model.FileVersion == FileVersionEnum.CryTek_3_6) { this.BytesPerElement = (UInt32)b.ReadInt16(); // Star Citizen 2.0 is using an int16 here now. b.ReadInt16(); // unknown value. Doesn't look like padding though. } this.SkipBytes(b, 8); // Now do loops to read for each of the different Data Stream Types. If vertices, need to populate Vector3s for example. switch (this.DataStreamType) { #region case DataStreamTypeEnum.VERTICES: case DataStreamTypeEnum.VERTICES: // Ref is 0x00000000 this.Vertices = new Vector3[this.NumElements]; switch (this.BytesPerElement) { case 12: for (Int32 i = 0; i < this.NumElements; i++) { this.Vertices[i].x = b.ReadSingle(); this.Vertices[i].y = b.ReadSingle(); this.Vertices[i].z = b.ReadSingle(); } break; case 8: // Prey files, and old Star Citizen files for (Int32 i = 0; i < NumElements; i++) { uint bver = 0; float ver = 0; // 2 byte floats. Use the Half structure from TK.Math //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.Vertices[i].x = ver; //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.Vertices[i].y = ver; bver = b.ReadUInt16(); //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.Vertices[i].z = ver; //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.Vertices[i].w = ver; Half xshort = new Half(); xshort.bits = b.ReadUInt16(); this.Vertices[i].x = xshort.ToSingle(); Half yshort = new Half(); yshort.bits = b.ReadUInt16(); this.Vertices[i].y = yshort.ToSingle(); Half zshort = new Half(); zshort.bits = b.ReadUInt16(); this.Vertices[i].z = zshort.ToSingle(); b.ReadUInt16(); } break; case 16: //Console.WriteLine("method: (3)"); for (Int32 i = 0; i < this.NumElements; i++) { this.Vertices[i].x = b.ReadSingle(); this.Vertices[i].y = b.ReadSingle(); this.Vertices[i].z = b.ReadSingle(); this.Vertices[i].w = b.ReadSingle(); // TODO: Sometimes there's a W to these structures. Will investigate. } break; } break; #endregion #region case DataStreamTypeEnum.INDICES: case DataStreamTypeEnum.INDICES: // Ref is this.Indices = new UInt32[NumElements]; if (this.BytesPerElement == 2) { for (Int32 i = 0; i < this.NumElements; i++) { this.Indices[i] = (UInt32)b.ReadUInt16(); //Console.WriteLine("Indices {0}: {1}", i, this.Indices[i]); } } if (this.BytesPerElement == 4) { for (Int32 i = 0; i < this.NumElements; i++) { this.Indices[i] = b.ReadUInt32(); } } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.NORMALS: case DataStreamTypeEnum.NORMALS: this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.Normals[i].x = b.ReadSingle(); this.Normals[i].y = b.ReadSingle(); this.Normals[i].z = b.ReadSingle(); } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.UVS: case DataStreamTypeEnum.UVS: this.UVs = new UV[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.UVs[i].U = b.ReadSingle(); this.UVs[i].V = b.ReadSingle(); } //Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.TANGENTS: case DataStreamTypeEnum.TANGENTS: this.Tangents = new Tangent[this.NumElements, 2]; this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { switch (this.BytesPerElement) { case 0x10: // These have to be divided by 32767 to be used properly (value between 0 and 1) this.Tangents[i, 0].x = b.ReadInt16(); this.Tangents[i, 0].y = b.ReadInt16(); this.Tangents[i, 0].z = b.ReadInt16(); this.Tangents[i, 0].w = b.ReadInt16(); this.Tangents[i, 1].x = b.ReadInt16(); this.Tangents[i, 1].y = b.ReadInt16(); this.Tangents[i, 1].z = b.ReadInt16(); this.Tangents[i, 1].w = b.ReadInt16(); break; case 0x08: // These have to be divided by 127 to be used properly (value between 0 and 1) // Tangent this.Tangents[i, 0].w = b.ReadSByte() / 127.0; this.Tangents[i, 0].x = b.ReadSByte() / 127.0; this.Tangents[i, 0].y = b.ReadSByte() / 127.0; this.Tangents[i, 0].z = b.ReadSByte() / 127.0; // Binormal this.Tangents[i, 1].w = b.ReadSByte() / 127.0; this.Tangents[i, 1].x = b.ReadSByte() / 127.0; this.Tangents[i, 1].y = b.ReadSByte() / 127.0; this.Tangents[i, 1].z = b.ReadSByte() / 127.0; // Calculate the normal based on the cross product of the tangents. //this.Normals[i].x = (Tangents[i,0].y * Tangents[i,1].z - Tangents[i,0].z * Tangents[i,1].y); //this.Normals[i].y = 0 - (Tangents[i,0].x * Tangents[i,1].z - Tangents[i,0].z * Tangents[i,1].x); //this.Normals[i].z = (Tangents[i,0].x * Tangents[i,1].y - Tangents[i,0].y * Tangents[i,1].x); //Console.WriteLine("Tangent: {0:F6} {1:F6} {2:F6}", Tangents[i,0].x, Tangents[i, 0].y, Tangents[i, 0].z); //Console.WriteLine("Binormal: {0:F6} {1:F6} {2:F6}", Tangents[i, 1].x, Tangents[i, 1].y, Tangents[i, 1].z); //Console.WriteLine("Normal: {0:F6} {1:F6} {2:F6}", Normals[i].x, Normals[i].y, Normals[i].z); break; default: throw new Exception("Need to add new Tangent Size"); } } // Utils.Log(LogLevelEnum.Debug, "Offset is {0:X}", b.BaseStream.Position); break; #endregion #region case DataStreamTypeEnum.COLORS: case DataStreamTypeEnum.COLORS: switch (this.BytesPerElement) { case 3: this.RGBColors = new IRGB[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.RGBColors[i].r = b.ReadByte(); this.RGBColors[i].g = b.ReadByte(); this.RGBColors[i].b = b.ReadByte(); } break; case 4: this.RGBAColors = new IRGBA[this.NumElements]; for (Int32 i = 0; i < this.NumElements; i++) { this.RGBAColors[i].r = b.ReadByte(); this.RGBAColors[i].g = b.ReadByte(); this.RGBAColors[i].b = b.ReadByte(); this.RGBAColors[i].a = b.ReadByte(); } break; default: Utils.Log("Unknown Color Depth"); for (Int32 i = 0; i < this.NumElements; i++) { this.SkipBytes(b, this.BytesPerElement); } break; } break; #endregion #region case DataStreamTypeEnum.VERTSUVS: case DataStreamTypeEnum.VERTSUVS: // 3 half floats for verts, 3 half floats for normals, 2 half floats for UVs // Utils.Log(LogLevelEnum.Debug, "In VertsUVs..."); this.Vertices = new Vector3[this.NumElements]; this.Normals = new Vector3[this.NumElements]; this.RGBColors = new IRGB[this.NumElements]; this.UVs = new UV[this.NumElements]; switch (this.BytesPerElement) // new Star Citizen files { case 20: // Dymek wrote this. Used in 2.6 skin files. 3 floats for vertex position, 4 bytes for normals, 2 halfs for UVs. Normals are calculated from Tangents for (Int32 i = 0; i < this.NumElements; i++) { this.Vertices[i].x = b.ReadSingle(); this.Vertices[i].y = b.ReadSingle(); this.Vertices[i].z = b.ReadSingle(); // For some reason, skins are an extra 1 meter in the z direction. // Normals are stored in a signed byte, prob div by 127. this.Normals[i].x = (float)b.ReadSByte() / 127; this.Normals[i].y = (float)b.ReadSByte() / 127; this.Normals[i].z = (float)b.ReadSByte() / 127; b.ReadSByte(); // Should be FF. Half uvu = new Half(); uvu.bits = b.ReadUInt16(); this.UVs[i].U = uvu.ToSingle(); Half uvv = new Half(); uvv.bits = b.ReadUInt16(); this.UVs[i].V = uvv.ToSingle(); //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.UVs[i].U = ver; //bver = b.ReadUInt16(); //ver = Byte4HexToFloat(bver.ToString("X8")); //this.UVs[i].V = ver; } break; case 16: // Dymek updated this. //Console.WriteLine("method: (5), 3 half floats for verts, 3 colors, 2 half floats for UVs"); for (Int32 i = 0; i < this.NumElements; i++) { ushort bver = 0; float ver = 0; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].x = ver; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].y = ver; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].z = ver; bver = b.ReadUInt16(); ver = Byte2HexIntFracToFloat2(bver.ToString("X4")) / 127; this.Vertices[i].w = ver; // Almost always 1 // Next structure is Colors, not normals. For 16 byte elements, normals are calculated from Tangent data. //this.RGBColors[i].r = b.ReadByte(); //this.RGBColors[i].g = b.ReadByte(); //this.RGBColors[i].b = b.ReadByte(); //b.ReadByte(); // additional byte. //this.Normals[i].x = (b.ReadByte() - 128.0f) / 127.5f; //this.Normals[i].y = (b.ReadByte() - 128.0f) / 127.5f; //this.Normals[i].z = (b.ReadByte() - 128.0f) / 127.5f; //b.ReadByte(); // additional byte. // Read a Quat, convert it to vector3 Vector4 quat = new Vector4(); quat.x = (b.ReadByte() - 128.0f) / 127.5f; quat.y = (b.ReadByte() - 128.0f) / 127.5f; quat.z = (b.ReadByte() - 128.0f) / 127.5f; quat.w = (b.ReadByte() - 128.0f) / 127.5f; this.Normals[i].x = (2 * (quat.x * quat.z + quat.y * quat.w)); this.Normals[i].y = (2 * (quat.y * quat.z - quat.x * quat.w)); this.Normals[i].z = (2 * (quat.z * quat.z + quat.w * quat.w)) - 1; // UVs ABSOLUTELY should use the Half structures. Half uvu = new Half(); uvu.bits = b.ReadUInt16(); this.UVs[i].U = uvu.ToSingle(); Half uvv = new Half(); uvv.bits = b.ReadUInt16(); this.UVs[i].V = uvv.ToSingle(); #region Legacy version using Halfs //Half xshort = new Half(); //xshort.bits = b.ReadUInt16(); //this.Vertices[i].x = xshort.ToSingle(); //Half yshort = new Half(); //yshort.bits = b.ReadUInt16(); //this.Vertices[i].y = yshort.ToSingle(); //Half zshort = new Half(); //zshort.bits = b.ReadUInt16(); //this.Vertices[i].z = zshort.ToSingle(); //Half xnorm = new Half(); //xnorm.bits = b.ReadUInt16(); //this.Normals[i].x = xnorm.ToSingle(); //Half ynorm = new Half(); //ynorm.bits = b.ReadUInt16(); //this.Normals[i].y = ynorm.ToSingle(); //Half znorm = new Half(); //znorm.bits = b.ReadUInt16(); //this.Normals[i].z = znorm.ToSingle(); //Half uvu = new Half(); //uvu.bits = b.ReadUInt16(); //this.UVs[i].U = uvu.ToSingle(); //Half uvv = new Half(); //uvv.bits = b.ReadUInt16(); //this.UVs[i].V = uvv.ToSingle(); #endregion } break; default: Utils.Log("Unknown VertUV structure"); for (Int32 i = 0; i < this.NumElements; i++) { this.SkipBytes(b, this.BytesPerElement); } break; } break; #endregion #region case DataStreamTypeEnum.BONEMAP: case DataStreamTypeEnum.BONEMAP: SkinningInfo skin = GetSkinningInfo(); skin.HasBoneMapDatastream = true; skin.BoneMapping = new List <MeshBoneMapping>(); // Bones should have 4 bone IDs (index) and 4 weights. for (int i = 0; i < NumElements; i++) { MeshBoneMapping tmpMap = new MeshBoneMapping(); switch (this.BytesPerElement) { case 8: tmpMap.BoneIndex = new int[4]; tmpMap.Weight = new int[4]; for (int j = 0; j < 4; j++) // read the 4 bone indexes first { tmpMap.BoneIndex[j] = b.ReadByte(); } for (int j = 0; j < 4; j++) // read the weights. { tmpMap.Weight[j] = b.ReadByte(); } skin.BoneMapping.Add(tmpMap); break; case 12: tmpMap.BoneIndex = new int[4]; tmpMap.Weight = new int[4]; for (int j = 0; j < 4; j++) // read the 4 bone indexes first { tmpMap.BoneIndex[j] = b.ReadUInt16(); } for (int j = 0; j < 4; j++) // read the weights. { tmpMap.Weight[j] = b.ReadByte(); } skin.BoneMapping.Add(tmpMap); break; default: Utils.Log("Unknown BoneMapping structure"); break; } } break; #endregion #region DataStreamTypeEnum.Unknown1 case DataStreamTypeEnum.UNKNOWN1: this.Tangents = new Tangent[this.NumElements, 2]; this.Normals = new Vector3[this.NumElements]; for (Int32 i = 0; i < NumElements; i++) { this.Tangents[i, 0].w = b.ReadSByte() / 127.0; this.Tangents[i, 0].x = b.ReadSByte() / 127.0; this.Tangents[i, 0].y = b.ReadSByte() / 127.0; this.Tangents[i, 0].z = b.ReadSByte() / 127.0; // Binormal this.Tangents[i, 1].w = b.ReadSByte() / 127.0; this.Tangents[i, 1].x = b.ReadSByte() / 127.0; this.Tangents[i, 1].y = b.ReadSByte() / 127.0; this.Tangents[i, 1].z = b.ReadSByte() / 127.0; // Calculate the normal based on the cross product of the tangents. this.Normals[i].x = (Tangents[i, 0].y * Tangents[i, 1].z - Tangents[i, 0].z * Tangents[i, 1].y); this.Normals[i].y = 0 - (Tangents[i, 0].x * Tangents[i, 1].z - Tangents[i, 0].z * Tangents[i, 1].x); this.Normals[i].z = (Tangents[i, 0].x * Tangents[i, 1].y - Tangents[i, 0].y * Tangents[i, 1].x); } break; #endregion // Prey normals? #region default: default: Utils.Log(LogLevelEnum.Debug, "***** Unknown DataStream Type *****"); break; #endregion } }
internal extern static void Vertex2hNV(Half x, Half y);
public static StringBuilder AppendInvariant(this StringBuilder sb, Half value) { return(sb.Append(value.ToString(CultureInfo.InvariantCulture))); }
internal extern static void Vertex4hNV(Half x, Half y, Half z, Half w);
/// <summary> /// Constructor for swizzle_hvec2. /// </summary> internal swizzle_hvec2(Half x, Half y) { this.x = x; this.y = y; }
internal extern static void VertexAttrib2hNV(UInt32 index, Half x, Half y);
private static float HalfToSingle(ushort value) { return Half.ToHalf(value); }
internal extern static unsafe void VertexAttribs4hvNV(UInt32 index, Int32 n, Half* v);
/// <summary> /// Initializes new instance of <see cref="Bytes2"/> type. /// </summary> /// <param name="value"> /// <see cref="Half"/> value to initialize this object with. /// </param> public Bytes2(Half value) : this() { this.HalfFloat = value; }
internal extern static unsafe void VertexWeighthvNV(Half* weight);
public override void ReadFromBuffer(NetBuffer buffer) { x = buffer.ReadHalf(); y = buffer.ReadHalf(); }
public static unsafe float HalfToSingle(Half half) { uint result = mantissaTable[offsetTable[half.value >> 10] + (half.value & 0x3ff)] + exponentTable[half.value >> 10]; return *((float*)&result); }
/// <summary> /// Constructor for swizzle_hvec3. /// </summary> internal swizzle_hvec3(Half x, Half y, Half z) { this.x = x; this.y = y; this.z = z; }
public static Half Abs(Half half) { return Half.ToHalf((ushort)(half.value & 0x7fff)); }
extern static IntPtr THSTorch_half_to_scalar(Half value);
public static bool IsInfinity(Half half) { return ((half.value & 0x7fff) == 0x7c00); }
public static Scalar ToScalar(this Half value) { return(new Scalar(THSTorch_half_to_scalar(value))); }
public static bool IsNegativeInfinity(Half half) { return (half.value == 0xfc00); }
public static void Write(this byte[] buffer, Half value, int start = 0) { using (var writer = new BinaryWriter(new MemoryStream(buffer, start, 2, true), Encoding.UTF8, false)) writer.Write(value.RawValue); }