/*! SLCurveBezier::findParamByDist gets parameter s distance in arc length from Q(t1). Returns max SLfloat if can't find it. */ SLfloat SLCurveBezier::findParamByDist(SLfloat t1, SLfloat s) { // ensure that we remain within valid parameter space if (s > arcLength(t1, _points[_points.size()-1].w)) return _points[_points.size()-1].w; // make first guess SLfloat p = t1 + s*(_points[_points.size()-1].w-_points[0].w)/_totalLength; for (SLuint i = 0; i < 32; ++i) { // compute function value and test against zero SLfloat func = arcLength(t1, p) - s; if (SL_abs(func) < 1.0e-03f) return p; // perform Newton-Raphson iteration step SLfloat speed = velocity(p).length(); assert(SL_abs(speed) > FLT_EPSILON); p -= func/speed; } // done iterating, return failure case return FLT_MAX; }
/*! SLCamera::onTouch2Move gets called whenever two fingers move on a handheld screen. */ SLbool SLCamera::onTouch2Move(const SLint x1, const SLint y1, const SLint x2, const SLint y2) { SLScene* s = SLScene::current; SLSceneView* sv = s->activeSV(); SLVec2f now1((SLfloat)x1, (SLfloat)y1); SLVec2f now2((SLfloat)x2, (SLfloat)y2); SLVec2f delta1(now1-_oldTouchPos1); SLVec2f delta2(now2-_oldTouchPos2); // Average out the deltas over the last 4 events for correct 1 pixel moves static SLuint cnt=0; static SLVec2f d1[4]; static SLVec2f d2[4]; d1[cnt%4] = delta1; d2[cnt%4] = delta2; SLVec2f avgDelta1(d1[0].x+d1[1].x+d1[2].x+d1[3].x, d1[0].y+d1[1].y+d1[2].y+d1[3].y); SLVec2f avgDelta2(d2[0].x+d2[1].x+d2[2].x+d2[3].x, d2[0].y+d2[1].y+d2[2].y+d2[3].y); avgDelta1 /= 4.0f; avgDelta2 /= 4.0f; cnt++; SLfloat r1, phi1, r2, phi2; avgDelta1.toPolar(r1, phi1); avgDelta2.toPolar(r2, phi2); // Scale the mouse delta by the lookAt distance SLfloat lookAtDist; if (_lookAtRay.length < FLT_MAX) lookAtDist = _lookAtRay.length; else lookAtDist = _focalDist; // scale factor depending on the space sice at focal dist SLfloat spaceH = tan(SL_DEG2RAD*_fov/2) * lookAtDist * 2.0f; SLfloat spaceW = spaceH * sv->scrWdivH(); //SL_LOG("avgDelta1: (%05.2f,%05.2f), dPhi=%05.2f\n", avgDelta1.x, avgDelta1.y, SL_abs(phi1-phi2)); // if fingers move parallel slide camera vertically or horizontally if (SL_abs(phi1-phi2) < 0.2f) { // Calculate center between finger points SLVec2f nowCenter((now1+now2)*0.5f); SLVec2f oldCenter((_oldTouchPos1+_oldTouchPos2)*0.5f); // For first move set oldCenter = nowCenter if (oldCenter == SLVec2f::ZERO) oldCenter = nowCenter; SLVec2f delta(nowCenter - oldCenter); // scale to 0-1 delta.x /= (SLfloat)sv->scrW(); delta.y /= (SLfloat)sv->scrH(); // scale to space size delta.x *= spaceW; delta.y *= spaceH; if (_camAnim==turntableYUp || _camAnim==turntableZUp) { // apply delta to x- and y-position _vm.translation(_vm.m(12) + delta.x, _vm.m(13) - delta.y, _vm.m(14)); setWMandState(); } else if (_camAnim == walkingYUp || _camAnim == walkingZUp) { _maxSpeed.x = delta.x * 100.0f, _maxSpeed.z = delta.y * 100.0f; } } else // Two finger pinch { // Calculate vector between fingers SLVec2f nowDist(now2 - now1); SLVec2f oldDist(_oldTouchPos2-_oldTouchPos1); // For first move set oldDist = nowDist if (oldDist == SLVec2f::ZERO) oldDist = nowDist; SLfloat delta = oldDist.length() - nowDist.length(); if (_camAnim==turntableYUp) { // scale to 0-1 delta /= (SLfloat)sv->scrH(); // scale to space height delta *= spaceH*2; // apply delta to the z-position _vm.translation(_vm.m(12), _vm.m(13), _vm.m(14) - delta); setWMandState(); } else if (_camAnim == walkingYUp) { // change field of view _fov += SL_sign(delta) * 0.5f; currentFOV = _fov; } } _oldTouchPos1.set((SLfloat)x1, (SLfloat)y1); _oldTouchPos2.set((SLfloat)x2, (SLfloat)y2); return true; }