GLFileGL2.pas 8.4 KB

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