横扫天下会 最高指挥官

 找回密码
 注册
查看: 1960|回复: 0

最高指挥官SCM/SCA模型动画数据结构布局源件

[复制链接]
发表于 2012-2-15 19:09 | 显示全部楼层 |阅读模式
本帖最后由 MAXUF 于 2012-4-26 21:41 编辑

dumpsca.py
  1. #**************************************************************************************************
  2. # Copyright (c) 2006 Gas Powered Games Corp. All Rights Reserved.
  3. # Gas Powered Games and Supreme Commander are the exclusive trademarks of Gas Powered Games Corp.
  4. #**************************************************************************************************

  5. def DumpSCA(filename):
  6.    
  7.     import struct,string

  8.     data = file(filename, 'rb').read()

  9.     fileheader_fmt = '4sllflllll'
  10.     fileheader_size = struct.calcsize(fileheader_fmt)   

  11.     start,stop = 0,fileheader_size
  12.    
  13.     (magic,             \
  14.      version,           \
  15.      numframes,         \
  16.      durationseconds,   \
  17.      numbones,          \
  18.      namesoffset,       \
  19.      linksoffset,       \
  20.      firstframeoffset,  \
  21.      framesize) = struct.unpack(fileheader_fmt,data[start:stop])
  22.    
  23.     print "----------------"
  24.     print " Animation Header"
  25.     print "----------------"
  26.     print "File Type:",magic
  27.     print "Version:",version
  28.     print "NumFrames:",numframes
  29.     print "NumBones:",numbones
  30.     print "Duration: %-10.5f" % durationseconds
  31.     print "NamesOffset:",namesoffset
  32.     print "LinkOffset:",linksoffset
  33.     print "DataOffset:",firstframeoffset
  34.     print "FrameSize:",framesize
  35.    
  36.     print "\n----------------"
  37.     print " Bone Info"
  38.     print "----------------"

  39.     start = namesoffset
  40.     stop = linksoffset
  41.     rawnames = struct.unpack(str(stop-start)+'s',data[start:stop])

  42.     bonenames = string.split(rawnames[0],'\0')[:-1]

  43.     links_fmt = str(numbones)+'l'
  44.     links_size = struct.calcsize(links_fmt)
  45.    
  46.     start = linksoffset
  47.     stop = start + links_size
  48.     bonelinks = struct.unpack(links_fmt,data[start:stop])

  49.     b = 0
  50.     for b in range(0,len(bonenames)) :
  51.         if (bonelinks[b] == -1) :
  52.             print  "#%d %-12s (<local root>)" % (b, bonenames[b])
  53.         else :
  54.             print  "#%d %-12s (child of #%d %s)" % (b, bonenames[b], bonelinks[b], bonenames[bonelinks[b]])
  55.    
  56.     print "\n----------------"
  57.     print " Animation Data"
  58.     print "----------------"

  59.     vec3_prettyprint = "(%11.5f,%11.5f,%11.5f)"
  60.     quat_prettyprint = "(%11.5f,%11.5f,%11.5f,%11.5f)"

  61.     frameheader_fmt = 'fl'
  62.     frameheader_size = struct.calcsize(frameheader_fmt)

  63.     posrot_fmt = '3f4f'
  64.     posrot_size = struct.calcsize(posrot_fmt)

  65.     start,stop = firstframeoffset,firstframeoffset+posrot_size
  66.     root_posrot = struct.unpack(posrot_fmt,data[start:stop])

  67.     print ("Root Delta:  Pos: " + vec3_prettyprint + " Rot:  " + quat_prettyprint) % root_posrot

  68.     for f in range (0, numframes) :
  69.         start,stop = stop,stop+frameheader_size           
  70.         (keytime,keyflags) = struct.unpack(frameheader_fmt,data[start:stop])
  71.         # Don't dump all the keys, only the beginning, middle, and end...
  72.         dumpit = (f < 2) or ((f > (numframes/2)-2) and (f < (numframes/2+1))) or f > (numframes-3)
  73.         if dumpit :
  74.             print "\nFrame: %-4d Time: %-11.5f Flags: 0x%08X\n" % (f, keytime, keyflags)
  75.         for b in range (0, numbones) :
  76.             start,stop = stop,stop+posrot_size
  77.             keydata = struct.unpack(posrot_fmt,data[start:stop])
  78.             if dumpit:
  79.                 print "   %2d: %-14s " % (b,'['+bonenames[b]+']'), (" Pos: " + vec3_prettyprint + " Rot:  " + quat_prettyprint) % keydata

  80. if __name__ == '__main__' :
  81.     import sys
  82.     from os import path

  83.     if len(sys.argv) == 2 :
  84.         DumpSCA(sys.argv[1])
  85.     else:
  86.         print "usage %s <SCA filename>" % path.basename(sys.argv[0])
