std::vector<entity_id_t> EntitySelection::PickEntitiesInRect(CSimulation2& simulation, const CCamera& camera, int sx0, int sy0, int sx1, int sy1, player_id_t owner, bool allowEditorSelectables) { PROFILE2("PickEntitiesInRect"); // Make sure sx0 <= sx1, and sy0 <= sy1 if (sx0 > sx1) std::swap(sx0, sx1); if (sy0 > sy1) std::swap(sy0, sy1); CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY); ENSURE(cmpRangeManager); std::vector<entity_id_t> hitEnts; const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable); for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it) { entity_id_t ent = it->first; CEntityHandle handle = it->second->GetEntityHandle(); // Check if this entity is only selectable in Atlas if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !allowEditorSelectables) continue; // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN) continue; // Ignore entities not owned by 'owner' CmpPtr<ICmpOwnership> cmpOwnership(handle); if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner)) continue; // Find the current interpolated model position. // (We just use the centre position and not the whole bounding box, because maybe // that's better for users trying to select objects in busy areas) CmpPtr<ICmpVisual> cmpVisual(handle); if (!cmpVisual) continue; CVector3D position = cmpVisual->GetPosition(); // Reject if it's not on-screen (e.g. it's behind the camera) if (!camera.GetFrustum().IsPointVisible(position)) continue; // Compare screen-space coordinates float x, y; camera.GetScreenCoordinates(position, x, y); int ix = (int)x; int iy = (int)y; if (sx0 <= ix && ix <= sx1 && sy0 <= iy && iy <= sy1) hitEnts.push_back(ent); } return hitEnts; }
void CThreadDebugger::ExecuteHook(JSContext* UNUSED(cx), const char* UNUSED(filename), unsigned UNUSED(lineno), JSScript* UNUSED(script), JSFunction* UNUSED(fun), void* UNUSED(callerdata)) { // Search all breakpoints that have no trap set yet { PROFILE2("ExecuteHook"); SetAllNewTraps(); } return; }
void CComponentManager::FlushDestroyedComponents() { PROFILE2("Flush Destroyed Components"); while (!m_DestructionQueue.empty()) { // Make a copy of the destruction queue, so that the iterators won't be invalidated if the // CMessageDestroy handlers try to destroy more entities themselves std::vector<entity_id_t> queue; queue.swap(m_DestructionQueue); // Flatten all the dynamic subscriptions to ensure there are no dangling // references in the 'removed' lists to components we're going to delete FlattenDynamicSubscriptions(); for (std::vector<entity_id_t>::iterator it = queue.begin(); it != queue.end(); ++it) { entity_id_t ent = *it; CEntityHandle handle = LookupEntityHandle(ent); CMessageDestroy msg(ent); PostMessage(ent, msg); // Destroy the components, and remove from m_ComponentsByTypeId: std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::iterator iit = m_ComponentsByTypeId.begin(); for (; iit != m_ComponentsByTypeId.end(); ++iit) { std::map<entity_id_t, IComponent*>::iterator eit = iit->second.find(ent); if (eit != iit->second.end()) { eit->second->Deinit(); RemoveComponentDynamicSubscriptions(eit->second); m_ComponentTypesById[iit->first].dealloc(eit->second); iit->second.erase(ent); handle.GetComponentCache()->interfaces[m_ComponentTypesById[iit->first].iid] = NULL; } } free(handle.GetComponentCache()); m_ComponentCaches.erase(ent); // Remove from m_ComponentsByInterface std::vector<boost::unordered_map<entity_id_t, IComponent*> >::iterator ifcit = m_ComponentsByInterface.begin(); for (; ifcit != m_ComponentsByInterface.end(); ++ifcit) { ifcit->erase(ent); } } } }
// dispatch all pending events to the various receivers. static void PumpEvents() { PROFILE3("dispatch events"); SDL_Event_ ev; while (SDL_PollEvent(&ev.ev)) { PROFILE2("event"); if (g_GUI) { std::string data = g_GUI->GetScriptInterface().StringifyJSON( ScriptInterface::ToJSVal(g_GUI->GetScriptInterface().GetContext(), ev)); PROFILE2_ATTR("%s", data.c_str()); } in_dispatch_event(&ev); } g_TouchInput.Frame(); }
// dispatch all pending events to the various receivers. static void PumpEvents() { PROFILE3("dispatch events"); SDL_Event_ ev; while (in_poll_event(&ev)) { PROFILE2("event"); if (g_GUI) { JS::Value tmpVal; ScriptInterface::ToJSVal(g_GUI->GetScriptInterface()->GetContext(), tmpVal, ev); std::string data = g_GUI->GetScriptInterface()->StringifyJSON(tmpVal); PROFILE2_ATTR("%s", data.c_str()); } in_dispatch_event(&ev); } g_TouchInput.Frame(); }
void FrameStart() { ProcessFrames(); SFrame frame; frame.num = m_Profiler.GetFrameNumber(); // On (at least) some NVIDIA Windows drivers, when GPU-bound, or when // vsync enabled and not CPU-bound, the first glGet* call at the start // of a frame appears to trigger a wait (to stop the GPU getting too // far behind, or to wait for the vsync period). // That will be this GL_TIMESTAMP get, which potentially distorts the // reported results. So we'll only do it fairly rarely, and for most // frames we'll just assume the clocks don't drift much const double RESYNC_PERIOD = 1.0; // seconds double now = m_Profiler.GetTime(); if (m_Frames.empty() || now > m_Frames.back().syncTimeStart + RESYNC_PERIOD) { PROFILE2("profile timestamp resync"); pglGetInteger64v(GL_TIMESTAMP, &frame.syncTimestampStart); ogl_WarnIfError(); frame.syncTimeStart = m_Profiler.GetTime(); // (Have to do GetTime again after GL_TIMESTAMP, because GL_TIMESTAMP // might wait a while before returning its now-current timestamp) } else { // Reuse the previous frame's sync data frame.syncTimeStart = m_Frames[m_Frames.size()-1].syncTimeStart; frame.syncTimestampStart = m_Frames[m_Frames.size()-1].syncTimestampStart; } m_Frames.push_back(frame); RegionEnter("frame"); }
Go::SplineSurface* ASMs2D::projectSolution (const IntegrandBase& integrnd) const { PROFILE2("ASMs2D::projectSolution"); const int basis = 1; // Compute parameter values of the result sampling points (Greville points) std::array<RealArray,2> gpar; for (int dir = 0; dir < 2; dir++) if (!this->getGrevilleParameters(gpar[dir],dir,basis)) return nullptr; // Evaluate the secondary solution at all sampling points Matrix sValues; if (!this->evalSolution(sValues,integrnd,gpar.data()) || sValues.rows() == 0) return nullptr; const Go::SplineSurface* psurf = this->getBasis(basis); // Project the results onto the spline basis to find control point // values based on the result values evaluated at the Greville points. // Note that we here implicitly assume that the number of Greville points // equals the number of control points such that we don't have to resize // the result array. Think that is always the case, but beware if trying // other projection schemes later. RealArray weights; if (psurf->rational()) psurf->getWeights(weights); const Vector& vec = sValues; return Go::SurfaceInterpolator::regularInterpolation(psurf->basis(0), psurf->basis(1), gpar[0], gpar[1], const_cast<Vector&>(vec), sValues.rows(), psurf->rational(), weights); }
LR::LRSplineSurface* ASMu2D::projectSolution (const IntegrandBase& integr) const { PROFILE2("ASMu2D::projectSolution"); // Compute parameter values of the result sampling points (Greville points) std::array<RealArray,2> gpar; for (int dir = 0; dir < 2; dir++) if (!this->getGrevilleParameters(gpar[dir],dir)) return nullptr; // Evaluate the secondary solution at all sampling points Matrix sValues; if (!this->evalSolution(sValues,integr,gpar.data())) return nullptr; // Project the results onto the spline basis to find control point // values based on the result values evaluated at the Greville points. // Note that we here implicitly assume that the number of Greville points // equals the number of control points such that we don't have to resize // the result array. Think that is always the case, but beware if trying // other projection schemes later. return this->regularInterpolation(gpar[0],gpar[1],sValues); }
static void Frame() { g_Profiler2.RecordFrameStart(); PROFILE2("frame"); g_Profiler2.IncrementFrameNumber(); PROFILE2_ATTR("%d", g_Profiler2.GetFrameNumber()); ogl_WarnIfError(); // get elapsed time const double time = timer_Time(); g_frequencyFilter->Update(time); // .. old method - "exact" but contains jumps #if 0 static double last_time; const double time = timer_Time(); const float TimeSinceLastFrame = (float)(time-last_time); last_time = time; ONCE(return); // first call: set last_time and return // .. new method - filtered and more smooth, but errors may accumulate #else const float realTimeSinceLastFrame = 1.0 / g_frequencyFilter->SmoothedFrequency(); #endif ENSURE(realTimeSinceLastFrame > 0.0f); // decide if update/render is necessary bool need_render = !g_app_minimized; bool need_update = true; // If we are not running a multiplayer game, disable updates when the game is // minimized or out of focus and relinquish the CPU a bit, in order to make // debugging easier. if(g_PauseOnFocusLoss && !g_NetClient && !g_app_has_focus) { PROFILE3("non-focus delay"); need_update = false; // don't use SDL_WaitEvent: don't want the main loop to freeze until app focus is restored SDL_Delay(10); } // TODO: throttling: limit update and render frequency to the minimum. // this is mostly relevant for "inactive" state, so that other windows // get enough CPU time, but it's always nice for power+thermal management. // this scans for changed files/directories and reloads them, thus // allowing hotloading (changes are immediately assimilated in-game). ReloadChangedFiles(); ProgressiveLoad(); RendererIncrementalLoad(); PumpEvents(); // if the user quit by closing the window, the GL context will be broken and // may crash when we call Render() on some drivers, so leave this loop // before rendering if (quit) return; // respond to pumped resize events if (g_ResizedW || g_ResizedH) { g_VideoMode.ResizeWindow(g_ResizedW, g_ResizedH); g_ResizedW = g_ResizedH = 0; } if (g_NetClient) g_NetClient->Poll(); ogl_WarnIfError(); g_GUI->TickObjects(); ogl_WarnIfError(); if (g_Game && g_Game->IsGameStarted() && need_update) { g_Game->Update(realTimeSinceLastFrame); g_Game->GetView()->Update(float(realTimeSinceLastFrame)); } // Immediately flush any messages produced by simulation code if (g_NetClient) g_NetClient->Flush(); g_UserReporter.Update(); g_Console->Update(realTimeSinceLastFrame); ogl_WarnIfError(); if(need_render) { Render(); PROFILE3("swap buffers"); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_GL_SwapWindow(g_VideoMode.GetWindow()); #else SDL_GL_SwapBuffers(); #endif } ogl_WarnIfError(); g_Profiler.Frame(); g_GameRestarted = false; }
Go::SplineSurface* ASMs2D::scRecovery (const IntegrandBase& integrand) const { PROFILE2("ASMs2D::scRecovery"); const int m = integrand.derivativeOrder(); const int p1 = surf->order_u(); const int p2 = surf->order_v(); const int nel1 = surf->numCoefs_u() - p1 + 1; // Get Gaussian quadrature point coordinates const int ng1 = p1 - m; const int ng2 = p2 - m; const double* xg = GaussQuadrature::getCoord(ng1); const double* yg = GaussQuadrature::getCoord(ng2); if (!xg || !yg) return nullptr; // Compute parameter values of the Gauss points over the whole patch std::array<Matrix,2> gaussPt; std::array<RealArray,2> gpar; gpar[0] = this->getGaussPointParameters(gaussPt[0],0,ng1,xg); gpar[1] = this->getGaussPointParameters(gaussPt[1],1,ng2,yg); #if SP_DEBUG > 2 for (size_t j = 0; j < gpar[1].size(); j++) for (size_t i = 0; i < gpar[0].size(); i++) std::cout <<"Gauss point "<< i <<","<< j <<" = " << gpar[0][i] <<" "<< gpar[1][j] << std::endl; #endif // Evaluate the secondary solution at all Gauss points Matrix sField; if (!this->evalSolution(sField,integrand,gpar.data())) return nullptr; // Compute parameter values of the Greville points if (!this->getGrevilleParameters(gpar[0],0)) return nullptr; if (!this->getGrevilleParameters(gpar[1],1)) return nullptr; const int n1 = p1 - m + 1; // Patch size in first parameter direction const int n2 = p2 - m + 1; // Patch size in second parameter direction const size_t nCmp = sField.rows(); // Number of result components const size_t nPol = (n1+1)*(n2+1); // Number of terms in polynomial expansion Matrix sValues(nCmp,gpar[0].size()*gpar[1].size()); Vector P(nPol); Go::Point X, G; // Loop over all Greville points int istart, jstart = 0; size_t ig, jg, k, l, ip = 1; for (jg = 0; jg < gpar[1].size(); jg++) for (ig = 0; ig < gpar[0].size(); ig++, ip++) { // Special case for the first and last Greville points in each direction if (ig == 0) istart = 1; else if (ig < gpar[0].size()-1) istart = ig; if (jg == 0) jstart = 1; else if (jg < gpar[1].size()-1) jstart = jg; // Physical coordinates of current Greville point surf->point(G,gpar[0][ig],gpar[1][jg]); #if SP_DEBUG > 1 std::cout <<"\nGreville point "<< ig <<","<< jg <<" (u,v) = " << gpar[0][ig] <<" "<< gpar[1][jg] <<" X = "<< G << std::endl; #endif // Set up the local projection matrices DenseMatrix A(nPol,nPol,true); Matrix B(nPol,nCmp); // Loop over all non-zero knot-spans in the support of // the basis function associated with current Greville point for (int js = jstart; js < jstart+n2; js++) if (js >= p2-1 && surf->knotSpan(1,js) > 0.0) for (int is = istart; is < istart+n1; is++) if (is >= p1-1 && surf->knotSpan(0,is) > 0.0) { // Loop over the Gauss points in current knot-span int jp = ((js-p2+1)*ng1*nel1 + is-p1+1)*ng2 + 1; for (int j = 1; j <= ng2; j++, jp += ng1*(nel1-1)) for (int i = 1; i <= ng1; i++, jp++) { // Fetch parameter values of current integration point double u = gaussPt[0](i,is-p1+2); double v = gaussPt[1](j,js-p2+2); // Evaluate the polynomial expansion at current Gauss point surf->point(X,u,v); evalMonomials(n1+1,n2+1,X[0]-G[0],X[1]-G[1],P); #if SP_DEBUG > 1 std::cout <<"Itg. point "<< i <<","<< j <<" (u,v) = " << u <<" "<< v <<" X = "<< X <<" P-matrix:"<< P; #endif for (k = 1; k <= nPol; k++) { // Accumulate the projection matrix, A += P^t * P for (l = k; l <= nPol; l++) // do the upper triangle only A(k,l) += P(k)*P(l); // Accumulate the right-hand-side matrix, B += P^t * sigma for (l = 1; l <= nCmp; l++) B(k,l) += P(k)*sField(l,jp); } } } #if SP_DEBUG > 2 std::cout <<"---- Matrix A -----"<< A <<"-------------------"<< std::endl; std::cout <<"---- Vector B -----"<< B <<"-------------------"<< std::endl; #endif // Solve the local equation system if (!A.solve(B)) return nullptr; // Evaluate the projected field at current Greville point (first row of B) for (l = 1; l <= nCmp; l++) sValues(l,ip) = B(1,l); #if SP_DEBUG > 1 std::cout <<"Greville point "<< ig <<","<< jg <<" :"; for (k = 1; k <= nCmp; k++) std::cout <<" "<< sValues(k,ip); std::cout << std::endl; #endif } // Project the Greville point results onto the spline basis // to find the control point values RealArray weights; if (surf->rational()) surf->getWeights(weights); const Vector& vec = sValues; return Go::SurfaceInterpolator::regularInterpolation(surf->basis(0), surf->basis(1), gpar[0], gpar[1], const_cast<Vector&>(vec), nCmp, surf->rational(), weights); }
bool ProcessReport() { PROFILE2("process report"); shared_ptr<CUserReport> report; { CScopeLock lock(m_WorkerMutex); if (m_ReportQueue.empty()) return false; report = m_ReportQueue.front(); m_ReportQueue.pop_front(); } ConstructRequestData(*report); m_RequestDataOffset = 0; m_ResponseData.clear(); curl_easy_setopt(m_Curl, CURLOPT_POSTFIELDSIZE_LARGE, (curl_off_t)m_RequestData.size()); SetStatus("connecting"); #if DEBUG_UPLOADS TIMER(L"CUserReporterWorker request"); #endif CURLcode err = curl_easy_perform(m_Curl); #if DEBUG_UPLOADS printf(">>>\n%s\n<<<\n", m_ResponseData.c_str()); #endif if (err == CURLE_OK) { long code = -1; curl_easy_getinfo(m_Curl, CURLINFO_RESPONSE_CODE, &code); SetStatus("completed:" + CStr::FromInt(code)); // Check for success code if (code == 200) return true; // If the server returns the 410 Gone status, interpret that as meaning // it no longer supports uploads (at least from this version of the game), // so shut down and stop talking to it (to avoid wasting bandwidth) if (code == 410) { CScopeLock lock(m_WorkerMutex); m_Shutdown = true; return false; } } else { SetStatus("failed:" + CStr::FromInt(err) + ":" + m_ErrorBuffer); } // We got an unhandled return code or a connection failure; // push this report back onto the queue and try again after // a long interval { CScopeLock lock(m_WorkerMutex); m_ReportQueue.push_front(report); } m_PauseUntilTime = timer_Time() + RECONNECT_INVERVAL; return false; }
void Run() { // Set libcurl's proxy configuration // (This has to be done in the thread because it's potentially very slow) SetStatus("proxy"); std::wstring proxy; { PROFILE2("get proxy config"); if (sys_get_proxy_config(wstring_from_utf8(m_URL), proxy) == INFO::OK) curl_easy_setopt(m_Curl, CURLOPT_PROXY, utf8_from_wstring(proxy).c_str()); } SetStatus("waiting"); /* * We use a semaphore to let the thread be woken up when it has * work to do. Various actions from the main thread can wake it: * * SetEnabled() * * Shutdown() * * Submit() * * Retransmission timeouts, once every several seconds * * If multiple actions have triggered wakeups, we might respond to * all of those actions after the first wakeup, which is okay (we'll do * nothing during the subsequent wakeups). We should never hang due to * processing fewer actions than wakeups. * * Retransmission timeouts are triggered via the main thread - we can't simply * use SDL_SemWaitTimeout because on Linux it's implemented as an inefficient * busy-wait loop, and we can't use a manual busy-wait with a long delay time * because we'd lose responsiveness. So the main thread pings the worker * occasionally so it can check its timer. */ // Wait until the main thread wakes us up while (true) { g_Profiler2.RecordRegionEnter("semaphore wait"); ENSURE(SDL_SemWait(m_WorkerSem) == 0); g_Profiler2.RecordRegionLeave(); // Handle shutdown requests as soon as possible if (GetShutdown()) return; // If we're not enabled, ignore this wakeup if (!GetEnabled()) continue; // If we're still pausing due to a failed connection, // go back to sleep again if (timer_Time() < m_PauseUntilTime) continue; // We're enabled, so process as many reports as possible while (ProcessReport()) { // Handle shutdowns while we were sending the report if (GetShutdown()) return; } } }
static void Frame() { g_Profiler2.RecordFrameStart(); PROFILE2("frame"); g_Profiler2.IncrementFrameNumber(); PROFILE2_ATTR("%d", g_Profiler2.GetFrameNumber()); ogl_WarnIfError(); // get elapsed time const double time = timer_Time(); g_frequencyFilter->Update(time); // .. old method - "exact" but contains jumps #if 0 static double last_time; const double time = timer_Time(); const float TimeSinceLastFrame = (float)(time-last_time); last_time = time; ONCE(return); // first call: set last_time and return // .. new method - filtered and more smooth, but errors may accumulate #else const float TimeSinceLastFrame = 1.0 / g_frequencyFilter->SmoothedFrequency(); #endif ENSURE(TimeSinceLastFrame > 0.0f); // decide if update/render is necessary bool need_render = !g_app_minimized; bool need_update = true; // If we are not running a multiplayer game, disable updates when the game is // minimized or out of focus and relinquish the CPU a bit, in order to make // debugging easier. if( g_PauseOnFocusLoss && !g_NetClient && !g_app_has_focus ) { PROFILE3("non-focus delay"); need_update = false; // don't use SDL_WaitEvent: don't want the main loop to freeze until app focus is restored SDL_Delay(10); } // TODO: throttling: limit update and render frequency to the minimum. // this is mostly relevant for "inactive" state, so that other windows // get enough CPU time, but it's always nice for power+thermal management. bool is_building_archive = ProgressiveBuildArchive(); // this scans for changed files/directories and reloads them, thus // allowing hotloading (changes are immediately assimilated in-game). // must not be done during archive building because it changes the // archive file each iteration, but keeps it locked; reloading // would trigger a warning because the file can't be opened. if(!is_building_archive) ReloadChangedFiles(); ProgressiveLoad(); RendererIncrementalLoad(); PumpEvents(); // if the user quit by closing the window, the GL context will be broken and // may crash when we call Render() on some drivers, so leave this loop // before rendering if (quit) return; // respond to pumped resize events if (g_ResizedW || g_ResizedH) { g_VideoMode.ResizeWindow(g_ResizedW, g_ResizedH); g_ResizedW = g_ResizedH = 0; } if (g_NetClient) g_NetClient->Poll(); ogl_WarnIfError(); g_GUI->TickObjects(); ogl_WarnIfError(); if (g_Game && g_Game->IsGameStarted() && need_update) { g_Game->Update(TimeSinceLastFrame); g_Game->GetView()->Update(float(TimeSinceLastFrame)); CCamera* camera = g_Game->GetView()->GetCamera(); CMatrix3D& orientation = camera->m_Orientation; float* pos = &orientation._data[12]; float* dir = &orientation._data[8]; float* up = &orientation._data[4]; // HACK: otherwise sound effects are L/R flipped. No idea what else // is going wrong, because the listener and camera are supposed to // coincide in position and orientation. float down[3] = { -up[0], -up[1], -up[2] }; { PROFILE3("sound update"); if (snd_update(pos, dir, down) < 0) debug_printf(L"snd_update failed\n"); } } else { PROFILE3("sound update (0)"); if (snd_update(0, 0, 0) < 0) debug_printf(L"snd_update (pos=0 version) failed\n"); } // Immediately flush any messages produced by simulation code if (g_NetClient) g_NetClient->Flush(); g_UserReporter.Update(); g_Console->Update(TimeSinceLastFrame); ogl_WarnIfError(); if(need_render) { Render(); PROFILE3("swap buffers"); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_GL_SwapWindow(g_VideoMode.GetWindow()); #else SDL_GL_SwapBuffers(); #endif } ogl_WarnIfError(); g_Profiler.Frame(); g_GameRestarted = false; }
bool ASMs3Dmx::integrate (Integrand& integrand, int lIndex, GlobalIntegral& glInt, const TimeDomain& time) { if (!svol) return true; // silently ignore empty patches if (m_basis.empty()) return false; PROFILE2("ASMs3Dmx::integrate(B)"); bool useElmVtx = integrand.getIntegrandType() & Integrand::ELEMENT_CORNERS; std::map<char,ThreadGroups>::const_iterator tit; if ((tit = threadGroupsFace.find(lIndex)) == threadGroupsFace.end()) { std::cerr <<" *** ASMs3D::integrate: No thread groups for face "<< lIndex << std::endl; return false; } const ThreadGroups& threadGrp = tit->second; // Get Gaussian quadrature points and weights const double* xg = GaussQuadrature::getCoord(nGauss); const double* wg = GaussQuadrature::getWeight(nGauss); if (!xg || !wg) return false; // Find the parametric direction of the face normal {-3,-2,-1, 1, 2, 3} const int faceDir = (lIndex+1)/(lIndex%2 ? -2 : 2); const int t1 = 1 + abs(faceDir)%3; // first tangent direction const int t2 = 1 + t1%3; // second tangent direction // Compute parameter values of the Gauss points over the whole patch face std::array<Matrix,3> gpar; for (int d = 0; d < 3; d++) if (-1-d == faceDir) { gpar[d].resize(1,1); gpar[d].fill(svol->startparam(d)); } else if (1+d == faceDir) { gpar[d].resize(1,1); gpar[d].fill(svol->endparam(d)); } else this->getGaussPointParameters(gpar[d],d,nGauss,xg); // Evaluate basis function derivatives at all integration points std::vector<std::vector<Go::BasisDerivs>> splinex(m_basis.size()); #pragma omp parallel for schedule(static) for (size_t i = 0; i < m_basis.size(); ++i) m_basis[i]->computeBasisGrid(gpar[0],gpar[1],gpar[2],splinex[i]); const int n1 = svol->numCoefs(0); const int n2 = svol->numCoefs(1); const int p1 = svol->order(0); const int p2 = svol->order(1); const int p3 = svol->order(2); std::vector<size_t> elem_sizes; for (auto& it : m_basis) elem_sizes.push_back(it->order(0)*it->order(1)*it->order(2)); const int nel1 = n1 - p1 + 1; const int nel2 = n2 - p2 + 1; std::map<char,size_t>::const_iterator iit = firstBp.find(lIndex); size_t firstp = iit == firstBp.end() ? 0 : iit->second; // === Assembly loop over all elements on the patch face ===================== bool ok = true; for (size_t g = 0; g < threadGrp.size() && ok; ++g) { #pragma omp parallel for schedule(static) for (size_t t = 0; t < threadGrp[g].size(); ++t) { MxFiniteElement fe(elem_sizes); fe.xi = fe.eta = fe.zeta = faceDir < 0 ? -1.0 : 1.0; fe.u = gpar[0](1,1); fe.v = gpar[1](1,1); fe.w = gpar[2](1,1); std::vector<Matrix> dNxdu(m_basis.size()); Matrix Xnod, Jac; Vec4 X; Vec3 normal; for (size_t l = 0; l < threadGrp[g][t].size() && ok; ++l) { int iel = threadGrp[g][t][l]; fe.iel = MLGE[iel]; if (fe.iel < 1) continue; // zero-volume element int i1 = p1 + iel % nel1; int i2 = p2 + (iel / nel1) % nel2; int i3 = p3 + iel / (nel1*nel2); // Get element face area in the parameter space double dA = this->getParametricArea(++iel,abs(faceDir)); if (dA < 0.0) // topology error (probably logic error) { ok = false; break; } // Set up control point coordinates for current element if (!this->getElementCoordinates(Xnod,iel)) { ok = false; break; } if (useElmVtx) this->getElementCorners(i1-1,i2-1,i3-1,fe.XC); // Initialize element quantities LocalIntegral* A = integrand.getLocalIntegral(elem_sizes,fe.iel,true); if (!integrand.initElementBou(MNPC[iel-1],elem_sizes,nb,*A)) { A->destruct(); ok = false; break; } // Define some loop control variables depending on which face we are on int nf1, j1, j2; switch (abs(faceDir)) { case 1: nf1 = nel2; j2 = i3-p3; j1 = i2-p2; break; case 2: nf1 = nel1; j2 = i3-p3; j1 = i1-p1; break; case 3: nf1 = nel1; j2 = i2-p2; j1 = i1-p1; break; default: nf1 = j1 = j2 = 0; } // --- Integration loop over all Gauss points in each direction -------- int k1, k2, k3; int ip = (j2*nGauss*nf1 + j1)*nGauss; int jp = (j2*nf1 + j1)*nGauss*nGauss; fe.iGP = firstp + jp; // Global integration point counter for (int j = 0; j < nGauss; j++, ip += nGauss*(nf1-1)) for (int i = 0; i < nGauss; i++, ip++, fe.iGP++) { // Local element coordinates and parameter values // of current integration point switch (abs(faceDir)) { case 1: k2 = i; k3 = j; k1 = 0; break; case 2: k1 = i; k3 = j; k2 = 0; break; case 3: k1 = i; k2 = j; k3 = 0; break; default: k1 = k2 = k3 = 0; } if (gpar[0].size() > 1) { fe.xi = xg[k1]; fe.u = gpar[0](k1+1,i1-p1+1); } if (gpar[1].size() > 1) { fe.eta = xg[k2]; fe.v = gpar[1](k2+1,i2-p2+1); } if (gpar[2].size() > 1) { fe.zeta = xg[k3]; fe.w = gpar[2](k3+1,i3-p3+1); } // Fetch basis function derivatives at current integration point for (size_t b = 0; b < m_basis.size(); ++b) SplineUtils::extractBasis(splinex[b][ip],fe.basis(b+1),dNxdu[b]); // Compute Jacobian inverse of the coordinate mapping and // basis function derivatives w.r.t. Cartesian coordinates fe.detJxW = utl::Jacobian(Jac,normal,fe.grad(geoBasis),Xnod,dNxdu[geoBasis-1],t1,t2); if (fe.detJxW == 0.0) continue; // skip singular points for (size_t b = 0; b < m_basis.size(); ++b) if (b != (size_t)geoBasis-1) fe.grad(b+1).multiply(dNxdu[b],Jac); if (faceDir < 0) normal *= -1.0; // Cartesian coordinates of current integration point X = Xnod * fe.basis(geoBasis); X.t = time.t; // Evaluate the integrand and accumulate element contributions fe.detJxW *= 0.25*dA*wg[i]*wg[j]; if (!integrand.evalBouMx(*A,fe,time,X,normal)) ok = false; } // Finalize the element quantities if (ok && !integrand.finalizeElementBou(*A,fe,time)) ok = false; // Assembly of global system integral if (ok && !glInt.assemble(A->ref(),fe.iel)) ok = false; A->destruct(); } } } return ok; }
bool ASMs3Dmx::integrate (Integrand& integrand, GlobalIntegral& glInt, const TimeDomain& time) { if (!svol) return true; // silently ignore empty patches if (m_basis.empty()) return false; PROFILE2("ASMs3Dmx::integrate(I)"); bool use2ndDer = integrand.getIntegrandType() & Integrand::SECOND_DERIVATIVES; bool useElmVtx = integrand.getIntegrandType() & Integrand::ELEMENT_CORNERS; // Get Gaussian quadrature points and weights const double* xg = GaussQuadrature::getCoord(nGauss); const double* wg = GaussQuadrature::getWeight(nGauss); if (!xg || !wg) return false; // Compute parameter values of the Gauss points over the whole patch std::array<Matrix,3> gpar; for (int d = 0; d < 3; d++) this->getGaussPointParameters(gpar[d],d,nGauss,xg); // Evaluate basis function derivatives at all integration points std::vector<std::vector<Go::BasisDerivs>> splinex(m_basis.size()); std::vector<std::vector<Go::BasisDerivs2>> splinex2(m_basis.size()); if (use2ndDer) { #pragma omp parallel for schedule(static) for (size_t i=0;i<m_basis.size();++i) m_basis[i]->computeBasisGrid(gpar[0],gpar[1],gpar[2],splinex2[i]); } else { #pragma omp parallel for schedule(static) for (size_t i=0;i<m_basis.size();++i) m_basis[i]->computeBasisGrid(gpar[0],gpar[1],gpar[2],splinex[i]); } std::vector<size_t> elem_sizes; for (auto& it : m_basis) elem_sizes.push_back(it->order(0)*it->order(1)*it->order(2)); const int p1 = svol->order(0); const int p2 = svol->order(1); const int p3 = svol->order(2); const int n1 = svol->numCoefs(0); const int n2 = svol->numCoefs(1); const int n3 = svol->numCoefs(2); const int nel1 = n1 - p1 + 1; const int nel2 = n2 - p2 + 1; const int nel3 = n3 - p3 + 1; // === Assembly loop over all elements in the patch ========================== bool ok=true; for (size_t g=0;g<threadGroupsVol.size() && ok;++g) { #pragma omp parallel for schedule(static) for (size_t t=0;t<threadGroupsVol[g].size();++t) { MxFiniteElement fe(elem_sizes); std::vector<Matrix> dNxdu(m_basis.size()); std::vector<Matrix3D> d2Nxdu2(m_basis.size()); Matrix3D Hess; double dXidu[3]; Matrix Xnod, Jac; Vec4 X; for (size_t l = 0; l < threadGroupsVol[g][t].size() && ok; ++l) { int iel = threadGroupsVol[g][t][l]; fe.iel = MLGE[iel]; if (fe.iel < 1) continue; // zero-volume element int i1 = p1 + iel % nel1; int i2 = p2 + (iel / nel1) % nel3; int i3 = p3 + iel / (nel1*nel2); // Get element volume in the parameter space double dV = this->getParametricVolume(++iel); if (dV < 0.0) // topology error (probably logic error) { ok = false; break; } // Set up control point (nodal) coordinates for current element if (!this->getElementCoordinates(Xnod,iel)) { ok = false; break; } if (useElmVtx) this->getElementCorners(i1-1,i2-1,i3-1,fe.XC); if (integrand.getIntegrandType() & Integrand::G_MATRIX) { // Element size in parametric space dXidu[0] = svol->knotSpan(0,i1-1); dXidu[1] = svol->knotSpan(1,i2-1); dXidu[2] = svol->knotSpan(2,i3-1); } // Initialize element quantities LocalIntegral* A = integrand.getLocalIntegral(elem_sizes,fe.iel,false); if (!integrand.initElement(MNPC[iel-1],elem_sizes,nb,*A)) { A->destruct(); ok = false; break; } // --- Integration loop over all Gauss points in each direction -------- int ip = (((i3-p3)*nGauss*nel2 + i2-p2)*nGauss*nel1 + i1-p1)*nGauss; int jp = (((i3-p3)*nel2 + i2-p2*nel1 + i1-p1))*nGauss*nGauss*nGauss; fe.iGP = firstIp + jp; // Global integration point counter for (int k = 0; k < nGauss; k++, ip += nGauss*(nel2-1)*nGauss*nel1) for (int j = 0; j < nGauss; j++, ip += nGauss*(nel1-1)) for (int i = 0; i < nGauss; i++, ip++, fe.iGP++) { // Local element coordinates of current integration point fe.xi = xg[i]; fe.eta = xg[j]; fe.zeta = xg[k]; // Parameter values of current integration point fe.u = gpar[0](i+1,i1-p1+1); fe.v = gpar[1](j+1,i2-p2+1); fe.w = gpar[2](k+1,i3-p3+1); // Fetch basis function derivatives at current integration point if (use2ndDer) { for (size_t b = 0; b < m_basis.size(); ++b) SplineUtils::extractBasis(splinex2[b][ip],fe.basis(b+1),dNxdu[b], d2Nxdu2[b]); } else { for (size_t b = 0; b < m_basis.size(); ++b) SplineUtils::extractBasis(splinex[b][ip],fe.basis(b+1),dNxdu[b]); } // Compute Jacobian inverse of the coordinate mapping and // basis function derivatives w.r.t. Cartesian coordinates fe.detJxW = utl::Jacobian(Jac,fe.grad(geoBasis),Xnod, dNxdu[geoBasis-1]); if (fe.detJxW == 0.0) continue; // skip singular points for (size_t b = 0; b < m_basis.size(); ++b) if (b != (size_t)geoBasis-1) fe.grad(b+1).multiply(dNxdu[b],Jac); // Compute Hessian of coordinate mapping and 2nd order derivatives if (use2ndDer) { if (!utl::Hessian(Hess,fe.hess(geoBasis),Jac,Xnod, d2Nxdu2[geoBasis-1],fe.grad(geoBasis),true)) ok = false; for (size_t b = 0; b < m_basis.size() && ok; ++b) if ((int)b != geoBasis) if (!utl::Hessian(Hess,fe.hess(b+1),Jac,Xnod, d2Nxdu2[b],fe.grad(b+1),false)) ok = false; } // Compute G-matrix if (integrand.getIntegrandType() & Integrand::G_MATRIX) utl::getGmat(Jac,dXidu,fe.G); // Cartesian coordinates of current integration point X = Xnod * fe.basis(geoBasis); X.t = time.t; // Evaluate the integrand and accumulate element contributions fe.detJxW *= 0.125*dV*wg[i]*wg[j]*wg[k]; if (!integrand.evalIntMx(*A,fe,time,X)) ok = false; } // Finalize the element quantities if (ok && !integrand.finalizeElement(*A,time,firstIp+jp)) ok = false; // Assembly of global system integral if (ok && !glInt.assemble(A->ref(),fe.iel)) ok = false; A->destruct(); } } } return ok; }
void CGUIManager::LoadPage(SGUIPage& page) { // If we're hotloading then try to grab some data from the previous page shared_ptr<ScriptInterface::StructuredClone> hotloadData; if (page.gui) { shared_ptr<ScriptInterface> scriptInterface = page.gui->GetScriptInterface(); JSContext* cx = scriptInterface->GetContext(); JSAutoRequest rq(cx); JS::RootedValue global(cx, scriptInterface->GetGlobalObject()); JS::RootedValue hotloadDataVal(cx); scriptInterface->CallFunction(global, "getHotloadData", &hotloadDataVal); hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal); } page.inputs.clear(); page.gui.reset(new CGUI(m_ScriptRuntime)); page.gui->Initialize(); VfsPath path = VfsPath("gui") / page.name; page.inputs.insert(path); CXeromyces xero; if (xero.Load(g_VFS, path, "gui_page") != PSRETURN_OK) // Fail silently (Xeromyces reported the error) return; int elmt_page = xero.GetElementID("page"); int elmt_include = xero.GetElementID("include"); XMBElement root = xero.GetRoot(); if (root.GetNodeName() != elmt_page) { LOGERROR("GUI page '%s' must have root element <page>", utf8_from_wstring(page.name)); return; } XERO_ITER_EL(root, node) { if (node.GetNodeName() != elmt_include) { LOGERROR("GUI page '%s' must only have <include> elements inside <page>", utf8_from_wstring(page.name)); continue; } std::string name = node.GetText(); CStrW nameW (node.GetText().FromUTF8()); PROFILE2("load gui xml"); PROFILE2_ATTR("name: %s", name.c_str()); TIMER(nameW.c_str()); if (name.back() == '/') { VfsPath directory = VfsPath("gui") / nameW; VfsPaths pathnames; vfs::GetPathnames(g_VFS, directory, L"*.xml", pathnames); for (const VfsPath& path : pathnames) page.gui->LoadXmlFile(path, page.inputs); } else { VfsPath path = VfsPath("gui") / nameW; page.gui->LoadXmlFile(path, page.inputs); } } // Remember this GUI page, in case the scripts call FindObjectByName shared_ptr<CGUI> oldGUI = m_CurrentGUI; m_CurrentGUI = page.gui; page.gui->SendEventToAll("load"); shared_ptr<ScriptInterface> scriptInterface = page.gui->GetScriptInterface(); JSContext* cx = scriptInterface->GetContext(); JSAutoRequest rq(cx); JS::RootedValue initDataVal(cx); JS::RootedValue hotloadDataVal(cx); JS::RootedValue global(cx, scriptInterface->GetGlobalObject()); if (page.initData) scriptInterface->ReadStructuredClone(page.initData, &initDataVal); if (hotloadData) scriptInterface->ReadStructuredClone(hotloadData, &hotloadDataVal); // Call the init() function if (!scriptInterface->CallFunctionVoid( global, "init", initDataVal, hotloadDataVal) ) { LOGERROR("GUI page '%s': Failed to call init() function", utf8_from_wstring(page.name)); } m_CurrentGUI = oldGUI; }
bool ASMs2D::globalL2projection (Matrix& sField, const IntegrandBase& integrand, bool continuous) const { if (!surf) return true; // silently ignore empty patches PROFILE2("ASMs2D::globalL2"); const int p1 = surf->order_u(); const int p2 = surf->order_v(); const int n1 = surf->numCoefs_u(); const int n2 = surf->numCoefs_v(); const int nel1 = n1 - p1 + 1; const int nel2 = n2 - p2 + 1; // Get Gaussian quadrature point coordinates (and weights if continuous) const int ng1 = continuous ? nGauss : p1 - 1; const int ng2 = continuous ? nGauss : p2 - 1; const double* xg = GaussQuadrature::getCoord(ng1); const double* yg = GaussQuadrature::getCoord(ng2); const double* wg = continuous ? GaussQuadrature::getWeight(nGauss) : nullptr; if (!xg || !yg) return false; if (continuous && !wg) return false; // Compute parameter values of the Gauss points over the whole patch Matrix gp; std::array<RealArray,2> gpar; gpar[0] = this->getGaussPointParameters(gp,0,ng1,xg); gpar[1] = this->getGaussPointParameters(gp,1,ng2,yg); // Evaluate basis functions at all integration points std::vector<Go::BasisPtsSf> spl0; std::vector<Go::BasisDerivsSf> spl1; if (continuous) surf->computeBasisGrid(gpar[0],gpar[1],spl1); else surf->computeBasisGrid(gpar[0],gpar[1],spl0); // Evaluate the secondary solution at all integration points if (!this->evalSolution(sField,integrand,gpar.data())) { std::cerr <<" *** ASMs2D::globalL2projection: Failed for patch "<< idx+1 <<" nPoints="<< gpar[0].size()*gpar[1].size() << std::endl; return false; } // Set up the projection matrices const size_t nnod = this->getNoNodes(1); const size_t ncomp = sField.rows(); SparseMatrix A(SparseMatrix::SUPERLU); StdVector B(nnod*ncomp); A.redim(nnod,nnod); double dA = 1.0; Vector phi(p1*p2); Matrix dNdu, Xnod, J; // === Assembly loop over all elements in the patch ========================== int iel = 0; for (int i2 = 0; i2 < nel2; i2++) for (int i1 = 0; i1 < nel1; i1++, iel++) { if (MLGE[iel] < 1) continue; // zero-area element if (continuous) { // Set up control point (nodal) coordinates for current element if (!this->getElementCoordinates(Xnod,1+iel)) return false; else if ((dA = 0.25*this->getParametricArea(1+iel)) < 0.0) return false; // topology error (probably logic error) } // --- Integration loop over all Gauss points in each direction ---------- int ip = (i2*ng1*nel1 + i1)*ng2; for (int j = 0; j < ng2; j++, ip += ng1*(nel1-1)) for (int i = 0; i < ng1; i++, ip++) { if (continuous) SplineUtils::extractBasis(spl1[ip],phi,dNdu); else phi = spl0[ip].basisValues; // Compute the Jacobian inverse and derivatives double dJw = 1.0; if (continuous) { dJw = dA*wg[i]*wg[j]*utl::Jacobian(J,dNdu,Xnod,dNdu,false); if (dJw == 0.0) continue; // skip singular points } // Integrate the linear system A*x=B for (size_t ii = 0; ii < phi.size(); ii++) { int inod = MNPC[iel][ii]+1; for (size_t jj = 0; jj < phi.size(); jj++) { int jnod = MNPC[iel][jj]+1; A(inod,jnod) += phi[ii]*phi[jj]*dJw; } for (size_t r = 1; r <= ncomp; r++) B(inod+(r-1)*nnod) += phi[ii]*sField(r,ip+1)*dJw; } } } #if SP_DEBUG > 1 std::cout << " ---- Matrix A -----\n"; std::cout << A << std::endl; std::cout << " -------------------\n"; std::cout << " ---- Vector B -----\n"; std::cout << B << std::endl; std::cout << " -------------------\n"; #endif // Solve the patch-global equation system if (!A.solve(B)) return false; // Store the control-point values of the projected field sField.resize(ncomp,nnod); for (size_t i = 1; i <= nnod; i++) for (size_t j = 1; j <= ncomp; j++) sField(j,i) = B(i+(j-1)*nnod); return true; }
void HierarchicalPathfinder::MakeGoalReachable(u16 i0, u16 j0, PathGoal& goal, pass_class_t passClass) { PROFILE2("MakeGoalReachable"); RegionID source = Get(i0, j0, passClass); // Find everywhere that's reachable std::set<RegionID> reachableRegions; FindReachableRegions(source, reachableRegions, passClass); // Check whether any reachable region contains the goal // And get the navcell that's the closest to the point u16 bestI = 0; u16 bestJ = 0; u32 dist2Best = std::numeric_limits<u32>::max(); for (const RegionID& region : reachableRegions) { // Skip region if its chunk doesn't contain the goal area entity_pos_t x0 = Pathfinding::NAVCELL_SIZE * (region.ci * CHUNK_SIZE); entity_pos_t z0 = Pathfinding::NAVCELL_SIZE * (region.cj * CHUNK_SIZE); entity_pos_t x1 = x0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; entity_pos_t z1 = z0 + Pathfinding::NAVCELL_SIZE * CHUNK_SIZE; if (!goal.RectContainsGoal(x0, z0, x1, z1)) continue; u16 i,j; u32 dist2; // If the region contains the goal area, the goal is reachable // Remember the best point for optimization. if (GetChunk(region.ci, region.cj, passClass).RegionNearestNavcellInGoal(region.r, i0, j0, goal, i, j, dist2)) { // If it's a point, no need to move it, we're done if (goal.type == PathGoal::POINT) return; if (dist2 < dist2Best) { bestI = i; bestJ = j; dist2Best = dist2; } } } // If the goal area wasn't reachable, // find the navcell that's nearest to the goal's center if (dist2Best == std::numeric_limits<u32>::max()) { u16 iGoal, jGoal; Pathfinding::NearestNavcell(goal.x, goal.z, iGoal, jGoal, m_W, m_H); FindNearestNavcellInRegions(reachableRegions, iGoal, jGoal, passClass); // Construct a new point goal at the nearest reachable navcell PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(iGoal, jGoal, newGoal.x, newGoal.z); goal = newGoal; return; } ENSURE(dist2Best != std::numeric_limits<u32>::max()); PathGoal newGoal; newGoal.type = PathGoal::POINT; Pathfinding::NavcellCenter(bestI, bestJ, newGoal.x, newGoal.z); goal = newGoal; }
LR::LRSplineSurface* ASMu2D::scRecovery (const IntegrandBase& integrand) const { PROFILE2("ASMu2D::scRecovery"); const int m = integrand.derivativeOrder(); const int p1 = lrspline->order(0); const int p2 = lrspline->order(1); // Get Gaussian quadrature point coordinates const int ng1 = p1 - m; const int ng2 = p2 - m; const double* xg = GaussQuadrature::getCoord(ng1); const double* yg = GaussQuadrature::getCoord(ng2); if (!xg || !yg) return nullptr; // Compute parameter values of the Greville points std::array<RealArray,2> gpar; if (!this->getGrevilleParameters(gpar[0],0)) return nullptr; if (!this->getGrevilleParameters(gpar[1],1)) return nullptr; const int n1 = p1 - m + 1; // Patch size in first parameter direction const int n2 = p2 - m + 1; // Patch size in second parameter direction const size_t nCmp = integrand.getNoFields(); // Number of result components const size_t nPol = n1*n2; // Number of terms in polynomial expansion Matrix sValues(nCmp,gpar[0].size()); Vector P(nPol); Go::Point X, G; // Loop over all Greville points (one for each basis function) size_t k, l, ip = 0; std::vector<LR::Element*>::const_iterator elStart, elEnd, el; std::vector<LR::Element*> supportElements; for (LR::Basisfunction *b : lrspline->getAllBasisfunctions()) { #if SP_DEBUG > 2 std::cout <<"Basis: "<< *b <<"\n ng1 ="<< ng1 <<"\n ng2 ="<< ng2 <<"\n nPol="<< nPol << std::endl; #endif // Special case for basis functions with too many zero knot spans by using // the extended support // if(nel*ng1*ng2 < nPol) if(true) { // KMO: Here I'm not sure how this will change when m > 1. // In that case I think we would need smaller patches (as in the tensor // splines case). But how to do that??? supportElements = b->getExtendedSupport(); elStart = supportElements.begin(); elEnd = supportElements.end(); #if SP_DEBUG > 2 std::cout <<"Extended basis:"; for (el = elStart; el != elEnd; el++) std::cout <<"\n " << **el; std::cout << std::endl; #endif } else { elStart = b->supportedElementBegin(); elEnd = b->supportedElementEnd(); } // Physical coordinates of current Greville point lrspline->point(G,gpar[0][ip],gpar[1][ip]); // Set up the local projection matrices DenseMatrix A(nPol,nPol); Matrix B(nPol,nCmp); // Loop over all non-zero knot-spans in the support of // the basis function associated with current Greville point for (el = elStart; el != elEnd; el++) { int iel = (**el).getId()+1; // evaluate all gauss points for this element std::array<RealArray,2> gaussPt, unstrGauss; this->getGaussPointParameters(gaussPt[0],0,ng1,iel,xg); this->getGaussPointParameters(gaussPt[1],1,ng2,iel,yg); #if SP_DEBUG > 2 std::cout << "Element " << **el << std::endl; #endif // convert to unstructred mesh representation expandTensorGrid(gaussPt.data(),unstrGauss.data()); // Evaluate the secondary solution at all Gauss points Matrix sField; if (!this->evalSolution(sField,integrand,unstrGauss.data())) return nullptr; // Loop over the Gauss points in current knot-span int i, j, ig = 1; for (j = 0; j < ng2; j++) for (i = 0; i < ng1; i++, ig++) { // Evaluate the polynomial expansion at current Gauss point lrspline->point(X,gaussPt[0][i],gaussPt[1][j]); evalMonomials(n1,n2,X[0]-G[0],X[1]-G[1],P); #if SP_DEBUG > 2 std::cout <<"Greville point: "<< G <<"\nGauss point: "<< gaussPt[0][i] <<", "<< gaussPt[0][j] <<"\nMapped gauss point: "<< X <<"\nP-matrix:"<< P <<"--------------------\n"<< std::endl; #endif for (k = 1; k <= nPol; k++) { // Accumulate the projection matrix, A += P^t * P for (l = 1; l <= nPol; l++) A(k,l) += P(k)*P(l); // Accumulate the right-hand-side matrix, B += P^t * sigma for (l = 1; l <= nCmp; l++) B(k,l) += P(k)*sField(l,ig); } } } #if SP_DEBUG > 2 std::cout <<"---- Matrix A -----"<< A <<"-------------------"<< std::endl; std::cout <<"---- Vector B -----"<< B <<"-------------------"<< std::endl; #endif // Solve the local equation system if (!A.solve(B)) return nullptr; // Evaluate the projected field at current Greville point (first row of B) ip++; for (l = 1; l <= nCmp; l++) sValues(l,ip) = B(1,l); #if SP_DEBUG > 1 std::cout <<"Greville point "<< ip <<" (u,v) = " << gpar[0][ip-1] <<" "<< gpar[1][ip-1] <<" :"; for (k = 1; k <= nCmp; k++) std::cout <<" "<< sValues(k,ip); std::cout << std::endl; #endif } // Project the Greville point results onto the spline basis // to find the control point values return this->regularInterpolation(gpar[0],gpar[1],sValues); }
bool ASMunstruct::refine (const LR::RefineData& prm, Vectors& sol, const char* fName) { PROFILE2("ASMunstruct::refine()"); if (!geo) return false; else if (shareFE && !prm.refShare) { nnod = geo->nBasisFunctions(); return true; } // to pick up if LR splines get stuck while doing refinement, // print entry and exit point of this function double beta = prm.options.size() > 0 ? prm.options[0]/100.0 : 0.10; int multiplicity = prm.options.size() > 1 ? prm.options[1] : 1; if (multiplicity > 1) for (int d = 0; d < geo->nVariate(); d++) { int p = geo->order(d) - 1; if (multiplicity > p) multiplicity = p; } enum refinementStrategy strat = LR_FULLSPAN; if (prm.options.size() > 2) switch (prm.options[2]) { case 1: strat = LR_MINSPAN; break; case 2: strat = LR_STRUCTURED_MESH; break; } bool linIndepTest = prm.options.size() > 3 ? prm.options[3] != 0 : false; int maxTjoints = prm.options.size() > 4 ? prm.options[4] : -1; int maxAspectRatio = prm.options.size() > 5 ? prm.options[5] : -1; bool closeGaps = prm.options.size() > 6 ? prm.options[6] != 0 : false; char doRefine = 0; if (!prm.errors.empty()) doRefine = 'E'; // Refine based on error indicators else if (!prm.elements.empty()) doRefine = 'I'; // Refine the specified elements if (doRefine) { std::vector<int> nf(sol.size()); for (size_t j = 0; j < sol.size(); j++) if (!(nf[j] = LR::extendControlPoints(geo,sol[j],this->getNoFields(1)))) return false; // set refinement parameters if (maxTjoints > 0) geo->setMaxTjoints(maxTjoints); if (maxAspectRatio > 0) geo->setMaxAspectRatio((double)maxAspectRatio); geo->setCloseGaps(closeGaps); geo->setRefMultiplicity(multiplicity); geo->setRefStrat(strat); // do actual refinement if (doRefine == 'E') geo->refineByDimensionIncrease(prm.errors,beta); else if (strat == LR_STRUCTURED_MESH) geo->refineBasisFunction(prm.elements); else geo->refineElement(prm.elements); geo->generateIDs(); nnod = geo->nBasisFunctions(); for (int i = sol.size()-1; i >= 0; i--) { sol[i].resize(nf[i]*geo->nBasisFunctions()); LR::contractControlPoints(geo,sol[i],nf[i]); } } if (fName) { char fullFileName[256]; strcpy(fullFileName, "lrspline_"); strcat(fullFileName, fName); std::ofstream lrOut(fullFileName); lrOut << *geo; lrOut.close(); LR::LRSplineSurface* lr = dynamic_cast<LR::LRSplineSurface*>(geo); if (lr) { // open files for writing strcpy(fullFileName, "param_"); strcat(fullFileName, fName); std::ofstream paramMeshFile(fullFileName); strcpy(fullFileName, "physical_"); strcat(fullFileName, fName); std::ofstream physicalMeshFile(fullFileName); strcpy(fullFileName, "param_dot_"); strcat(fullFileName, fName); std::ofstream paramDotMeshFile(fullFileName); strcpy(fullFileName, "physical_dot_"); strcat(fullFileName, fName); std::ofstream physicalDotMeshFile(fullFileName); lr->writePostscriptMesh(paramMeshFile); lr->writePostscriptElements(physicalMeshFile); lr->writePostscriptFunctionSpace(paramDotMeshFile); lr->writePostscriptMeshWithControlPoints(physicalDotMeshFile); // close all files paramMeshFile.close(); physicalMeshFile.close(); paramDotMeshFile.close(); physicalDotMeshFile.close(); } } if (doRefine) std::cout <<"Refined mesh: "<< geo->nElements() <<" elements " << geo->nBasisFunctions() <<" nodes."<< std::endl; if (linIndepTest) { std::cout <<"Testing for linear independence by overloading "<< std::endl; bool isLinIndep = geo->isLinearIndepByOverloading(false); if (!isLinIndep) { std::cout <<"Inconclusive..."<< std::endl; #ifdef HAS_BOOST std::cout <<"Testing for linear independence by full tensor expansion "<< std::endl; isLinIndep = geo->isLinearIndepByMappingMatrix(false); #endif } if (isLinIndep) std::cout <<"...Passed."<< std::endl; else { std::cout <<"FAILED!!!"<< std::endl; exit(228); } } return true; }
bool ASMu2D::globalL2projection (Matrix& sField, const IntegrandBase& integrand, bool continuous) const { if (!lrspline) return true; // silently ignore empty patches PROFILE2("ASMu2D::globalL2"); const int p1 = lrspline->order(0); const int p2 = lrspline->order(1); // Get Gaussian quadrature points const int ng1 = continuous ? nGauss : p1 - 1; const int ng2 = continuous ? nGauss : p2 - 1; const double* xg = GaussQuadrature::getCoord(ng1); const double* yg = GaussQuadrature::getCoord(ng2); const double* wg = continuous ? GaussQuadrature::getWeight(nGauss) : nullptr; if (!xg || !yg) return false; if (continuous && !wg) return false; // Set up the projection matrices const size_t nnod = this->getNoNodes(); const size_t ncomp = integrand.getNoFields(); SparseMatrix A(SparseMatrix::SUPERLU); StdVector B(nnod*ncomp); A.redim(nnod,nnod); double dA = 0.0; Vector phi; Matrix dNdu, Xnod, Jac; Go::BasisDerivsSf spl1; Go::BasisPtsSf spl0; // === Assembly loop over all elements in the patch ========================== std::vector<LR::Element*>::iterator el = lrspline->elementBegin(); for (int iel = 1; el != lrspline->elementEnd(); el++, iel++) { if (continuous) { // Set up control point (nodal) coordinates for current element if (!this->getElementCoordinates(Xnod,iel)) return false; else if ((dA = 0.25*this->getParametricArea(iel)) < 0.0) return false; // topology error (probably logic error) } // Compute parameter values of the Gauss points over this element std::array<RealArray,2> gpar, unstrGpar; this->getGaussPointParameters(gpar[0],0,ng1,iel,xg); this->getGaussPointParameters(gpar[1],1,ng2,iel,yg); // convert to unstructred mesh representation expandTensorGrid(gpar.data(),unstrGpar.data()); // Evaluate the secondary solution at all integration points if (!this->evalSolution(sField,integrand,unstrGpar.data())) return false; // set up basis function size (for extractBasis subroutine) phi.resize((**el).nBasisFunctions()); // --- Integration loop over all Gauss points in each direction ---------- int ip = 0; for (int j = 0; j < ng2; j++) for (int i = 0; i < ng1; i++, ip++) { if (continuous) { lrspline->computeBasis(gpar[0][i],gpar[1][j],spl1,iel-1); SplineUtils::extractBasis(spl1,phi,dNdu); } else { lrspline->computeBasis(gpar[0][i],gpar[1][j],spl0,iel-1); phi = spl0.basisValues; } // Compute the Jacobian inverse and derivatives double dJw = 1.0; if (continuous) { dJw = dA*wg[i]*wg[j]*utl::Jacobian(Jac,dNdu,Xnod,dNdu,false); if (dJw == 0.0) continue; // skip singular points } // Integrate the linear system A*x=B for (size_t ii = 0; ii < phi.size(); ii++) { int inod = MNPC[iel-1][ii]+1; for (size_t jj = 0; jj < phi.size(); jj++) { int jnod = MNPC[iel-1][jj]+1; A(inod,jnod) += phi[ii]*phi[jj]*dJw; } for (size_t r = 1; r <= ncomp; r++) B(inod+(r-1)*nnod) += phi[ii]*sField(r,ip+1)*dJw; } } } #if SP_DEBUG > 2 std::cout <<"---- Matrix A -----"<< A <<"-------------------"<< std::endl; std::cout <<"---- Vector B -----"<< B <<"-------------------"<< std::endl; #endif // Solve the patch-global equation system if (!A.solve(B)) return false; // Store the control-point values of the projected field sField.resize(ncomp,nnod); for (size_t i = 1; i <= nnod; i++) for (size_t j = 1; j <= ncomp; j++) sField(j,i) = B(i+(j-1)*nnod); return true; }
void ScriptInterface::ForceGC() { PROFILE2("JS_GC"); JS_GC(this->GetJSRuntime()); }
std::vector<entity_id_t> EntitySelection::PickSimilarEntities(CSimulation2& simulation, const CCamera& camera, const std::string& templateName, player_id_t owner, bool includeOffScreen, bool matchRank, bool allowEditorSelectables, bool allowFoundations) { PROFILE2("PickSimilarEntities"); CmpPtr<ICmpTemplateManager> cmpTemplateManager(simulation, SYSTEM_ENTITY); CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY); std::vector<entity_id_t> hitEnts; const CSimulation2::InterfaceListUnordered& ents = simulation.GetEntitiesWithInterfaceUnordered(IID_Selectable); for (CSimulation2::InterfaceListUnordered::const_iterator it = ents.begin(); it != ents.end(); ++it) { entity_id_t ent = it->first; CEntityHandle handle = it->second->GetEntityHandle(); // Check if this entity is only selectable in Atlas if (static_cast<ICmpSelectable*>(it->second)->IsEditorOnly() && !allowEditorSelectables) continue; if (matchRank) { // Exact template name matching, optionally also allowing foundations std::string curTemplateName = cmpTemplateManager->GetCurrentTemplateName(ent); bool matches = (curTemplateName == templateName || (allowFoundations && curTemplateName.substr(0, 11) == "foundation|" && curTemplateName.substr(11) == templateName)); if (!matches) continue; } // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) // In this case, the checking is done to avoid selecting garrisoned units if (cmpRangeManager->GetLosVisibility(handle, owner) == ICmpRangeManager::VIS_HIDDEN) continue; // Ignore entities not owned by 'owner' CmpPtr<ICmpOwnership> cmpOwnership(simulation.GetSimContext(), ent); if (owner != INVALID_PLAYER && (!cmpOwnership || cmpOwnership->GetOwner() != owner)) continue; // Ignore off screen entities if (!includeOffScreen) { // Find the current interpolated model position. CmpPtr<ICmpVisual> cmpVisual(simulation.GetSimContext(), ent); if (!cmpVisual) continue; CVector3D position = cmpVisual->GetPosition(); // Reject if it's not on-screen (e.g. it's behind the camera) if (!camera.GetFrustum().IsPointVisible(position)) continue; } if (!matchRank) { // Match by selection group name // (This is relatively expensive since it involves script calls, so do it after all other tests) CmpPtr<ICmpIdentity> cmpIdentity(simulation.GetSimContext(), ent); if (!cmpIdentity || cmpIdentity->GetSelectionGroupName() != templateName) continue; } hitEnts.push_back(ent); } return hitEnts; }
bool CShaderManager::NewProgram(const char* name, const CShaderDefines& baseDefines, CShaderProgramPtr& program) { PROFILE2("loading shader"); PROFILE2_ATTR("name: %s", name); if (strncmp(name, "fixed:", 6) == 0) { program = CShaderProgramPtr(CShaderProgram::ConstructFFP(name+6, baseDefines)); if (!program) return false; program->Reload(); return true; } VfsPath xmlFilename = L"shaders/" + wstring_from_utf8(name) + L".xml"; CXeromyces XeroFile; PSRETURN ret = XeroFile.Load(g_VFS, xmlFilename); if (ret != PSRETURN_OK) return false; #if USE_SHADER_XML_VALIDATION { TIMER_ACCRUE(tc_ShaderValidation); // Serialize the XMB data and pass it to the validator XML_Start(); XML_SetPrettyPrint(false); XML_WriteXMB(XeroFile); bool ok = m_Validator.ValidateEncoded(wstring_from_utf8(name), XML_GetOutput()); if (!ok) return false; } #endif // Define all the elements and attributes used in the XML file #define EL(x) int el_##x = XeroFile.GetElementID(#x) #define AT(x) int at_##x = XeroFile.GetAttributeID(#x) EL(attrib); EL(define); EL(fragment); EL(stream); EL(uniform); EL(vertex); AT(file); AT(if); AT(loc); AT(name); AT(semantics); AT(type); AT(value); #undef AT #undef EL CPreprocessorWrapper preprocessor; preprocessor.AddDefines(baseDefines); XMBElement Root = XeroFile.GetRoot(); bool isGLSL = (Root.GetAttributes().GetNamedItem(at_type) == "glsl"); VfsPath vertexFile; VfsPath fragmentFile; CShaderDefines defines = baseDefines; std::map<CStrIntern, int> vertexUniforms; std::map<CStrIntern, CShaderProgram::frag_index_pair_t> fragmentUniforms; std::map<CStrIntern, int> vertexAttribs; int streamFlags = 0; XERO_ITER_EL(Root, Child) { if (Child.GetNodeName() == el_define) { defines.Add(CStrIntern(Child.GetAttributes().GetNamedItem(at_name)), CStrIntern(Child.GetAttributes().GetNamedItem(at_value))); } else if (Child.GetNodeName() == el_vertex) { vertexFile = L"shaders/" + Child.GetAttributes().GetNamedItem(at_file).FromUTF8(); XERO_ITER_EL(Child, Param) { XMBAttributeList Attrs = Param.GetAttributes(); CStr cond = Attrs.GetNamedItem(at_if); if (!cond.empty() && !preprocessor.TestConditional(cond)) continue; if (Param.GetNodeName() == el_uniform) { vertexUniforms[CStrIntern(Attrs.GetNamedItem(at_name))] = Attrs.GetNamedItem(at_loc).ToInt(); } else if (Param.GetNodeName() == el_stream) { CStr StreamName = Attrs.GetNamedItem(at_name); if (StreamName == "pos") streamFlags |= STREAM_POS; else if (StreamName == "normal") streamFlags |= STREAM_NORMAL; else if (StreamName == "color") streamFlags |= STREAM_COLOR; else if (StreamName == "uv0") streamFlags |= STREAM_UV0; else if (StreamName == "uv1") streamFlags |= STREAM_UV1; else if (StreamName == "uv2") streamFlags |= STREAM_UV2; else if (StreamName == "uv3") streamFlags |= STREAM_UV3; } else if (Param.GetNodeName() == el_attrib) { int attribLoc = ParseAttribSemantics(Attrs.GetNamedItem(at_semantics)); vertexAttribs[CStrIntern(Attrs.GetNamedItem(at_name))] = attribLoc; } } }
std::vector<entity_id_t> EntitySelection::PickEntitiesAtPoint(CSimulation2& simulation, const CCamera& camera, int screenX, int screenY, player_id_t player, bool allowEditorSelectables, int range) { PROFILE2("PickEntitiesAtPoint"); CVector3D origin, dir; camera.BuildCameraRay(screenX, screenY, origin, dir); CmpPtr<ICmpRangeManager> cmpRangeManager(simulation, SYSTEM_ENTITY); ENSURE(cmpRangeManager); /* We try to approximate where the mouse is hovering by drawing a ray from * the center of the camera and through the mouse then taking the position * at which the ray intersects the terrain. */ // TODO: Do this smarter without being slow. CVector3D pos3d = camera.GetWorldCoordinates(screenX, screenY, true); // Change the position to 2D by removing the terrain height. CFixedVector2D pos(fixed::FromFloat(pos3d.X), fixed::FromFloat(pos3d.Z)); // Get a rough group of entities using our approximated origin. SpatialQueryArray ents; cmpRangeManager->GetSubdivision()->GetNear(ents, pos, entity_pos_t::FromInt(range)); // Filter for relevent entities and calculate precise distances. std::vector<std::pair<float, entity_id_t> > hits; // (dist^2, entity) pairs for (int i = 0; i < ents.size(); ++i) { CmpPtr<ICmpSelectable> cmpSelectable(simulation, ents[i]); if (!cmpSelectable) continue; CEntityHandle handle = cmpSelectable->GetEntityHandle(); // Check if this entity is only selectable in Atlas if (!allowEditorSelectables && cmpSelectable->IsEditorOnly()) continue; // Ignore entities hidden by LOS (or otherwise hidden, e.g. when not IsInWorld) if (cmpRangeManager->GetLosVisibility(handle, player) == ICmpRangeManager::VIS_HIDDEN) continue; CmpPtr<ICmpVisual> cmpVisual(handle); if (!cmpVisual) continue; CVector3D center; float tmin, tmax; CBoundingBoxOriented selectionBox = cmpVisual->GetSelectionBox(); if (selectionBox.IsEmpty()) { if (!allowEditorSelectables) continue; // Fall back to using old AABB selection method for decals // see: http://trac.wildfiregames.com/ticket/1032 CBoundingBoxAligned aABBox = cmpVisual->GetBounds(); if (aABBox.IsEmpty()) continue; if (!aABBox.RayIntersect(origin, dir, tmin, tmax)) continue; aABBox.GetCentre(center); } else { if (!selectionBox.RayIntersect(origin, dir, tmin, tmax)) continue; center = selectionBox.m_Center; } // Find the perpendicular distance from the object's centre to the picker ray float dist2; CVector3D closest = origin + dir * (center - origin).Dot(dir); dist2 = (closest - center).LengthSquared(); hits.push_back(std::make_pair(dist2, ents[i])); } // Sort hits by distance std::sort(hits.begin(), hits.end()); // lexicographic comparison // Extract the entity IDs std::vector<entity_id_t> hitEnts; hitEnts.reserve(hits.size()); for (size_t i = 0; i < hits.size(); ++i) hitEnts.push_back(hits[i].second); return hitEnts; }