GXS.FileB3D.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. //
  2. // The graphics engine GLXEngine. The unit of GXScene for Delphi
  3. //
  4. unit GXS.FileB3D;
  5. (* B3D VectorFile class to load Blitz 3D model files *)
  6. interface
  7. uses
  8. System.Classes,
  9. System.SysUtils,
  10. Stage.VectorTypes,
  11. Stage.VectorGeometry,
  12. Stage.TextureFormat,
  13. GXS.ApplicationFileIO,
  14. GXS.VectorLists,
  15. GXS.VectorFileObjects,
  16. GXS.Texture,
  17. GXS.Material,
  18. Formatx.B3D;
  19. type
  20. TgxB3DVectorFile = class(TgxVectorFile)
  21. public
  22. class function Capabilities: TDataFileCapabilities; override;
  23. procedure LoadFromStream(AStream: TStream); override;
  24. end;
  25. implementation // -------------------------------------------------------------
  26. // ------------------------------ TgxB3DVectorFile ----------------------------
  27. class function TgxB3DVectorFile.Capabilities: TDataFileCapabilities;
  28. begin
  29. Result := [DfcRead];
  30. end;
  31. procedure TgxB3DVectorFile.LoadFromStream(AStream: TStream);
  32. var
  33. B3d: TFileB3D;
  34. S: string;
  35. Mo: TgxMeshObject;
  36. I, J: Integer;
  37. FaceGroup: TgxFGVertexIndexList;
  38. // lightmapBmp : TBitmap;
  39. Node: PNODEChunk;
  40. B3DMat: TB3DMaterial;
  41. B3DTex: TB3DTexture;
  42. B3DLightTex: TB3DTexture;
  43. Vertex: PVertexData;
  44. Triangles: PTRISChunk;
  45. V, V1: TAffineVector;
  46. Matrix: TMatrix4f;
  47. MatLib: TgxMaterialLibrary;
  48. LightLib: TgxMaterialLibrary;
  49. RotQuat: TQuaternion;
  50. RotMat: TMatrix4f;
  51. function GetOrAllocateMaterial(MaterialNum: Integer; AMat: TB3DMaterial;
  52. ATex: TB3DTexture; ALightmap: TB3DTexture): string;
  53. var
  54. LibMat: TgxLibMaterial;
  55. TexName: string;
  56. LightName: string;
  57. begin
  58. if GetOwner is TgxBaseMesh then
  59. begin
  60. MatLib := TgxBaseMesh(GetOwner).MaterialLibrary;
  61. LightLib := TgxBaseMesh(GetOwner).LightmapLibrary;
  62. // got a linked material library?
  63. if Assigned(MatLib) then
  64. begin
  65. Result := AMat.GetMaterialName;
  66. // add base material
  67. LibMat := MatLib.Materials.GetLibMaterialByName(Result);
  68. if not Assigned(LibMat) then
  69. begin
  70. if Assigned(ATex) then
  71. TexName := ATex.GetTextureName
  72. else
  73. TexName := '';
  74. if not FileExists(TexName) then
  75. TexName := ExtractFileName(TexName);
  76. if TexName <> '' then
  77. LibMat := MatLib.AddTextureMaterial(Result + IntToStr(MaterialNum),
  78. TexName, False)
  79. else
  80. begin
  81. LibMat := MatLib.Materials.Add;
  82. LibMat.Name := Result + IntToStr(MaterialNum);
  83. end;
  84. Libmat.Material.FrontProperties.Diffuse.Red := AMat.MaterialData.Red;
  85. Libmat.Material.FrontProperties.Diffuse.Green :=
  86. AMat.MaterialData.Green;
  87. Libmat.Material.FrontProperties.Diffuse.Blue :=
  88. AMat.MaterialData.Blue;
  89. Libmat.Material.FrontProperties.Diffuse.Alpha :=
  90. AMat.MaterialData.Alpha;
  91. Libmat.Material.FrontProperties.Shininess :=
  92. Round(AMat.MaterialData.Shininess * 100.0);
  93. Libmat.Material.MaterialOptions := [MoNoLighting];
  94. if AMat.MaterialData.Alpha <> 1 then
  95. begin
  96. Libmat.Material.FaceCulling := FcNoCull;
  97. Libmat.Material.BlendingMode := BmTransparency;
  98. end;
  99. if Assigned(ATex) then
  100. begin
  101. LibMat.TextureOffset.AsAffineVector :=
  102. AffineVectorMake(ATex.TextureData.X_pos,
  103. ATex.TextureData.Y_pos, 0);
  104. LibMat.TextureScale.AsAffineVector :=
  105. AffineVectorMake(ATex.TextureData.X_scale,
  106. ATex.TextureData.Y_scale, 1);
  107. if ATex.TextureData.Flags = 2 then
  108. begin
  109. Libmat.Material.FaceCulling := FcNoCull;
  110. Libmat.Material.BlendingMode := BmTransparency;
  111. end;
  112. if AMat.MaterialData.Alpha <> 1 then
  113. begin
  114. Libmat.Material.Texture.ImageAlpha := TiaAlphaFromIntensity;
  115. Libmat.Material.Texture.TextureFormat := TfRGBA;
  116. Libmat.Material.Texture.TextureMode := TmModulate;
  117. end;
  118. end;
  119. end;
  120. // add lightmap material
  121. if (Assigned(LightLib)) and (Assigned(ALightmap)) then
  122. begin
  123. LightName := ALightmap.GetTextureName;
  124. // add base material
  125. LibMat := LightLib.Materials.GetLibMaterialByName(LightName
  126. { + IntToStr(MaterialNum) } );
  127. if not Assigned(LibMat) then
  128. begin
  129. if not FileExists(LightName) then
  130. LightName := ExtractFileName(LightName);
  131. LibMat := LightLib.AddTextureMaterial(LightName
  132. { + IntToStr(MaterialNum) } , LightName, False);
  133. LibMat.Material.Texture.TextureMode := TmReplace;
  134. if Assigned(ALightMap) then
  135. begin
  136. LibMat.TextureOffset.AsAffineVector :=
  137. AffineVectorMake(ALightMap.TextureData.X_pos,
  138. ALightMap.TextureData.Y_pos, 0);
  139. LibMat.TextureScale.AsAffineVector :=
  140. AffineVectorMake(ALightMap.TextureData.X_scale,
  141. ALightMap.TextureData.Y_scale, 1);
  142. end;
  143. end;
  144. // modify the material lightmap index
  145. AMat.MaterialData.Texture_id[1] := LibMat.Index;
  146. end;
  147. end
  148. else
  149. Result := '';
  150. end
  151. else
  152. Result := '';
  153. end;
  154. begin
  155. B3d := TFileB3D.Create;
  156. try
  157. // first, load the b3d model sturctures from stream
  158. B3d.LoadFromStream(AStream);
  159. // then add all the materials and lightmaps from b3d structures
  160. for I := 0 to B3d.Materials.Count - 1 do
  161. begin
  162. B3DMat := TB3DMaterial(B3d.Materials.Objects[I]);
  163. B3DTex := nil;
  164. B3DLightTex := nil;
  165. // check if there is one texture layer
  166. if B3DMat.MaterialData.N_texs > 0 then
  167. begin
  168. if B3DMat.MaterialData.Texture_id[0] >= 0 then
  169. B3DTex := TB3DTexture(B3d.Textures.Objects
  170. [B3DMat.MaterialData.Texture_id[0]]);
  171. // check if there are two texture layer
  172. if B3DMat.MaterialData.N_texs > 1 then
  173. // why lightmap in some case on channel 2?
  174. if B3DMat.MaterialData.Texture_id[1] >= 0 then
  175. B3DLightTex :=
  176. TB3DTexture(B3d.Textures.Objects
  177. [B3DMat.MaterialData.Texture_id[1]])
  178. else
  179. { //check if there are three texture layer }
  180. if B3DMat.MaterialData.N_texs > 2 then
  181. if B3DMat.MaterialData.Texture_id[2] >= 0 then
  182. B3DLightTex :=
  183. TB3DTexture(B3d.Textures.Objects
  184. [B3DMat.MaterialData.Texture_id[2]]);
  185. end;
  186. GetOrAllocateMaterial(I, B3DMat, B3DTex, B3DLightTex);
  187. end;
  188. if GetOwner is TgxBaseMesh then
  189. (GetOwner as TgxBaseMesh).NormalsOrientation := MnoDefault;
  190. Node := B3d.Nodes.NodeData;
  191. while Node <> nil do
  192. begin
  193. if Node^.Meshes <> nil then
  194. begin
  195. Mo := TgxMeshObject.CreateOwned(Owner.MeshObjects);
  196. SetString(S, Node^.Name, Strlen(Node^.Name));
  197. // if Pos('16', s)>1 then
  198. // Pos('17', s);
  199. Mo.Name := S;
  200. Mo.Mode := MomFaceGroups;
  201. // add all the vertices, normals, colors and texture-coords(including the lightmap texture)
  202. Vertex := Node^.Meshes^.Vertices.Vertices;
  203. while Assigned(Vertex) do
  204. begin
  205. // W3D modif inversed z
  206. Mo.Vertices.Add(AffineVectorMake(Vertex^.Y, Vertex^.X, Vertex^.Z));
  207. if (Node^.Meshes^.Vertices.Flags and 1) > 0 then
  208. Mo.Normals.Add(VectorNormalize(AffineVectorMake(Vertex^.Ny,
  209. Vertex^.Nx, Vertex^.Nz)));
  210. if (Node^.Meshes^.Vertices.Flags and 2) > 0 then
  211. begin
  212. Mo.Colors.Add(VectorMake(Vertex^.Red, Vertex^.Green, Vertex^.Blue,
  213. Vertex^.Alpha));
  214. end;
  215. case Node^.Meshes^.Vertices.Tex_coord_sets of
  216. 1:
  217. begin
  218. case Node^.Meshes^.Vertices.Tex_coord_set_size of
  219. 2:
  220. Mo.TexCoords.Add(Vertex^.Tex_coords[0],
  221. -Vertex^.Tex_coords[1], 0);
  222. 3:
  223. Mo.TexCoords.Add(Vertex^.Tex_coords[0],
  224. -Vertex^.Tex_coords[1], Vertex^.Tex_coords[2]);
  225. end;
  226. end;
  227. 2: // lightmap tex_coord included
  228. begin
  229. case Node^.Meshes^.Vertices.Tex_coord_set_size of
  230. 2:
  231. Mo.TexCoords.Add(Vertex^.Tex_coords[0],
  232. -Vertex^.Tex_coords[1], 0);
  233. 3:
  234. Mo.TexCoords.Add(Vertex^.Tex_coords[0],
  235. -Vertex^.Tex_coords[1], Vertex^.Tex_coords[2]);
  236. end;
  237. Mo.LightMapTexCoords.Add
  238. (Vertex^.Tex_coords
  239. [Node^.Meshes^.Vertices.Tex_coord_set_size],
  240. -Vertex^.Tex_coords
  241. [Node^.Meshes^.Vertices.Tex_coord_set_size + 1]);
  242. end;
  243. end;
  244. Vertex := Vertex^.Next;
  245. end;
  246. // add facegroups
  247. Triangles := Node^.Meshes^.Triangles;
  248. while Assigned(Triangles) do
  249. begin
  250. FaceGroup := TgxFGVertexIndexList.CreateOwned(Mo.FaceGroups);
  251. if Triangles^.Brush_id >= 0 then
  252. begin
  253. FaceGroup.MaterialName := B3d.Materials[Triangles^.Brush_id] +
  254. InttoStr(Triangles^.Brush_id);
  255. FaceGroup.LightMapIndex :=
  256. TB3DMaterial(B3d.Materials.Objects[Triangles^.Brush_id])
  257. .MaterialData.Texture_id[1];
  258. end
  259. else
  260. begin
  261. FaceGroup.MaterialName := '';
  262. FaceGroup.LightMapIndex := -1;
  263. end;
  264. for J := 0 to Length(Triangles^.Vertex_id) - 1 do
  265. FaceGroup.VertexIndices.Add(Triangles^.Vertex_id[J]);
  266. while FaceGroup.VertexIndices.Count mod 3 <> 0 do
  267. FaceGroup.VertexIndices.Delete(FaceGroup.VertexIndices.Count - 1);
  268. Triangles := Triangles.Next;
  269. FaceGroup.Reverse;
  270. end;
  271. RotQuat := QuaternionMake([Node^.Rotation.Z, Node^.Rotation.Y,
  272. Node^.Rotation.W], Node^.Rotation.X);
  273. RotMat := QuaternionToMatrix(RotQuat);
  274. Mo.Vertices.TransformAsVectors(RotMat);
  275. { mo.SetPosition( Node^.Position[1], Node^.Position[0], Node^.Position[2]);
  276. mo.SetScale( Node^.Scale[1], Node^.Scale[0], Node^.Scale[2]);
  277. }
  278. if Pos('ENT_', UpperCase(Mo.Name)) = 0 then
  279. V := AffineVectorMake(Node^.Position.Y,
  280. Node^.Position.X, Node^.Position.Z)
  281. else
  282. begin
  283. V := AffineVectorMake(0.0, 0.0, 0.0);
  284. end;
  285. V1 := AffineVectorMake(Node^.Scale.Y, Node^.Scale.X, Node^.Scale.Z);
  286. Matrix := CreateScaleAndTranslationMatrix(VectorMake(V1), VectorMake(V));
  287. Mo.Vertices.TransformAsPoints(Matrix);
  288. end;
  289. Node := Node^.Next;
  290. end;
  291. finally
  292. B3d.Free;
  293. end;
  294. end;
  295. initialization
  296. // ------------------------------------------------------------------
  297. // ------------------------------------------------------------------
  298. // ------------------------------------------------------------------
  299. RegisterVectorFileFormat('b3d', 'Blitz 3D model files', TgxB3DVectorFile);
  300. end.