复制代码
dumpscm.py
  1. #**************************************************************************************************
  2. # Copyright (c) 2006 Gas Powered Games Corp. All Rights Reserved.
  3. # Gas Powered Games and Supreme Commander are the exclusive trademarks of Gas Powered Games Corp.
  4. #**************************************************************************************************

  5. #define some pretty print formats
  6. vec4pp = "[%11.5f,%11.5f,%11.5f,%11.5f]"                             
  7. vec3pp = "[%11.5f,%11.5f,%11.5f]"                             
  8. vec2pp = "[%11.5f,%11.5f]"                             

  9. def DumpVert(v,d):

  10.     print "VERT[%4d]" % v
  11.     print ("  Pos:      " + vec3pp) % d[0:3]
  12.     print ("  Tangent:  " + vec3pp) % d[3:6]
  13.     print ("  Normal:   " + vec3pp) % d[6:9]
  14.     print ("  Binormal: " + vec3pp) % d[9:12]
  15.     print ("  UV0:      " + vec2pp) % d[12:14]
  16.     print ("  UV1:      " + vec2pp) % d[14:16]
  17.     print  "  Bone %3d" % d[16:17]
  18.    
  19. def DumpSCM(filename) :
  20.    
  21.     import struct,string

  22.     data = file(filename, 'rb').read()

  23.     start,stop = 0,struct.calcsize('4sL')
  24.     marker,version = struct.unpack('4sL',data[start:stop])

  25.     start,stop = stop,stop+struct.calcsize('2L')
  26.     boneoffset,bonecount = struct.unpack ('2L',data[start:stop])

  27.     start,stop = stop,stop+struct.calcsize('3L')
  28.     vertoffset,extravertoffset,vertcount = struct.unpack ('3L',data[start:stop])

  29.     start,stop = stop,stop+struct.calcsize('2L')
  30.     indexoffset,indexcount = struct.unpack ('2L',data[start:stop])
  31.     tricount = indexcount/3

  32.     start,stop = stop,stop+struct.calcsize('2L')
  33.     infooffset,infocount = struct.unpack ('2L',data[start:stop])

  34.     print "*** HEADER ***\n"

  35.     print 'File Type: %s' %marker
  36.     print 'Version: %d' % version
  37.     print 'Bone count: %d, Bone offset: %d' % (bonecount,boneoffset)
  38.     print 'Vertex count: %d, Vertex offset: %d, ExtraVert offset: %d' % (vertcount,vertoffset,extravertoffset)
  39.     print 'Triangle coun:t %d, Triangle offset: %d' % (tricount,indexoffset)
  40.     print 'Info count: %d, Info offset: %d' % (infocount,infooffset)

  41.     padding = str(32-(stop+4)%32)+'s4s'
  42.     start = stop+struct.calcsize(padding)
  43.     stop = boneoffset
  44.     rawnames = struct.unpack(str(stop-start)+'s',data[start:stop])

  45.     print "\n*** BONE NAMES ***\n"
  46.     bonenames = string.split(rawnames[0],'\0')[:-1]
  47.     for b in range(0,len(bonenames)):
  48.         print "[%2d] %s" % (b,bonenames[b])

  49.     print "\n*** BONE DATA ***\n"

  50.     bonestruct = '16f3f4f4i'
  51.     bonesize = struct.calcsize(bonestruct)
  52.     start,stop = boneoffset,boneoffset+bonesize
  53.     for b in range(0,bonecount):
  54.         bone = struct.unpack(bonestruct,data[start:stop])
  55.         start,stop = stop,stop+bonesize
  56.         print "\nBONE %d : [%s]" % (b,bonenames[b])
  57.         print ' Parent Bone'
  58.         if (bone[24] == -1) :
  59.             print '  -1 <root>'
  60.         else :
  61.             print '  %d <%s>' % (bone[24],bonenames[bone[24]])
  62.         print ' Parent Relative Position'
  63.         print ('  '+vec3pp) % bone[16:19]
  64.         print ' Parent Relative Rotation'
  65.         print ('  ' +vec4pp) % bone[19:23]
  66.         print ' Rest Pose Inverse'
  67.         for row in range(4):
  68.             print ('  '+ vec4pp) % bone[row*4:row*4+4]

  69.     print "\n*** VERTEX DATA ***\n"

  70.     vertstruct = '3f3f3f3f2f2f4B'
  71.     vertsize = struct.calcsize(vertstruct)
  72.     stop = vertoffset
  73.     if (vertcount < 7):
  74.         for v in range(0,vertcount):
  75.             start,stop = stop,stop+vertsize
  76.             vert = struct.unpack(vertstruct,data[start:stop])
  77.             DumpVert(v,vert)
  78.     else:
  79.         for v in range(0,3):
  80.             start,stop = stop,stop+vertsize
  81.             vert = struct.unpack(vertstruct,data[start:stop])
  82.             DumpVert(v,vert)
  83.         print "...skipping %d verts..." % (vertcount-5)
  84.         stop = vertoffset+(vertsize*(vertcount-3))
  85.         for v in range(vertcount-3,vertcount):
  86.             start,stop = stop,stop+vertsize
  87.             vert = struct.unpack(vertstruct,data[start:stop])
  88.             DumpVert(v,vert)

  89.     if (extravertoffset != 0) :
  90.         print "EXTRAVERTS (first 5 only...)\n"
  91.         extravertstruct = '2f'
  92.         extravertsize = struct.calcsize(extravertstruct)
  93.         start,stop = extravertoffset,extravertoffset+extravertsize
  94.         for v in range(0,min(5,vertcount)):
  95.             xvert = struct.unpack(extravertstruct,data[start:stop])
  96.             start,stop = stop,stop+extravertsize
  97.             print xvert[0:2]
  98.     else :
  99.         print "No EXTRAVERT data for this model\n"

  100.     print "\n*** TRIANGLE INDICES ***\n"

  101.     tristruct = '3h'
  102.     trisize = struct.calcsize(tristruct)
  103.     stop = indexoffset

  104.     if (tricount < 7) :
  105.         for t in range(0,tricount):
  106.             start,stop = stop,stop+trisize
  107.             tri = struct.unpack(tristruct,data[start:stop])
  108.             print tri[0],
  109.             print tri[1],
  110.             print tri[2]
  111.     else :
  112.         for t in range(0,3):
  113.             start,stop = stop,stop+trisize
  114.             tri = struct.unpack(tristruct,data[start:stop])
  115.             print "%4d: %s" % (t, tri)
  116.         print "...skipping %d triangles..." % (tricount-5)
  117.         stop = indexoffset+(trisize*(tricount-3))
  118.         for t in range(tricount-3,tricount):
  119.             start,stop = stop,stop+trisize
  120.             tri = struct.unpack(tristruct,data[start:stop])
  121.             print "%4d: %s" % (t, tri)
  122.                     
  123.     print "\n*** INFO ***\n"

  124.     infostruct = str(infocount)+'s'
  125.     infosize = struct.calcsize(infostruct)
  126.     start,stop = infooffset,infooffset+infosize
  127.     info = struct.unpack(infostruct,data[start:stop])
  128.     infostrings = string.split(info[0],'\0')[:-1]
  129.     for i in infostrings:
  130.         print " %s" % i

  131. if __name__ == '__main__' :
  132.     import sys
  133.     from os import path

  134.     if len(sys.argv) == 2 :
  135.         DumpSCM(sys.argv[1])
  136.     else:
  137.         print "usage %s <SCM filename>" % path.basename(sys.argv[0])
