#include "World3D.h" #include "DXBuffer.h" #include "Globals.h" #include "GraphicsApi.h" #include "MouseEvent.h" #include "Model3D.h" #include "Drawing3D.h" using namespace Framework; // Contents of the World3D class from World3D.h // Konstructor World3D::World3D() : Model3DCollection() { members = new RCArray(); pointLightCount = 0; diffuseLightCount = 0; pointLights = 0; diffuseLights = 0; rend = 0; } // Destructor World3D::~World3D() { members->release(); delete[] pointLights; delete[] diffuseLights; } // Blocks access to the object and waits for access if necessary void World3D::lock() { cs.lock(); } // Releases the object for other threads void World3D::unlock() { cs.unlock(); } // Adds an object to the world // obj: The object to be added void World3D::addDrawable(Model3D* obj) { cs.lock(); if (debugDX) { for (auto i : *members) { if (i == obj) throw std::exception(); } } members->add(obj); rend = 1; cs.unlock(); } // Removes an object from the world // obj: The object to be removed void World3D::removeDrawable(Model3D* obj) { cs.lock(); int index = 0; for (Model3D* member : *members) { if (member == obj) { members->remove(index); rend = 1; break; } index++; } cs.unlock(); } //! Adds a collection of objects to the world //! \param collection The collection to be added void World3D::addCollection(Model3DCollection* collection) { cs.lock(); modelCollections.add(collection); rend = 1; cs.unlock(); } //! removes a collection of models from the world //! \param zCollection The collection to be removed void World3D::removeCollection(Model3DCollection* zCollection) { cs.lock(); int index = 0; for (Model3DCollection* collection : modelCollections) { if (collection == zCollection) { modelCollections.remove(index); rend = 1; break; } index++; } cs.unlock(); } // Processes a mouse event // me: The mouse event to be processed void World3D::doMouseEvent(MouseEvent3D& me) { // cs.lock() // int anz = 0; // int index = 0; // for( Drawable3D **i = members; index < arraySize; i++, index++ ) //{ // if( *i ) // { // distSq[ anz ] = me.pos.abstandSq( ( *i )->getPos() ); // alphaVS[ anz ] = *i; // anz++; // } // } // index = 0; // for( Drawable3D **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 ]->doMouseEvent( me ); // if( me.processed ) // { // cs.unlock(); // return; // } // used[ ind ] = 1; // } // } while( ind >= 0 ); // cs.unlock(); } // Processes the elapsed time // tickval: The time in seconds since the last call of the function // return: true if the object has changed, false // otherwise. bool World3D::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; } // Calculates the color of a view ray from a specific point // in a specific direction // point: The origin of the ray, // dir: The direction of the ray // return: The color of the ray int World3D::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; } //! executes a function on every model void Framework::World3D::forAll(std::function f) { for (auto m : *members) f(m); for (auto c : modelCollections) c->forAll(f); } //! executes a tick function on every model bool World3D::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; } //! executes a render function on every model void World3D::render(std::function f) { for (auto m : *members) f(m); for (auto c : modelCollections) c->render(f); } int Framework::World3D::getPointLightCount() const { return pointLightCount; } int Framework::World3D::getDiffuseLightCount() const { return diffuseLightCount; } void Framework::World3D::copyLight(DXBuffer* zDiffuse, DXBuffer* zPoints) const { zDiffuse->setData(diffuseLights); zDiffuse->setLength(diffuseLightCount * (int)sizeof(DiffuseLight)); zDiffuse->copyData(); zPoints->setData(pointLights); zPoints->setLength(pointLightCount * (int)sizeof(PointLight)); zPoints->copyData(); } //! adds a new diffuse light source //! \param light The new light source void Framework::World3D::addDiffuseLight(DiffuseLight light) { DiffuseLight* tmp = new DiffuseLight[diffuseLightCount + 1]; memcpy(tmp, diffuseLights, sizeof(DiffuseLight) * diffuseLightCount); tmp[diffuseLightCount] = light; delete[] diffuseLights; diffuseLights = tmp; diffuseLightCount++; } //! adds a new point light source //! \param light The new light source void Framework::World3D::addPointLight(PointLight light) { PointLight* tmp = new PointLight[pointLightCount + 1]; memcpy(tmp, pointLights, sizeof(PointLight) * pointLightCount); tmp[pointLightCount] = light; delete[] pointLights; pointLights = tmp; pointLightCount++; } //! Returns the reference to a diffuse light source //! \param index The index of the light source DiffuseLight& Framework::World3D::getDiffuseLight(int index) const { return diffuseLights[index]; } //! Returns the reference to a point light source //! \param index The index of the light source PointLight& Framework::World3D::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::World3D::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::World3D::removePointLight(int index) { for (int i = index; i < pointLightCount - 1; i++) { pointLights[i] = pointLights[i + 1]; } pointLightCount--; }