Import ASE.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace ASE{ // so local structures are unique
  5. /******************************************************************************/
  6. // ASE stores animation keyframes relative to previous frames
  7. /******************************************************************************/
  8. struct FaceNrm
  9. {
  10. Vec nrm[3];
  11. };
  12. struct Face
  13. {
  14. VecI ind;
  15. Int sub_material;
  16. Face() {ind.zero(); sub_material=0;}
  17. };
  18. struct Mtrl : XMaterial
  19. {
  20. Int global_index;
  21. Memc<Mtrl> sub_mtrl;
  22. void import(FileTextEx &f, C Str &path)
  23. {
  24. for(; f.level(); )
  25. {
  26. if(f.cur("*MATERIAL_TWOSIDED" ))cull = false ;else
  27. if(f.cur("*MATERIAL_NAME" ))name = f.getName();else
  28. //if(f.cur("*MATERIAL_AMBIENT" ))ambient = f.getVec ();else
  29. if(f.cur("*MATERIAL_DIFFUSE" ))color.xyz= f.getVec ();else
  30. //if(f.cur("*MATERIAL_SPECULAR" ))specular = f.getVec ();else
  31. if(f.cur("*MATERIAL_SHINE" ))specular = f.getFlt ();else
  32. if(f.cur("*MATERIAL_TRANSPARENCY"))color.w =1-f.getFlt ();else
  33. if(f.cur("*MAP_GENERIC") && f.getIn())
  34. {
  35. for(; f.level(); )
  36. {
  37. if(f.cur("*BITMAP") && !color_map.is())color_map=f.getName();
  38. }
  39. }else
  40. if(f.cur("*MAP_DIFFUSE") && f.getIn())
  41. {
  42. for(; f.level(); )
  43. {
  44. if(f.cur("*BITMAP"))color_map=f.getName();
  45. }
  46. }else
  47. if(f.cur("*MAP_SHINE") && f.getIn())
  48. {
  49. for(; f.level(); )
  50. {
  51. if(f.cur("*BITMAP"))specular_map=f.getName();
  52. }
  53. }else
  54. if(f.cur("*MAP_OPACITY") && f.getIn())
  55. {
  56. for(; f.level(); )
  57. {
  58. if(f.cur("*BITMAP"))alpha_map=f.getName();
  59. }
  60. }else
  61. if(f.cur("*MAP_BUMP") && f.getIn())
  62. {
  63. for(; f.level(); )
  64. {
  65. if(f.cur("*BITMAP"))normal_map=f.getName();else
  66. if(f.cur("*MAP_GENERIC") && f.getIn())
  67. {
  68. for(; f.level(); )
  69. {
  70. if(f.cur("*BITMAP") && !normal_map.is())normal_map=f.getName();
  71. }
  72. }
  73. }
  74. }else
  75. if(f.cur("*SUBMATERIAL") && f.getIn())sub_mtrl.New().import(f, path);
  76. }
  77. fixPath(path);
  78. }
  79. void copyTo(MemPtr<XMaterial> materials) {global_index=materials.elms(); materials.New()=T; FREPAO(sub_mtrl).copyTo(materials);}
  80. };
  81. struct Node
  82. {
  83. Int material;
  84. Str name, parent;
  85. Matrix matrix;
  86. Memc<Vec > pos;
  87. Memc<FaceNrm> nrm;
  88. Memc<Vec2 > tex;
  89. Memc<Face > tri;
  90. Memc<VecI > ttex;
  91. Node() {matrix.identity(); material=-1;}
  92. };
  93. struct Ase
  94. {
  95. Memc<Mtrl> mtrl;
  96. Memc<Node> node;
  97. };
  98. /******************************************************************************/
  99. static void ImportASE(FileTextEx &f, Ase &ase, C Str &path)
  100. {
  101. for(; f.level(); )
  102. {
  103. if(f.cur("*MATERIAL_LIST") && f.getIn())
  104. {
  105. for(; f.level(); )
  106. {
  107. if(f.cur("*MATERIAL") && f.getIn())ase.mtrl.New().import(f, path);
  108. }
  109. }else
  110. if(f.cur("*GROUP" ) && f.getIn())ImportASE(f, ase, path);else
  111. if(f.cur("*GEOMOBJECT") && f.getIn())
  112. {
  113. Node &node=ase.node.New();
  114. for(; f.level(); )
  115. {
  116. if(f.cur("*NODE_NAME" ))node.name =f.getName();else
  117. if(f.cur("*NODE_PARENT"))node.parent=f.getName();else
  118. if(f.cur("*NODE_TM" ) && f.getIn())
  119. {
  120. for(; f.level(); )
  121. {
  122. if(f.cur("*TM_ROW0"))f.get(node.matrix.x );else
  123. if(f.cur("*TM_ROW1"))f.get(node.matrix.y );else
  124. if(f.cur("*TM_ROW2"))f.get(node.matrix.z );else
  125. if(f.cur("*TM_ROW3"))f.get(node.matrix.pos);
  126. }
  127. }else
  128. if(f.cur("*MESH") && f.getIn())
  129. {
  130. for(; f.level(); )
  131. {
  132. if(f.cur("*MESH_VERTEX_LIST") && f.getIn())
  133. {for(; f.level(); ){
  134. if(f.cur("*MESH_VERTEX"))
  135. {
  136. f.getWord();
  137. f.get(node.pos.New());
  138. }
  139. }}else
  140. if(f.cur("*MESH_FACE_LIST") && f.getIn())
  141. {for(; f.level(); ){
  142. if(f.cur("*MESH_FACE"))
  143. {
  144. VecI &tri=node.tri.New().ind; // range checks are done later
  145. f.getWord();
  146. f.getWord(); tri.x=f.getInt();
  147. f.getWord(); tri.y=f.getInt();
  148. f.getWord(); tri.z=f.getInt();
  149. }else
  150. if(f.cur("*MESH_MTLID"))
  151. {
  152. if(node.tri.elms())node.tri.last().sub_material=f.getInt();
  153. }
  154. }}else
  155. if(f.cur("*MESH_TVERTLIST") && f.getIn())
  156. {for(; f.level(); ){
  157. if(f.cur("*MESH_TVERT"))
  158. {
  159. f.getWord();
  160. Vec2 &tex=node.tex.New(); f.get(tex); tex.y=1-tex.y;
  161. }
  162. }}else
  163. if(f.cur("*MESH_TFACELIST") && f.getIn())
  164. {for(; f.level(); ){
  165. if(f.cur("*MESH_TFACE"))
  166. {
  167. f.getWord();
  168. f.get(node.ttex.New());
  169. }
  170. }}else
  171. if(f.cur("*MESH_NORMALS") && f.getIn())
  172. {
  173. node.nrm.setNum(node.tri.elms());
  174. for(Int face=-1, vtx; f.level(); )
  175. {
  176. if(f.cur("*MESH_FACENORMAL" )){face=f.getInt(); vtx=0;}else
  177. if(f.cur("*MESH_VERTEXNORMAL") && InRange(face, node.tri.elms()) && vtx<3){f.getWord(); f.get(node.nrm[face].nrm[vtx++]);}
  178. }
  179. }
  180. }
  181. }else
  182. if(f.cur("*MATERIAL_REF"))node.material=f.getInt();
  183. }
  184. }
  185. }
  186. }
  187. /******************************************************************************/
  188. } // namespace ASE
  189. /******************************************************************************/
  190. Bool ImportASE(C Str &name, Mesh *mesh, MemPtr<XMaterial> materials, MemPtr<Int> part_material_index)
  191. {
  192. using namespace ASE;
  193. if(mesh)mesh->del();
  194. materials .clear();
  195. part_material_index.clear();
  196. FileTextEx f; if(f.read(name))
  197. {
  198. Ase ase; ImportASE(f, ase, GetPath(name));
  199. // materials
  200. if(materials)FREPA(ase.mtrl)ase.mtrl[i].copyTo(materials);
  201. // mesh
  202. if(mesh)
  203. {
  204. FREPA(ase.node)
  205. {
  206. MeshPart part;
  207. MeshBase &base=part.base;
  208. ASE::Node &src =ase .node[i];
  209. Set(part.name, src.name);
  210. base.create(src.tri.elms()*3, 0, src.tri.elms(), 0);
  211. Int j=0; FREPA(src.tri)
  212. {
  213. C VecI &ind=src.tri[i].ind; REPA(ind)if(!InRange(ind.c[i], src.pos))return false;
  214. base.tri.ind(i).set(j, j+1, j+2);
  215. base.vtx.pos(j++)=src.pos[ind.c[0]];
  216. base.vtx.pos(j++)=src.pos[ind.c[1]];
  217. base.vtx.pos(j++)=src.pos[ind.c[2]];
  218. }
  219. if(src.nrm.elms())
  220. {
  221. base.include(VTX_NRM);
  222. Int j=0; FREPA(src.nrm)
  223. {
  224. C FaceNrm &nrm=src.nrm[i];
  225. base.vtx.nrm(j++)=nrm.nrm[0];
  226. base.vtx.nrm(j++)=nrm.nrm[1];
  227. base.vtx.nrm(j++)=nrm.nrm[2];
  228. }
  229. Transform(base.vtx.nrm(), src.matrix.orn(), base.vtxs());
  230. Normalize(base.vtx.nrm(), base.vtxs());
  231. }
  232. if(src.ttex.elms())
  233. {
  234. base.include(VTX_TEX0);
  235. j=0; FREPA(src.ttex)
  236. {
  237. C VecI &ttex=src.ttex[i]; REPA(ttex)if(!InRange(ttex.c[i], src.tex))return false;
  238. base.vtx.tex0(j++)=src.tex[ttex.c[0]];
  239. base.vtx.tex0(j++)=src.tex[ttex.c[1]];
  240. base.vtx.tex0(j++)=src.tex[ttex.c[2]];
  241. }
  242. }
  243. if(InRange(src.material, ase.mtrl) && ase.mtrl[src.material].sub_mtrl.elms()) // if selected material has sub-materials
  244. {
  245. base.include(TRI_ID); FREPA(base.tri)base.tri.id(i)=src.tri[i].sub_material;
  246. }
  247. base.weldVtx(VTX_ALL, EPSD, EPS_COL_COS, -1); // use small epsilon in case mesh is scaled down
  248. if(base.tri.id()) // we need to split into parts
  249. {
  250. Mesh temp; base.copyId(temp, ~TRI_ID);
  251. FREPA(temp)if(temp.parts[i].is())
  252. {
  253. Swap(mesh->parts.New(), temp.parts[i]);
  254. if(part_material_index)
  255. {
  256. Mtrl &mtrl=ase.mtrl[src.material]; // this will always be in range, because this is executed for tri.id, and that is created only if 'src.material' is in range
  257. part_material_index.add(InRange(i, mtrl.sub_mtrl) ? mtrl.sub_mtrl[i].global_index : mtrl.global_index);
  258. }
  259. }
  260. }else
  261. {
  262. if(part.is())
  263. {
  264. Swap(mesh->parts.New(), part);
  265. if(part_material_index)part_material_index.add(InRange(src.material, ase.mtrl) ? ase.mtrl[src.material].global_index : -1);
  266. }
  267. }
  268. }
  269. mesh->rightToLeft().setBox();
  270. REPA(*mesh)if(!mesh->parts[i].base.vtx.nrm())mesh->parts[i].base.setNormals();
  271. CleanMesh(*mesh);
  272. }
  273. return true;
  274. }
  275. return false;
  276. }
  277. /******************************************************************************/
  278. }
  279. /******************************************************************************/