/*! SLCurveBezier::subdivideRender adds points along the curve to the point vector renderPoints by recursively subdividing the curve with the Casteljau scheme. */ void SLCurveBezier::subdivideRender(SLVVec3f &renderPoints, const SLMat4f &wm, SLfloat epsilon, const SLVec3f& P0, const SLVec3f& P1, const SLVec3f& P2, const SLVec3f& P3) { // add first point transformed by wm if not already in the list if (renderPoints.size()==0) renderPoints.push_back(wm.multVec(P0)); else if (P0 != renderPoints[renderPoints.size()-1]) renderPoints.push_back(wm.multVec(P0)); // check to see if basically straight SLfloat Lmin = P0.distance(P3); SLfloat Lmax = P0.distance(P1) + P1.distance(P2) + P2.distance(P3); SLfloat diff = Lmin - Lmax; if (diff*diff < epsilon) return; // otherwise get control points for subdivision SLVec3f L1 = (P0 + P1) * 0.5f; SLVec3f H = (P1 + P2) * 0.5f; SLVec3f L2 = (L1 + H) * 0.5f; SLVec3f R2 = (P2 + P3) * 0.5f; SLVec3f R1 = (H + R2) * 0.5f; SLVec3f mid = (L2 + R1) * 0.5f; // subdivide subdivideRender(renderPoints, wm, epsilon, P0, L1, L2, mid); subdivideRender(renderPoints, wm, epsilon, mid, R1, R2, P3); }
//----------------------------------------------------------------------------- //! Gets called whenever the mouse is moved. SLbool SLCamera::onMouseMove(const SLMouseButton button, const SLint x, const SLint y, const SLKey mod) { if (button == ButtonLeft) //================================================ { // new vars needed SLVec3f position = this->translation(); SLVec3f forward = this->forward(); SLVec3f right = this->right(); SLVec3f up = this->up(); // The lookAt point SLVec3f laP = position + _focalDist * forward; // Determine rotation point as the center of the AABB of the hitNode SLVec3f rtP; if (_lookAtRay.length < FLT_MAX && _lookAtRay.hitNode) rtP = _lookAtRay.hitNode->aabb()->centerWS(); else rtP = laP; // Determine rot angles around x- & y-axis SLfloat dY = (y-_oldTouchPos1.y) * _rotFactor; SLfloat dX = (x-_oldTouchPos1.x) * _rotFactor; if (_camAnim==turntableYUp) //....................................... { SLMat4f rot; rot.translate(rtP); rot.rotate(-dX, SLVec3f(0,1,0)); rot.rotate(-dY, right); rot.translate(-rtP); _om.setMatrix(rot * _om); needWMUpdate(); } else if (_camAnim==turntableZUp) //.................................. { SLMat4f rot; rot.translate(rtP); rot.rotate(dX, SLVec3f(0,0,1)); rot.rotate(dY, right); rot.translate(-rtP); _om.setMatrix(rot * _om); needWMUpdate(); } else if (_camAnim==walkingYUp) //.................................... { dY *= 0.5f; dX *= 0.5f; SLMat4f rot; rot.rotate(-dX, SLVec3f(0, 1, 0)); rot.rotate(-dY, right); forward.set(rot.multVec(forward)); lookAt(position + forward); } else if (_camAnim==walkingZUp) //.................................... { dY *= 0.5f; dX *= 0.5f; SLMat4f rot; rot.rotate(-dX, SLVec3f(0, 0, 1)); rot.rotate(-dY, right); forward.set(rot.multVec(forward)); lookAt(position + forward, SLVec3f(0, 0, 1)); } _oldTouchPos1.set((SLfloat)x,(SLfloat)y); } else if (button == ButtonMiddle) //============================================== { if (_camAnim==turntableYUp || _camAnim==turntableZUp) { // Calculate the fraction delta of the mouse movement SLVec2f dMouse(x-_oldTouchPos1.x, _oldTouchPos1.y-y); dMouse.x /= (SLfloat)_scrW; dMouse.y /= (SLfloat)_scrH; // 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 * _aspect; dMouse.x *= spaceW; dMouse.y *= spaceH; if (mod==KeyCtrl) { translate(SLVec3f(-dMouse.x, 0, dMouse.y), TS_Object); } else { translate(SLVec3f(-dMouse.x, -dMouse.y, 0), TS_Object); } _oldTouchPos1.set((SLfloat)x,(SLfloat)y); } } //======================================================================== return true; }
/*! SLCurveBezier::draw does the OpenGL rendering of the Bezier curve in world space. */ void SLCurveBezier::draw(const SLMat4f &wm) { SLint numControlPoints = 2*((SLint)_points.size()-1); // Create buffer object if (!_vao.id()) { // Build renderPoints by recursively subdividing the curve SLVVec3f renderPoints; for (SLuint i = 0; i < _points.size()-1; ++i) { subdivideRender(renderPoints, wm, 0.00001f, _points[i].vec3(), _controls[2*i], _controls[2*i+1], _points[i+1].vec3()); } // add last point to the curve vector renderPoints.push_back(wm.multVec(_points[_points.size()-1].vec3())); // add inputs points for (SLuint i = 0; i < _points.size(); ++i) renderPoints.push_back(wm.multVec(_points[i].vec3())); // add control points for (SLint i = 0; i < numControlPoints; ++i) renderPoints.push_back(wm.multVec(_controls[i])); // add tangent points for (SLint i = 0; i < numControlPoints; ++i) { renderPoints.push_back(wm.multVec(_controls[i])); int iPoint = (SLint)((SLfloat)i/2.0f + 0.5f); renderPoints.push_back(wm.multVec(_points[iPoint].vec3())); } // Generate finally the OpenGL rendering buffer _vao.generateVertexPos(&renderPoints); } if (!_vao.id()) return; // Set the view transform SLGLState* stateGL = SLGLState::getInstance(); stateGL->modelViewMatrix.setMatrix(stateGL->viewMatrix); SLint numTangentPoints = numControlPoints * 2; SLint numCurvePoints = _vao.numVertices() - (SLint)_points.size() - numControlPoints - numTangentPoints; // Draw curve as a line strip through interpolated points _vao.drawArrayAsColored(PT_lineStrip, SLCol3f::RED, 1, 0, numCurvePoints); // ES2 has often problems with rendering points #ifndef SL_GLES2 // Draw curve as a line strip through interpolated points _vao.drawArrayAsColored(PT_points, SLCol4f::RED, 3, 0, numCurvePoints); // Draw input points _vao.drawArrayAsColored(PT_points, SLCol4f::BLUE, 6, numCurvePoints, (SLuint)_points.size()); // Draw control points _vao.drawArrayAsColored(PT_points, SLCol4f::YELLOW, 6, numCurvePoints + (SLuint)_points.size(), numControlPoints); // Draw tangent points as lines _vao.drawArrayAsColored(PT_lines, SLCol4f::YELLOW, 1, numCurvePoints + (SLint)_points.size() + numControlPoints, numTangentPoints); #endif }