예제 #1
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        public static void ReadUVData(byte[] data, VRTF.ElementLayout layout, ref float[] output, float scale)
        {
            byte[] element = new byte[VRTF.ByteSizeFromFormat(layout.Format)];
            Array.Copy(data, layout.Offset, element, 0, element.Length);

            switch (layout.Format)
            {
            case VRTF.ElementFormat.Short2:
                for (int i = 0; i < output.Length; i++)
                {
                    output[i] += (float)BitConverter.ToInt16(element, i * sizeof(short)) * scale;
                }
                break;

            case VRTF.ElementFormat.Short4:
                for (int i = 0; i < output.Length; i++)
                {
                    output[i] += (float)BitConverter.ToInt16(element, i * sizeof(short)) / short.MaxValue;
                }
                break;

            case VRTF.ElementFormat.Short4_DropShadow:
                for (int i = 0; i < output.Length - 1; i++)
                {
                    output[i] += (float)BitConverter.ToInt16(element, i * sizeof(short)) / short.MaxValue;
                }
                output[output.Length - 1] += (float)BitConverter.ToInt16(element, (output.Length - 1) * sizeof(short)) / 511;
                break;

            default:
                ReadFloatData(data, layout, ref output);
                break;
            }
        }
예제 #2
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        private static void PositionMinMax(VRTF vrtf, IEnumerable <Vertex> vertices)
        {
            positionMin = 0f;
            positionMax = 0f;
            VRTF.ElementLayout layout = vrtf.Layouts.FirstOrDefault(x => x.Format == VRTF.ElementFormat.UShort4N && x.Usage == VRTF.ElementUsage.Position);
            if (layout == null)
            {
                return;
            }

            List <float> positionFloats = new List <float>();

            foreach (float[] fs in vertices.Select(x => x.Position))
            {
                if (fs != null)
                {
                    positionFloats.AddRange(fs);
                }
            }

            if (positionFloats.Count > 0)
            {
                positionMax = positionMin = Math.Abs(positionFloats[0]);
                foreach (float f in positionFloats)
                {
                    float x = Math.Abs(f);
                    if (positionMin > x)
                    {
                        positionMin = x;
                    }
                    if (positionMax < x)
                    {
                        positionMax = x;
                    }
                }
            }

            //positionMin = positionFloats.Count > 0 ? positionFloats.Min(x => Math.Abs(x)) : 0;
            //positionMax = positionFloats.Count > 0 ? positionFloats.Max(x => Math.Abs(x)) : 0;
        }
예제 #3
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        private static bool WriteUVData(float[] input, VRTF.ElementLayout layout, byte[] output, float scale)
        {
            bool okay = true;

            switch (layout.Format)
            {
            case VRTF.ElementFormat.Short2:
                for (int i = 0; i < input.Length; i++)
                {
                    if ((short)Math.Round(input[i] / scale) != (long)Math.Round(input[i] / scale))
                    {
                        okay = false;
                    }
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] / scale)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                break;

            case VRTF.ElementFormat.Short4:
                for (int i = 0; i < input.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] * short.MaxValue)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                break;

            case VRTF.ElementFormat.Short4_DropShadow:
                for (int i = 0; i < input.Length - 1; i++)
                {
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] * short.MaxValue)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                Array.Copy(BitConverter.GetBytes((short)Math.Round(input[input.Length - 1] * 511)), 0, output, layout.Offset + (input.Length - 1) * sizeof(short), sizeof(short));
                break;

            default:
                WriteFloatData(input, layout, output);
                break;
            }
            return(okay);
        }
예제 #4
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        private static void WritePositionData(float[] input, VRTF.ElementLayout layout, byte[] output, float max)
        {
            switch (layout.Format)
            {
            case VRTF.ElementFormat.UShort4N:
                //scalar = (max >= 1) ? 511 : (ulong)short.MaxValue;
                //-- could try "max < 1.0 / 512.0"?
                //ulong scalar = (ulong)(max < 1 ? short.MaxValue : 511);
                //scalar++;
                //2011-08-30 changed to fixed 512 as LoveseatDanishModern had problems
                ulong scalar = 512;
                for (int i = 0; i < input.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] * scalar)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                Array.Copy(BitConverter.GetBytes((short)(scalar == 512 ? 0 : scalar - 1)), 0, output, layout.Offset + 3 * sizeof(short), sizeof(short));
                break;

            default:
                WriteFloatData(input, layout, output);
                break;
            }
        }
