2
0

GXS.FileMS3D.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.FileMS3D;
  5. (* Support for MS3D file format *)
  6. interface
  7. {$I Stage.Defines.inc}
  8. uses
  9. System.Classes,
  10. System.SysUtils,
  11. System.Math,
  12. GXS.VectorFileObjects,
  13. Stage.VectorTypes,
  14. GXS.Material,
  15. GXS.Color,
  16. GXS.Texture,
  17. Stage.VectorGeometry,
  18. GXS.VectorLists,
  19. GXS.ApplicationFileIO;
  20. const
  21. MAX_MS3D_VERTICES = 8192;
  22. MAX_MS3D_TRIANGLES = 16384;
  23. MAX_MS3D_GROUPS = 128;
  24. MAX_MS3D_MATERIALS = 128;
  25. MAX_MS3D_JOINTS = 128;
  26. MAX_MS3D_KEYFRAMES = 5000;
  27. type
  28. // typedef struct
  29. // {
  30. // byte flags; // SELECTED | HIDDEN
  31. // char name[32]; //
  32. // word numtriangles; //
  33. // word triangleIndices[numtriangles]; // the groups group the triangles
  34. // char materialIndex; // -1 = no material
  35. // } ms3d_group_t;
  36. TMS3DGroup = class
  37. public
  38. Flags: byte;
  39. Name: array[0..31] of AnsiChar;
  40. NumTriangles: word;
  41. TriangleIndices: TList;
  42. MaterialIndex: Shortint;
  43. constructor Create;
  44. destructor Destroy; override;
  45. end;
  46. // typdef struct
  47. // {
  48. // char id[10]; // always "MS3D000000"
  49. // int version; // 4
  50. // } ms3d_header_t;
  51. {$A-}
  52. TMS3DHeader = record
  53. ID: array[0..9] of AnsiChar;
  54. Version: integer;
  55. end;
  56. // typedef struct
  57. // {
  58. // byte flags; // SELECTED | SELECTED2 | HIDDEN
  59. // float vertex[3]; //
  60. // char boneId; // -1 = no bone
  61. // byte referenceCount;
  62. // } ms3d_vertex_t;
  63. TMS3DVertex = record
  64. Flags: byte;
  65. Vertex: TD3DVector;
  66. BoneId: AnsiChar;
  67. ReferenceCount: byte;
  68. end;
  69. PMS3DVertexArray = ^TMS3DVertexArray;
  70. TMS3DVertexArray = array[0..MAX_MS3D_VERTICES - 1] of TMS3DVertex;
  71. // typedef struct
  72. // {
  73. // word flags; // SELECTED | SELECTED2 | HIDDEN
  74. // word vertexIndices[3]; //
  75. // float vertexNormals[3][3]; //
  76. // float s[3]; //
  77. // float t[3]; //
  78. // byte smoothingGroup; // 1 - 32
  79. // byte groupIndex; //
  80. // } ms3d_triangle_t;
  81. TMS3DTriangle = record
  82. Flags: word;
  83. VertexIndices: array[0..2] of word;
  84. VertexNormals: array[0..2] of TD3DVector;
  85. S: array[0..2] of single;
  86. T: array[0..2] of single;
  87. SmoothingGroup: byte; // 1 - 32
  88. GroupIndex: byte;
  89. end;
  90. PMS3DTriangleArray = ^TMS3DTriangleArray;
  91. TMS3DTriangleArray = array[0..MAX_MS3D_TRIANGLES - 1] of TMS3DTriangle;
  92. // typedef struct
  93. // {
  94. // char name[32]; //
  95. // float ambient[4]; //
  96. // float diffuse[4]; //
  97. // float specular[4]; //
  98. // float emissive[4]; //
  99. // float shininess; // 0.0f - 128.0f
  100. // float transparency; // 0.0f - 1.0f
  101. // char mode; // 0, 1, 2 is unused now
  102. // char texture[128]; // texture.bmp
  103. // char alphamap[128]; // alpha.bmp
  104. // } ms3d_material_t;
  105. TMS3DMaterial = record
  106. Name: array[0..31] of AnsiChar;
  107. Ambient: TgxColorVector;
  108. Diffuse: TgxColorVector;
  109. Specular: TgxColorVector;
  110. Emissive: TgxColorVector;
  111. Shininess: single;
  112. Transparency: single;
  113. Mode: AnsiChar;
  114. Texture: array[0..127] of AnsiChar;
  115. Alphamap: array[0..127] of AnsiChar;
  116. end;
  117. // typedef struct
  118. // {
  119. // float time; // time in seconds
  120. // float rotation[3]; // x, y, z angles
  121. // } ms3d_keyframe_rot_t;
  122. TMS3DKeyframeRotation = record
  123. Time: single;
  124. Rotation: TD3DVector;
  125. end;
  126. PMS3DKeyframeRotationArray = ^TMS3DKeyframeRotationArray;
  127. TMS3DKeyframeRotationArray = array[0..MAX_MS3D_KEYFRAMES - 1] of TMS3DKeyframeRotation;
  128. // typedef struct
  129. // {
  130. // float time; // time in seconds
  131. // float position[3]; // local position
  132. // } ms3d_keyframe_pos_t;
  133. TMS3DKeyframePosition = record
  134. Time: single;
  135. Position: TD3DVector;
  136. end;
  137. PMS3DKeyframePositionArray = ^TMS3DKeyframePositionArray;
  138. TMS3DKeyframePositionArray = array[0..MAX_MS3D_KEYFRAMES - 1] of TMS3DKeyframePosition;
  139. // typedef struct
  140. // {
  141. // byte flags; // SELECTED | DIRTY
  142. // char name[32]; //
  143. // char parentName[32]; //
  144. // float rotation[3]; // local reference matrix
  145. // float position[3];
  146. //
  147. // word numKeyFramesRot; //
  148. // word numKeyFramesTrans; //
  149. //
  150. // ms3d_keyframe_rot_t keyFramesRot[numKeyFramesRot]; // local animation matrices
  151. // ms3d_keyframe_pos_t keyFramesTrans[numKeyFramesTrans]; // local animation matrices
  152. // } ms3d_joint_t;
  153. TMS3DJointBase = record
  154. Flags: byte;
  155. Name: array[0..31] of AnsiChar;
  156. ParentName: array[0..31] of AnsiChar;
  157. Rotation: TD3DVector;
  158. Position: TD3DVector;
  159. NumKeyFramesRot: word;
  160. NumKeyFramesTrans: word;
  161. end;
  162. TMS3DJoint = record
  163. Base : TMS3DJointBase;
  164. KeyFramesRot: PMS3DKeyframeRotationArray;
  165. KeyFramesTrans: PMS3DKeyframePositionArray;
  166. end;
  167. PMS3DJointArray = ^TMS3DJointArray;
  168. TMS3DJointArray = array[0..MAX_MS3D_JOINTS - 1] of TMS3DJoint;
  169. TMS3DComment=record
  170. index: Integer;
  171. commentLength: integer;
  172. comment: array of AnsiChar;
  173. end;
  174. pMS3DComment=^TMS3DComment;
  175. TMS3DCommentList=class(TList)
  176. private
  177. protected
  178. public
  179. destructor Destroy; override;
  180. function NewComment: pMS3DComment;
  181. end;
  182. TMS3D_vertex_ex_t=record
  183. boneIds: array[0..2] of byte;
  184. weights: array[0..2] of byte;
  185. extra: cardinal;
  186. unknown: cardinal;
  187. end;
  188. pMS3D_vertex_ex_t=^TMS3D_vertex_ex_t;
  189. TVertexWeightList=class(TList)
  190. private
  191. FsubVersion: Integer;
  192. function GetWeight(idx: Integer): pMS3D_vertex_ex_t;
  193. procedure SetsubVersion(const Value: Integer);
  194. protected
  195. public
  196. function newWeight: pMS3D_vertex_ex_t;
  197. procedure Clear; override;
  198. destructor Destroy; override;
  199. property Weight[idx: Integer]: pMS3D_vertex_ex_t read GetWeight;
  200. property subVersion: Integer read FsubVersion write SetsubVersion;
  201. end;
  202. type
  203. { The MilkShape vector file.
  204. By Mattias Fagerlund, [email protected]. Yada yada. Eric rules! }
  205. TgxMS3DVectorFile = class(TgxVectorFile)
  206. public
  207. class function Capabilities: TDataFileCapabilities; override;
  208. procedure LoadFromStream(aStream: TStream); override;
  209. end;
  210. {$A+}
  211. // ------------------------------------------------------------------
  212. implementation
  213. // ------------------------------------------------------------------
  214. { TMS3DGroup }
  215. constructor TMS3DGroup.Create;
  216. begin
  217. TriangleIndices := TList.Create;
  218. end;
  219. destructor TMS3DGroup.Destroy;
  220. begin
  221. TriangleIndices.Free;
  222. inherited;
  223. end;
  224. { TMS3DCommentList }
  225. destructor TMS3DCommentList.destroy;
  226. var
  227. i: integer;
  228. comment: pMS3DComment;
  229. begin
  230. for i:=0 to count-1 do begin
  231. comment:=items[i];
  232. comment^.comment:=nil;
  233. dispose(comment);
  234. end;
  235. inherited;
  236. end;
  237. function TMS3DCommentList.NewComment: pMS3DComment;
  238. begin
  239. new(result);
  240. add(result);
  241. end;
  242. { TVertexWeightList }
  243. procedure TVertexWeightList.clear;
  244. var
  245. i: integer;
  246. begin
  247. for i:=0 to count-1 do Dispose(Weight[i]);
  248. inherited;
  249. end;
  250. destructor TVertexWeightList.destroy;
  251. begin
  252. clear;
  253. inherited;
  254. end;
  255. function TVertexWeightList.GetWeight(idx: Integer): pMS3D_vertex_ex_t;
  256. begin
  257. result:=pMS3D_vertex_ex_t(items[idx]);
  258. end;
  259. function TVertexWeightList.newWeight: pMS3D_vertex_ex_t;
  260. var
  261. p: pMS3D_vertex_ex_t;
  262. begin
  263. new(p);
  264. add(p);
  265. result:=p;
  266. end;
  267. procedure TVertexWeightList.SetsubVersion(const Value: Integer);
  268. begin
  269. FsubVersion := Value;
  270. end;
  271. { TgxMS3DVectorFile }
  272. class function TgxMS3DVectorFile.Capabilities: TDataFileCapabilities;
  273. begin
  274. Result := [dfcRead];
  275. end;
  276. procedure TgxMS3DVectorFile.LoadFromStream(aStream: TStream);
  277. var
  278. i, j, k: integer;
  279. itemp: Cardinal;
  280. wtemp: word;
  281. TexCoordID: integer;
  282. MO: TgxMeshObject;
  283. FaceGroup: TFGVertexNormalTexIndexList;
  284. Sk_MO: TgxSkeletonMeshObject;
  285. GroupList: TList;
  286. GLLibMaterial: TgxLibMaterial;
  287. // Milkshape 3d
  288. ms3d_header: TMS3DHeader;
  289. nNumVertices: word;
  290. ms3d_vertices: PMS3DVertexArray;
  291. nNumTriangles: word;
  292. ms3d_triangle: TMS3DTriangle;
  293. ms3d_triangle2: TMS3DTriangle;
  294. ms3d_triangles: PMS3DTriangleArray;
  295. nNumGroups: word;
  296. Group: TMS3DGroup;
  297. nNumMaterials: word;
  298. ms3d_material: TMS3DMaterial;
  299. fAnimationFPS: single;
  300. fCurrentTime: single;
  301. iTotalFrames: integer;
  302. nNumJoints: word;
  303. ms3d_joints: PMS3DJointArray;
  304. bonelist: TStringList;
  305. bone: TgxSkeletonBone;
  306. frame: TgxSkeletonFrame;
  307. rot, pos: TVector3f;
  308. //Tod
  309. subVersionComments: integer;
  310. subVersionVertexExtra: integer;
  311. nNumGroupComments: integer;
  312. nNumMaterialComments: integer;
  313. nNumJointComments: integer;
  314. nHasModelComment: integer;
  315. ms3d_comment: pMS3DComment;
  316. vertexWeight: pMS3D_vertex_ex_t;
  317. ms3d_norm_Array: array of TD3DVector;
  318. ms3d_norm: TD3DVector;
  319. path, libtexture: string;
  320. dotpos: Integer;
  321. //Helper classes for MS3D comments if you want to use them.
  322. groupCommentList: TMS3DCommentList;
  323. materialCommentList: TMS3DCommentList;
  324. jointCommentList: TMS3DCommentList;
  325. modelCommentList: TMS3DCommentList;
  326. procedure AddFaceVertex(ID: integer);
  327. begin
  328. // Add the texCoord
  329. TexCoordID := MO.TexCoords.Add(ms3d_triangle.s[ID], -ms3d_triangle.t[ID]);
  330. //Ok, here we add the vertex and the normal. We pass in the vertex index for both the vertex and the normal.
  331. // This is because we have already added the normals to the Mesh in the same order as the vertices.
  332. FaceGroup.Add(ms3d_triangle.vertexIndices[ID], ms3d_triangle.vertexIndices[ID], TexCoordID);
  333. end;
  334. function AddRotations(rot, baserot: TAffineVector): TAffineVector;
  335. var
  336. mat1, mat2, rmat: TMatrix4f;
  337. s, c: Single;
  338. Trans: TTransformations;
  339. begin
  340. mat1 := IdentityHMGMatrix;
  341. mat2 := IdentityHMGMatrix;
  342. SinCos(rot.X, s, c);
  343. rmat := CreateRotationMatrixX(s, c);
  344. mat1 := MatrixMultiply(mat1, rmat);
  345. SinCos(rot.Y, s, c);
  346. rmat := CreateRotationMatrixY(s, c);
  347. mat1 := MatrixMultiply(mat1, rmat);
  348. SinCos(rot.Z, s, c);
  349. rmat := CreateRotationMatrixZ(s, c);
  350. mat1 := MatrixMultiply(mat1, rmat);
  351. SinCos(baserot.X, s, c);
  352. rmat := CreateRotationMatrixX(s, c);
  353. mat2 := MatrixMultiply(mat2, rmat);
  354. SinCos(baserot.Y, s, c);
  355. rmat := CreateRotationMatrixY(s, c);
  356. mat2 := MatrixMultiply(mat2, rmat);
  357. SinCos(baserot.Z, s, c);
  358. rmat := CreateRotationMatrixZ(s, c);
  359. mat2 := MatrixMultiply(mat2, rmat);
  360. mat1 := MatrixMultiply(mat1, mat2);
  361. if MatrixDecompose(mat1, Trans) then
  362. SetVector(Result, Trans[ttRotateX], Trans[ttRotateY], Trans[ttRotateZ])
  363. else
  364. Result := NullVector;
  365. end;
  366. begin
  367. GroupList := TList.Create;
  368. FaceGroup := nil;
  369. ms3d_vertices := nil;
  370. ms3d_triangles := nil;
  371. ms3d_joints := nil;
  372. ms3d_norm_Array := nil;
  373. groupCommentList := nil;
  374. materialCommentList := nil;
  375. jointCommentList := nil;
  376. modelCommentList := nil;
  377. try
  378. //Save the path of the MS3D so we can load the texture from that location instead of the EXE location.
  379. path := ExtractFilePath(ResourceName);
  380. if Length(path)>0 then
  381. path := IncludeTrailingPathDelimiter( path );
  382. // First comes the header.
  383. aStream.ReadBuffer(ms3d_header, sizeof(TMS3DHeader));
  384. Assert(ms3d_header.version = 4, Format('The MilkShape3D importer can only handle MS3D files of version 4, this is version ', [ms3d_header.id]));
  385. // Then comes the number of vertices
  386. aStream.ReadBuffer(nNumVertices, sizeof(nNumVertices));
  387. // Create the vertex list
  388. if Owner is TgxActor then
  389. begin
  390. MO := TgxSkeletonMeshObject.CreateOwned(Owner.MeshObjects);
  391. TgxSkeletonMeshObject(MO).BonesPerVertex := 4;
  392. end
  393. else
  394. MO := TgxMeshObject.CreateOwned(Owner.MeshObjects);
  395. MO.Mode := momFaceGroups;
  396. // Then comes nNumVertices * sizeof (ms3d_vertex_t)
  397. ms3d_vertices := AllocMem(sizeof(TMS3DVertex) * nNumVertices);
  398. aStream.ReadBuffer(ms3d_vertices^, sizeof(TMS3DVertex) * nNumVertices);
  399. for i := 0 to nNumVertices - 1 do
  400. with ms3d_vertices^[i] do
  401. begin
  402. // Add the vertex to the vertexlist
  403. MO.Vertices.Add(vertex.v);
  404. if Owner is TgxActor then
  405. TgxSkeletonMeshObject(MO).AddWeightedBone(Byte(BoneID), 1);
  406. end;
  407. // number of triangles
  408. aStream.ReadBuffer(nNumTriangles, sizeof(nNumTriangles));
  409. // nNumTriangles * sizeof (ms3d_triangle_t)
  410. ms3d_triangles := AllocMem(sizeof(TMS3DTriangle) * nNumTriangles);
  411. aStream.ReadBuffer(ms3d_triangles^, sizeof(TMS3DTriangle) * nNumTriangles);
  412. // Now we have to match up the vertices with the normals that are in the triangles list
  413. // This is because Milkshape stores normals in the triangles group. A vertex can be used
  414. // many times by different faces. We need to compress that down to 1 vertex = 1 normal
  415. ms3d_norm.X := 0;
  416. ms3d_norm.Y := 0;
  417. ms3d_norm.Z := 0;
  418. setLength(ms3d_norm_Array, nNumVertices);
  419. for i := 0 to nNumVertices - 1 do
  420. ms3d_norm_Array[i] := ms3d_norm;
  421. for i := 0 to nNumTriangles - 1 do
  422. begin
  423. ms3d_triangle2 := ms3d_triangles^[i];
  424. ms3d_norm_Array[ms3d_triangle2.VertexIndices[0]] := ms3d_triangle2.VertexNormals[0];
  425. ms3d_norm_Array[ms3d_triangle2.VertexIndices[1]] := ms3d_triangle2.VertexNormals[1];
  426. ms3d_norm_Array[ms3d_triangle2.VertexIndices[2]] := ms3d_triangle2.VertexNormals[2];
  427. end;
  428. // Now add the normals in the same order as the vertices to the mesh
  429. for i := 0 to nNumVertices - 1 do
  430. begin
  431. MO.Normals.Add(ms3d_norm_Array[i].v);
  432. end;
  433. ms3d_norm_Array := nil;
  434. // number of groups
  435. aStream.ReadBuffer(nNumGroups, sizeof(nNumGroups));
  436. // nNumGroups * sizeof (ms3d_group_t)
  437. for i := 0 to nNumGroups - 1 do
  438. begin
  439. // Read the first part of the group
  440. Group := TMS3DGroup.Create;
  441. GroupList.Add(Group);
  442. aStream.ReadBuffer(Group.Flags, sizeof(Group.Flags));
  443. aStream.ReadBuffer(Group.name, sizeof(Group.name));
  444. aStream.ReadBuffer(Group.numtriangles, sizeof(Group.numtriangles));
  445. for j := 0 to Group.numtriangles - 1 do
  446. begin
  447. aStream.ReadBuffer(wtemp, sizeof(wtemp));
  448. itemp := wtemp;
  449. Group.triangleIndices.Add(pointer(itemp));
  450. end;
  451. aStream.ReadBuffer(Group.materialIndex, sizeof(Group.materialIndex));
  452. // if materialindex=-1, then there is no material, and all faces should
  453. // be added to a base VIL
  454. if Group.materialIndex = -1 then
  455. begin
  456. // If there's no base VIL, create one!
  457. if FaceGroup = nil then
  458. FaceGroup := TFGVertexNormalTexIndexList.CreateOwned(MO.FaceGroups);
  459. for j := 0 to Group.numtriangles - 1 do
  460. begin
  461. ms3d_triangle := ms3d_triangles^[Cardinal(Group.triangleIndices[j])];
  462. AddFaceVertex(0);
  463. AddFaceVertex(1);
  464. AddFaceVertex(2);
  465. end;
  466. end;
  467. end;
  468. // number of materials
  469. aStream.ReadBuffer(nNumMaterials, sizeof(nNumMaterials));
  470. // nNumMaterials * sizeof (ms3d_material_t)
  471. for i := 0 to nNumMaterials - 1 do
  472. begin
  473. aStream.ReadBuffer(ms3d_material, sizeof(TMS3DMaterial));
  474. // Create the material, if there's a materiallibrary!
  475. if Assigned(Owner.MaterialLibrary) then
  476. begin
  477. libtexture := string(ms3d_material.texture);
  478. dotpos := System.Pos('.', libtexture);
  479. Delete(libtexture, dotpos, Length(libtexture)-dotpos+1);
  480. GLLibMaterial := Owner.MaterialLibrary.LibMaterialByName(libtexture);
  481. if Assigned(GLLibMaterial) then
  482. begin
  483. GLLibMaterial.Material.Texture.Disabled := False;
  484. end
  485. else if FileStreamExists(path + string(ms3d_material.texture)) then
  486. GLLibMaterial := Owner.MaterialLibrary.AddTextureMaterial(libtexture, path + string(ms3d_material.texture))
  487. else
  488. begin
  489. if not Owner.IgnoreMissingTextures then
  490. Exception.Create('Texture file not found: ' + path + string(ms3d_material.texture));
  491. GLLibMaterial := Owner.MaterialLibrary.Materials.Add;
  492. GLLibMaterial.Name := string(ms3d_material.name);
  493. end;
  494. GLLibMaterial.Material.FrontProperties.Emission.Color := ms3d_material.emissive;
  495. GLLibMaterial.Material.FrontProperties.Ambient.Color := ms3d_material.ambient;
  496. GLLibMaterial.Material.FrontProperties.Diffuse.Color := ms3d_material.diffuse;
  497. GLLibMaterial.Material.FrontProperties.Specular.Color := ms3d_material.specular;
  498. // Shinintess is 0 to 128 in both MS3D and GLScene. Why not 0 to 127? Odd.
  499. GLLibMaterial.Material.FrontProperties.Shininess := round(ms3d_material.shininess);
  500. // ms3d_material.transparency is allready set as alpha channel on all
  501. // colors above
  502. if ms3d_material.transparency < 1 then
  503. begin
  504. GLLibMaterial.Material.BlendingMode := bmTransparency;
  505. GLLibMaterial.Material.FaceCulling := fcNoCull; //Make transparent materials two sided.
  506. end;
  507. GLLibMaterial.Material.Texture.TextureMode := tmModulate;
  508. // Create a new face group and add all triangles for this material
  509. // here. We must cycle through all groups that have this material
  510. FaceGroup := TFGVertexNormalTexIndexList.CreateOwned(MO.FaceGroups);
  511. FaceGroup.MaterialName := GLLibMaterial.Name;
  512. for j := 0 to GroupList.Count - 1 do
  513. begin
  514. Group := TMS3DGroup(GroupList[j]);
  515. if Group.materialIndex = i then
  516. for k := 0 to Group.numtriangles - 1 do
  517. begin
  518. ms3d_triangle := ms3d_triangles^[Cardinal(Group.triangleIndices[k])];
  519. AddFaceVertex(0);
  520. AddFaceVertex(1);
  521. AddFaceVertex(2);
  522. end;
  523. end;
  524. end
  525. else
  526. begin
  527. Exception.Create(ResourceName + ' has materials but there is no material library assigned to the object loading this MS3D file.' + #10#13 + 'If this is what you want, then you can safely ignore this exception.');
  528. end;
  529. end;
  530. // save some keyframer data
  531. aStream.ReadBuffer(fAnimationFPS, sizeof(fAnimationFPS));
  532. aStream.ReadBuffer(fCurrentTime, sizeof(fCurrentTime));
  533. aStream.ReadBuffer(iTotalFrames, sizeof(iTotalFrames));
  534. if Owner is TgxActor then
  535. begin
  536. TgxActor(Owner).Interval := trunc(1 / fAnimationFPS * 1000);
  537. end;
  538. // number of joints
  539. aStream.ReadBuffer(nNumJoints, sizeof(nNumJoints));
  540. // nNumJoints * sizeof (ms3d_joint_t)
  541. ms3d_joints := AllocMem(sizeof(TMS3DJoint) * nNumJoints);
  542. // We have to read the joints one by one!
  543. for i := 0 to nNumJoints - 1 do
  544. begin
  545. // Read the joint base
  546. aStream.ReadBuffer(ms3d_joints^[i].Base, sizeof(TMS3DJointBase));
  547. if (i = 0) then
  548. Assert(ms3d_joints^[i].base.numKeyFramesRot = iTotalFrames, 'This importer only works if the number of key frames = the number of total frames. i.e. Every frame must be a key frame');
  549. if ms3d_joints^[i].base.numKeyFramesRot > 0 then
  550. begin
  551. // Allocate memory for the rotations
  552. ms3d_joints^[i].keyFramesRot := AllocMem(sizeof(TMS3DKeyframeRotation) * ms3d_joints^[i].base.numKeyFramesRot);
  553. // Read the rotations
  554. aStream.ReadBuffer(ms3d_joints^[i].keyFramesRot^, sizeof(TMS3DKeyframeRotation) * ms3d_joints^[i].base.numKeyFramesRot);
  555. end
  556. else
  557. ms3d_joints^[i].keyFramesRot := nil;
  558. if ms3d_joints^[i].base.numKeyFramesTrans > 0 then
  559. begin
  560. // Allocate memory for the translations
  561. ms3d_joints^[i].keyFramesTrans := AllocMem(sizeof(TMS3DKeyframePosition) * ms3d_joints^[i].base.numKeyFramesTrans);
  562. // Read the translations
  563. aStream.ReadBuffer(ms3d_joints^[i].keyFramesTrans^, sizeof(TMS3DKeyframePosition) * ms3d_joints^[i].base.numKeyFramesTrans);
  564. end
  565. else
  566. ms3d_joints^[i].keyFramesTrans := nil;
  567. end;
  568. //Below is the Comments sections. We don't do anything with them at all. Only read in for future use if needed
  569. aStream.ReadBuffer(subVersionComments, sizeof(subVersionComments));
  570. //*******************
  571. //* now read in the Group Comments.
  572. //*******************
  573. aStream.ReadBuffer(nNumGroupComments, sizeof(nNumGroupComments));
  574. groupCommentList := TMS3DCommentList.Create;
  575. if (nNumGroupComments > 0) then
  576. groupCommentList.Capacity := nNumGroupComments;
  577. for i := 0 to nNumGroupComments - 1 do
  578. begin
  579. ms3d_comment := groupCommentList.NewComment;
  580. aStream.ReadBuffer(ms3d_comment^.index, sizeOf(ms3d_comment^.index));
  581. aStream.ReadBuffer(ms3d_comment^.commentLength, sizeOf(ms3d_comment^.commentLength));
  582. setLength(ms3d_comment^.comment, ms3d_comment^.commentLength);
  583. aStream.ReadBuffer(ms3d_comment^.comment[0], ms3d_comment^.commentLength);
  584. end;
  585. ////////
  586. //*******************
  587. //* now read in the Material Comments.
  588. //*******************
  589. aStream.ReadBuffer(nNumMaterialComments, sizeof(nNumMaterialComments));
  590. MaterialCommentList := TMS3DCommentList.Create;
  591. if (nNumMaterialComments > 0) then
  592. MaterialCommentList.Capacity := nNumMaterialComments;
  593. for i := 0 to nNumMaterialComments - 1 do
  594. begin
  595. ms3d_comment := MaterialCommentList.NewComment;
  596. aStream.ReadBuffer(ms3d_comment^.index, sizeOf(ms3d_comment^.index));
  597. aStream.ReadBuffer(ms3d_comment^.commentLength, sizeOf(ms3d_comment^.commentLength));
  598. setLength(ms3d_comment^.comment, ms3d_comment^.commentLength);
  599. aStream.ReadBuffer(ms3d_comment^.comment[0], ms3d_comment^.commentLength);
  600. end;
  601. ////////
  602. //*******************
  603. //* now read in the Joint Comments.
  604. //*******************
  605. aStream.ReadBuffer(nNumJointComments, sizeof(nNumJointComments));
  606. JointCommentList := TMS3DCommentList.Create;
  607. if (nNumJointComments > 0) then
  608. JointCommentList.Capacity := nNumJointComments;
  609. for i := 0 to nNumJointComments - 1 do
  610. begin
  611. ms3d_comment := JointCommentList.NewComment;
  612. aStream.ReadBuffer(ms3d_comment^.index, sizeOf(ms3d_comment^.index));
  613. aStream.ReadBuffer(ms3d_comment^.commentLength, sizeOf(ms3d_comment^.commentLength));
  614. setLength(ms3d_comment^.comment, ms3d_comment^.commentLength);
  615. aStream.ReadBuffer(ms3d_comment^.comment[0], ms3d_comment^.commentLength);
  616. end;
  617. ////////
  618. //*******************
  619. //* now read in the Model Comment (if any). The milkshape spec on this is somewhat wrong, as it does not use the same
  620. //* comments structure as the previous ones. Index is not included and I guess is assumed to always be 0 as there
  621. //* can only be one
  622. //*******************
  623. aStream.ReadBuffer(nHasModelComment, sizeof(nHasModelComment));
  624. ModelCommentList := TMS3DCommentList.Create;
  625. for i := 0 to nHasModelComment - 1 do
  626. begin
  627. ms3d_comment := ModelCommentList.NewComment;
  628. ms3d_comment^.index := 0;
  629. aStream.ReadBuffer(ms3d_comment^.commentLength, sizeOf(ms3d_comment^.commentLength));
  630. setLength(ms3d_comment^.comment, ms3d_comment^.commentLength);
  631. aStream.ReadBuffer(ms3d_comment^.comment[0], ms3d_comment^.commentLength);
  632. end;
  633. ////////
  634. //Read in the vertex weights
  635. //
  636. aStream.ReadBuffer(subVersionVertexExtra, sizeof(subVersionVertexExtra));
  637. Sk_MO := TgxSkeletonMeshObject(MO);
  638. if Owner is TgxActor then
  639. begin
  640. for i := 0 to nNumVertices - 1 do
  641. begin
  642. new(vertexWeight);
  643. aStream.ReadBuffer(vertexWeight^.boneIds[0], sizeOf(vertexWeight^.boneIds));
  644. aStream.ReadBuffer(vertexWeight^.weights[0], sizeOf(vertexWeight^.weights));
  645. aStream.ReadBuffer(vertexWeight^.extra, sizeOf(vertexWeight^.extra));
  646. if (subVersionVertexExtra = 3) then
  647. aStream.ReadBuffer(vertexWeight^.unknown, sizeOf(vertexWeight^.unknown));
  648. Sk_MO.VerticesBonesWeights^[i]^[0].Weight := 1;
  649. if (vertexWeight.boneIds[0] <> 255) then
  650. begin
  651. Sk_MO.VerticesBonesWeights^[i]^[0].Weight := vertexWeight.weights[0] / 100;
  652. Sk_MO.VerticesBonesWeights^[i]^[1].Weight := vertexWeight.weights[1] / 100;
  653. Sk_MO.VerticesBonesWeights^[i]^[1].BoneID := vertexWeight.boneIds[0];
  654. end
  655. else
  656. begin
  657. Sk_MO.VerticesBonesWeights^[i]^[1].Weight := 0;
  658. Sk_MO.VerticesBonesWeights^[i]^[1].BoneID := 0;
  659. end;
  660. if (vertexWeight.boneIds[1] <> 255) then
  661. begin
  662. Sk_MO.VerticesBonesWeights^[i]^[2].Weight := vertexWeight.weights[2] / 100;
  663. Sk_MO.VerticesBonesWeights^[i]^[2].BoneID := vertexWeight.boneIds[1];
  664. end
  665. else
  666. begin
  667. Sk_MO.VerticesBonesWeights^[i]^[2].Weight := 0;
  668. Sk_MO.VerticesBonesWeights^[i]^[2].BoneID := 0;
  669. end;
  670. if (vertexWeight.boneIds[2] <> 255) then
  671. begin
  672. Sk_MO.VerticesBonesWeights^[i]^[3].Weight := 1.0 - (vertexWeight.weights[0] + vertexWeight.weights[1] + vertexWeight.weights[2]) / 100;
  673. Sk_MO.VerticesBonesWeights^[i]^[3].BoneID := vertexWeight.boneIds[2];
  674. end
  675. else
  676. begin
  677. Sk_MO.VerticesBonesWeights^[i]^[3].Weight := 0;
  678. Sk_MO.VerticesBonesWeights^[i]^[3].BoneID := 0;
  679. end;
  680. dispose(vertexWeight);
  681. end;
  682. end;
  683. // ***
  684. // Mesh Transformation:
  685. //
  686. // 0. Build the transformation matrices from the rotation and position
  687. // 1. Multiply the vertices by the inverse of local reference matrix (lmatrix0)
  688. // 2. then translate the result by (lmatrix0 * keyFramesTrans)
  689. // 3. then multiply the result by (lmatrix0 * keyFramesRot)
  690. //
  691. // For normals skip step 2.
  692. //
  693. //
  694. //
  695. // NOTE: this file format may change in future versions!
  696. //
  697. //
  698. // - Mete Ciragan
  699. // ***
  700. if (Owner is TgxActor) and (nNumJoints > 0) then
  701. begin
  702. // Bone names are added to a list initally to sort out parents
  703. bonelist := TStringList.Create;
  704. for i := 0 to nNumJoints - 1 do
  705. bonelist.Add(string(ms3d_joints^[i].Base.Name));
  706. // Find parent bones and add their children
  707. for i := 0 to nNumJoints - 1 do
  708. begin
  709. j := bonelist.IndexOf(string(ms3d_joints^[i].Base.ParentName));
  710. if j = -1 then
  711. bone := TgxSkeletonBone.CreateOwned(Owner.Skeleton.RootBones)
  712. else
  713. bone := TgxSkeletonBone.CreateOwned(Owner.Skeleton.RootBones.BoneByID(j));
  714. bone.Name := string(ms3d_joints^[i].Base.Name);
  715. bone.BoneID := i;
  716. end;
  717. bonelist.Free;
  718. // Set up the base pose
  719. frame := TgxSkeletonFrame.CreateOwned(Owner.Skeleton.Frames);
  720. for i := 0 to nNumJoints - 1 do
  721. begin
  722. pos := ms3d_joints^[i].Base.Position.V;
  723. rot := ms3d_joints^[i].Base.Rotation.V;
  724. frame.Position.Add(pos);
  725. frame.Rotation.Add(rot);
  726. end;
  727. // Now load the animations
  728. for i := 0 to nNumJoints - 1 do
  729. begin
  730. for j := 0 to ms3d_joints^[i].Base.NumKeyFramesRot - 1 do
  731. begin
  732. if (j + 1) = Owner.Skeleton.Frames.Count then
  733. frame := TgxSkeletonFrame.CreateOwned(Owner.Skeleton.Frames)
  734. else
  735. frame := Owner.Skeleton.Frames[j + 1];
  736. if ms3d_joints^[i].Base.ParentName = '' then
  737. begin
  738. pos := ms3d_joints^[i].KeyFramesTrans^[j].Position.V;
  739. //pos:=ms3d_joints^[i].Base.Position.V;
  740. rot := ms3d_joints^[i].KeyFramesRot^[j].Rotation.V;
  741. end
  742. else
  743. begin
  744. pos := ms3d_joints^[i].KeyFramesTrans^[0].Position.V; //Always read tranlation position from the first frame
  745. AddVector(pos, ms3d_joints^[i].Base.Position.V);
  746. rot := ms3d_joints^[i].KeyFramesRot^[j].Rotation.V;
  747. rot := AddRotations(rot, ms3d_joints^[i].Base.Rotation.V);
  748. end;
  749. frame.Position.Add(pos);
  750. frame.Rotation.Add(rot);
  751. end;
  752. end;
  753. Owner.Skeleton.RootBones.PrepareGlobalMatrices;
  754. TgxSkeletonMeshObject(MO).PrepareBoneMatrixInvertedMeshes;
  755. with TgxActor(Owner).Animations.Add do
  756. begin
  757. Reference := aarSkeleton;
  758. StartFrame := 0;
  759. EndFrame := Owner.Skeleton.Frames.Count;
  760. end;
  761. end;
  762. finally
  763. if Assigned(ms3d_vertices) then
  764. FreeMem(ms3d_vertices);
  765. if Assigned(ms3d_triangles) then
  766. FreeMem(ms3d_triangles);
  767. if Assigned(ms3d_joints) then
  768. begin
  769. // Free the internal storage of the joint
  770. for i := 0 to nNumJoints - 1 do
  771. begin
  772. if Assigned(ms3d_joints^[i].keyFramesRot) then
  773. FreeMem(ms3d_joints^[i].keyFramesRot);
  774. if Assigned(ms3d_joints^[i].keyFramesTrans) then
  775. FreeMem(ms3d_joints^[i].keyFramesTrans);
  776. end;
  777. FreeMem(ms3d_joints);
  778. end;
  779. // Finalize
  780. for i := 0 to GroupList.Count - 1 do
  781. TMS3DGroup(GroupList[i]).Free;
  782. GroupList.Free;
  783. if (assigned(groupCommentList)) then
  784. groupCommentList.free;
  785. if (assigned(materialCommentList)) then
  786. materialCommentList.free;
  787. if (assigned(jointCommentList)) then
  788. jointCommentList.free;
  789. if (assigned(modelCommentList)) then
  790. modelCommentList.free;
  791. end;
  792. end;
  793. // ------------------------------------------------------------------
  794. // ------------------------------------------------------------------
  795. // ------------------------------------------------------------------
  796. initialization
  797. // ------------------------------------------------------------------
  798. // ------------------------------------------------------------------
  799. // ------------------------------------------------------------------
  800. RegisterVectorFileFormat('ms3d', 'MilkShape3D files', TgxMS3DVectorFile);
  801. end.