#include "Welt3D.h" #include "Zeichnung3D.h" #include "MausEreignis.h" #include "Model3D.h" #include "GraphicsApi.h" #include "DXBuffer.h" #include "Globals.h" using namespace Framework; Welt3DIterator::Welt3DIterator( Welt3D* zWelt ) : ReferenceCounter(), modelIterator( zWelt->members->begin() ), collectionIterator( zWelt->modelCollections.begin() ) { this->zWelt = zWelt; currentCollectionIterator = collectionIterator.hasNext() ? collectionIterator.next()->getIterator() : 0; nextModel = 0; calculateNext(); } Welt3DIterator::~Welt3DIterator() { if( currentCollectionIterator ) currentCollectionIterator->release(); this->zWelt->unlock(); } void Welt3DIterator::calculateNext() { if( modelIterator ) { nextModel = modelIterator; ++modelIterator; } else if( currentCollectionIterator && currentCollectionIterator->hasNext() ) { nextModel = currentCollectionIterator->getNext(); } else { nextModel = 0; while( collectionIterator.hasNext() && !nextModel ) { if( currentCollectionIterator ) currentCollectionIterator->release(); currentCollectionIterator = collectionIterator.next()->getIterator(); if( currentCollectionIterator->hasNext() ) nextModel = currentCollectionIterator->getNext(); } } } Model3D* Welt3DIterator::getNext() { Model3D* tmp = nextModel; if( nextModel ) calculateNext(); return tmp; } bool Welt3DIterator::hasNext() { return nextModel != 0; } // Inhalt der Welt3D Klasse aus Welt3D.h // Konstructor Welt3D::Welt3D() : ReferenceCounter() { members = new RCArray< Model3D >(); pointLightCount = 0; diffuseLightCount = 0; pointLights = 0; diffuseLights = 0; rend = 0; } // Destruktor Welt3D::~Welt3D() { members->release(); delete[] pointLights; delete[] diffuseLights; } // Blockiert den zugriff auf das Objekt und wartet gegebenfalls auf den Zugriff void Welt3D::lock() { cs.lock(); } // Gibt das Objekt für andere Threads frei void Welt3D::unlock() { cs.unlock(); } // Fügt der Welt ein Objekt hinzu // obj: Das Objekt, was hinzugefügt werden soll void Welt3D::addZeichnung( Model3D* obj ) { cs.lock(); if( debugDX ) { for( auto i : *members ) { if( i == obj ) throw std::exception(); } } members->add( obj ); rend = 1; cs.unlock(); } // Entfernt ein Objekt aus der Welt // obj: Das Objekt, das entwernt werden soll void Welt3D::removeZeichnung( Model3D* obj ) { cs.lock(); int index = 0; for( Model3D* member : *members ) { if( member == obj ) { members->remove( index ); rend = 1; break; } index++; } cs.unlock(); } //! Fügt der Welt eine Collection von Objekten hinzu //! \param collection Die Collection, die hinzugefügt werden soll void Welt3D::addCollection( Model3DCollection* collection ) { cs.lock(); modelCollections.add( collection ); rend = 1; cs.unlock(); } //! removes a collection of models from the world //! \param zCollection Die Collection die entfernt werden soll void Welt3D::removeCollection( Model3DCollection* zCollection ) { cs.lock(); int index = 0; for( Model3DCollection* collection : modelCollections ) { if( collection == zCollection ) { modelCollections.remove( index ); rend = 1; break; } index++; } cs.unlock(); } // Verarbeitet ein Mausereignis // me: Das Mausereignis, das verarbeitet werden soll void Welt3D::doMausEreignis( MausEreignis3D& me ) { //cs.lock() //int anz = 0; //int index = 0; //for( Zeichnung3D **i = members; index < arraySize; i++, index++ ) //{ // if( *i ) // { // distSq[ anz ] = me.pos.abstandSq( ( *i )->getPos() ); // alphaVS[ anz ] = *i; // anz++; // } //} //index = 0; //for( Zeichnung3D **i = membersAlpha; index < arraySizeAlpha; i++, index++ ) //{ // if( *i ) // { // distSq[ anz ] = me.pos.abstandSq( ( *i )->getPos() ); // alphaVS[ anz ] = *i; // anz++; // } //} //float maxEntf; //int ind; //do //{ // maxEntf = -1; // ind = -1; // for( int i = 0; i < anz; i++ ) // { // if( !used[ i ] && distSq[ i ] > maxEntf ) // { // maxEntf = distSq[ i ]; // ind = i; // } // } // if( ind >= 0 ) // { // alphaVS[ ind ]->doMausEreignis( me ); // if( me.verarbeitet ) // { // cs.unlock(); // return; // } // used[ ind ] = 1; // } //} while( ind >= 0 ); //cs.unlock(); } // 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 Welt3D::tick( double tickval ) { cs.lock(); for( auto m : *members ) rend |= m->tick( tickval ); cs.unlock(); bool tmp = rend; rend = 0; return tmp; } // brerechnet die Farbe eines Sichtstrahls, der von einem bestimmten punkt aus in eine bestimmte richtung schaut // point: Der ursprung des Strahls, // dir: Die Richtung des Strahls // return: Die Farbe des Strahls int Welt3D::traceRay( Vec3< float >& point, Vec3< float >& dir ) { float min = INFINITY; int minId = -1; int index = 0; int pId = 0; for( auto m : *members ) { float tmp = m->traceRay( point, dir, min, pId ); if( min > tmp && tmp >= 0 ) { min = tmp; minId = index; } index++; } if( minId >= 0 ) return members->z( minId )->traceRay( point, dir, pId, this ); return 0xFF000000; } // Gibt einen Iterator zurück, mit dem alle Members aufgezählt werden können Model3DIterator* Welt3D::getIterator() { lock(); return new Welt3DIterator( this ); } int Framework::Welt3D::getPointLightCount() const { return pointLightCount; } int Framework::Welt3D::getDiffuseLightCount() const { return diffuseLightCount; } void Framework::Welt3D::copyLight( DXBuffer* zDiffuse, DXBuffer* zPoints ) const { zDiffuse->setData( diffuseLights ); zDiffuse->setLength( diffuseLightCount * (int)sizeof( DiffuseLight ) ); zDiffuse->copieren(); zPoints->setData( pointLights ); zPoints->setLength( pointLightCount * (int)sizeof( PointLight ) ); zPoints->copieren(); } //! fügt eine neue diffuse lichtquelle hinzu //! \param light Die neue Lichtquelle void Framework::Welt3D::addDiffuseLight( DiffuseLight light ) { DiffuseLight* tmp = new DiffuseLight[ diffuseLightCount + 1 ]; memcpy( tmp, diffuseLights, sizeof( DiffuseLight ) * diffuseLightCount ); tmp[ diffuseLightCount ] = light; delete[] diffuseLights; diffuseLights = tmp; diffuseLightCount++; } //! fügt eine neue Punkt lichtquelle hinzu //! \param light Die neue Lichtquelle void Framework::Welt3D::addPointLight( PointLight light ) { PointLight* tmp = new PointLight[ pointLightCount + 1 ]; memcpy( tmp, pointLights, sizeof( PointLight ) * pointLightCount ); tmp[ pointLightCount ] = light; delete[] pointLights; pointLights = tmp; pointLightCount++; } //! Gibt die Referenz auf eine Diffuse Lichtquelle zurück //! \param index Der Index der Lichtquelle DiffuseLight& Framework::Welt3D::getDiffuseLight( int index ) const { return diffuseLights[ index ]; } //! Gibt die Referenz auf eine Punkt Lichtquelle zurück //! \param index Der Index der Lichtquelle PointLight& Framework::Welt3D::getPointLight( int index ) const { return pointLights[ index ]; }