예제 #5
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        private static void WriteFloatData(float[] input, VRTF.ElementLayout layout, byte[] output)
        {
            ulong  scalar;
            double max;

            switch (layout.Format)
            {
            case VRTF.ElementFormat.Float1:
            case VRTF.ElementFormat.Float2:
            case VRTF.ElementFormat.Float3:
            case VRTF.ElementFormat.Float4:
                for (int i = 0; i < input.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes(input[i]), 0, output, layout.Offset + i * sizeof(float), sizeof(float));
                }
                break;

            case VRTF.ElementFormat.ColorUByte4:
                switch (layout.Usage)
                {
                case VRTF.ElementUsage.Colour:
                    for (int i = 0; i < input.Length; i++)
                    {
                        output[layout.Offset + i] = (byte)Math.Round(input[i] * byte.MaxValue);
                    }
                    break;

                case VRTF.ElementUsage.BlendWeight:
                    for (int i = 0; i < input.Length; i++)
                    {
                        output[layout.Offset + kColorUByte4Map[i]] = (byte)Math.Round(input[i] * byte.MaxValue);
                    }
                    break;

                case VRTF.ElementUsage.Normal:
                case VRTF.ElementUsage.Tangent:
                    // -0.98828125 == (((0.5 + 1) / 128f) - 1)
                    for (int i = 0; i < input.Length - 1; i++)
                    {
                        output[layout.Offset + 2 - i] = (byte)(input[i] < -0.98828125 ? 0 : (Math.Round((input[i] + 1) * 128) - 1));
                    }
                    //--
                    // Wes: (signed char) bytes[0]=vert[2+vrtfp.offset[j]];
                    //      (float)       norms[0]=(float)bytes[0];
                    //                    norms[0]=(norms[0]<(float)0.0)?(norms[0]+(float)128.0):(norms[0]-(float)128.0);
                    //??
                    //--
                    // input: +1 > 0 > -1
                    // map step1: +2 > +1 > 0
                    // map step2: 255 > 127.5 > 0
                    //for (int i = 0; i < input.Length - 1; i++)
                    //    output[layout.Offset + 2 - i] = (byte)Math.Round((input[i] + 1) * 127.5);

                    if (input[input.Length - 1] == -1)
                    {
                        output[layout.Offset + 3] = 0;
                    }
                    else if (input[input.Length - 1] == 0)
                    {
                        output[layout.Offset + 3] = 127;
                    }
                    else if (input[input.Length - 1] == 1)
                    {
                        output[layout.Offset + 3] = 255;
                    }
                    else
                    {
                        System.Diagnostics.Debug.WriteLine(String.Format("Unexpected handedness {0}.", input[input.Length - 1]));
                    }
                    break;
                }
                break;

            case VRTF.ElementFormat.Short2:
                for (int i = 0; i < input.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] * short.MaxValue)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                break;

            case VRTF.ElementFormat.Short4:
                max    = Math.Ceiling(input.Max(x => Math.Abs(x)));
                scalar = (ulong)(max < 1 ? short.MaxValue : short.MaxValue / max);
                //scalar++;
                for (int i = 0; i < input.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] * scalar)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                Array.Copy(BitConverter.GetBytes((short)(scalar /*- 1/**/)), 0, output, layout.Offset + 3 * sizeof(short), sizeof(short));
                break;

            case VRTF.ElementFormat.UShort4N:
                max    = Math.Ceiling(input.Max(x => Math.Abs(x)));
                scalar = (ulong)(max < 1.0 ? short.MaxValue : 512);
                //scalar++;
                for (int i = 0; i < input.Length; i++)
                {
                    Array.Copy(BitConverter.GetBytes((short)Math.Round(input[i] * scalar)), 0, output, layout.Offset + i * sizeof(short), sizeof(short));
                }
                Array.Copy(BitConverter.GetBytes((short)(scalar == 512 ? 0 : scalar /*- 1/**/)), 0, output, layout.Offset + 3 * sizeof(short), sizeof(short));
                break;
            }
        }
