#include "Welt3D.h" #include "DXBuffer.h" #include "Globals.h" #include "GraphicsApi.h" #include "MausEreignis.h" #include "Model3D.h" #include "Zeichnung3D.h" using namespace Framework; // Inhalt der Welt3D Klasse aus Welt3D.h // Konstructor Welt3D::Welt3D() : Model3DCollection() { members = new RCArray(); 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(); rend |= tick( [this, &tickval](Model3D* m) { rend |= m->tick(tickval); }, 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& point, Vec3& dir) { float min = INFINITY; int pId = 0; Model3D* nearest = 0; forAll([this, &point, &dir, &pId, &min, &nearest](Model3D* m) { float tmp = m->traceRay(point, dir, min, pId); if (min > tmp && tmp >= 0) { min = tmp; nearest = m; } }); if (nearest) return nearest->traceRay(point, dir, pId, this); return 0xFF000000; } //! führt eine funktion auf jedem Model aus void Framework::Welt3D::forAll(std::function f) { for (auto m : *members) f(m); for (auto c : modelCollections) c->forAll(f); } //! führt eine tick funktion auf jedem Model aus bool Welt3D::tick(std::function f, double time) { for (auto m : *members) f(m); bool res = 0; for (auto c : modelCollections) res |= c->tick(f, time); return res; } //! führt eine render funktion auf jedem Model aus void Welt3D::render(std::function f) { for (auto m : *members) f(m); for (auto c : modelCollections) c->render(f); } 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]; } //! removes a specific fiffuse light from the world //! \param index the index of the light DLLEXPORT void Framework::Welt3D::removeDiffuseLight(int index) { for (int i = index; i < diffuseLightCount - 1; i++) { diffuseLights[i] = diffuseLights[i + 1]; } diffuseLightCount--; } //! removes a specific point light from the world //! \param index the index of the light DLLEXPORT void Framework::Welt3D::removePointLight(int index) { for (int i = index; i < pointLightCount - 1; i++) { pointLights[i] = pointLights[i + 1]; } pointLightCount--; }