PageRenderTime 36ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Mesh.cpp

https://gitlab.com/ayufan/ayuine2b
C++ | 479 lines | 273 code | 94 blank | 112 comment | 62 complexity | 1e7587aec743849b4a8245a62178afba MD5 | raw file
  1. //------------------------------------//
  2. //
  3. // Mesh.cpp
  4. //
  5. // Author: ayufan (ayufan[at]o2.pl)
  6. // Project: ayuine2
  7. // Date: 2006-7-31
  8. //
  9. //------------------------------------//
  10. #include "StdAfx.hpp"
  11. namespace ayuine
  12. {
  13. //------------------------------------//
  14. // Mesh: Collection
  15. Collection<Mesh>::ObjectMap Collection<Mesh>::_objects;
  16. //------------------------------------//
  17. // MeshCollider: Enumeration
  18. static EnumValue ColliderTypeEnum[] = {
  19. {"none", mctNone},
  20. {"sphere", mctSphere},
  21. {"box", mctBox},
  22. {"convex", mctConvex},
  23. {"static", mctStatic},
  24. {"", 0}
  25. };
  26. //------------------------------------//
  27. // Mesh: Static Fields
  28. Property Mesh::Properties[] = {
  29. // Physics Fields
  30. Property(OffsetOf(Mesh, ColliderType), ColliderTypeEnum, "Collider"),
  31. Property(OffsetOf(Mesh, ColliderObject),ptBoolean, "ColliderObject"),
  32. Property(OffsetOf(Mesh, Density), ptValue, "Density"),
  33. // Render Fields
  34. Property(OffsetOf(Mesh, PRT), ptBoolean, "PRT"),
  35. Property()
  36. };
  37. //------------------------------------//
  38. // MeshVertex: Static Fields
  39. VertexDeclElement MeshVertex::Decl[] = {
  40. {0, OffsetOf(MeshVertex, Origin), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
  41. {0, OffsetOf(MeshVertex, Coords[0]),D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
  42. {0, OffsetOf(MeshVertex, Normal), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
  43. {0, OffsetOf(MeshVertex, Tangent), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
  44. D3DDECL_END()
  45. };
  46. //------------------------------------//
  47. // MeshSurface: Constructor
  48. MeshSurface::MeshSurface() {
  49. IndexStart = IndexCount = 0;
  50. }
  51. //------------------------------------//
  52. // MeshObject: Constructor
  53. MeshObject::MeshObject() {
  54. VertexStart = VertexCount = 0;
  55. IndexStart = IndexCount = 0;
  56. Frame = 0;
  57. }
  58. MeshObject::MeshObject(const MeshObject &oldObjectConst) {
  59. MeshObject &oldObject = const_cast<MeshObject&>(oldObjectConst);
  60. // Skopiuj i usuń stary obiekt
  61. memcpy(this, &oldObject, sizeof(MeshObject));
  62. memset(&oldObject, 0, sizeof(MeshObject));
  63. }
  64. //------------------------------------//
  65. // Mesh: Constructor
  66. Mesh::Mesh() {
  67. // Physics Fields
  68. ColliderType = mctNone;
  69. ColliderObject = false;
  70. Density = 1.0f;
  71. Mass = 0;
  72. // Render Fields
  73. PRT = false;
  74. }
  75. //------------------------------------//
  76. // Mesh: Destructor
  77. Mesh::~Mesh() {
  78. }
  79. //------------------------------------//
  80. // Mesh: Methods
  81. void Mesh::load(const string &name) {
  82. Engine::Log->print("Mesh: Loading %s...", name.c_str());
  83. // Zresetuj ustawienia
  84. ColliderType = mctNone;
  85. Mass = 10.0f;
  86. try {
  87. // Wczytaj mesha
  88. Reader reader(Engine::VFS->file(va("%s.cfg", name.c_str()), ftMesh).c_str());
  89. // Wczytaj podstawowe parametry
  90. reader.readProperties(Properties, this);
  91. }
  92. catch(Exception &e) {
  93. }
  94. // Spróbuj wczytać .mesh
  95. try {
  96. loadMesh(name);
  97. goto done;
  98. }
  99. catch(Exception &e) {
  100. }
  101. // Spróbuj wczytać .mesh (unigine)
  102. try {
  103. loadMeshU(name);
  104. goto done;
  105. }
  106. catch(Exception &e) {
  107. }
  108. // Spróbuj wczytać .obj
  109. try {
  110. loadObj(name);
  111. goto done;
  112. }
  113. catch(Exception &e) {
  114. }
  115. // Wypisz błšd
  116. Engine::Log->warning("Mesh: Couldn't load %s !", name.c_str());
  117. // Wyczyœć bufory
  118. Vertices.clear();
  119. Indices.clear();
  120. Objects.clear();
  121. done:
  122. // Zainiciuj dane
  123. deviceReset(true);
  124. physicsReset();
  125. }
  126. void Mesh::loadMesh(const string &name) {
  127. // Otwórz plik z meshem
  128. SmartPtr<File> s(Engine::VFS->loadFile(va("%s.mesh", name.c_str()), ftMesh));
  129. // Wczytaj mesha
  130. *s << *this;
  131. _loaded = true;
  132. }
  133. void Mesh::save(const string &name) {
  134. Engine::Log->print("Mesh: Saving %s...", name.c_str());
  135. // Odtwórz plik do zapisu
  136. SmartPtr<File> s(Engine::VFS->saveFile(va("%s.mesh", name.c_str()), ftMesh));
  137. // Zapisz mesha
  138. *s << *this;
  139. }
  140. void Mesh::deviceReset(bool theBegin) {
  141. // Oznacz wszystkie materiały
  142. for(u32 i = 0; i < Objects.size(); i++) {
  143. MeshObject* object = &Objects.at(i);
  144. for(u32 j = 0; j < object->Surfaces.size(); j++) {
  145. object->Surfaces.at(j).Material.cache();
  146. }
  147. if(Engine::Config->PRT && PRT) {
  148. object->PRT.cache();
  149. }
  150. }
  151. // Utwórz nowe bufory
  152. if(theBegin) {
  153. // Utwórz opis formatu wierzchołków
  154. VertexType.reset(new ayuine::VertexType(MeshVertex::Decl));
  155. // Utwórz nowy bufor wierzchołków
  156. if(Vertices.size()) {
  157. VertexBuffer.reset(new ayuine::VertexBuffer(Vertices.size(), sizeof(MeshVertex)));
  158. VertexBuffer->update(Vertices, Vertices.size());
  159. }
  160. // Utwórz nowy bufor indeksów
  161. if(Indices.size()) {
  162. IndexBuffer.reset(new ayuine::IndexBuffer(Indices.size(), if16, false));
  163. IndexBuffer->update(Indices, Indices.size());
  164. }
  165. }
  166. }
  167. void Mesh::deviceLost(bool theEnd) {
  168. // Zniszcz bufory
  169. if(theEnd) {
  170. // Zniszcz opis formatu wierzchołków
  171. VertexType.reset();
  172. // Zniszcz stary bufor wierzchołków
  173. VertexBuffer.reset();
  174. // Zniszcz stary bufor indeksów
  175. IndexBuffer.reset();
  176. }
  177. }
  178. void Mesh::physicsReset() {
  179. // Utwórz odpowiedniego collidera
  180. if(ColliderType == mctNone) {
  181. // Ustaw collidera
  182. Collider.reset(new NullCollider());
  183. if(ColliderObject) {
  184. // Zresetuj kolidery dla obiektów
  185. for(u32 i = 0; i < Objects.size(); i++) {
  186. MeshObject* object = &Objects.at(i);
  187. // Zresetuj collidera
  188. object->Collider.reset(new NullCollider());
  189. // Oblicz masę
  190. object->Mass = 0;
  191. }
  192. }
  193. // Oblicz masę
  194. Mass = 0;
  195. }
  196. else if(ColliderType == mctStatic) {
  197. StaticCollider* collider = new StaticCollider();
  198. // Spróbuj wczytać collidera
  199. try {
  200. // Otwóz plik z colliderem
  201. SmartPtr<File> s(Engine::VFS->loadFile(va("%s.cld", name()), ftMesh));
  202. // Wczytaj collidera
  203. *s << *collider;
  204. goto done;
  205. }
  206. catch(Exception &e) {
  207. Engine::Log->warning("Mesh: Collider not found ! Building...");
  208. }
  209. // Rozpocznij budowanie collidera
  210. collider->begin();
  211. {
  212. Array<vec3> verts;
  213. // Dodaj każdš obiekt
  214. for(u32 i = 0; i < Objects.size(); i++) {
  215. MeshObject* object = &Objects.at(i);
  216. // SprawdŸ wszystkie powierzchnie
  217. for(u32 j = 0; j < object->Surfaces.size(); j++) {
  218. MeshSurface* surface = &object->Surfaces.at(j);
  219. // SprawdŸ materiał
  220. if(!surface->Material || !surface->Material->collidable())
  221. continue;
  222. // Zmień rozmiar listy wierzchołków
  223. verts.resize(surface->IndexCount);
  224. // Dodaj wierzchołki materiału
  225. for(u32 k = 0; k < surface->IndexCount; k++) {
  226. verts.at(k) = Vertices.at(object->VertexStart + Indices.at(surface->IndexStart + surface->IndexCount - 1 - k)).Origin;
  227. }
  228. // Dodaj œciankę do collidera
  229. if(verts.size()) {
  230. // Dodaj każdy trójkšt oddzielnie
  231. for(u32 k = 2; k < verts.size(); k += 3)
  232. collider->addFace(surface->Material->hash(), &verts.at(k - 2), 3);
  233. //collider->addFace(surface->Material->hash(), &verts[0], verts.size());
  234. }
  235. }
  236. }
  237. }
  238. // Zakończ budowanie collidera
  239. collider->end(false);
  240. // Zapisz collidera
  241. try {
  242. // Otwórz plik z colliderem
  243. SmartPtr<File> s(Engine::VFS->saveFile(va("%s.cld", name()), ftMesh));
  244. // Zapisz collidera
  245. *s << *collider;
  246. }
  247. catch(Exception &e) {
  248. Engine::Log->warning("Mesh: Can't save collider %s !", name());
  249. }
  250. done:
  251. // Ustaw collidera
  252. Collider.reset(collider);
  253. // Oblicz masę
  254. Mass = FLT_MAX;
  255. }
  256. else {
  257. Array<vec3> verts;
  258. // Zbuduj sferę
  259. if(ColliderObject) {
  260. Array<ayuine::Collider*> colliders;
  261. // Wyzeruj masę
  262. Mass = 0;
  263. // Zbuduj collidery dla każdego obiektu oddzielnie
  264. for(u32 i = 0; i < Objects.size(); i++) {
  265. MeshObject* object = &Objects.at(i);
  266. // Wyczyœć listę wierzchołków
  267. verts.reset();
  268. // SprawdŸ wszystkie powierzchnie
  269. for(u32 j = 0; j < object->Surfaces.size(); j++) {
  270. MeshSurface* surface = &object->Surfaces.at(j);
  271. // SprawdŸ materiał
  272. if(!surface->Material || !surface->Material->collidable())
  273. continue;
  274. // Dodaj wierzchołki materiału
  275. for(u32 k = 0; k < surface->IndexCount; k++) {
  276. verts.push(Vertices.at(object->VertexStart + Indices.at(surface->IndexStart + k)).Origin);
  277. }
  278. }
  279. // Utwórz collidera
  280. if(verts.empty()) {
  281. object->Collider.reset(new NullCollider());
  282. // Ustaw masę
  283. object->Mass = 0;
  284. }
  285. else {
  286. if(ColliderType == mctSphere) {
  287. bsphere sphere;
  288. // Oblicz sferę
  289. sphere.assign(&verts[0], verts.size());
  290. // Utwórz collidera
  291. object->Collider.reset(new SphereCollider(sphere));
  292. }
  293. else if(ColliderType == mctBox) {
  294. bbox box;
  295. // Oblicz sferę
  296. box.assign(&verts[0], verts.size());
  297. // Utwórz collidera
  298. object->Collider.reset(new BoxCollider(box));
  299. }
  300. else if(ColliderType == mctConvex) {
  301. // Utwórz collidera
  302. object->Collider.reset(new ConvexCollider(&verts[0], verts.size()));
  303. }
  304. else {
  305. Assert("Invalid ColliderType" && false);
  306. }
  307. // Oblicz masę
  308. object->Mass = Density * object->Collider->Volume;
  309. // Dodaj masę
  310. Mass += object->Mass;
  311. // Dodaj collidera do listy
  312. colliders.push(object->Collider);
  313. }
  314. }
  315. // Utwórz collidera złożonego z colliderów pojedyńczych obiektów
  316. if(colliders.empty()) {
  317. Collider.reset(new NullCollider());
  318. }
  319. else {
  320. Collider.reset(new CompoundCollider(colliders));
  321. }
  322. }
  323. else {
  324. // Zbuduj collidery dla całego mesha
  325. for(u32 i = 0; i < Objects.size(); i++) {
  326. MeshObject* object = &Objects.at(i);
  327. // Wyczyœć listę wierzchołków
  328. verts.reset();
  329. // SprawdŸ wszystkie powierzchnie
  330. for(u32 j = 0; j < object->Surfaces.size(); j++) {
  331. MeshSurface* surface = &object->Surfaces.at(j);
  332. // SprawdŸ materiał
  333. if(!surface->Material || !surface->Material->collidable())
  334. continue;
  335. // Dodaj wierzchołki materiału
  336. for(u32 k = 0; k < surface->IndexCount; k++) {
  337. verts.push(Vertices.at(object->VertexStart + Indices.at(surface->IndexStart + k)).Origin);
  338. }
  339. }
  340. }
  341. // Utwórz collidera
  342. if(verts.empty()) {
  343. Collider.reset(new NullCollider());
  344. // Ustaw masę
  345. Mass = 0;
  346. }
  347. else {
  348. if(ColliderType == mctSphere) {
  349. bsphere sphere;
  350. // Oblicz sferę
  351. sphere.assign(&verts[0], verts.size());
  352. // Utwórz collidera
  353. Collider.reset(new SphereCollider(sphere));
  354. }
  355. else if(ColliderType == mctBox) {
  356. bbox box;
  357. // Oblicz sferę
  358. box.assign(&verts[0], verts.size());
  359. // Utwórz collidera
  360. Collider.reset(new BoxCollider(box));
  361. }
  362. else if(ColliderType == mctConvex) {
  363. // Utwórz collidera
  364. Collider.reset(new ConvexCollider(&verts[0], verts.size()));
  365. }
  366. else {
  367. Assert("Invalid ColliderType" && false);
  368. }
  369. // Oblicz masę
  370. Mass = Density * Collider->Volume;
  371. }
  372. }
  373. }
  374. }
  375. void Mesh::physicsLost() {
  376. // Zniszcz głównego collidera
  377. Collider.reset();
  378. // Zniszcz collidera dla każdego obiektu
  379. for(u32 i = 0; i < Objects.size(); i++) {
  380. MeshObject* object = &Objects.at(i);
  381. // Zresetuj collidera
  382. object->Collider.reset();
  383. }
  384. }
  385. };