GLS.FileGL2.pas 8.2 KB

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