Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Using the mesh API

Discussion in 'Scripting' started by bronxbomber92, Jun 20, 2007.

  1. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    I've got this class that's suppose to load MD2 model. I don't really know how to apply it an actual mesh in the scene? I do know that once I have the mesh I need to do this
    Code (csharp):
    1.  Vector2[] UV = new Vector2[mNumTriangles*3];
    2.        
    3.         int k = 0;
    4.         for( int i = 0; i < mNumTriangles; i++ )
    5.         {
    6.             UV[k] = mTexCoords[mTriangles[i].mTexIndices[0]];
    7.             UV[k+1] = mTexCoords[mTriangles[i].mTexIndices[0]];
    8.             UV[k+2] = mTexCoords[mTriangles[i].mTexIndices[0]];
    9.         }
    10.        
    11.         mesh.vertices = mVertices;
    12.         mesh.uv = UV;
    Anyways, any help on hooking this up in a scene would be of great help!

    Here's the class (the drawing function is temporary, it can be changed to work :p)
    Code (csharp):
    1. sing UnityEngine;
    2. using System.Collections;
    3. using System.IO;
    4. using System.Runtime.InteropServices;
    5. using System;
    6.  
    7. public struct MD2Header
    8. {
    9.     public int mMagic; // 844121161 or "IDP2" - ( ('2' << 24) + ('P' << 16) + ('D' << 8) + 'I' )
    10.     public int mVersion; // 8
    11.    
    12.     public int mSkinWidth; // Texture width
    13.     public int mSkinHeight; // Texture height
    14.    
    15.     public int mFrameSize; // A single frame's size in bytes
    16.     public int mNumSkins; // Number of textures with the model
    17.     public int mNumVertices; // Number of vertices per frame
    18.     public int mNumTexCoords; // Number of texture coordinates
    19.     public int mNumTriangles; // Number of triangles per frame
    20.     public int mNumGLCommands; // Number of OGL commands
    21.     public int mNumFrames; // Number of frames
    22.    
    23.     public int mSkinsOffset; // Position in bytes from the start to the texture names
    24.     public int mTexCoordsOffset; // Position in bytes from the start to the texture coords
    25.     public int mTrianglesOffset; // Position in bytes from the start to the triangle list
    26.     public int mFramesOffset; // Position in bytes from the start to the frames list
    27.     public int mGLCommandsOffset;  // Position in bytes from the start to the OGL commands list
    28.     public int mEndOffset;   // Position in bytes from the start to the end of the file
    29. }
    30.  
    31. public struct MD2Vertex
    32. {
    33.     public byte[] mVerts; // Compressed vertices
    34.     public byte mLightNormalIndex; // Index into an array of normals by ID software
    35. }
    36.  
    37.  
    38. // float vect[3];
    39. //vect[i] = (mVertices.mVerts[i] * mScale[i]) + mTranslate[i];
    40. public struct MD2Frame
    41. {
    42.     public float[] mScale;
    43.     public float[] mTranslate;
    44.     public byte[] name;
    45.     public MD2Vertex[] mVertices;
    46. }
    47.  
    48. public struct MD2Triangle
    49. {
    50.     public short[] mVertIndices;
    51.     public short[] mTexIndices;
    52. }
    53.  
    54. // Divide u by SkinWidth and v by SkinHeight to get real tex coords
    55. public struct MD2TexCoordShort
    56. {
    57.     public short u, v;
    58. }
    59.  
    60. public struct MD2TexCoord
    61. {
    62.     public float u, v;
    63. }
    64.  
    65. public struct MD2GLCommandVertex
    66. {
    67.     public float s, t;
    68.     public int VertIndex;
    69. }
    70.  
    71. public struct Animation
    72. {
    73.     public int mFirstFrame; // 1st frame of the animation
    74.     public int mLastFrame; // Number of frame (animate mFirstFrame through mFirstFrame + mLastFrame)
    75.     public int mFPS; // frames per second
    76. }
    77.  
    78. public struct AnimationState
    79. {
    80.     public int mStartFrame;         // first frame
    81.     public int mEndFrame;           // last frame
    82.     public int mFps;                // fps
    83.    
    84.     /* interpolation */
    85.     public float mTime;             // current time
    86.     public float mOldTime;          // Old time
    87.     public float mInterpolation;    // The actual interpolation
    88.    
    89.     public int mType;               // Animation type (STAND, RUN, ATTACK, ect..)
    90.     public int mFrame;          // Current frame
    91.     public int mNextFrame;      // Next frame
    92.     public bool mLoop;              // Does the animation loop?
    93.     public bool mIncrease;          // Should me increase the next frame (for non looping anim)
    94. }
    95.  
    96.  
    97. public class CModelMD2 : MonoBehaviour
    98. {  
    99.     private int mNumVerts; // Vertices per frame
    100.     private int mNumFrames; // Total number of frames in the model
    101.     private int mNumTexCoords; // Number of texture coordinates
    102.     private int mNumSkins;
    103.     private int mNumTriangles;
    104.    
    105.     private Vector3[] mVertices;
    106.     private Vector2[] mTexCoords;
    107.    
    108.     private MD2Frame[] mFrames;
    109.     private MD2Triangle[] mTriangles;
    110.     private MD2TexCoordShort[] mCompressedTexCoords;
    111.    
    112.     private AnimationState mAnimation; // The Current animation state
    113.  
    114.  
    115.     public void LoadModel( string filename )
    116.     {
    117.         FileStream fs = new FileStream( filename, FileMode.Open, FileAccess.Read );
    118.         BinaryReader pFile = new BinaryReader(fs);
    119.         MD2Header header;
    120.        
    121.         // Read in the header
    122.         byte[] buff = pFile.ReadBytes(Marshal.SizeOf(typeof(MD2Header)));//read the header as binary data
    123.         GCHandle handle = GCHandle.Alloc(buff, GCHandleType.Pinned); //prevent the GC from affecting the buffer
    124.         header = (MD2Header)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MD2Header)); //get the header from the buffer
    125.         handle.Free();
    126.        
    127.         if( header.mMagic != 844121161 || header.mVersion != 8 )
    128.         {
    129.             return;
    130.         }
    131.        
    132.         mNumVerts = header.mNumVertices;
    133.         mNumFrames = header.mNumFrames;
    134.         mNumTexCoords = header.mNumTexCoords;
    135.         mNumTriangles = header.mNumTriangles;
    136.         mNumSkins = header.mNumSkins;
    137.        
    138.         mVertices = new Vector3[mNumVerts * mNumFrames];
    139.         mFrames = new MD2Frame[mNumFrames * header.mFrameSize];
    140.         mTriangles = new MD2Triangle[mNumTriangles];
    141.         mTexCoords = new Vector2[mNumTexCoords];
    142.         mCompressedTexCoords = new MD2TexCoordShort[mNumTexCoords];
    143.        
    144.         // Read in the texture coords
    145.         pFile.BaseStream.Seek( header.mTexCoordsOffset, SeekOrigin.Begin );
    146.         for(int i = 0; i < mNumTexCoords; i++ )
    147.         {
    148.             buff = pFile.ReadBytes(Marshal.SizeOf(typeof(MD2TexCoordShort)));//read the header as binary data
    149.             handle = GCHandle.Alloc(buff, GCHandleType.Pinned); //prevent the GC from affecting the buffer
    150.             mCompressedTexCoords[i] = (MD2TexCoordShort)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MD2TexCoordShort)); //get the header from the buffer
    151.             handle.Free();
    152.            
    153.             // Get the real tex coords
    154.             mTexCoords[i].x = mCompressedTexCoords[i].u / (float)header.mSkinWidth;
    155.             mTexCoords[i].y = mCompressedTexCoords[i].v / (float)header.mSkinHeight;
    156.             mTexCoords[i].y = 1.0f - mTexCoords[i].y;
    157.         }
    158.        
    159.         // Read in the triangles
    160.         pFile.BaseStream.Seek( header.mTrianglesOffset, SeekOrigin.Begin );
    161.         for(int i = 0; i < mNumTriangles; i++ )
    162.         {
    163.             buff = pFile.ReadBytes(Marshal.SizeOf(typeof(MD2Triangle)));//read the header as binary data
    164.             handle = GCHandle.Alloc(buff, GCHandleType.Pinned); //prevent the GC from affecting the buffer
    165.             mTriangles[i] = (MD2Triangle)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MD2Triangle)); //get the header from the buffer
    166.             handle.Free();
    167.         }
    168.        
    169.         // Read in the frames
    170.         pFile.BaseStream.Seek( header.mFramesOffset, SeekOrigin.Begin );
    171.         for(int i = 0; i < mNumTriangles; i++ )
    172.         {
    173.             buff = pFile.ReadBytes(Marshal.SizeOf(typeof(MD2Frame)));//read the header as binary data
    174.             handle = GCHandle.Alloc(buff, GCHandleType.Pinned); //prevent the GC from affecting the buffer
    175.             mFrames[i] = (MD2Frame)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MD2Frame)); //get the header from the buffer
    176.             handle.Free();
    177.         }
    178.        
    179.         // read in the vertices
    180.         int k = 0;
    181.         for( int i = 0; i < mNumFrames; i++ )
    182.         {
    183.             for( int j = 0; j < mNumVerts; j++ )
    184.             {
    185.                 mVertices[k].x = (mFrames[i].mVertices[j].mVerts[0] * mFrames[i].mScale[0]) + mFrames[i].mTranslate[0];
    186.                 mVertices[k].y = (mFrames[i].mVertices[j].mVerts[1] * mFrames[i].mScale[1]) + mFrames[i].mTranslate[1];
    187.                 mVertices[k].z = (mFrames[i].mVertices[j].mVerts[2] * mFrames[i].mScale[2]) + mFrames[i].mTranslate[2];
    188.                 k++;
    189.             }
    190.         }
    191.     }
    192.  
    193.     public void DrawFrame( int frame, Mesh mesh )
    194.     {
    195.         Vector2[] UV = new Vector2[mNumTriangles*3];
    196.        
    197.         int k = 0;
    198.         for( int i = 0; i < mNumTriangles; i++ )
    199.         {
    200.             UV[k] = mTexCoords[mTriangles[i].mTexIndices[0]];
    201.             UV[k+1] = mTexCoords[mTriangles[i].mTexIndices[0]];
    202.             UV[k+2] = mTexCoords[mTriangles[i].mTexIndices[0]];
    203.         }
    204.        
    205.         mesh.vertices = mVertices;
    206.         mesh.uv = UV;
    207.        
    208.     }
    209.    
    210.     // Use this for initialization
    211.     void Start ()
    212.     {
    213.        
    214.     }
    215.    
    216.     // Update is called once per frame
    217.     void Update () {
    218.    
    219.     }
    220. }
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Start with an empty object and give it a MeshFilter and a MeshRenderer component (from Components > Mesh menu). The GameObject class has an instance method called GetComponent that enables you to access the MeshFilter as an object from the script. The MeshFilter component has a property called "mesh" which is an instance of the Mesh class. If you look at the docs for this class, you will find it has properties called vertices, triangles, uv, etc. You just need to assign the arrays you get from parsing your original model data to these properties. When the display updates (after the Update or FixedUpdate method is called) then your mesh will be visible - assuming you did everything correctly!

    I strongly recommend doing things in stages when testing your mesh code. Join the verts in array order with Debug lines to get a good rough impression that they are OK. Then, add triangles and check for holes. If the object disappears when you add normals then check they are the right way round by looking at the object from inside. Check each "feature" you add before proceeding to the next and the whole process shouldn't turn into a nightmare.

    If you need any further help, I could pass you the text of an article on mesh generation that I originally wrote for the vanished Unity magazine. Just let me know...
     
  3. bronxbomber92

    bronxbomber92

    Joined:
    Nov 11, 2006
    Posts:
    888
    Thanks, I'll give this a try! I know the actual loading code, and getting the acual vertices work because this was all C++ and OpenGL before :p

    Thanks!