Import B3D.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace B3D{ // so local structures are unique
  5. /******************************************************************************/
  6. #define BLENDER 1 // 1 for gandaldf's exporter, 0 for milkshape
  7. #if DEBUG
  8. #define LOG 0
  9. #else
  10. #define LOG 0
  11. #endif
  12. /******************************************************************************/
  13. struct NODE;
  14. /******************************************************************************/
  15. #pragma pack(push, 1)
  16. struct Chunk
  17. {
  18. Char8 c[4];
  19. UInt size;
  20. Bool equal(CChar8 *name)C {return c[0]==name[0] && c[1]==name[1] && c[2]==name[2] && c[3]==name[3];}
  21. Str8 asStr( )C {Str8 s; FREPA(c)s+=c[i]; return s;}
  22. };
  23. struct BONE
  24. {
  25. Int vertex_id;
  26. Flt weight;
  27. };
  28. struct FRAME
  29. {
  30. Int frame;
  31. Vec pos, scale;
  32. Quaternion quat;
  33. FRAME() {frame=0; pos.zero(); scale=1; quat.identity();}
  34. };
  35. struct ANIM
  36. {
  37. Int flags, frames;
  38. Flt fps;
  39. ANIM() {flags=0; frames=0; fps=60;}
  40. };
  41. struct F_TEXS
  42. {
  43. UInt flags, blend;
  44. Vec2 pos , scale;
  45. Flt rotate;
  46. };
  47. #pragma pack(pop)
  48. struct TEXS
  49. {
  50. Bool has_alpha, second_tex;
  51. Str8 file;
  52. Vec2 pos, scale;
  53. Flt rotate;
  54. };
  55. struct BRUS
  56. {
  57. Bool cull, full_bright;
  58. Str8 name;
  59. Vec4 color;
  60. Flt specular;
  61. Memc<Int> tex_id;
  62. };
  63. struct VRT
  64. {
  65. Vec pos, nrm;
  66. Vec4 color;
  67. Vec2 tex[8];
  68. Memc<IndexWeight> skin;
  69. };
  70. struct TRIS
  71. {
  72. Int brush;
  73. Memc<VecI> ind;
  74. };
  75. struct MESH_BONE
  76. {
  77. Byte parent;
  78. NODE *node;
  79. MESH_BONE() {parent=0xFF; node=null;}
  80. };
  81. struct MESH
  82. {
  83. Byte has_nrm, has_color, tex_coords;
  84. Int brush;
  85. Memc<VRT > vrt ;
  86. Memc<TRIS > tris ;
  87. Memc<MESH_BONE> bones;
  88. MESH() {has_nrm=has_color=false; tex_coords=0;}
  89. };
  90. struct KEYS
  91. {
  92. Bool has_pos, has_scale, has_rot;
  93. Memc<FRAME> frames;
  94. KEYS() {has_pos=has_scale=has_rot=false;}
  95. };
  96. struct NODE
  97. {
  98. Str name;
  99. Bool bone;
  100. Byte bone_index;
  101. Matrix local_matrix, global_matrix;
  102. NODE *parent;
  103. Memc<MESH> meshes;
  104. Memc<BONE> bones ;
  105. Memc<KEYS> keys ;
  106. Memc<ANIM> anims ;
  107. Memx<NODE> nodes ; // use 'Memx' because nodes are referencing each other using 'parent'
  108. NODE() {bone=false; bone_index=0xFF; local_matrix.identity(); global_matrix.identity(); parent=null;}
  109. };
  110. /******************************************************************************/
  111. static Str8 GetStr(File &f)
  112. {
  113. for(Str8 s; ; )
  114. {
  115. Char8 c=f.getByte(); if(!c)return s;
  116. s+=c;
  117. }
  118. }
  119. /******************************************************************************/
  120. static void ImportB3DNode(File &f, Chunk &c, Memx<NODE> &nodes, NODE *parent, TextData &log)
  121. {
  122. c.size+=f.pos();
  123. NODE &node =nodes.New();
  124. node.name =GetStr(f);
  125. node.parent=parent;
  126. Vec pos, scale;
  127. Quaternion quat;
  128. f>>pos>>scale>>quat.w>>quat.xyz;
  129. node. local_matrix.orn()=Matrix3(quat).scale(scale);
  130. node. local_matrix.pos =pos;
  131. node.global_matrix=node.local_matrix; if(parent)node.global_matrix*=parent->global_matrix;
  132. if(LOG)
  133. {
  134. /*log.putLine(S+"name=\""+node.name+"\", local_m.x="+node.local_matrix.x
  135. +", local_m.y="+node.local_matrix.y
  136. +", local_m.z="+node.local_matrix.z);*/
  137. }
  138. for(; !f.end() && c.size>f.pos(); )
  139. {
  140. Chunk c; f>>c; //if(LOG)log.putLine(c.asStr());
  141. if(c.equal("NODE"))
  142. {
  143. ImportB3DNode(f, c, node.nodes, &node, log);
  144. }else
  145. if(c.equal("MESH"))
  146. {
  147. c.size+=f.pos();
  148. MESH &mesh=node.meshes.New(); f>>mesh.brush;
  149. for(; !f.end() && c.size>f.pos(); )
  150. {
  151. Chunk c; f>>c;
  152. if(c.equal("VRTS"))
  153. {
  154. c.size+=f.pos();
  155. Int flags, tex_coord_sets, tex_coord_set_size; f>>flags>>tex_coord_sets>>tex_coord_set_size;
  156. mesh.has_nrm =FlagTest(flags, 1);
  157. mesh.has_color =FlagTest(flags, 2);
  158. mesh.tex_coords=tex_coord_sets;
  159. for(; !f.end() && c.size>f.pos(); )
  160. {
  161. VRT &v=mesh.vrt.New();
  162. f>>v.pos ;
  163. if(mesh.has_nrm )f>>v.nrm ;
  164. if(mesh.has_color)f>>v.color;
  165. FREPD(i, tex_coord_sets )
  166. FREPD(j, tex_coord_set_size)
  167. {
  168. Flt t; f>>t;
  169. if(i<Elms(v.tex) && j<2)v.tex[i].c[j]=t;
  170. }
  171. }
  172. }else
  173. if(c.equal("TRIS"))
  174. {
  175. c.size+=f.pos();
  176. TRIS &tris=mesh.tris.New(); f>>tris.brush;
  177. for(; !f.end() && c.size>f.pos(); )f>>tris.ind.New(); // range checks are done later
  178. }else
  179. {
  180. f.skip(c.size); // skip chunk
  181. }
  182. }
  183. }else
  184. if(c.equal("BONE"))
  185. {
  186. node.bone=true;
  187. c.size+=f.pos();
  188. for(; !f.end() && c.size>f.pos(); )f>>node.bones.New();
  189. }else
  190. if(c.equal("KEYS"))
  191. {
  192. c.size+=f.pos();
  193. KEYS &key=node.keys.New();
  194. Int flags; f>>flags;
  195. key.has_pos =FlagTest(flags, 1);
  196. key.has_scale=FlagTest(flags, 2);
  197. key.has_rot =FlagTest(flags, 4);
  198. for(; !f.end() && c.size>f.pos(); )
  199. {
  200. FRAME &frame=key.frames.New();
  201. f>>frame.frame;
  202. if(key.has_pos )f>>frame.pos ;
  203. if(key.has_scale)f>>frame.scale;
  204. if(key.has_rot )f>>frame.quat.w>>frame.quat.xyz;
  205. }
  206. }else
  207. if(c.equal("ANIM"))
  208. {
  209. f>>node.anims.New();
  210. }else
  211. {
  212. f.skip(c.size); // skip chunk
  213. }
  214. }
  215. }
  216. /******************************************************************************/
  217. static void ProcessBones(Memx<NODE> &nodes, Byte parent_index, MESH *last_mesh)
  218. {
  219. FREPA(nodes)
  220. {
  221. NODE &node=nodes[i];
  222. if(node.meshes.elms())last_mesh=&node.meshes.first();
  223. node.bone_index=parent_index;
  224. if(last_mesh && node.bone)
  225. {
  226. node.bone_index=last_mesh->bones.elms();
  227. MESH_BONE &mb=last_mesh->bones.New ();
  228. mb.parent= parent_index;
  229. mb.node =&node;
  230. }
  231. ProcessBones(node.nodes, node.bone_index, last_mesh);
  232. }
  233. }
  234. /******************************************************************************/
  235. static void ProcessNodes(Memx<NODE> &nodes, Memc<MeshPart> &parts, MemPtr<Int> part_material_index, Memc<TEXS> &texs, Memc<BRUS> &brus, Skeleton &skeleton, MemtN<Byte, 256> &old_to_new)
  236. {
  237. FREPA(nodes)
  238. {
  239. NODE &node=nodes[i]; Matrix3 matrix3=node.global_matrix; matrix3.normalize();
  240. FREPA(node.meshes)
  241. {
  242. MESH &mesh=node.meshes[i];
  243. if(mesh.vrt.elms())FREPA(mesh.tris)
  244. {
  245. TRIS &tris=mesh.tris[i]; if(tris.ind.elms())
  246. {
  247. MeshPart &part=parts.New(); Set(part.name, node.name); if(part_material_index)part_material_index.add(tris.brush);
  248. MeshBase &mshb=part .base;
  249. mshb.create(mesh.vrt.elms(), 0, tris.ind.elms(), 0, (mesh.has_nrm?VTX_NRM:0)|((mesh.tex_coords>=1)?VTX_TEX0:0)|((mesh.tex_coords>=2)?VTX_TEX1:0)|(mesh.bones.elms()?VTX_SKIN:0));
  250. // vertexes
  251. REPA(mesh.vrt)mshb.vtx.pos (i)=mesh.vrt[i].pos*node.global_matrix ;
  252. if(mesh.has_nrm )REPA(mesh.vrt)mshb.vtx.nrm (i)=mesh.vrt[i].nrm* matrix3;
  253. if(mesh.tex_coords>=1)REPA(mesh.vrt)mshb.vtx.tex0(i)=mesh.vrt[i].tex[0];
  254. if(mesh.tex_coords>=2)REPA(mesh.vrt)mshb.vtx.tex1(i)=mesh.vrt[i].tex[1];
  255. if(mesh.bones.elms() )
  256. {
  257. REPA(mesh.bones)
  258. {
  259. MESH_BONE &mb=mesh.bones[i];
  260. NODE &node=*mb.node;
  261. if(InRange(node.bone_index, old_to_new))
  262. {
  263. Int matrix=old_to_new[node.bone_index];
  264. FREPA(node.bones)
  265. {
  266. C BONE &bone=node.bones[i];
  267. if(InRange(bone.vertex_id, mesh.vrt))mesh.vrt[bone.vertex_id].skin.New().set(matrix, bone.weight);
  268. }
  269. }
  270. }
  271. REPA(mesh.vrt)SetSkin(mesh.vrt[i].skin, mshb.vtx.matrix(i), mshb.vtx.blend(i), &skeleton);
  272. }
  273. // triangles
  274. Bool invalid=false;
  275. FREPA(tris.ind)
  276. {
  277. VecI &ind=mshb.tri.ind(i); ind=tris.ind[i]; REPA(ind)if(!InRange(ind.c[i], mshb.vtx)){ind.zero(); invalid=true; break;}
  278. }
  279. if(invalid)mshb.removeDegenerateFaces(0);
  280. mshb.removeUnusedVtxs();
  281. if(!mshb.vtx.nrm())mshb.setNormals();
  282. if(Memc<Int> *tex_id=(InRange(tris.brush, brus) ? &brus[tris.brush].tex_id : null))
  283. {
  284. TEXS *tx[2]=
  285. {
  286. (tex_id->elms()>=1) ? &texs[(*tex_id)[0]] : null,
  287. (tex_id->elms()>=2) ? &texs[(*tex_id)[1]] : null,
  288. };
  289. switch(tex_id->elms())
  290. {
  291. case 1: if(tx[0]->second_tex && mshb.vtx.tex1() )Swap(mshb.vtx._tex0, mshb.vtx._tex1); break;
  292. case 2: if(tx[0]->second_tex && !tx[1]->second_tex)Swap(mshb.vtx._tex0, mshb.vtx._tex1); break;
  293. }
  294. }
  295. }
  296. }
  297. }
  298. ProcessNodes(node.nodes, parts, part_material_index, texs, brus, skeleton, old_to_new);
  299. }
  300. }
  301. /******************************************************************************/
  302. static void CreateAnimation(C Memc<MESH_BONE> &mesh_bone, Skeleton &skeleton, XAnimation &animation)
  303. {
  304. Animation &anim=animation.anim;
  305. anim.bones.setNum(mesh_bone.elms());
  306. FREPA(mesh_bone)
  307. {
  308. C NODE &node= *mesh_bone [i].node;
  309. AnimBone &abon= anim.bones[i];
  310. SkelBone &sbon=skeleton.bones[i];
  311. Bool parent=(sbon.parent!=0xFF);
  312. Matrix3 parent_matrix_inv; if(parent)skeleton.bones[sbon.parent].inverse(parent_matrix_inv);
  313. abon.set(sbon.name);
  314. REPA(node.keys)if(node.keys[i].has_rot)
  315. {
  316. C Memc<FRAME> &frames=node.keys[i].frames;
  317. abon.orns.setNumZero(frames.elms());
  318. FREPA(frames)
  319. {
  320. C FRAME &frame=frames [i];
  321. AnimBone::Orn &orn =abon.orns[i];
  322. // set time
  323. orn.time=frame.frame;
  324. anim.length(Max(anim.length(), orn.time), false);
  325. // set rotation
  326. orn.orn=sbon;
  327. // animate
  328. {
  329. if(node.parent)orn.orn*=~node.parent->global_matrix.orn() ; // transform bone from global space to local space relative to parent
  330. orn.orn*=~node. local_matrix.orn() * Matrix3(frame.quat); // perform transformation from source to target matrix, looks like 'frame' is the target matrix
  331. if(node.parent)orn.orn*= node.parent->global_matrix.orn() ; // transform bone from local space to global space
  332. }
  333. //
  334. if(parent)orn.orn*=parent_matrix_inv;
  335. }
  336. break;
  337. }
  338. FREPA(node.keys)if(node.keys[i].has_pos)
  339. {
  340. C Memc<FRAME> &frames=node.keys[i].frames;
  341. abon.poss.setNumZero(frames.elms());
  342. FREPA(frames)
  343. {
  344. C FRAME &frame=frames [i];
  345. AnimBone::Pos &pos =abon.poss[i];
  346. // set time
  347. pos.time=frame.frame;
  348. anim.length(Max(anim.length(), pos.time), false);
  349. // set position
  350. pos.pos=frame.pos-node.local_matrix.pos;
  351. if(node.parent)pos.pos*=node.parent->global_matrix.orn();
  352. if(parent )pos.pos*=parent_matrix_inv;
  353. }
  354. break;
  355. }
  356. abon.sortFrames();
  357. }
  358. // scale length
  359. if(mesh_bone.elms())for(NODE *node=mesh_bone[0].node; node; node=node->parent)
  360. {
  361. if(node->anims.elms())
  362. {
  363. ANIM &src=node->anims.first();
  364. anim.length(Max(anim.length(), (Flt)src.frames) , false);
  365. anim.length(anim.length()/(src.fps ? src.fps : 60), true );
  366. animation.fps=(src.fps ? src.fps : 60);
  367. break;
  368. }
  369. }
  370. // process
  371. anim.setTangents().removeUnused().setRootMatrix();
  372. }
  373. /******************************************************************************/
  374. static Bool CreateSkeleton(C Memx<NODE> &nodes, Skeleton &skeleton, XAnimation *animation)
  375. {
  376. FREPA(nodes)
  377. {
  378. C NODE &node=nodes[i]; FREPA(node.meshes)
  379. {
  380. C MESH &mesh=node.meshes[i]; if(mesh.bones.elms())
  381. {
  382. skeleton.bones.setNum(mesh.bones.elms());
  383. FREPA(mesh.bones)
  384. {
  385. C MESH_BONE &src =mesh .bones[i];
  386. SkelBone &dest=skeleton.bones[i];
  387. Set(dest.name, src.node->name);
  388. dest.pos = src.node->global_matrix.pos;
  389. #if BLENDER
  390. dest.dir = !src.node->global_matrix.y;
  391. dest.perp=-!src.node->global_matrix.z;
  392. #else
  393. dest.dir =!src.node->global_matrix.x;
  394. dest.perp=!src.node->global_matrix.y;
  395. #endif
  396. dest.parent= src.parent;
  397. }
  398. skeleton.setBoneLengths();
  399. if(animation)CreateAnimation(mesh.bones, skeleton, *animation);
  400. return true;
  401. }
  402. }
  403. if(CreateSkeleton(node.nodes, skeleton, animation))return true;
  404. }
  405. return false;
  406. }
  407. /******************************************************************************/
  408. } // namespace B3D
  409. /******************************************************************************/
  410. Bool ImportB3D(C Str &name, Mesh *mesh, Skeleton *skeleton, XAnimation *animation, MemPtr<XMaterial> materials, MemPtr<Int> part_material_index)
  411. {
  412. if(mesh )mesh ->del();
  413. if(skeleton )skeleton ->del();
  414. if(animation)animation->del();
  415. materials .clear();
  416. part_material_index.clear();
  417. #if !WEB // structs are unaligned, would need using 'Unaligned' func
  418. using namespace B3D;
  419. Memc<TEXS> texs;
  420. Memc<BRUS> brus;
  421. Memx<NODE> node;
  422. File f; if(f.readTry(name))
  423. {
  424. Chunk c; f>>c; if(c.equal("BB3D"))
  425. {
  426. TextData log; if(LOG)log.save(name+".txt");
  427. UInt ver; f>>ver;
  428. for(; !f.end(); )
  429. {
  430. f>>c; //if(LOG)log.putLine(c.asStr());
  431. if(c.equal("TEXS"))
  432. {
  433. c.size+=f.pos();
  434. for(; !f.end() && c.size>f.pos(); )
  435. {
  436. F_TEXS f_t;
  437. TEXS &t=texs.New(); t.file=GetStr(f); f>>f_t; t.pos=f_t.pos; t.scale=f_t.scale; t.rotate=f_t.rotate;
  438. t.has_alpha =FlagTest(f_t.flags, 2);
  439. t.second_tex=FlagTest(f_t.flags, 65536);
  440. //LogN(S+"T "+f_t.flags+' '+f_t.blend+' '+t.file);
  441. }
  442. }else
  443. if(c.equal("BRUS"))
  444. {
  445. c.size+=f.pos();
  446. Int n_texs=f.getInt();
  447. for(; !f.end() && c.size>f.pos(); )
  448. {
  449. BRUS &b=brus.New(); b.name=GetStr(f); Int blend, fx; f>>b.color>>b.specular>>blend>>fx; REP(n_texs){Int tex_id; f>>tex_id; if(InRange(tex_id, texs))b.tex_id.add(tex_id);}
  450. b.cull =!FlagTest(fx, 16);
  451. b.full_bright= FlagTest(fx, 1);
  452. //Log(S+"B "+blend+' '+fx+' '+b.name); FREPA(b.tex_id)Log(S+' '+texs[b.tex_id[i]].file); LogN();
  453. }
  454. }else
  455. if(c.equal("NODE"))
  456. {
  457. ImportB3DNode(f, c, node, null, log);
  458. }else
  459. {
  460. f.skip(c.size); // skip chunk
  461. }
  462. if(!f.ok())return false;
  463. }
  464. // finalize
  465. Skeleton temp, *skel=(skeleton ? skeleton : (mesh || animation) ? &temp : null); // if skel not specified, but we want mesh or animation, then we have to process it
  466. if(skel)
  467. {
  468. MemtN<Byte, 256> old_to_new;
  469. ProcessBones (node, 0xFF, null);
  470. CreateSkeleton(node, *skel, animation);
  471. skel->sortBones(old_to_new).setBoneTypes(); if(VIRTUAL_ROOT_BONE)REPAO(old_to_new)++;
  472. if(animation)animation->anim.setBoneTypeIndexesFromSkeleton(*skel);
  473. if(mesh)
  474. {
  475. Memc<MeshPart> parts;
  476. ProcessNodes(node, parts, part_material_index, texs, brus, *skel, old_to_new);
  477. mesh->create(parts.elms()); FREPA(*mesh)Swap(mesh->parts[i], parts[i]);
  478. mesh->skeleton(skel).skeleton(null).setBox(); CleanMesh(*mesh);
  479. }
  480. if(skeleton){skel->setBoneShapes(); if(skeleton!=skel)Swap(*skeleton, *skel);}
  481. }
  482. // materials
  483. if(materials)FREPA(brus)
  484. {
  485. BRUS &b =brus[i];
  486. XMaterial &material=materials.New();
  487. material.name =b.name;
  488. material.cull =b.cull;
  489. material.color =b.color;
  490. material.specular=b.specular;
  491. material.ambient =b.full_bright;
  492. if(b.tex_id.elms()>=1)material.color_map=texs[b.tex_id[0]].file;
  493. if(b.tex_id.elms()>=2)material.light_map=texs[b.tex_id[1]].file;
  494. if(b.tex_id.elms()>=1 && texs[b.tex_id[0]].has_alpha)
  495. {
  496. material.technique=MTECH_ALPHA_TEST;
  497. material.color.w =0.5f;
  498. }
  499. material.fixPath(GetPath(name));
  500. }
  501. return true;
  502. }
  503. }
  504. #endif
  505. return false;
  506. }
  507. /******************************************************************************/
  508. }
  509. /******************************************************************************/