[C#] Converting array of bytes to array of structs? menu

User Tag List

Results 1 to 4 of 4
  1. #1
    xalcon's Avatar Contributor ふたなり
    Authenticator enabled
    Reputation
    198
    Join Date
    Oct 2008
    Posts
    291
    Thanks G/R
    20/58
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    [C#] Converting array of bytes to array of structs?

    Hi there,
    currently I'm working on my wow world parser (nav mesh generation :3) and I'm realy far now. But I've a little problem with speed. The parser needs the most time for parsing the vertices, indices and normal vectors from the wmo groupfiles.

    I have a stream which I read with this method:
    Indices:
    Code:
    this.indices = new ushort[polys * 3];
    for (int i = 0; i < polys * 3; i++)
    {
    	this.indices[i] = chunk.ReadStruct<ushort>();
    }
    Normals and Vertices
    Code:
    this.vertices = new Vector3D[chunk.Length / 3];
    for (int i = 0; i < chunk.Length / 3; i++)
    {
    	this.vertices[i] = chunk.ReadStruct<Vector3D>();
    }
    ReadSturct<T>():
    Code:
    public static T ReadStruct<T>(this Stream s) where T : struct
    {
    	var sz = Marshal.SizeOf(typeof(T));
    	var buf = new byte[sz];
    	s.Read(buf, 0, sz);
    	var handle = GCHandle.Alloc(buf, GCHandleType.Pinned);
    	var t = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
    	handle.Free();
    	return t;
    }
    which gets painfully slow, when reading big wmoRoot files (and their associated groups) like Ogrimmar2.wmo
    So I made a performance check using visual studios cpu sampling feature:
    Parsing Normals: 30%
    Parsing Vertices: 29.8%
    Parsing Indices: 24.3%
    I've found a way to read chunks of primitive arrays like ushort[]. After using the code below, I was able to reduce the workload on the index parsing from 24.3% to around 0.1%!!
    Code:
    public static TDest[] ConvertArray<TSource, TDest>(TSource[] source)
    	where TSource : struct
    	where TDest : struct
    {
    
    	if (source == null)
    		throw new ArgumentNullException("source");
    
    	var sourceType = typeof(TSource);
    	var destType = typeof(TDest);
    
    	var sourceByteSize = Buffer.ByteLength(source);
    	var destTypeSize = Marshal.SizeOf(destType);
    	if (sourceByteSize % destTypeSize != 0)
    		throw new Exception(
    			"The source array is " + sourceByteSize + " bytes, which can " +
    			"not be transfered to chunks of " + destTypeSize + ", the size " +
    			"of type " + typeof(TDest).Name + ". Change destination type or " +
    			"pad the source array with additional values."
    		);
    
    	var destCount = sourceByteSize / destTypeSize;
    	var destArray = new TDest[destCount];
    
    	Buffer.BlockCopy(source, 0, destArray, 0, sourceByteSize);
    
    	return destArray;
    }

    The problem is, I can't use the ConvertArray() method to convert byte arrays to arrays of struct X (like Vector3D), since Buffer.BlockCopy() is not able to copy into a struct. Is there any solution to speed up my vertex and normal parsing, too?
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

    [C#] Converting array of bytes to array of structs?
  2. #2
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Have you tried casting from a fixed byte* to the struct? Eg;

    Code:
    fixed (byte* pBuffer = bytes)
    for(int i = 0; i < count; i++)
        ret[i] = ((StructureType*)pBuffer)[i];

  3. #3
    xalcon's Avatar Contributor ふたなり
    Authenticator enabled
    Reputation
    198
    Join Date
    Oct 2008
    Posts
    291
    Thanks G/R
    20/58
    Trade Feedback
    0 (0%)
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    You are my hero, apoc.

    Before: 8.65 seconds
    After: 0.94 seconds

    That is realy awesome Thank you!

    Sadly, VS don't like to give me an unmanaged pointer to T
    Code:
    public static unsafe T[] Convert<T>(byte[] buffer)
    {
    	T[] v = new T[buffer.Length / (Marshal.SizeOf(typeof(T)))];
    	fixed (byte* pBuffer = buffer)
    	{
    		for (int i = 0; i < v.Length; i++)
    			v[i] = ((T*)pBuffer)[i];
    	}
    	return v;
    }
    But anyway, changing T to a specific type works and since I don't have so much different structures I need to parse fast, this is working realy well too!
    Here is some working code:
    Code:
    public static unsafe Vector3D[] GetVertices(byte[] buffer)
    {
    	Vector3D[] vecs = new Vector3D[buffer.Length / (3*4)];
    	fixed (byte* pBuffer = buffer)
    	{
    		for (int i = 0; i < vecs.Length; i++)
    			vecs[i] = ((Vector3D*)pBuffer)[i];
    	}
    	return vecs;
    }
    // Edit:
    I've changed another part to this converting aproach and... now I only need 0.090 seconds O__O to load Ogrimmar2.wmo... and the most time I spend on removing unimportant polygons (Flags & 4 && Material == 0xFF). Just 42 ms for parsing all WMO related stuff... compared to the 8.6 seconds before... its ridiculous

    *Hug apoc*
    Last edited by xalcon; 03-29-2012 at 07:31 AM.
    "Threads should always commit suicide - they should never be murdered" - DirectX SDK

  4. #4
    Apoc's Avatar Angry Penguin
    Reputation
    1387
    Join Date
    Jan 2008
    Posts
    2,750
    Thanks G/R
    0/12
    Trade Feedback
    0 (0%)
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Originally Posted by xalcon View Post
    You are my hero, apoc.

    Before: 8.65 seconds
    After: 0.94 seconds

    That is realy awesome Thank you!

    Sadly, VS don't like to give me an unmanaged pointer to T
    Code:
    public static unsafe T[] Convert<T>(byte[] buffer)
    {
        T[] v = new T[buffer.Length / (Marshal.SizeOf(typeof(T)))];
        fixed (byte* pBuffer = buffer)
        {
            for (int i = 0; i < v.Length; i++)
                v[i] = ((T*)pBuffer)[i];
        }
        return v;
    }
    There are ways to get around that, but you'll need some more stuff that is probably not worth it for the stuff you're doing.

Similar Threads

  1. [Guide] AoB/Array of Bytes edits
    By Parog in forum Mobile & Flash Game Hacks
    Replies: 4
    Last Post: 06-15-2014, 06:49 PM
  2. [Array] Need help.
    By Yamanaki in forum Programming
    Replies: 14
    Last Post: 03-17-2008, 02:06 PM
All times are GMT -5. The time now is 11:21 PM. Powered by vBulletin® Version 4.2.3
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. User Alert System provided by Advanced User Tagging (Pro) - vBulletin Mods & Addons Copyright © 2024 DragonByte Technologies Ltd.
Digital Point modules: Sphinx-based search