Model3D.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. #include "Model3D.h"
  2. #include "Model2D.h"
  3. #include "DXBuffer.h"
  4. #include "Textur.h"
  5. #ifdef WIN32
  6. #include "Render3D.h"
  7. #include <d3d11.h>
  8. #endif
  9. #include <stdexcept>
  10. using namespace Framework;
  11. // Inhalt der Knochen Klasse
  12. // Konstruktor
  13. Knochen::Knochen( int id )
  14. {
  15. pos = Vec3< float >( 0, 0, 0 );
  16. winkel = Vec3< float >( 0, 0, 0 );
  17. geschwister = 0;
  18. kinder = 0;
  19. this->id = id;
  20. }
  21. // Destruktor
  22. Knochen::~Knochen()
  23. {
  24. delete geschwister;
  25. delete kinder;
  26. }
  27. // private
  28. // Fügt dem Knochen ein Geschwister Knochen hinzu
  29. // k: Der Knochen, der hinzugefügt werden soll
  30. void Knochen::addGeschwisterKnochen( Knochen *k )
  31. {
  32. if( !geschwister )
  33. geschwister = k;
  34. else
  35. geschwister->addGeschwisterKnochen( k );
  36. }
  37. // public
  38. // Setzt die Position des Knochens relativ zum Model Ursprung
  39. // pos: Die Position
  40. void Knochen::setPosition( Vec3< float > &pos )
  41. {
  42. this->pos = pos;
  43. }
  44. // Setzt die Drehung des Knochens relativ zum Model Ursprung
  45. // winkel: Ein Vektor der die Drehung um die verschiedenen Achsen als Komponenten hat
  46. void Knochen::setDrehung( Vec3< float > &winkel )
  47. {
  48. this->winkel = winkel;
  49. }
  50. // Fügt einem bestimmten Knochen ein Kind Knochen hinzu
  51. // id: Die id des Knochens, wo der Knochen als Kind hinzugefügt werden soll
  52. // k: Der Knochen, der hinzugefügt werden soll
  53. void Knochen::addKind( int id, Knochen *k )
  54. {
  55. if( this->id == id )
  56. {
  57. if( !kinder )
  58. kinder = k;
  59. else
  60. kinder->addGeschwisterKnochen( k );
  61. }
  62. else
  63. {
  64. if( kinder )
  65. kinder->addKind( id, k );
  66. else
  67. {
  68. Text err = "Es wurde kein Knochen mit der Id: ";
  69. err += id;
  70. err += " im Skelett gefunden, um ein Kind Knochen hinzuzufügen. Datei:" __FILE__ ", Zeile: ";
  71. err += __LINE__;
  72. err += "!";
  73. delete k;
  74. throw std::out_of_range( (const char*)err );
  75. }
  76. }
  77. }
  78. // Berechnet die Matrizen des Knochen und die von all seinen Geschwister Knochen und Kind Knochen
  79. // elternMat: Die fertig berechnete Matrix des Elternknochens
  80. // matBuffer: Ein Array, in dem alle berechneten Matrizen gespeichert werden sollen
  81. // kamMatrix: Die vereiniegung der view und projektions Matrizen
  82. void Knochen::kalkulateMatrix( Mat4< float > &elternMat, Mat4< float > *matBuffer, Mat4< float > &kamMat )
  83. {
  84. if( geschwister )
  85. geschwister->kalkulateMatrix( elternMat, matBuffer, kamMat );
  86. matBuffer[ id ] = matBuffer[ id ].translation( pos ) * matBuffer[ id ].rotationZ( winkel.z ) * matBuffer[ id ].rotationX( winkel.x ) * matBuffer[ id ].rotationY( winkel.y );
  87. matBuffer[ id ] = elternMat * matBuffer[ id ];
  88. if( kinder )
  89. kinder->kalkulateMatrix( matBuffer[ id ], matBuffer, kamMat );
  90. matBuffer[ id ] = kamMat * matBuffer[ id ];
  91. }
  92. // Kopiert den Knochen mit allen Geschwister Knochen und Kind Knochen
  93. Knochen *Knochen::kopiereKnochen() const
  94. {
  95. Knochen *ret = new Knochen( id );
  96. ret->pos = pos;
  97. ret->winkel = winkel;
  98. if( geschwister )
  99. ret->geschwister = geschwister->kopiereKnochen();
  100. if( kinder )
  101. ret->kinder = kinder->kopiereKnochen();
  102. return ret;
  103. }
  104. // Gibt die Id des Knochens zurück
  105. int Knochen::getId() const
  106. {
  107. return id;
  108. }
  109. // Inhalt der Skelett Klasse
  110. // Konstruktor
  111. Skelett::Skelett()
  112. {
  113. k = 0;
  114. nextId = 0;
  115. ref = 1;
  116. }
  117. // Destruktor
  118. Skelett::~Skelett()
  119. {
  120. if( k )
  121. delete k;
  122. }
  123. // Gibt die Id des nächsten Knochens zurück und berechnet die neue Id für den Knochen danach
  124. // Es können maximal 128 Knochen für ein Skelett existieren. Wenn diese Zahl überschritten wird, so wird -1 zurückgegeben
  125. int Skelett::getNextKnochenId()
  126. {
  127. return nextId++;
  128. }
  129. // Fügt dem Skellet einen Knochen hinzu
  130. // k: Der Knochen
  131. // elternId: Die Id des Eltern Knochens. Wenn der Knochen kein Elternknochen besitzt, kannder Parameter weggelassen werden.
  132. void Skelett::addKnochen( Knochen *k, int elternId )
  133. {
  134. if( !this->k )
  135. this->k = k;
  136. else
  137. this->k->addKind( elternId, k );
  138. if( k->getId() >= nextId )
  139. nextId = k->getId() + 1;
  140. }
  141. // Berechnet die Matrizen der Knochen
  142. // modelMatrix: Die Matrix, die das Skelett in den Raum der Welt transformiert
  143. // matBuffer: Ein Array von Matrizen, der durch die Knochen Matrizen gefüllt wird
  144. // return: gibt die Anzahl der verwendeten Matrizen zurück
  145. // kamMatrix: Die vereiniegung der view und projektions Matrizen
  146. int Skelett::kalkulateMatrix( Mat4< float > &modelMatrix, Mat4< float > *matBuffer, Mat4< float > &kamMatrix )
  147. {
  148. k->kalkulateMatrix( modelMatrix, matBuffer, kamMatrix );
  149. return nextId;
  150. }
  151. // Kopiert das Skelett
  152. Skelett *Skelett::kopiereSkelett() const
  153. {
  154. Skelett *ret = new Skelett();
  155. ret->nextId = nextId;
  156. if( k )
  157. ret->addKnochen( k->kopiereKnochen() );
  158. return ret;
  159. }
  160. // Erhöht den Reference Counting Zähler.
  161. Skelett *Skelett::getThis()
  162. {
  163. ref++;
  164. return this;
  165. }
  166. // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
  167. // return: 0.
  168. Skelett *Skelett::release()
  169. {
  170. ref--;
  171. if( !ref )
  172. delete this;
  173. return 0;
  174. }
  175. // Inhalt des Polygon3D Struct
  176. // Konstruktor
  177. Polygon3D::Polygon3D()
  178. {
  179. indexAnz = 0;
  180. indexList = 0;
  181. indexBuffer = new DXIndexBuffer( sizeof( int ) );
  182. }
  183. // Destruktor
  184. Polygon3D::~Polygon3D()
  185. {
  186. indexBuffer->release();
  187. delete[] indexList;
  188. }
  189. // Inhalt der Model3DData Klasse
  190. // Konstruktor
  191. Model3DData::Model3DData()
  192. {
  193. id = -1;
  194. skelett = 0;
  195. vertexList = 0;
  196. polygons = new Array< Polygon3D* >();
  197. vertexBuffer = new DXVertexBuffer( sizeof( Vertex3D ) );
  198. radius = 0;
  199. ref = 1;
  200. }
  201. // Destruktor
  202. Model3DData::~Model3DData()
  203. {
  204. clearModel();
  205. vertexBuffer->release();
  206. polygons->release();
  207. }
  208. // Löscht alle Model daten
  209. void Model3DData::clearModel()
  210. {
  211. delete[] vertexList;
  212. vertexList = 0;
  213. for( auto i = polygons->getArray(); i.set; i++ )
  214. delete i.var;
  215. polygons->leeren();
  216. if( skelett )
  217. skelett->release();
  218. skelett = 0;
  219. radius = 0;
  220. }
  221. // Setzt den Zeiger auf ein standartmäßig verwendete Skelett
  222. // s: Das Skelett, das verwendet werden soll
  223. void Model3DData::setSkelettZ( Skelett *s )
  224. {
  225. if( skelett )
  226. skelett->release();
  227. skelett = s;
  228. }
  229. // Setzt einen Zeiger auf eine Liste mit allen Vertecies des Models
  230. // vertexList: Ein Array mit Vertecies
  231. // anz: Die Anzahl der Vertecies im Array
  232. void Model3DData::setVertecies( Vertex3D *vertexList, int anz )
  233. {
  234. delete[] this->vertexList;
  235. this->vertexList = vertexList;
  236. vertexBuffer->setData( vertexList );
  237. vertexBuffer->setLength( (int)sizeof( Vertex3D ) * anz );
  238. radius = 0;
  239. for( int i = 0; i < anz; i++ )
  240. {
  241. float r = vertexList[ i ].pos.getLength();
  242. if( r > radius )
  243. radius = r;
  244. }
  245. }
  246. // Fügt ein Polygon zum Model hinzu
  247. // polygon: Das Polygon, das hinzugefügt erden soll
  248. void Model3DData::addPolygon( Polygon3D *polygon )
  249. {
  250. polygons->add( polygon );
  251. }
  252. // Konvertiert ein 2d Model zu 3D
  253. // model: Das 2d Model, das zu 3d konvertiert werden soll
  254. // z: Die z koordinate aller punkte des Models
  255. void Model3DData::copyModel2D( Model2DData *model, float z )
  256. {
  257. if( model && model->vListen && model->polygons )
  258. {
  259. clearModel();
  260. int vAnz = 0;
  261. for( auto i = model->polygons->getArray(); i.set; i++ )
  262. vAnz += i.var.vertex->getEintragAnzahl();
  263. vertexList = new Vertex3D[ vAnz ];
  264. vertexBuffer->setData( vertexList );
  265. vertexBuffer->setLength( (int)sizeof( Vertex3D ) * vAnz );
  266. int index = 0;
  267. for( auto i = model->vListen->getArray(); i.set; i++ )
  268. {
  269. Polygon3D *p = new Polygon3D();
  270. p->indexAnz = 0;
  271. for( auto j = i.var->getArray(); j.set; j++ )
  272. {
  273. for( auto *k = &j.var->zListe()->getArray(); k->next->next && k->next->next->set; k = k->next )
  274. p->indexAnz += 3;
  275. }
  276. p->indexList = new int[ p->indexAnz ];
  277. p->indexBuffer->setData( p->indexList );
  278. p->indexBuffer->setLength( (int)sizeof( int ) * p->indexAnz );
  279. p->indexAnz = 0;
  280. for( auto j = i.var->getArray(); j.set; j++ )
  281. {
  282. for( auto *k = &j.var->zListe()->getArray(); k && k->set; k = k->next )
  283. {
  284. vertexList[ index ].pos = Vec3< float >( k->var->punkt->x, k->var->punkt->y, z );
  285. vertexList[ index ].tPos = ( Vec2< float > )*k->var->textur;
  286. if( k->next && k->next->set && k->next->next && k->next->next->set )
  287. {
  288. p->indexList[ p->indexAnz ] = index;
  289. p->indexAnz++;
  290. p->indexList[ p->indexAnz ] = index + 1;
  291. p->indexAnz++;
  292. p->indexList[ p->indexAnz ] = index + 2;
  293. p->indexAnz++;
  294. }
  295. index++;
  296. }
  297. }
  298. addPolygon( p );
  299. }
  300. }
  301. }
  302. // Entfernt ein Polygon
  303. // index: Der Index des Polygons
  304. void Model3DData::removePolygon( int index )
  305. {
  306. if( !polygons->hat( index ) )
  307. return;
  308. delete polygons->get( index );
  309. polygons->remove( index );
  310. }
  311. // Aktualisiert die Vertecies
  312. // zRObj: Das Objekt, mit dem die Grafikkarte verwaltet wird
  313. void Model3DData::aktualisiereVertecies( Render3D *zRObj )
  314. {
  315. vertexBuffer->copieren( zRObj );
  316. }
  317. // Berechnet die Matrizen der Knochen
  318. // modelMatrix: Die Matrix, die das Skelett in den Raum der Welt transformiert
  319. // matBuffer: Ein Array von Matrizen, der durch die Knochen Matrizen gefüllt wird
  320. // return: gibt die Anzahl der verwendeten Matrizen zurück
  321. // kamMatrix: Die vereiniegung der view und projektions Matrizen
  322. int Model3DData::kalkulateMatrix( Mat4< float > &modelMatrix, Mat4< float > *matBuffer, Mat4< float > &kamMatrix ) const
  323. {
  324. if( !skelett )
  325. return 0;
  326. return skelett->kalkulateMatrix( modelMatrix, matBuffer, kamMatrix );
  327. }
  328. // Zeichnet alle Polygons
  329. // world: Die Welt Matrix, die das Model in die Welt transformiert
  330. // zTxt: Eine Liste mit Texturen der einzelnen Polygone
  331. // zRObj: Das Objekt, mit dem gezeichnet werden soll
  332. void Model3DData::render( Mat4< float > &welt, const Model3DTextur *zTxt, Render3D *zRObj )
  333. {
  334. int ind = 0;
  335. for( auto *i = &polygons->getArray(); i && i->set; i = i->next )
  336. {
  337. i->var->indexBuffer->copieren( zRObj );
  338. Textur *t = zTxt->zPolygonTextur( ind );
  339. if( t && t->brauchtUpdate() )
  340. t->updateTextur( zRObj );
  341. #ifdef WIN32
  342. zRObj->draw( i->var->indexBuffer, t );
  343. #endif
  344. ind++;
  345. }
  346. }
  347. // Gibt die Anzahl an Polygonen zurück
  348. int Model3DData::getPolygonAnzahl() const
  349. {
  350. return polygons->getEintragAnzahl();
  351. }
  352. // Gibt ein bestimmtes Polygon zurück
  353. // index: Der Index des Polygons
  354. Polygon3D *Model3DData::getPolygon( int index ) const
  355. {
  356. if( !polygons->hat( index ) )
  357. return 0;
  358. return polygons->get( index );
  359. }
  360. // Gibt den radius einer Kugel zurück, die das gesammte Model umschließt
  361. float Model3DData::getRadius() const
  362. {
  363. return radius;
  364. }
  365. // Gibt die Id der Daten zurück, wenn sie in einer Model3DList registriert wurden. (siehe Framework::zM3DRegister())
  366. int Model3DData::getId() const
  367. {
  368. return id;
  369. }
  370. // Gibt einen Buffer mit allen Vertecies des Models zurück
  371. const DXVertexBuffer *Model3DData::zVertexBuffer() const
  372. {
  373. return vertexBuffer;
  374. }
  375. // Erhöht den Reference Counting Zähler.
  376. // return: this.
  377. Model3DData *Model3DData::getThis()
  378. {
  379. ref++;
  380. return this;
  381. }
  382. // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
  383. // return: 0.
  384. Model3DData *Model3DData::release()
  385. {
  386. ref--;
  387. if( !ref )
  388. delete this;
  389. return 0;
  390. }
  391. // Inhalt der Model3DTextur
  392. // Konstruktor
  393. Model3DTextur::Model3DTextur()
  394. {
  395. textures = new RCArray< Textur >();
  396. ref = 1;
  397. }
  398. // Destruktor
  399. Model3DTextur::~Model3DTextur()
  400. {
  401. textures->release();
  402. }
  403. // Legt fest, welche Textur für welches Polygon ist
  404. // pI: Der Index des Polygons
  405. // txt: Die Textur des Polygons
  406. void Model3DTextur::setPolygonTextur( int pI, Textur *txt )
  407. {
  408. textures->set( txt, pI );
  409. }
  410. // Gibt einen Zeiger auf die Textur eines Polygons zurück ohne erhöhten Reference Counter
  411. // i: Der Index des Polygons
  412. Textur *Model3DTextur::zPolygonTextur( int i ) const
  413. {
  414. return textures->z( i );
  415. }
  416. // Erhöht den Reference Counting Zähler.
  417. // return: this.
  418. Model3DTextur *Model3DTextur::getThis()
  419. {
  420. ref++;
  421. return this;
  422. }
  423. // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
  424. // return: 0.
  425. Model3DTextur *Model3DTextur::release()
  426. {
  427. ref--;
  428. if( !ref )
  429. delete this;
  430. return 0;
  431. }
  432. // Inhalt der Model3D Klasse
  433. // Konstruktor
  434. Model3D::Model3D()
  435. : Zeichnung3D()
  436. {
  437. model = 0;
  438. textur = 0;
  439. skelett = 0;
  440. ref = 1;
  441. }
  442. // Destruktor
  443. Model3D::~Model3D()
  444. {
  445. if( model )
  446. model->release();
  447. if( textur )
  448. textur->release();
  449. if( skelett )
  450. skelett->release();
  451. }
  452. // Setzt den Zeiger auf das zum Annimieren verwendete Skelett
  453. // s: Das Skelett, das verwendet werden soll
  454. void Model3D::setSkelettZ( Skelett *s )
  455. {
  456. if( skelett )
  457. skelett->release();
  458. skelett = s;
  459. }
  460. // Setzt die Daten des Models
  461. // data: Die Daten
  462. void Model3D::setModelDaten( Model3DData *data )
  463. {
  464. if( model )
  465. model->release();
  466. model = data;
  467. }
  468. // Setzt die zum Zeichnen zu benutzenden Texturen
  469. // txt: Ein Liste mit Texturen zu den verschiedenen Polygonen zugeordnet
  470. void Model3D::setModelTextur( Model3DTextur *txt )
  471. {
  472. if( textur )
  473. textur->release();
  474. textur = txt;
  475. }
  476. // Errechnet die Matrizen aller Knochen des Skeletts des Models
  477. // viewProj: Die miteinander multiplizierten Kameramatrizen
  478. // matBuffer: Ein Array mit Matrizen, der gefüllt werden soll
  479. // return: Die Anzahl der Matrizen, die das Model benötigt
  480. int Model3D::errechneMatrizen( Mat4< float > &viewProj, Mat4< float > *matBuffer )
  481. {
  482. int ret = 0;
  483. if( skelett )
  484. ret = skelett->kalkulateMatrix( welt, matBuffer, viewProj );
  485. else if( model )
  486. ret = model->kalkulateMatrix( welt, matBuffer, viewProj );
  487. if( !ret )
  488. return Zeichnung3D::errechneMatrizen( viewProj, matBuffer );
  489. return ret;
  490. }
  491. // Verarbeitet die vergangene Zeit
  492. // tickval: Die zeit in sekunden, die seit dem letzten Aufruf der Funktion vergangen ist
  493. // return: true, wenn sich das Objekt verändert hat, false sonnst.
  494. bool Model3D::tick( double tickval )
  495. {
  496. radius = model ? model->getRadius() : 0;
  497. return Zeichnung3D::tick( tickval );
  498. }
  499. // Zeichnet das Model
  500. // zRObj: Ein Zeiger auf das Objekt, das zum Zeichnen verwendet werden soll (ohne erhöhten Reference Counter)
  501. void Model3D::render( Render3D *zRObj )
  502. {
  503. if( !model )
  504. return;
  505. model->aktualisiereVertecies( zRObj );
  506. #ifdef WIN32
  507. zRObj->beginnModel( this );
  508. #endif
  509. model->render( welt, textur, zRObj );
  510. }
  511. // Gibt die Id der Daten zurück, wenn sie in einer Model3DList registriert wurden. (siehe Framework::zM3DRegister())
  512. int Model3D::getDatenId() const
  513. {
  514. return model ? model->getId() : -1;
  515. }
  516. // Gibt einen Buffer mit allen Vertecies des Models zurück
  517. const DXVertexBuffer *Model3D::zVertexBuffer() const
  518. {
  519. return model ? model->zVertexBuffer() : 0;
  520. }
  521. // Erhöht den Reference Counting Zähler.
  522. // return: this.
  523. Model3D *Model3D::getThis()
  524. {
  525. ref++;
  526. return this;
  527. }
  528. // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
  529. // return: 0.
  530. Model3D *Model3D::release()
  531. {
  532. ref--;
  533. if( !ref )
  534. delete this;
  535. return 0;
  536. }