复制代码
ScaFile_format.h
  1. /**************************************************************************************************
  2. Copyright (c) 2006 Gas Powered Games Corp. All Rights Reserved.
  3. Gas Powered Games and Supreme Commander are the exclusive trademarks of Gas Powered Games Corp.
  4. ***************************************************************************************************/

  5. #ifndef SCAFILE_H
  6. #define SCAFILE_H


  7. // SScaFileHeader -- The header for .SCA files.
  8. //
  9. struct SScaFileHeader
  10. {
  11.     // The FOURCC 'ANIM'
  12.     unsigned long mMagic;

  13.     // The .SCA version number.
  14.     unsigned long mVersion;

  15.     // The number of frames in this animation.
  16.     unsigned long mNumFrames;

  17.     // The duration (in seconds) of this animation.  
  18.     // The animation plays at (mNumFrames-1)/mDuration frames per second.
  19.     float mDuration;

  20.     // The number of bones in this animation.
  21.     unsigned long mNumBones;

  22.     // Offset of the bone names (SScaFileBoneNames[0])
  23.     unsigned long mBoneNamesOffset;

  24.     // Offset of the bone link info (SScaFileBoneLinks[0])
  25.     unsigned long mBoneLinksOffset;

  26.     // Offset of the actual animation data (SScaFileAnimData[0])
  27.     unsigned long mFirstFrameOffset;

  28.     // The number of bytes in one animation frame.
  29.     unsigned long mFrameSize;
  30. };

  31. // SScaFileBoneNames -- The bone names used in this animation.
  32. //
  33. struct SScaFileBoneNames
  34. {
  35.     // Array of bone names.  There are header.mNumBones NUL terminated
  36.     // strings concatenated together starting here.
  37.     char mBoneNameData[1]; //(array size is mNumBones)
  38. };

  39. // SScaFileBoneLinks -- The parent links for the bones used in this animation.
  40. //
  41. struct SScaFileBoneLinks
  42. {
  43.     // Array of bone indices.
  44.     unsigned long mParentBoneIndex[]; //(array size is mNumBones)
  45. };

  46. // SScaFileBoneKeyframe -- The data for single bone at a single key
  47. // frame.
  48. //
  49. struct SScaFileBoneKeyframe
  50. {
  51.     // Position relative to the parent bone.
  52.     // Vector (x,y,z)
  53.     float mPosition[3];

  54.     // Rotation relative to the parent bone.
  55.     // Quaternion (w,x,y,z)
  56.     float mRotation[4];
  57. };

  58. // SScaFileKeyframe -- The data about a single key frame.
  59. //
  60. struct SScaFileKeyframe
  61. {
  62.     // The time (in seconds) of this keyframe.
  63.     float mTime;

  64.     // Various flags.  None defined yet.
  65.     unsigned long mFlags;

  66.     // Array of keyframe data for each bone.
  67.     SScaFileBoneKeyframe mBones[1];  //(array size is mNumBones)
  68. };

  69. // SScaFileAnimData -- The actual animation data.
  70. //
  71. struct SScaFileAnimData
  72. {
  73.     // The total position delta between the first frame and the last frame.
  74.     // Vector (x,y,z)
  75.     float mPositionDelta[3];

  76.     // The total orientation delta between the first frame and the last frame.
  77.     // Quaternion (w,x,y,z)
  78.     float mOrientDelta[4];

  79.     // The per-frame data.
  80.     SScaFileKeyframe mFrames[1];  //(array size is mNumFrames)
  81. };


  82. #endif SCAFILE_H
