123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681 |
- #include "Model3D.h"
- #include "Model2D.h"
- #include "DXBuffer.h"
- #include "Textur.h"
- #include "Animation3D.h"
- #ifdef WIN32
- #include "Render3D.h"
- #include <d3d11.h>
- #endif
- #include <stdexcept>
- using namespace Framework;
- // Inhalt der Knochen Klasse
- // Konstruktor
- Knochen::Knochen( int id )
- {
- pos = Vec3< float >( 0, 0, 0 );
- winkel = Vec3< float >( 0, 0, 0 );
- geschwister = 0;
- kinder = 0;
- this->id = id;
- }
- // Destruktor
- Knochen::~Knochen()
- {
- delete geschwister;
- delete kinder;
- }
- // private
- // Fügt dem Knochen ein Geschwister Knochen hinzu
- // k: Der Knochen, der hinzugefügt werden soll
- void Knochen::addGeschwisterKnochen( Knochen *k )
- {
- if( !geschwister )
- geschwister = k;
- else
- geschwister->addGeschwisterKnochen( k );
- }
- // public
- // Setzt die Position des Knochens relativ zum Model Ursprung
- // pos: Die Position
- void Knochen::setPosition( Vec3< float > &pos )
- {
- this->pos = pos;
- }
- // Setzt die Drehung des Knochens relativ zum Model Ursprung
- // winkel: Ein Vektor der die Drehung um die verschiedenen Achsen als Komponenten hat
- void Knochen::setDrehung( Vec3< float > &winkel )
- {
- this->winkel = winkel;
- }
- // Fügt einem bestimmten Knochen ein Kind Knochen hinzu
- // id: Die id des Knochens, wo der Knochen als Kind hinzugefügt werden soll
- // k: Der Knochen, der hinzugefügt werden soll
- void Knochen::addKind( int id, Knochen *k )
- {
- if( this->id == id )
- {
- if( !kinder )
- kinder = k;
- else
- kinder->addGeschwisterKnochen( k );
- }
- else
- {
- if( kinder )
- kinder->addKind( id, k );
- else
- {
- Text err = "Es wurde kein Knochen mit der Id: ";
- err += id;
- err += " im Skelett gefunden, um ein Kind Knochen hinzuzufügen. Datei:" __FILE__ ", Zeile: ";
- err += __LINE__;
- err += "!";
- delete k;
- throw std::out_of_range( (const char*)err );
- }
- }
- }
- // Berechnet die Matrizen des Knochen und die von all seinen Geschwister Knochen und Kind Knochen
- // elternMat: Die fertig berechnete Matrix des Elternknochens
- // matBuffer: Ein Array, in dem alle berechneten Matrizen gespeichert werden sollen
- // kamMatrix: Die vereiniegung der view und projektions Matrizen
- void Knochen::kalkulateMatrix( Mat4< float > &elternMat, Mat4< float > *matBuffer, Mat4< float > &kamMat )
- {
- if( geschwister )
- geschwister->kalkulateMatrix( elternMat, matBuffer, kamMat );
- matBuffer[ id ] = matBuffer[ id ].translation( pos ) * matBuffer[ id ].rotationZ( winkel.z ) * matBuffer[ id ].rotationX( winkel.x ) * matBuffer[ id ].rotationY( winkel.y );
- matBuffer[ id ] = elternMat * matBuffer[ id ];
- if( kinder )
- kinder->kalkulateMatrix( matBuffer[ id ], matBuffer, kamMat );
- matBuffer[ id ] = kamMat * matBuffer[ id ];
- }
- // Kopiert den Knochen mit allen Geschwister Knochen und Kind Knochen
- Knochen *Knochen::kopiereKnochen() const
- {
- Knochen *ret = new Knochen( id );
- ret->pos = pos;
- ret->winkel = winkel;
- if( geschwister )
- ret->geschwister = geschwister->kopiereKnochen();
- if( kinder )
- ret->kinder = kinder->kopiereKnochen();
- return ret;
- }
- // Gibt die Id des Knochens zurück
- int Knochen::getId() const
- {
- return id;
- }
- // Gibt die Drehung des Knochens zurück
- Vec3< float > Knochen::getDrehung() const
- {
- return winkel;
- }
- // Gibt die Position des Knochens zurück
- Vec3< float > Knochen::getPosition() const
- {
- return pos;
- }
- // Gibt den Radius des Knochens zurück
- float Knochen::getRadius() const
- {
- float r = pos.getLength();
- if( geschwister )
- r = MAX( r, geschwister->getRadius() );
- if( kinder )
- r += kinder->getRadius();
- return r;
- }
- // Inhalt der Skelett Klasse
- // Konstruktor
- Skelett::Skelett()
- {
- k = 0;
- nextId = 0;
- ref = 1;
- }
- // Destruktor
- Skelett::~Skelett()
- {
- if( k )
- delete k;
- }
- // Gibt die Id des nächsten Knochens zurück und berechnet die neue Id für den Knochen danach
- // Es können maximal MAX_KNOCHEN_ANZ Knochen für ein Skelett existieren. Wenn diese Zahl überschritten wird, so wird -1 zurückgegeben
- int Skelett::getNextKnochenId()
- {
- return nextId++;
- }
- // Fügt dem Skellet einen Knochen hinzu
- // k: Der Knochen
- // elternId: Die Id des Eltern Knochens. Wenn der Knochen kein Elternknochen besitzt, kannder Parameter weggelassen werden.
- void Skelett::addKnochen( Knochen *k, int elternId )
- {
- if( !this->k )
- this->k = k;
- else
- this->k->addKind( elternId, k );
- if( k->getId() >= nextId )
- nextId = k->getId() + 1;
- }
- // Berechnet die Matrizen der Knochen
- // modelMatrix: Die Matrix, die das Skelett in den Raum der Welt transformiert
- // matBuffer: Ein Array von Matrizen, der durch die Knochen Matrizen gefüllt wird
- // return: gibt die Anzahl der verwendeten Matrizen zurück
- // kamMatrix: Die vereiniegung der view und projektions Matrizen
- int Skelett::kalkulateMatrix( Mat4< float > &modelMatrix, Mat4< float > *matBuffer, Mat4< float > &kamMatrix )
- {
- k->kalkulateMatrix( modelMatrix, matBuffer, kamMatrix );
- return nextId;
- }
- // Berechnet den Radius des Skeletts
- float Skelett::getRadius() const
- {
- if( k )
- return k->getRadius();
- return 0;
- }
- // Kopiert das Skelett
- Skelett *Skelett::kopiereSkelett() const
- {
- Skelett *ret = new Skelett();
- ret->nextId = nextId;
- if( k )
- ret->addKnochen( k->kopiereKnochen() );
- return ret;
- }
- // Erhöht den Reference Counting Zähler.
- Skelett *Skelett::getThis()
- {
- ref++;
- return this;
- }
- // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
- // return: 0.
- Skelett *Skelett::release()
- {
- ref--;
- if( !ref )
- delete this;
- return 0;
- }
- // Inhalt des Polygon3D Struct
- // Konstruktor
- Polygon3D::Polygon3D()
- {
- indexAnz = 0;
- indexList = 0;
- indexBuffer = new DXIndexBuffer( sizeof( int ) );
- }
- // Destruktor
- Polygon3D::~Polygon3D()
- {
- indexBuffer->release();
- delete[] indexList;
- }
- // Inhalt der Model3DData Klasse
- // Konstruktor
- Model3DData::Model3DData()
- {
- id = -1;
- skelett = 0;
- vertexList = 0;
- polygons = new Array< Polygon3D* >();
- vertexBuffer = new DXVertexBuffer( sizeof( Vertex3D ) );
- radius = 0;
- ref = 1;
- }
- // Destruktor
- Model3DData::~Model3DData()
- {
- clearModel();
- vertexBuffer->release();
- polygons->release();
- }
- // Löscht alle Model daten
- void Model3DData::clearModel()
- {
- delete[] vertexList;
- vertexList = 0;
- for( auto i = polygons->getArray(); i.set; i++ )
- delete i.var;
- polygons->leeren();
- if( skelett )
- skelett->release();
- skelett = 0;
- radius = 0;
- }
- // Setzt den Zeiger auf ein standartmäßig verwendete Skelett
- // s: Das Skelett, das verwendet werden soll
- void Model3DData::setSkelettZ( Skelett *s )
- {
- if( skelett )
- skelett->release();
- skelett = s;
- }
- // Setzt einen Zeiger auf eine Liste mit allen Vertecies des Models
- // vertexList: Ein Array mit Vertecies
- // anz: Die Anzahl der Vertecies im Array
- void Model3DData::setVertecies( Vertex3D *vertexList, int anz )
- {
- delete[] this->vertexList;
- this->vertexList = vertexList;
- vertexBuffer->setData( vertexList );
- vertexBuffer->setLength( (int)sizeof( Vertex3D ) * anz );
- radius = 0;
- for( int i = 0; i < anz; i++ )
- {
- float r = vertexList[ i ].pos.getLength();
- if( r > radius )
- radius = r;
- }
- }
- // Fügt ein Polygon zum Model hinzu
- // polygon: Das Polygon, das hinzugefügt erden soll
- void Model3DData::addPolygon( Polygon3D *polygon )
- {
- polygons->add( polygon );
- }
- // Konvertiert ein 2d Model zu 3D
- // model: Das 2d Model, das zu 3d konvertiert werden soll
- // z: Die z koordinate aller punkte des Models
- void Model3DData::copyModel2D( Model2DData *model, float z )
- {
- if( model && model->vListen && model->polygons )
- {
- clearModel();
- int vAnz = 0;
- for( auto i = model->polygons->getArray(); i.set; i++ )
- vAnz += i.var.vertex->getEintragAnzahl();
- vertexList = new Vertex3D[ vAnz ];
- vertexBuffer->setData( vertexList );
- vertexBuffer->setLength( (int)sizeof( Vertex3D ) * vAnz );
- int index = 0;
- for( auto i = model->vListen->getArray(); i.set; i++ )
- {
- Polygon3D *p = new Polygon3D();
- p->indexAnz = 0;
- for( auto j = i.var->getArray(); j.set; j++ )
- {
- for( auto *k = &j.var->zListe()->getArray(); k->next->next && k->next->next->set; k = k->next )
- p->indexAnz += 3;
- }
- p->indexList = new int[ p->indexAnz ];
- p->indexBuffer->setData( p->indexList );
- p->indexBuffer->setLength( (int)sizeof( int ) * p->indexAnz );
- p->indexAnz = 0;
- for( auto j = i.var->getArray(); j.set; j++ )
- {
- for( auto *k = &j.var->zListe()->getArray(); k && k->set; k = k->next )
- {
- vertexList[ index ].pos = Vec3< float >( k->var->punkt->x, k->var->punkt->y, z );
- vertexList[ index ].tPos = ( Vec2< float > )*k->var->textur;
- if( k->next && k->next->set && k->next->next && k->next->next->set )
- {
- p->indexList[ p->indexAnz ] = index;
- p->indexAnz++;
- p->indexList[ p->indexAnz ] = index + 1;
- p->indexAnz++;
- p->indexList[ p->indexAnz ] = index + 2;
- p->indexAnz++;
- }
- index++;
- }
- }
- addPolygon( p );
- }
- }
- }
- // Entfernt ein Polygon
- // index: Der Index des Polygons
- void Model3DData::removePolygon( int index )
- {
- if( !polygons->hat( index ) )
- return;
- delete polygons->get( index );
- polygons->remove( index );
- }
- // Aktualisiert die Vertecies
- // zRObj: Das Objekt, mit dem die Grafikkarte verwaltet wird
- void Model3DData::aktualisiereVertecies( Render3D *zRObj )
- {
- vertexBuffer->copieren( zRObj );
- }
- // Berechnet die Matrizen der Knochen
- // modelMatrix: Die Matrix, die das Skelett in den Raum der Welt transformiert
- // matBuffer: Ein Array von Matrizen, der durch die Knochen Matrizen gefüllt wird
- // return: gibt die Anzahl der verwendeten Matrizen zurück
- // kamMatrix: Die vereiniegung der view und projektions Matrizen
- int Model3DData::kalkulateMatrix( Mat4< float > &modelMatrix, Mat4< float > *matBuffer, Mat4< float > &kamMatrix ) const
- {
- if( !skelett )
- return 0;
- return skelett->kalkulateMatrix( modelMatrix, matBuffer, kamMatrix );
- }
- // Zeichnet alle Polygons
- // world: Die Welt Matrix, die das Model in die Welt transformiert
- // zTxt: Eine Liste mit Texturen der einzelnen Polygone
- // zRObj: Das Objekt, mit dem gezeichnet werden soll
- void Model3DData::render( Mat4< float > &welt, const Model3DTextur *zTxt, Render3D *zRObj )
- {
- int ind = 0;
- for( auto *i = &polygons->getArray(); i && i->set; i = i->next )
- {
- i->var->indexBuffer->copieren( zRObj );
- Textur *t = zTxt->zPolygonTextur( ind );
- if( t && t->brauchtUpdate() )
- t->updateTextur( zRObj );
- #ifdef WIN32
- zRObj->draw( i->var->indexBuffer, t );
- #endif
- ind++;
- }
- }
- // Gibt die Anzahl an Polygonen zurück
- int Model3DData::getPolygonAnzahl() const
- {
- return polygons->getEintragAnzahl();
- }
- // Gibt ein bestimmtes Polygon zurück
- // index: Der Index des Polygons
- Polygon3D *Model3DData::getPolygon( int index ) const
- {
- if( !polygons->hat( index ) )
- return 0;
- return polygons->get( index );
- }
- // Gibt den radius einer Kugel zurück, die das gesammte Model umschließt
- float Model3DData::getRadius() const
- {
- return radius;
- }
- // Gibt die Id der Daten zurück, wenn sie in einer Model3DList registriert wurden. (siehe Framework::zM3DRegister())
- int Model3DData::getId() const
- {
- return id;
- }
- // Gibt einen Buffer mit allen Vertecies des Models zurück
- const DXVertexBuffer *Model3DData::zVertexBuffer() const
- {
- return vertexBuffer;
- }
- // Erhöht den Reference Counting Zähler.
- // return: this.
- Model3DData *Model3DData::getThis()
- {
- ref++;
- return this;
- }
- // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
- // return: 0.
- Model3DData *Model3DData::release()
- {
- ref--;
- if( !ref )
- delete this;
- return 0;
- }
- // Inhalt der Model3DTextur
- // Konstruktor
- Model3DTextur::Model3DTextur()
- {
- textures = new RCArray< Textur >();
- ref = 1;
- }
- // Destruktor
- Model3DTextur::~Model3DTextur()
- {
- textures->release();
- }
- // Legt fest, welche Textur für welches Polygon ist
- // pI: Der Index des Polygons
- // txt: Die Textur des Polygons
- void Model3DTextur::setPolygonTextur( int pI, Textur *txt )
- {
- textures->set( txt, pI );
- }
- // Gibt einen Zeiger auf die Textur eines Polygons zurück ohne erhöhten Reference Counter
- // i: Der Index des Polygons
- Textur *Model3DTextur::zPolygonTextur( int i ) const
- {
- return textures->z( i );
- }
- // Erhöht den Reference Counting Zähler.
- // return: this.
- Model3DTextur *Model3DTextur::getThis()
- {
- ref++;
- return this;
- }
- // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
- // return: 0.
- Model3DTextur *Model3DTextur::release()
- {
- ref--;
- if( !ref )
- delete this;
- return 0;
- }
- // Inhalt der AnimationData Struktur
- Model3D::AnimationData *Model3D::AnimationData::getThis()
- {
- return this;
- }
- Model3D::AnimationData *Model3D::AnimationData::release()
- {
- a->release();
- delete this;
- return 0;
- }
- // Inhalt der Model3D Klasse
- // Konstruktor
- Model3D::Model3D()
- : Zeichnung3D()
- {
- model = 0;
- textur = 0;
- skelett = 0;
- animations = new RCArray< AnimationData >();
- ref = 1;
- }
- // Destruktor
- Model3D::~Model3D()
- {
- if( model )
- model->release();
- if( textur )
- textur->release();
- if( skelett )
- skelett->release();
- animations->release();
- }
- // Fügt eine Animation hinzu
- // a: Die neue Animation
- void Model3D::addAnimation( Animation3D *a, double speed )
- {
- AnimationData *d = new AnimationData();
- d->a = a;
- d->speed = speed;
- d->offset = 0;
- animations->add( d );
- }
- // Entfernt eine Animation
- // zA: Die zu entfernende Animation
- void Model3D::removeAnimation( Animation3D *zA )
- {
- for( int i = 0; i < animations->getEintragAnzahl(); i++ )
- {
- if( animations->z( i )->a == zA )
- {
- animations->remove( i );
- return;
- }
- }
- }
- // Setzt den Zeiger auf das zum Annimieren verwendete Skelett
- // s: Das Skelett, das verwendet werden soll
- void Model3D::setSkelettZ( Skelett *s )
- {
- if( skelett )
- skelett->release();
- skelett = s;
- }
- // Setzt die Daten des Models
- // data: Die Daten
- void Model3D::setModelDaten( Model3DData *data )
- {
- if( model )
- model->release();
- model = data;
- }
- // Setzt die zum Zeichnen zu benutzenden Texturen
- // txt: Ein Liste mit Texturen zu den verschiedenen Polygonen zugeordnet
- void Model3D::setModelTextur( Model3DTextur *txt )
- {
- if( textur )
- textur->release();
- textur = txt;
- }
- // Errechnet die Matrizen aller Knochen des Skeletts des Models
- // viewProj: Die miteinander multiplizierten Kameramatrizen
- // matBuffer: Ein Array mit Matrizen, der gefüllt werden soll
- // return: Die Anzahl der Matrizen, die das Model benötigt
- int Model3D::errechneMatrizen( Mat4< float > &viewProj, Mat4< float > *matBuffer )
- {
- int ret = 0;
- if( skelett )
- ret = skelett->kalkulateMatrix( welt, matBuffer, viewProj );
- else if( model )
- ret = model->kalkulateMatrix( welt, matBuffer, viewProj );
- if( !ret )
- return Zeichnung3D::errechneMatrizen( viewProj, matBuffer );
- return ret;
- }
- // Verarbeitet die vergangene Zeit
- // tickval: Die zeit in sekunden, die seit dem letzten Aufruf der Funktion vergangen ist
- // return: true, wenn sich das Objekt verändert hat, false sonnst.
- bool Model3D::tick( double tickval )
- {
- radius = model ? model->getRadius() : 0;
- if( skelett )
- {
- radius += skelett->getRadius();
- for( auto i = animations->getArray(); i.set && i.var; i++ )
- {
- rend = i.var->speed > 0;
- i.var->a->apply( skelett, i.var->offset, tickval * i.var->speed );
- }
- }
- return Zeichnung3D::tick( tickval );
- }
- // Zeichnet das Model
- // zRObj: Ein Zeiger auf das Objekt, das zum Zeichnen verwendet werden soll (ohne erhöhten Reference Counter)
- void Model3D::render( Render3D *zRObj )
- {
- if( !model )
- return;
- model->aktualisiereVertecies( zRObj );
- #ifdef WIN32
- zRObj->beginnModel( this );
- #endif
- model->render( welt, textur, zRObj );
- }
- // Gibt die Id der Daten zurück, wenn sie in einer Model3DList registriert wurden. (siehe Framework::zM3DRegister())
- int Model3D::getDatenId() const
- {
- return model ? model->getId() : -1;
- }
- // Gibt einen Buffer mit allen Vertecies des Models zurück
- const DXVertexBuffer *Model3D::zVertexBuffer() const
- {
- return model ? model->zVertexBuffer() : 0;
- }
- // Erhöht den Reference Counting Zähler.
- // return: this.
- Model3D *Model3D::getThis()
- {
- ref++;
- return this;
- }
- // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
- // return: 0.
- Model3D *Model3D::release()
- {
- ref--;
- if( !ref )
- delete this;
- return 0;
- }
|