int main( int argc, char** argv ) { double min[2] = { -M_PI, -M_PI }; double max[2] = { +M_PI, +M_PI }; bool periodic[2] = { false, false }; int nx[2] = { 8, 8 }; Mesh* mesh = new Mesh( "mesh", nx, "legendre", 8, min, max, periodic ); Field* field = new Field( "field", mesh, 1, NULL ); Transform* trans = new Transform( field ); mesh->Save(); trans->fMesh->Save(); field->SetICFunc( 0, r0 ); WriteXDMFHeader( 0 ); WriteXDMF( &field, 1, 0, 0.0, 0.0 ); WriteXDMFFooter( 0 ); trans->Interp(); WriteXDMFHeader( 1 ); WriteXDMF( &trans->fField, 1, 1, 0.0, 0.0 ); WriteXDMFFooter( 1 ); field->SetICFunc( 0, r1 ); WriteXDMFHeader( 2 ); WriteXDMF( &field, 1, 2, 0.0, 0.0 ); WriteXDMFFooter( 2 ); trans->Interp(); WriteXDMFHeader( 3 ); WriteXDMF( &trans->fField, 1, 3, 0.0, 0.0 ); WriteXDMFFooter( 3 ); trans->Forward(); WriteXDMFHeader( 4 ); WriteXDMF( &trans->fField, 1, 4, 0.0, 0.0 ); WriteXDMFFooter( 4 ); Filter( trans->fField ); trans->Backward(); WriteXDMFHeader( 5 ); WriteXDMF( &field, 1, 5, 0.0, 0.0 ); WriteXDMFFooter( 5 ); delete mesh; delete field; delete trans; return 1; }
Pollen() noexcept : type((Type)Random<uint32_t>(0u,3u)) { { Lock lock(mxCounter); if ((++counter) == 1) { //create an icosphere of radius 1.0f std::vector<Vec3> spherePositions; { Mesh mesh; auto data(mesh.Sphere({}, 1.0f, YGG_DEBUG_CONDITIONAL(2,4), true).Decompose()); for (auto i : data->Indices) spherePositions.push_back(data->Positions[i]); } //deform a copy of the sphere once for each type for (Type t = Type::Linear; t < Type::Count; t = (Type)((uint32_t)t + 1u)) { uint32_t spikeCount(40); switch (t) { case Type::Linear: spikeCount = 3 * spikeCount / 4; break; case Type::Square: spikeCount = 2 * spikeCount / 3; break; case Type::Circular: spikeCount = spikeCount / 2; break; } //pick equidistant points around unit sphere (see http://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf) std::vector<Vec3> spikes; float a((4.0f * Pi) / (float)spikeCount); float d(sqrtf(a)); uint32_t mTheta(Round<uint32_t>(Pi / d)); float dTheta(Pi / (float)mTheta); float dAlpha(a / dTheta); for (uint32_t m = 0; m < mTheta; ++m) { float theta((Pi*((float)m + 0.5f)) / (float)mTheta); uint32_t mAlpha(Round<uint32_t>((2.0f * Pi * sinf(theta)) / dAlpha)); for (uint32_t n = 0; n < mAlpha; ++n) { float alpha((2.0f * Pi * (float)n) / (float)mAlpha); spikes.emplace_back(sinf(theta) * cosf(alpha), sinf(theta)*sinf(alpha), cos(theta)); } } //minimum distance to consider a spike as being "in range" float rad = d / 2.1f; //loop through the vertices and deform the sphere based //on proximity to nearest spike std::vector<Vec3> positions(spherePositions); for (size_t v = 0; v < positions.size(); ++v) { //find closest spike float dist(Vec3::DistanceSquared(positions[v], spikes[0])); for (size_t s = 1; s < spikes.size(); ++s) dist = std::min(dist, Vec3::DistanceSquared(positions[v], spikes[s])); //convert distance into a proximity function & deform dist = ((rad - sqrtf(dist)) / rad); positions[v] *= metrics.Radius + metrics.Radius * 0.25f * ApplyDeformation(t, dist); } //create static mesh Mesh mesh; meshes.emplace_back(new StaticMesh(mesh.AddPositions(std::move(positions)).GenerateIndices().GenerateNormals())); } } if (Game::Physics()->Started() && !rigidBodyMesh) rigidBodyMesh = Game::Physics()->CreateSphereMesh(metrics.Radius); } entity.reset(Game::Scene()->Create("", this)); auto _position(PickSpawnLocation(true)); transform = entity->Add<Transform>(_position); transform->Forward(Random<Vec3>()); static std::vector<Colour> colours { Yellow, Olive, BlanchedAlmond, YellowGreen }; material.reset(new Phong(Colour(colours[Random<size_t>(0, colours.size() - 1)],0.0f))); entity->Add<MeshRenderer>(meshes[Random<size_t>(0, meshes.size() - 1)], material); if (Game::Physics()->Started()) rigidBody.reset(Game::Physics()->Create(rigidBodyMesh, true, _position, transform->Orientation(), metrics.Density)); entity->Add<Ticker>()->OnTick += [](Ticker* t, float deltaTime) { auto pollen(static_cast<Pollen*>(t->Entity()->Data)); if (Game::Physics()->Started()) pollen->transform->Pose(pollen->rigidBody->Position(), pollen->rigidBody->Orientation()); if (!world.Contains(pollen->transform->Position())) { Vec3 newPos(PickSpawnLocation(false)); pollen->transform->Position(newPos); if (Game::Physics()->Started()) pollen->rigidBody->Position(newPos).Stop(); pollen->spawnTime = 0.0f; } pollen->spawnTime += deltaTime; float alpha(std::min(pollen->spawnTime * 0.33f,1.0f)); if (!spawnBounds.Contains(pollen->transform->Position())) { alpha = std::min(1.0f - Clamp((Vec3::Distance(spawnBounds.Center, pollen->transform->Position()) - spawnBounds.Radius) / (world.Radius - spawnBounds.Radius), 0.0f, 1.0f), alpha); } pollen->material->Colour(Colour(pollen->material->Colour(), alpha)); }; }