GXS.FileGL2.pas 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. //
  2. // Graphic Scene Engine, http://glscene.org
  3. //
  4. (*
  5. Vector file object loading of Ghoul2 model and animation files.
  6. *)
  7. unit GXS.FileGL2;
  8. interface
  9. uses
  10. System.Classes,
  11. System.SysUtils,
  12. GXS.VectorFileObjects,
  13. GXS.ApplicationFileIO,
  14. GXS.Material,
  15. Stage.VectorGeometry,
  16. Stage.VectorTypes,
  17. GXS.VectorLists,
  18. Formatx.FileGL2;
  19. type
  20. TgxGLMVectorFile = class (TgxVectorFile)
  21. public
  22. class function Capabilities : TDataFileCapabilities; override;
  23. procedure LoadFromStream(aStream : TStream); override;
  24. end;
  25. TgxGLAVectorFile = class (TgxVectorFile)
  26. public
  27. class function Capabilities : TDataFileCapabilities; override;
  28. procedure LoadFromStream(aStream : TStream); override;
  29. end;
  30. var
  31. vGhoul2LevelOfDetail : Integer = 0; // Highest detail level by default
  32. vGhoul2MaxBonesPerVertex : Integer = 4; // Ghoul2 supports up to 4 bones
  33. // per vertex. Use this global
  34. // variable to set a different limit.
  35. //====================================================================
  36. implementation
  37. //====================================================================
  38. // ------------------
  39. // ------------------ TgxGLMVectorFile ------------------
  40. // ------------------
  41. class function TgxGLMVectorFile.Capabilities : TDataFileCapabilities;
  42. begin
  43. Result:=[dfcRead];
  44. end;
  45. procedure TgxGLMVectorFile.LoadFromStream(aStream : TStream);
  46. var
  47. GLMFile : TFileGLM;
  48. i,j,k,s,c,d : integer;
  49. mesh : TgxSkeletonMeshObject;
  50. fg : TgxFGVertexIndexList;
  51. VertOfs : integer;
  52. shader : string;
  53. vec2 : Tvector2f;
  54. numweights,
  55. boneref,
  56. boneid : Integer;
  57. boneweight,
  58. weighttot : Single;
  59. NumSurfVert : Integer;
  60. procedure AllocateMaterial(meshname,shader:string);
  61. var
  62. LibMat : TgxLibMaterial;
  63. begin
  64. if Assigned(Owner.MaterialLibrary) then with Owner.MaterialLibrary do begin
  65. if Assigned(Materials.GetLibMaterialByName(meshname)) then exit;
  66. LibMat:=Materials.Add;
  67. LibMat.name:=meshname;
  68. LibMat.Material.Texture.Disabled:=False;
  69. end;
  70. end;
  71. begin
  72. GLMFile:=TFileGLM.Create;
  73. GLMFile.LoadFromStream(aStream);
  74. try
  75. // Need a way to import all levels of detail, but this global
  76. // variable will do for now.
  77. d:=vGhoul2LevelOfDetail;
  78. if d>=Length(GLMFile.LODs) then exit;
  79. for s:=0 to Length(GLMFile.SurfaceHeirachy)-1 do begin
  80. mesh:=TgxSkeletonMeshObject.CreateOwned(Owner.MeshObjects);
  81. mesh.Mode:=momFaceGroups;
  82. mesh.Name:=trim(GLMFile.SurfaceHeirachy[s].name);
  83. shader:=trim(GLMFile.SurfaceHeirachy[s].shader);
  84. AllocateMaterial(mesh.Name,shader);
  85. // Set size of VerticesBonesWeights
  86. NumSurfVert:=0;
  87. for c:=0 to GLMFile.SurfaceHeirachy[s].numChildren-1 do begin
  88. i:=GLMFile.SurfaceHeirachy[s].childIndices[c]-1;
  89. NumSurfVert:=NumSurfVert+GLMFile.LODs[d].Surfaces[i].SurfaceHeader.numVerts;
  90. end;
  91. mesh.BonesPerVertex:=vGhoul2MaxBonesPerVertex;
  92. mesh.VerticeBoneWeightCount:=NumSurfVert;
  93. for c:=0 to GLMFile.SurfaceHeirachy[s].numChildren-1 do begin
  94. i:=GLMFile.SurfaceHeirachy[s].childIndices[c]-1;
  95. with GLMFile.LODs[d].Surfaces[i] do begin
  96. VertOfs:=mesh.Vertices.Count;
  97. for j:=0 to Length(Vertices)-1 do begin
  98. // Add vertices and normals
  99. mesh.Vertices.Add(Vertices[j].vertex);
  100. mesh.Normals.Add(Vertices[j].normal);
  101. // Fix and then add the Texture coords
  102. vec2:=TexCoords[j];
  103. vec2.Y:=1-vec2.Y; // reverse the v coordinate
  104. mesh.TexCoords.Add(vec2);
  105. // Add weighted bones
  106. numweights:=G2_GetVertWeights(Vertices[j]);
  107. weighttot:=0;
  108. for k:=0 to mesh.BonesPerVertex-1 do
  109. if k<numweights then begin
  110. boneref:=G2_GetVertBoneIndex(Vertices[j],k);
  111. boneid:=BoneReferences[boneref];
  112. boneweight:=G2_GetVertBoneWeight(Vertices[j],k,weighttot,numweights);
  113. mesh.VerticesBonesWeights^[mesh.Vertices.Count-1]^[k].BoneID:=boneid;
  114. mesh.VerticesBonesWeights^[mesh.Vertices.Count-1]^[k].Weight:=boneweight;
  115. end else begin
  116. mesh.VerticesBonesWeights^[mesh.Vertices.Count-1]^[k].BoneID:=0;
  117. mesh.VerticesBonesWeights^[mesh.Vertices.Count-1]^[k].Weight:=0;
  118. end;
  119. end;
  120. fg:=TgxFGVertexIndexList.CreateOwned(mesh.FaceGroups);
  121. fg.Mode:=fgmmTriangles;
  122. fg.MaterialName:=mesh.Name;
  123. for j:=0 to Length(Triangles)-1 do begin
  124. // The faces need to be wound in the opposite direction so...
  125. fg.VertexIndices.Add(Triangles[j].indices[0]+VertOfs);
  126. fg.VertexIndices.Add(Triangles[j].indices[2]+VertOfs);
  127. fg.VertexIndices.Add(Triangles[j].indices[1]+VertOfs);
  128. end;
  129. end;
  130. end;
  131. end;
  132. finally
  133. GLMFile.Free;
  134. end;
  135. end;
  136. // ------------------
  137. // ------------------ TgxGLAVectorFile ------------------
  138. // ------------------
  139. // Capabilities
  140. //
  141. class function TgxGLAVectorFile.Capabilities : TDataFileCapabilities;
  142. begin
  143. Result:=[dfcRead];
  144. end;
  145. // LoadFromStream
  146. //
  147. procedure TgxGLAVectorFile.LoadFromStream(aStream : TStream);
  148. var
  149. GLAFile : TFileGLA;
  150. i,j : Integer;
  151. frame : TgxSkeletonFrame;
  152. CompBone : TgxACompQuatBone;
  153. quat : TQuaternion;
  154. pos : TAffineVector;
  155. basepose : TgxSkeletonFrame;
  156. bonelist : TgxIntegerList;
  157. bone : TgxSkeletonBone;
  158. begin
  159. GLAFile:=TFileGLA.Create;
  160. GLAFile.LoadFromStream(aStream);
  161. try
  162. if not (Owner is TgxActor) then exit;
  163. TgxActor(Owner).Reference:=aarSkeleton;
  164. bonelist:=TgxIntegerList.Create;
  165. for i:=0 to GLAFile.AnimHeader.numBones-1 do
  166. bonelist.Add(i);
  167. while bonelist.count>0 do begin
  168. if GLAFile.Skeleton[bonelist[0]].parent = -1 then
  169. bone:=TgxSkeletonBone.CreateOwned(Owner.Skeleton.RootBones)
  170. else begin
  171. bone:=Owner.Skeleton.RootBones.BoneByID(GLAFile.Skeleton[bonelist[0]].parent);
  172. if Assigned(bone) then
  173. bone:=TgxSkeletonBone.CreateOwned(bone)
  174. end;
  175. if Assigned(bone) then begin
  176. bone.Name:=GLAFile.Skeleton[bonelist[0]].Name;
  177. bone.BoneID:=bonelist[0];
  178. end else
  179. bonelist.Add(bonelist[0]);
  180. bonelist.Delete(0);
  181. end;
  182. bonelist.Free;
  183. // Build the base pose
  184. basepose:=TgxSkeletonFrame.CreateOwned(TgxActor(Owner).Skeleton.Frames);
  185. basepose.Name:='basepose';
  186. basepose.TransformMode:=sftQuaternion;
  187. basepose.Position.AddNulls(GLAFile.AnimHeader.numBones);
  188. basepose.Quaternion.AddNulls(GLAFile.AnimHeader.numBones);
  189. // Load animation data
  190. for i:=0 to GLAFile.AnimHeader.numFrames-1 do begin
  191. // Create the frame
  192. frame:=TgxSkeletonFrame.CreateOwned(TgxActor(Owner).Skeleton.Frames);
  193. frame.Name:='Frame'+IntToStr(i);
  194. frame.TransformMode:=sftQuaternion;
  195. for j:=0 to GLAFile.AnimHeader.numBones-1 do begin
  196. // Uncompress bone and add to the frame
  197. CompBone:=GLAFile.GetCompressedMatrix(i,j);
  198. quat:=QuaternionMake([CompBone[1]-32726,CompBone[2]-32726,CompBone[3]-32726],CompBone[0]-32726);
  199. pos:=AffineVectorMake(CompBone[4]/64-512,CompBone[5]/64-512,CompBone[6]/64-512);
  200. frame.Quaternion.Add(quat);
  201. frame.Position.Add(pos);
  202. end;
  203. end;
  204. Owner.Skeleton.RootBones.PrepareGlobalMatrices;
  205. for i:=0 to Owner.MeshObjects.Count-1 do
  206. TgxSkeletonMeshObject(Owner.MeshObjects[i]).PrepareBoneMatrixInvertedMeshes;
  207. finally
  208. GLAFile.Free;
  209. end;
  210. end;
  211. // ------------------------------------------------------------------
  212. // ------------------------------------------------------------------
  213. // ------------------------------------------------------------------
  214. initialization
  215. // ------------------------------------------------------------------
  216. // ------------------------------------------------------------------
  217. // ------------------------------------------------------------------
  218. RegisterVectorFileFormat('glm', 'Ghoul2 (GLM) model files', TgxGLMVectorFile);
  219. RegisterVectorFileFormat('glx', 'Ghoul2 (GLX) model files', TgxGLMVectorFile);
  220. RegisterVectorFileFormat('gla', 'Ghoul2 (GLA) animation files', TgxGLAVectorFile);
  221. end.