예제 #6
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        private static bool SetVertices(MemoryStream s, VRTF vrtf, IEnumerable <Vertex> vertices, float[] uvscales)
        {
            bool okay = true;

            PositionMinMax(vrtf, vertices);

            byte[]             output   = new byte[vrtf.Stride];
            VRTF.ElementLayout position = vrtf.Layouts
                                          .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Position);
            VRTF.ElementLayout normal = vrtf.Layouts
                                        .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Normal);
            VRTF.ElementLayout[] uv = vrtf.Layouts
                                      .Where(x => x.Usage == VRTF.ElementUsage.UV)
                                      .ToArray();
            VRTF.ElementLayout blendIndices = vrtf.Layouts
                                              .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.BlendIndex);
            VRTF.ElementLayout blendWeights = vrtf.Layouts
                                              .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.BlendWeight);
            VRTF.ElementLayout tangents = vrtf.Layouts
                                          .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Tangent);
            VRTF.ElementLayout color = vrtf.Layouts
                                       .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Colour);
            if (uvscales == null)
            {
                uvscales = defaultUVScales;
            }
            foreach (Vertex v in vertices)
            {
                if (v.Position != null)
                {
                    WritePositionData(v.Position, position, output, positionMax);
                }
                if (v.Normal != null)
                {
                    WriteFloatData(v.Normal, normal, output);
                }
                for (int u = 0; u < uv.Length; u++)
                {
                    float scale = u < uvscales.Length && uvscales[u] != 0 ? uvscales[u] : uvscales[0];
                    if (v.UV[u] != null)
                    {
                        if (!WriteUVData(v.UV[u], uv[u], output, scale))
                        {
                            okay = false;
                        }
                    }
                }
                if (v.BlendIndices != null)
                {
                    Array.Copy(v.BlendIndices, 0, output, blendIndices.Offset, VRTF.ByteSizeFromFormat(blendIndices.Format));
                }
                if (v.BlendWeights != null)
                {
                    WriteFloatData(v.BlendWeights, blendWeights, output);
                }
                if (v.Tangents != null)
                {
                    WriteFloatData(v.Tangents, tangents, output);
                }
                if (v.Color != null)
                {
                    WriteFloatData(v.Color, color, output);
                }
                s.Write(output, 0, output.Length);
            }
            s.Flush();
            return(okay);
        }
예제 #7
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        //Currently not supported:
        //UByte4N,
        //Short2N, Short4N, UShort2N,
        //Dec3N, UDec3N,
        //Float16_2, Float16_4
        public static void ReadFloatData(byte[] data, VRTF.ElementLayout layout, ref float[] output)
        {
            byte[] element = new byte[VRTF.ByteSizeFromFormat(layout.Format)];
            Array.Copy(data, layout.Offset, element, 0, element.Length);
            float scalar;

            switch (layout.Format)
            {
            case VRTF.ElementFormat.Float1:
            case VRTF.ElementFormat.Float2:
            case VRTF.ElementFormat.Float3:
            case VRTF.ElementFormat.Float4:
                for (int i = 0; i < output.Length; i++)
                {
                    output[i] += BitConverter.ToSingle(element, i * sizeof(float));
                }
                break;

            case VRTF.ElementFormat.ColorUByte4:
                switch (layout.Usage)
                {
                case VRTF.ElementUsage.Colour:
                    for (int i = 0; i < output.Length; i++)
                    {
                        output[i] += element[i] / (float)byte.MaxValue;
                    }
                    break;

                case VRTF.ElementUsage.BlendWeight:
                    for (int i = 0; i < output.Length; i++)
                    {
                        output[i] += element[kColorUByte4Map[i]] / (float)byte.MaxValue;
                    }
                    break;

                case VRTF.ElementUsage.Normal:
                case VRTF.ElementUsage.Tangent:
                    for (int i = 0; i < output.Length - 1; i++)
                    {
                        output[i] += element[2 - i] == 0 ? -1 : (((element[2 - i] + 1) / 128f) - 1);
                    }
                    //--
                    // Wes: (signed char) bytes[0]=vert[2+vrtfp.offset[j]];
                    //      (float)       norms[0]=(float)bytes[0];
                    //                    norms[0]=(norms[0]<(float)0.0)?(norms[0]+(float)128.0):(norms[0]-(float)128.0);
                    //???
                    //--
                    // input: 255 > 128 > 127 > 0
                    // map step1: +2 > 0
                    // map step2: +1 > -1
                    //for (int i = 0; i < output.Length - 1; i++)
                    //    output[i] += (element[2 - i] / 127.5f) - 1f;

                    switch (element[3])
                    {
                    case 0: output[output.Length - 1] = -1f; break;                 // -1 determinant

                    case 127: output[output.Length - 1] = 0f; break;                // There is no determinant

                    case 255: output[output.Length - 1] = +1f; break;               // +1 determinant

                    default: System.Diagnostics.Debug.WriteLine(String.Format("Unexpected handedness {0}.", element[3])); break;
                    }
                    break;
                }
                break;

            case VRTF.ElementFormat.Short2:
                for (int i = 0; i < output.Length; i++)
                {
                    output[i] += BitConverter.ToInt16(element, i * sizeof(short)) / (float)short.MaxValue;
                }
                break;

            case VRTF.ElementFormat.Short4:
                scalar = BitConverter.ToUInt16(element, 3 * sizeof(short));
                if (scalar == 0)
                {
                    scalar = short.MaxValue;
                }
                //scalar++;
                for (int i = 0; i < output.Length; i++)
                {
                    output[i] += BitConverter.ToInt16(element, i * sizeof(short)) / scalar;
                }
                break;

            case VRTF.ElementFormat.UShort4N:
                scalar = BitConverter.ToUInt16(element, 3 * sizeof(ushort));
                if (scalar == 0)
                {
                    scalar = 511;
                }
                //scalar++;
                for (int i = 0; i < output.Length; i++)
                {
                    output[i] += BitConverter.ToInt16(element, i * sizeof(short)) / scalar;
                }
                break;
            }
        }