复制代码
ScmFile_format.h
  1. /**************************************************************************************************
  2. Copyright (c) 2006 Gas Powered Games Corp. All Rights Reserved.
  3. Gas Powered Games and Supreme Commander are the exclusive trademarks of Gas Powered Games Corp.
  4. ***************************************************************************************************/

  5. #ifndef SCMFILE_H
  6. #define SCMFILE_H

  7. // SCM VERSION 5 DATA LAYOUT

  8. // Multi-byte data is writting in little-endian ("Intel") format

  9. // There are 5 required and 2 optional sections in an SCM file, each indicated by a leading FOURCC code:

  10. // FOURCC  |  Contents
  11. // --------+------------------------
  12. // 'MODL'  | Header info
  13. // 'NAME'  | List of bone name strings
  14. // 'SKEL'  | Array of bone data
  15. // 'VTXL'  | Array of basic vertex data
  16. // 'TRIS'  | Array of triangle indices
  17. // 'VEXT'  | Array of extra vertex data (OPTIONAL SECTION)
  18. // 'INFO'  | List of null terminated information strings (OPTIONAL SECTION)

  19. // Section offsets in the file header point to the start of the data for that section (ie, the first byte AFTER
  20. // the section's identifying FOURCC) Padding characters are added to the end of each section to ensure that
  21. // the next section is 16-byte aligned. Ommitted sections are indicated by an offset of 0.

  22. // *** All offsets are relative to the start of the file ***

  23. //
  24. //
  25. struct ScmHeader
  26. {

  27.     // The FOURCC 'MODL'
  28.     unsigned long mMagic;

  29.         // The .SCM version number
  30.     unsigned long mVersion;

  31.     // Offset to SCM_BoneData[0]
  32.     unsigned long mBoneOffset;
  33.    
  34.     // Number of elements in SCM_BoneData that actually influence verts (no reference points)
  35.     unsigned long mWeightedBoneCount;

  36.     // Offset of basic vertex data section (SCM_VertData[0])
  37.     unsigned long mVertexOffset;

  38.     // Offset of extra vertex data section (SCM_VertExtraData[0])
  39.     // Contains additional per-vertex information. *** Currently unused (and omitted) in SupCom 1.0 ***
  40.     unsigned long mVertexExtraOffset;   

  41.     // Number of elements in the SCM_VertData array
  42.     // (and the SCM_VertExtraData array, if mVertexExtraOffset != 0)
  43.     unsigned long mVertexCount;        

  44.     // Offset of the triangle index section (SCM_TriangleData[0])
  45.     unsigned long mIndexOffset;         

  46.     // Number of elements in the SCM_TriangleData array
  47.     unsigned long mIndexCount;         

  48.     // Offset of information section (SCM_InfoData[0])
  49.     unsigned long mInfoOffset;
  50.               
  51.     // Number of elements in the SCM_InfoData list
  52.     unsigned long mInfoCount;           

  53.     // Number of elements in the SCM_BoneData array (including 'reference point' bones)
  54.     unsigned long mTotalBoneCount;      
  55. };

  56. //
  57. //
  58. struct ScmBoneData
  59. {
  60.         // Inverse transform of the bone relative to the local origin of the mesh
  61.     // 4x4 Matrix with row major (i.e. D3D default ordering)
  62.     float mRestPoseInverse[4][4];

  63.      // Position relative to the parent bone.
  64.     // Vector (x,y,z)
  65.     float mPosition[3];

  66.     // Rotation relative to the parent bone.
  67.     // Quaternion (w,x,y,z)
  68.     float mRotation[4];

  69.         // Offset of the bone's name string
  70.     unsigned long mNameOffset;

  71.         // Index of the bone's parent in the SCM_BoneData array
  72.     unsigned long mParentBoneIndex;

  73.     unsigned long RESERVED_0;      
  74.     unsigned long RESERVED_1;      
  75. };

  76. //
  77. //
  78. struct ScmVertData
  79. {
  80.         // Position of the vertex relative to the local origin of the mesh
  81.     float mPosition[3];

  82.         // 'Tangent Space' normal, tangent & binormal unit vectors
  83.     float mNormal[3];
  84.     float mTangent[3];
  85.     float mBinormal[3];

  86.         // Two sets of UV coordinates
  87.     float mUV0[2];
  88.     float mUV1[2];

  89.     // Up to 4-bone skinning can be supported using additional
  90.     // indices (in conjunction with bone weights in the optional VertexExtra array)
  91.     // Skinned meshes are not used in SupCom 1.0 so only mBoneIndex[0] is expected
  92.     // to contain a valid index.
  93.     unsigned char mBoneIndex[4];
  94. };

  95. struct ScmTriangleData
  96. {
  97.     unsigned short triIndices[3];
  98. };


  99. #endif SCMFILE_H
复制代码
以上文件来源于GPG论坛,本人估计是开发最高指挥官SCM/SCA模型动画格式导入导出插件所需要用到的数据结构布局源件.
最高指挥官模型解析器原始下载地址:
http://www.pixelheaven.net/supcom/SupCom3DFormats.rar
http://viking.gurut.org/tools/SupCom3DFormats.rar
最高指挥官模型解析器天下会备份下载地址:
SupCom3DFormats.rar (188.31 KB, 下载次数: 4)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|横扫天下会 最高指挥官 ( 沪ICP备11033600号-1 )

GMT+8, 2020-9-28 16:44 , Processed in 0.019436 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表