123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743 |
- #include "Model3D.h"
- #include "Model2D.h"
- #include "DXBuffer.h"
- #include "Textur.h"
- #include "Animation3D.h"
- #ifdef WIN32
- #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;
- }
- // Destruktor
- Polygon3D::~Polygon3D()
- {
- delete[] indexList;
- }
- // Inhalt der Model3DData Klasse
- // Konstruktor
- Model3DData::Model3DData()
- {
- id = -1;
- skelett = 0;
- vertexList = 0;
- vertexCount = 0;
- polygons = new Array< Polygon3D * >();
- ambientFactor = 1.f;
- diffusFactor = 0.f;
- specularFactor = 0.f;
- radius = 0;
- ref = 1;
- }
- // Destruktor
- Model3DData::~Model3DData()
- {
- clearModel();
- polygons->release();
- }
- // Löscht alle Model daten
- void Model3DData::clearModel()
- {
- delete[] vertexList;
- vertexCount = 0;
- vertexList = 0;
- for( auto i = polygons->getIterator(); i; i++ )
- delete i;
- polygons->leeren();
- if( skelett )
- skelett->release();
- skelett = 0;
- radius = 0;
- }
- // Berechnet die normalen für die Eckpunkte des Modells
- void Model3DData::calculateNormals()
- {
- for( int i = 0; i < vertexCount; i++ )
- {
- Vec3< float > normal( 0, 0, 0 );
- for( auto p = polygons->getIterator(); p; p++ )
- {
- int begin = 0;
- for( int j = 0; j < p->indexAnz; j++ )
- {
- if( j % 3 == 0 )
- begin = j;
- if( p->indexList[ j ] == i )
- {
- Vec3< float > a = vertexList[ p->indexList[ begin ] ].pos;
- Vec3< float > b = vertexList[ p->indexList[ begin + 1 ] ].pos;
- Vec3< float > c = vertexList[ p->indexList[ begin + 2 ] ].pos;
- normal += ( b - a ).crossProduct( c - a ).normalize();
- normal.normalize();
- }
- }
- }
- vertexList[ i ].normal = normal;
- }
- }
- // 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;
- vertexCount = 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 );
- }
- // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird
- // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1)
- void Model3DData::setAmbientFactor( float f )
- {
- ambientFactor = f;
- }
- // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird
- // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1)
- void Model3DData::setDiffusFactor( float f )
- {
- diffusFactor = f;
- }
- // Git den Factor an, mit dem die Reflektion von Lichtquellen multipliziert wird
- // f: der neue Faktor (von 0 bis 1, ambient + specular + diffuse = 1)
- void Model3DData::setSpecularFactor( float f )
- {
- specularFactor = f;
- }
- // 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->getIterator(); i; i++ )
- vAnz += i._.vertex->getEintragAnzahl();
- vertexList = new Vertex3D[ vAnz ];
- int index = 0;
- for( auto i = model->vListen->getIterator(); i; i++ )
- {
- Polygon3D *p = new Polygon3D();
- p->indexAnz = 0;
- for( auto j = i->getIterator(); j; j++ )
- {
- for( auto k = j->zListe()->getIterator(); k.hasNext() && k.next().hasNext(); k++ )
- p->indexAnz += 3;
- }
- p->indexList = new int[ p->indexAnz ];
- p->indexAnz = 0;
- for( auto j = i->getIterator(); j; j++ )
- {
- for( auto k = j->zListe()->getIterator(); k; k++ )
- {
- vertexList[ index ].pos = Vec3< float >( k->punkt->x, k->punkt->y, z );
- vertexList[ index ].tPos = ( Vec2< float > ) * k->textur;
- if( k.hasNext() && k.next().hasNext() )
- {
- 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 );
- }
- // 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 );
- }
- // 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 einen Iterator zurück, mit dem sich die Polygons auflisten lassen
- Iterator< Polygon3D * > Model3DData::getPolygons() const
- {
- return polygons->getIterator();
- }
- // 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;
- }
- // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird
- float Model3DData::getAmbientFactor() const
- {
- return ambientFactor;
- }
- // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird
- float Model3DData::getDiffusFactor() const
- {
- return diffusFactor;
- }
- // Git den Factor an, mit dem die Reflektion von Lichtquellen multipliziert wird
- float Model3DData::getSpecularFactor() const
- {
- return specularFactor;
- }
- // Gibt eine Kopie des Skeletts zurück, welches für annimationen verwendet werden kann
- Skelett *Model3DData::copySkelett() const
- {
- return skelett ? skelett->kopiereSkelett() : 0;
- }
- // Gibt die Anzahl an Vertices zurück
- int Model3DData::getVertexAnzahl() const
- {
- return vertexCount;
- }
- // Gibt einen Buffer mit allen Vertecies des Models zurück
- const Vertex3D *Model3DData::zVertexBuffer() const
- {
- return vertexList;
- }
- // 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 >();
- }
- // 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 die Daten des Models
- // data: Die Daten
- void Model3D::setModelDaten( Model3DData * data )
- {
- if( model )
- model->release();
- if( skelett )
- skelett = skelett->release();
- model = data;
- skelett = model->copySkelett();
- }
- // 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->getIterator(); i && i._; i++ )
- {
- rend = i->speed > 0;
- i->a->apply( skelett, i->offset, tickval * i->speed );
- }
- }
- return Zeichnung3D::tick( tickval );
- }
- // Gibt die Textur zurück
- Model3DTextur *Model3D::getTextur()
- {
- return textur ? textur->getThis() : 0;
- }
- // Gibt die Textur zurück (ohne erhöhten Reference Counter)
- Model3DTextur *Model3D::zTextur()
- {
- return textur;
- }
- // Gibt die ModelDaten zurück
- Model3DData *Model3D::getModelData()
- {
- return model ? model->getThis() : 0;
- }
- // Gibt die ModelDaten zurück (ohne erhöhten Reference Counter)
- Model3DData *Model3D::zModelData()
- {
- return model;
- }
- // 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;
- }
- // Git den Factor an, mit dem das umgebungslicht (textur farbe) multipliziert wird
- float Model3D::getAmbientFactor() const
- {
- return model ? model->getAmbientFactor() : 0.f;
- }
- // Git den Factor an, mit dem die Lichtfarbe von Lichtquellen multipliziert wird
- float Model3D::getDiffusFactor() const
- {
- return model ? model->getDiffusFactor() : 0.f;
- }
- // Git den Factor an, mit dem die Reflektion von Lichtquellen multipliziert wird
- float Model3D::getSpecularFactor() const
- {
- return model ? model->getSpecularFactor() : 0.f;
- }
- // Gibt die Anzahl an Vertices zurück
- int Model3D::getVertexAnzahl() const
- {
- return model ? model->getVertexAnzahl() : 0;
- }
- // Gibt einen Buffer mit allen Vertecies des Models zurück
- const Vertex3D *Model3D::zVertexBuffer() const
- {
- return model ? model->zVertexBuffer() : 0;
- }
|