예제 #8
0
파일: VBUF.cs 프로젝트: Onebeld/Regul
        public Vertex[] GetVertices(VRTF vrtf, long offset, int count, float[] uvscales)
        {
            long   streamOffset = offset;
            Stream s            = new MemoryStream(mBuffer);

            s.Seek(streamOffset, SeekOrigin.Begin);

            VRTF.ElementLayout position = vrtf.Layouts
                                          .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Position);
            VRTF.ElementLayout normal = vrtf.Layouts
                                        .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Normal);
            VRTF.ElementLayout[] uv = vrtf.Layouts
                                      .Where(x => x.Usage == VRTF.ElementUsage.UV)
                                      .ToArray();
            VRTF.ElementLayout blendIndices = vrtf.Layouts
                                              .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.BlendIndex);
            VRTF.ElementLayout blendWeights = vrtf.Layouts
                                              .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.BlendWeight);
            VRTF.ElementLayout tangents = vrtf.Layouts
                                          .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Tangent);
            VRTF.ElementLayout color = vrtf.Layouts
                                       .FirstOrDefault(x => x.Usage == VRTF.ElementUsage.Colour);

            Vertex[] verts = new Vertex[count];
            if (uvscales == null)
            {
                uvscales = new float[3];
            }
            for (int i = 0; i < count; i++)
            {
                Vertex v    = new Vertex();
                byte[] data = new byte[vrtf.Stride];
                s.Read(data, 0, vrtf.Stride);
                if (position != null)
                {
                    float[] posPoints = new float[VRTF.FloatCountFromFormat(position.Format)];
                    ReadFloatData(data, position, ref posPoints);
                    v.Position = posPoints;
                }
                if (normal != null)
                {
                    float[] normPoints = new float[VRTF.FloatCountFromFormat(normal.Format)];
                    ReadFloatData(data, normal, ref normPoints);
                    v.Normal = normPoints;
                }
                v.UV = new float[uv.Length][];
                for (int j = 0; j < uv.Length; j++)
                {
                    VRTF.ElementLayout u        = uv[j];
                    float[]            uvPoints = new float[VRTF.FloatCountFromFormat(u.Format)];
                    float scale = j < uvscales.Length && uvscales[j] != 0 ? uvscales[j] : uvscales[0];
                    ReadUVData(data, u, ref uvPoints, scale);
                    v.UV[j] = uvPoints;
                }
                if (blendIndices != null)
                {
                    byte[] blendIPoints = new byte[VRTF.ByteSizeFromFormat(blendIndices.Format)];
                    Array.Copy(data, blendIndices.Offset, blendIPoints, 0, blendIPoints.Length);
                    v.BlendIndices = blendIPoints;
                }
                if (blendWeights != null)
                {
                    float[] blendWPoints = new float[VRTF.FloatCountFromFormat(blendWeights.Format)];
                    ReadFloatData(data, blendWeights, ref blendWPoints);
                    v.BlendWeights = blendWPoints;
                }
                if (tangents != null)
                {
                    float[] tangentPoints = new float[VRTF.FloatCountFromFormat(tangents.Format)];
                    ReadFloatData(data, tangents, ref tangentPoints);
                    v.Tangents = tangentPoints;
                }
                if (color != null)
                {
                    float[] colorPoints = new float[VRTF.FloatCountFromFormat(color.Format)];
                    ReadFloatData(data, color, ref colorPoints);
                    v.Color = colorPoints;
                }
                verts[i] = v;
            }
            return(verts);
        }