SIMD::Matrix Sphere::tangentSpace(RT_FLOAT _u, RT_FLOAT _v) const { RT_FLOAT phi = _u*M_PI; RT_FLOAT theta = _v*(2*M_PI); SIMD::Vec n(std::cos(theta)*std::sin(phi), std::sin(theta)*std::sin(phi), std::cos(phi)), u, v; switch(static_cast<int>(n[2])) { // Hairy ball theorem: // Vector field can't be continuous on the surface of a sphere // Infinitely many tangents on poles case 1: u = SIMD::Vec(1, 0, 0); v = SIMD::Vec(0, 1, 0); break; case -1: u = SIMD::Vec(-1, 0, 0); v = SIMD::Vec(0, -1, 0); break; default: SIMD::Point Pn(0, 0, 1); u = Pn-SIMD::Point(n.data()); v = n.cross(u); v.normalize(); u = v.cross(n); } return SIMD::Matrix(u.data(), v.data(), n.data(), SIMD::Point().data()); }
void P_nested(vector<double> &P, const vector<double> &par, const NumericMatrix &Theta, const int &N, const int &nfact, const int &ncat, const int &correct) { NumericVector dummy(1); const int par_size = par.size(); vector<double> dpar(nfact+3), npar(par_size - nfact - 3, 1.0); for(int i = 0; i < nfact+3; ++i) dpar[i] = par[i]; for(int i = nfact+3; i < par_size; ++i) npar[i - (nfact+3) + nfact] = par[i]; vector<double> Pd(N*2), Pn(N*(ncat-1)); P_dich(Pd, dpar, Theta, dummy, N, nfact); P_nominal(Pn, npar, Theta, dummy, N, nfact, ncat-1, 0, 0); NumericMatrix PD = vec2mat(Pd, N, 2); NumericMatrix PN = vec2mat(Pn, N, ncat-1); int k = 0, which = 0; for(int i = 0; i < ncat; ++i){ if((i+1) == correct){ for(int j = 0; j < N; ++j){ P[which] = PD(j,1); ++which; } --k; } else { for(int j = 0; j < N; ++j){ P[which] = PD(j,0) * PN(j,k); ++which; } } ++k; } }
bool isScreenPointInRect(const Vec2 &pt, const Camera* camera, const Mat4& w2l, const Rect& rect, Vec3 *p) { if (nullptr == camera || rect.size.width <= 0 || rect.size.height <= 0) { return false; } // first, convert pt to near/far plane, get Pn and Pf Vec3 Pn(pt.x, pt.y, -1), Pf(pt.x, pt.y, 1); Pn = camera->unprojectGL(Pn); Pf = camera->unprojectGL(Pf); // then convert Pn and Pf to node space w2l.transformPoint(&Pn); w2l.transformPoint(&Pf); // Pn and Pf define a line Q(t) = D + t * E which D = Pn auto E = Pf - Pn; // second, get three points which define content plane // these points define a plane P(u, w) = A + uB + wC Vec3 A = Vec3(rect.origin.x, rect.origin.y, 0); Vec3 B(rect.origin.x + rect.size.width, rect.origin.y, 0); Vec3 C(rect.origin.x, rect.origin.y + rect.size.height, 0); B = B - A; C = C - A; // the line Q(t) intercept with plane P(u, w) // calculate the intercept point P = Q(t) // (BxC).A - (BxC).D // t = ----------------- // (BxC).E Vec3 BxC; Vec3::cross(B, C, &BxC); auto BxCdotE = BxC.dot(E); if (BxCdotE == 0) { return false; } auto t = (BxC.dot(A) - BxC.dot(Pn)) / BxCdotE; Vec3 P = Pn + t * E; if (p) { *p = P; } return rect.containsPoint(Vec2(P.x, P.y)); }
/* * This function handles automatic buffer preservation. It runs in its * own thread, which is only awake when keystrokes >= PSVKEYS and the * main thread is waiting for keyboard input. Even then, it spends * most of its time asleep. */ static void FAR psvhandler() { for (;;) { long sleeptime; DosSemWait(psvsema, SEM_INDEFINITE_WAIT); DosSemRequest(control, SEM_INDEFINITE_WAIT); /* * Start of critical section. */ if (keystrokes < PSVKEYS) { sleeptime = 0; /* * If we haven't had at least PSVKEYS * keystrokes, psvsema should be set. */ DosSemSet(psvsema); } else if ((sleeptime = (long) Pn(P_preservetime) * 1000 - CLK2MS(clock() - lastevent)) <= 0) { /* * If Pn(P_presevetime) seconds haven't yet * elapsed, sleep until they should have - but * NOT within the critical section (!). * * Otherwise do automatic preserve. * * exPreserveAllBuffers() should reset keystrokes to 0. */ (void) exPreserveAllBuffers(); sleeptime = 0; } /* * End of critical section. */ DosSemClear(control); /* * Sleep if we have to. */ if (sleeptime != 0) DosSleep(sleeptime); } }