//----------------------------------------------------------------------- Quaternion Quaternion::Exp () const { // If q = A*(x*i+y*j+z*k) where (x,y,z) is unit length, then // exp(q) = cos(A)+sin(A)*(x*i+y*j+z*k). If sin(A) is near zero, // use exp(q) = cos(A)+A*(x*i+y*j+z*k) since A/sin(A) has limit 1. Radian fAngle ( Math::Sqrt(x*x+y*y+z*z) ); scalar fSin = Math::Sin(fAngle); Quaternion kResult; kResult.w = Math::Cos(fAngle); if ( fabs(fSin) >= ms_fEpsilon ) { scalar fCoeff = fSin/(fAngle.valueRadians()); kResult.x = fCoeff*x; kResult.y = fCoeff*y; kResult.z = fCoeff*z; } else { kResult.x = x; kResult.y = y; kResult.z = z; } return kResult; }
void Camera::renderObject() { if(polygonMode == PM_SOLID) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); else if(polygonMode == PM_WIREFRAME) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else if(polygonMode == PM_POINTS) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); glLoadIdentity(); // Reset The View // update parameters if it's tracking if(autoTrackingEnabled && trackingTarget != NULL) { setOrientation(trackingTarget->getOrientation()); setPosition(trackingTarget->getPosition() + trackingOffset); } Radian radRotation; WasVec3d axis; rotation.inverse().toAngleAxis(radRotation, axis); glRotatef(radRotation.valueDegrees(), axis.x, axis.y, axis.z); glTranslatef(-translation[0], -translation[1], -translation[2]); }
void KisColorSelector::mousePressEvent(QMouseEvent* event) { m_clickPos = mapCoord(event->posF(), m_renderArea); m_mouseMoved = false; m_pressedButtons = event->buttons(); m_clickedRing = getSaturationIndex(m_clickPos); qint8 clickedLightPiece = getLightIndex(event->posF()); if (clickedLightPiece >= 0) { setLight(getLight(event->posF()), m_relativeLight); m_selectedLightPiece = clickedLightPiece; setSelectedColor(m_selectedColor, !(m_pressedButtons & Qt::RightButton), true); m_mouseMoved = true; } else if (m_clickedRing >= 0) { if (getNumPieces() > 1) { for(int i=0; i<getNumRings(); ++i) m_colorRings[i].setTemporaries(m_selectedColor); } else { Radian angle = std::atan2(m_clickPos.x(), m_clickPos.y()) - RAD_90; m_selectedColor.setH(angle.scaled(0.0f, 1.0f)); m_selectedColor.setS(getSaturation(m_clickedRing)); m_selectedColor.setX(getLight(m_light, m_selectedColor.getH(), m_relativeLight)); setSelectedColor(m_selectedColor, !(m_pressedButtons & Qt::RightButton), true); m_selectedRing = m_clickedRing; m_mouseMoved = true; update(); } } }
//----------------------------------------------------------------------- bool Quaternion::equals(const Quaternion& rhs, const Radian& tolerance) const { Real d = Dot(rhs); Radian angle = Math::ACos(2.0f * d*d - 1.0f); return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians(); }
// ----------------------------------------------------------------------------------------- bool CPepeEngineVector3::directionEquals(const CPepeEngineVector3& rhs, const Radian& tolerance) const { float dot = dotProduct(rhs); Radian angle = CPepeEngineMath::ACos(dot); return CPepeEngineMath::Abs(angle.valueRadians()) <= tolerance.valueRadians(); }
//----------------------------------------------------------------------- Quaternion Quaternion::Log () const { // If q = cos(A)+sin(A)*(x*i+y*j+z*k) where (x,y,z) is unit length, then // log(q) = A*(x*i+y*j+z*k). If sin(A) is near zero, use log(q) = // sin(A)*(x*i+y*j+z*k) since sin(A)/A has limit 1. Quaternion kResult; kResult.w = 0.0; if ( Math::Abs(w) < 1.0 ) { Radian fAngle ( Math::ACos(w) ); Real fSin = Math::Sin(fAngle); if ( Math::Abs(fSin) >= ms_fEpsilon ) { Real fCoeff = fAngle.valueRadians()/fSin; kResult.x = fCoeff*x; kResult.y = fCoeff*y; kResult.z = fCoeff*z; return kResult; } } kResult.x = x; kResult.y = y; kResult.z = z; return kResult; }
//----------------------------------------------------------------------------- /// void ImpostorPage::update() { if (m_mapImpostorBatches.empty()) // SVA speed up return; //Calculate the direction the impostor batches should be facing Vector3 camPos = m_pPagedGeom->_convertToLocal(m_pPagedGeom->getCamera()->getDerivedPosition()); // Update all batches Ogre::Real distX = camPos.x - m_vecCenter.x; Ogre::Real distZ = camPos.z - m_vecCenter.z; Ogre::Real distY = camPos.y - m_vecCenter.y; Ogre::Real distRelZ = Math::Sqrt(distX * distX + distZ * distZ); Radian pitch = Math::ATan2(distY, distRelZ); Radian yaw; if (distRelZ > m_pPagedGeom->getPageSize() * 3) { yaw = Math::ATan2(distX, distZ); } else { Vector3 dir = m_pPagedGeom->_convertToLocal(m_pPagedGeom->getCamera()->getDerivedDirection()); yaw = Math::ATan2(-dir.x, -dir.z); } TImpostorBatchs::iterator iter = m_mapImpostorBatches.begin(), iend = m_mapImpostorBatches.end(); while (iter != iend) { iter->second->setAngle(pitch.valueDegrees(), yaw.valueDegrees()); ++iter; } }
void ImpostorPage::update() { //Calculate the direction the impostor batches should be facing Vector3 camPos = geom->_convertToLocal(geom->getCamera()->getDerivedPosition()); //Update all batches float distX = camPos.x - center.x; float distZ = camPos.z - center.z; float distY = camPos.y - center.y; float distRelZ = Math::Sqrt(distX * distX + distZ * distZ); Radian pitch = Math::ATan2(distY, distRelZ); Radian yaw; if (distRelZ > geom->getPageSize() * 3) { yaw = Math::ATan2(distX, distZ); } else { Vector3 dir = geom->_convertToLocal(geom->getCamera()->getDerivedDirection()); yaw = Math::ATan2(-dir.x, -dir.z); } std::map<String, ImpostorBatch *>::iterator iter; for (iter = impostorBatches.begin(); iter != impostorBatches.end(); ++iter){ ImpostorBatch *ibatch = iter->second; ibatch->setAngle(pitch.valueDegrees(), yaw.valueDegrees()); } }
//----------------------------------------------------------------------- Quaternion Quaternion::Exp () const { // If q = A*(x*i+y*j+z*k) where (x,y,z) is unit length, then // exp(q) = e^w(cos(A)+sin(A)*(x*i+y*j+z*k)). If sin(A) is near zero, // use exp(q) = e^w(cos(A)+(x*i+y*j+z*k)) since sin(A)/A has limit 1. Radian fAngle ( Math::Sqrt(x*x+y*y+z*z) ); Real fSin = Math::Sin(fAngle); Real fExpW = Math::Exp(w); Quaternion kResult; kResult.w = fExpW*Math::Cos(fAngle); if ( Math::Abs(fAngle.valueRadians()) >= msEpsilon ) { Real fCoeff = fExpW*(fSin/(fAngle.valueRadians())); kResult.x = fCoeff*x; kResult.y = fCoeff*y; kResult.z = fCoeff*z; } else { kResult.x = fExpW*x; kResult.y = fExpW*y; kResult.z = fExpW*z; } return kResult; }
//----------------------------------------------------------------------- Quaternion Quaternion::Log () const { // If q = cos(A)+sin(A)*(x*i+y*j+z*k) where (x,y,z) is unit length, then // log(q) = (A/sin(A))*(x*i+y*j+z*k). If sin(A) is near zero, use // log(q) = (x*i+y*j+z*k) since A/sin(A) has limit 1. Quaternion kResult; kResult.w = 0.0; if ( Math::Abs(w) < 1.0 ) { // According to Neil Dantam, atan2 has the best stability. // http://www.neil.dantam.name/note/dantam-quaternion.pdf Real fNormV = Math::Sqrt(x*x + y*y + z*z); Radian fAngle ( Math::ATan2(fNormV, w) ); Real fSin = Math::Sin(fAngle); if ( Math::Abs(fSin) >= msEpsilon ) { Real fCoeff = fAngle.valueRadians()/fSin; kResult.x = fCoeff*x; kResult.y = fCoeff*y; kResult.z = fCoeff*z; return kResult; } } kResult.x = x; kResult.y = y; kResult.z = z; return kResult; }
//--------------------------------------------------------------------- bool NodeAnimationTrack::hasNonZeroKeyFrames(void) const { KeyFrameList::const_iterator i = mKeyFrames.begin(); for (; i != mKeyFrames.end(); ++i) { // look for keyframes which have any component which is non-zero // Since exporters can be a little inaccurate sometimes we use a // tolerance value rather than looking for nothing TransformKeyFrame* kf = static_cast<TransformKeyFrame*>(*i); Vector3 trans = kf->getTranslate(); Vector3 scale = kf->getScale(); Vector3 axis; Radian angle; kf->getRotation().ToAngleAxis(angle, axis); Real tolerance = 1e-3f; if (!trans.positionEquals(Vector3::ZERO, tolerance) || !scale.positionEquals(Vector3::UNIT_SCALE, tolerance) || !Math::RealEqual(angle.valueRadians(), 0.0f, tolerance)) { return true; } } return false; }
//----------------------------------------------------------------------- Quaternion Quaternion::Slerp (Real fT, const Quaternion& rkP, const Quaternion& rkQ, bool shortestPath) { Real fCos = rkP.Dot(rkQ); Radian fAngle ( Math::ACos(fCos) ); if ( Math::Abs(fAngle.valueRadians()) < ms_fEpsilon ) return rkP; Real fSin = Math::Sin(fAngle); Real fInvSin = 1.0/fSin; Real fCoeff0 = Math::Sin((1.0-fT)*fAngle)*fInvSin; Real fCoeff1 = Math::Sin(fT*fAngle)*fInvSin; // Do we need to invert rotation? if (fCos < 0.0f && shortestPath) { fCoeff0 = -fCoeff0; // taking the complement requires renormalisation Quaternion t(fCoeff0*rkP + fCoeff1*rkQ); t.normalise(); return t; } else { return fCoeff0*rkP + fCoeff1*rkQ; } }
void assign(Quaternion<T>& quat, const Radian& roll, const Radian& pitch, const Radian& yaw) { double angle = roll.v() * 0.5; double sr = std::sin(angle); double cr = std::cos(angle); angle = pitch.v() * 0.5; double sp = std::sin(angle); double cp = std::cos(angle); angle = yaw.v() * 0.5; double sy = std::sin(angle); double cy = std::cos(angle); double cpcy = cp * cy; double spcy = sp * cy; double cpsy = cp * sy; double spsy = sp * sy; quat.setW(cr * cpcy + sr * spsy); quat.setX(sr * cpcy - cr * spsy); quat.setY(cr * spcy + sr * cpsy); quat.setZ(cr * cpsy - sr * spcy); normalise(quat); }
bool Quaternion::equals(const Quaternion& rhs, const Radian& tolerance) const { Real fCos = Dot(rhs); Radian angle = Math::ACos(fCos); return (Math::Abs(angle.valueRadians()) <= tolerance.valueRadians()) || Math::RealEqual(angle.valueRadians(), Math::PI, tolerance.valueRadians()); }
//----------------------------------------------------------------------- void MeshParticleVisualData::setOrientation( const Radian &yaw, const Radian &pitch, const Radian &roll ) { Quaternion yawQua(Degree(yaw.valueDegrees()), Vector3::UNIT_Y); Quaternion pitchQua(Degree(pitch.valueDegrees()), Vector3::UNIT_X); Quaternion rollQua(Degree(roll.valueDegrees()), Vector3::UNIT_Z); mSceneNode->setOrientation(yawQua * pitchQua * rollQua); }
void CameraBehaviorVehicleSpline::update(const CameraManager::CameraContext &ctx) { if ( ctx.mCurrTruck->free_camerarail <= 0 ) { gEnv->cameraManager->switchToNextBehavior(); return; } Vector3 dir = (ctx.mCurrTruck->nodes[ctx.mCurrTruck->cameranodepos[0]].smoothpos - ctx.mCurrTruck->nodes[ctx.mCurrTruck->cameranodedir[0]].smoothpos).normalisedCopy(); targetPitch = 0.0f; if ( camPitching ) { targetPitch = -asin(dir.dotProduct(Vector3::UNIT_Y)); } if ( ctx.mCurrTruck->getAllLinkedBeams().size() != numLinkedBeams ) { createSpline(ctx); } updateSpline(); updateSplineDisplay(); camLookAt = spline->interpolate(splinePos); if ( RoR::Application::GetInputEngine()->isKeyDown(OIS::KC_LSHIFT) && RoR::Application::GetInputEngine()->isKeyDownValueBounce(OIS::KC_SPACE) ) { autoTracking = !autoTracking; #ifdef USE_MYGUI if ( autoTracking ) { RoR::Application::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("auto tracking enabled"), "camera_go.png", 3000); } else { RoR::Application::GetConsole()->putMessage(Console::CONSOLE_MSGTYPE_INFO, Console::CONSOLE_SYSTEM_NOTICE, _L("auto tracking disabled"), "camera_go.png", 3000); } #endif // USE_MYGUI } if ( autoTracking ) { Vector3 centerDir = ctx.mCurrTruck->getPosition() - camLookAt; if ( centerDir.length() > 1.0f ) { centerDir.normalise(); Radian oldTargetDirection = targetDirection; targetDirection = -atan2(centerDir.dotProduct(Vector3::UNIT_X), centerDir.dotProduct(-Vector3::UNIT_Z)); if ( targetDirection.valueRadians() * oldTargetDirection.valueRadians() < 0.0f && centerDir.length() < camDistMin) { camRotX = -camRotX; } } } CameraBehaviorOrbit::update(ctx); }
void LightRenderingParams::setParameters(const LightCore* light) { // Note: I could just copy the data directly to the parameter buffer if I ensured the parameter // layout matches Vector4 positionAndType = (Vector4)light->getPosition(); switch (light->getType()) { case LightType::Directional: positionAndType.w = 0; break; case LightType::Point: positionAndType.w = 0.3f; break; case LightType::Spot: positionAndType.w = 0.8f; break; } mBuffer.gLightPositionAndType.set(positionAndType); Vector4 colorAndIntensity; colorAndIntensity.x = light->getColor().r; colorAndIntensity.y = light->getColor().g; colorAndIntensity.z = light->getColor().b; colorAndIntensity.w = light->getIntensity(); mBuffer.gLightColorAndIntensity.set(colorAndIntensity); Radian spotAngle = Math::clamp(light->getSpotAngle() * 0.5f, Degree(1), Degree(90)); Radian spotFalloffAngle = Math::clamp(light->getSpotFalloffAngle() * 0.5f, Degree(1), (Degree)spotAngle); Vector4 spotAnglesAndInvSqrdRadius; spotAnglesAndInvSqrdRadius.x = spotAngle.valueRadians(); spotAnglesAndInvSqrdRadius.y = Math::cos(spotAnglesAndInvSqrdRadius.x); spotAnglesAndInvSqrdRadius.z = 1.0f / (Math::cos(spotFalloffAngle) - spotAnglesAndInvSqrdRadius.y); spotAnglesAndInvSqrdRadius.w = 1.0f / (light->getBounds().getRadius() * light->getBounds().getRadius()); mBuffer.gLightSpotAnglesAndSqrdInvRadius.set(spotAnglesAndInvSqrdRadius); mBuffer.gLightDirection.set(-light->getRotation().zAxis()); Vector4 lightGeometry; lightGeometry.x = light->getType() == LightType::Spot ? (float)LightCore::LIGHT_CONE_NUM_SIDES : 0; lightGeometry.y = (float)LightCore::LIGHT_CONE_NUM_SLICES; lightGeometry.z = light->getBounds().getRadius(); float coneRadius = Math::sin(spotAngle) * light->getRange(); lightGeometry.w = coneRadius; mBuffer.gLightGeometry.set(lightGeometry); Matrix4 transform = Matrix4::TRS(light->getPosition(), light->getRotation(), Vector3::ONE); mBuffer.gMatConeTransform.set(transform); mBuffer.flushToGPU(); }
// ----------------------------------------------------------------------------------------- bool CPepeEngineQuaternion::equals(const CPepeEngineQuaternion& rhs, const Radian& tolerance) const { float fCos = dot(rhs); Radian angle = CPepeEngineMath::ACos(fCos); return (CPepeEngineMath::Abs(angle.valueRadians()) <= tolerance.valueRadians()) || CPepeEngineMath::floatEqual(angle.valueRadians(), CPepeEngineMath::PI, tolerance.valueRadians()); }
void KisColorSelector::mouseMoveEvent(QMouseEvent* event) { QPointF dragPos = mapCoord(event->posF(), m_renderArea); qint8 clickedLightPiece = getLightIndex(event->posF()); if (clickedLightPiece >= 0) { setLight(getLight(event->posF()), m_relativeLight); m_selectedLightPiece = clickedLightPiece; setSelectedColor(m_selectedColor, m_selectedColorIsFgColor, true); } if (m_clickedRing < 0) return; if (getNumPieces() > 1) { float angle = std::atan2(dragPos.x(), dragPos.y()) - std::atan2(m_clickPos.x(), m_clickPos.y()); float dist = std::sqrt(dragPos.x()*dragPos.x() + dragPos.y()*dragPos.y()) * 0.80f; float threshold = 5.0f * (1.0f-(dist*dist)); if (qAbs(angle * TO_DEG) >= threshold || m_mouseMoved) { bool selectedRingMoved = true; if (m_pressedButtons & Qt::RightButton) { selectedRingMoved = m_clickedRing == m_selectedRing; m_colorRings[m_clickedRing].angle = m_colorRings[m_clickedRing].tmpAngle + angle; } else for(int i=0; i<getNumRings(); ++i) m_colorRings[i].angle = m_colorRings[i].tmpAngle + angle; if (selectedRingMoved) { KisColor color = m_colorRings[m_clickedRing].tmpColor; Radian angle = m_colorRings[m_clickedRing].getMovedAngel() + (color.getH()*PI2); color.setH(angle.scaled(0.0f, 1.0f)); color.setX(getLight(m_light, color.getH(), m_relativeLight)); m_selectedPiece = getHueIndex(angle, m_colorRings[m_clickedRing].getShift()); setSelectedColor(color, m_selectedColorIsFgColor, true); } m_mouseMoved = true; } } else { Radian angle = std::atan2(dragPos.x(), dragPos.y()) - RAD_90; m_selectedColor.setH(angle.scaled(0.0f, 1.0f)); m_selectedColor.setX(getLight(m_light, m_selectedColor.getH(), m_relativeLight)); setSelectedColor(m_selectedColor, m_selectedColorIsFgColor, true); } update(); }
void DemoApplication::SmoothCamera::Move (Real deltaTranslation, Real deltaStrafe, Radian pitchAngleStep, Radian yawAngleStep) { // here we update the camera movement at simulation rate m_cameraYawAngle = fmodf (m_cameraYawAngle.valueRadians() + yawAngleStep.valueRadians(), 3.141592f * 2.0f); m_cameraPitchAngle = Math::Clamp (m_cameraPitchAngle.valueRadians() + pitchAngleStep.valueRadians(), - 80.0f * 3.141592f / 180.0f, 80.0f * 3.141592f / 180.0f); Matrix3 rot; rot.FromEulerAnglesZYX (Radian (0.0f), m_cameraYawAngle, m_cameraPitchAngle); Matrix4 matrix (rot); m_cameraTranslation += Vector3 (matrix[0][2], matrix[1][2], matrix[2][2]) * deltaTranslation; m_cameraTranslation += Vector3 (matrix[0][0], matrix[1][0], matrix[2][0]) * deltaStrafe; matrix.setTrans(m_cameraTranslation); matrix = matrix.transpose(); Update (matrix[0]); }
//----------------------------------------------------------------------- Quaternion Quaternion::SlerpExtraSpins (Real fT, const Quaternion& rkP, const Quaternion& rkQ, int iExtraSpins) { Real fCos = rkP.Dot(rkQ); Radian fAngle ( Math::ACos(fCos) ); if ( Math::Abs(fAngle.valueRadians()) < msEpsilon ) return rkP; Real fSin = Math::Sin(fAngle); Radian fPhase ( Math::PI*iExtraSpins*fT ); Real fInvSin = 1.0f/fSin; Real fCoeff0 = Math::Sin((1.0f-fT)*fAngle - fPhase)*fInvSin; Real fCoeff1 = Math::Sin(fT*fAngle + fPhase)*fInvSin; return fCoeff0*rkP + fCoeff1*rkQ; }
TEST(RadianTest, ConstructTest) { Radian r; EXPECT_EQ(0.0f, r.GetRadian()); Radian r2(3.14f); EXPECT_EQ(3.14f, r2.GetRadian()); // Copy construct Radian r3(r); EXPECT_EQ(r.GetRadian(), r3.GetRadian()); // Assignment Radian r4 = r; EXPECT_EQ(r.GetRadian(), r4.GetRadian()); }
//--------------------------------------------------------------------- void XMLSkeletonSerializer::writeBone(TiXmlElement* bonesElement, const Bone* pBone) { TiXmlElement* boneElem = bonesElement->InsertEndChild(TiXmlElement("bone"))->ToElement(); // Bone name & handle boneElem->SetAttribute("id", StringConverter::toString(pBone->getHandle())); boneElem->SetAttribute("name", pBone->getName()); // Position TiXmlElement* subNode = boneElem->InsertEndChild(TiXmlElement("position"))->ToElement(); Vector3 pos = pBone->getPosition(); subNode->SetAttribute("x", StringConverter::toString(pos.x)); subNode->SetAttribute("y", StringConverter::toString(pos.y)); subNode->SetAttribute("z", StringConverter::toString(pos.z)); // Orientation subNode = boneElem->InsertEndChild(TiXmlElement("rotation"))->ToElement(); // Show Quaternion as angle / axis Radian angle; Vector3 axis; pBone->getOrientation().ToAngleAxis(angle, axis); TiXmlElement* axisNode = subNode->InsertEndChild(TiXmlElement("axis"))->ToElement(); subNode->SetAttribute("angle", StringConverter::toString(angle.valueRadians())); axisNode->SetAttribute("x", StringConverter::toString(axis.x)); axisNode->SetAttribute("y", StringConverter::toString(axis.y)); axisNode->SetAttribute("z", StringConverter::toString(axis.z)); // Scale optional Vector3 scale = pBone->getScale(); if (scale != Vector3::UNIT_SCALE) { TiXmlElement* scaleNode = boneElem->InsertEndChild(TiXmlElement("scale"))->ToElement(); scaleNode->SetAttribute("x", StringConverter::toString(scale.x)); scaleNode->SetAttribute("y", StringConverter::toString(scale.y)); scaleNode->SetAttribute("z", StringConverter::toString(scale.z)); } }
void assign(Quaternion<T>& quat, const Vector3f& axis, const Radian& angle) { double sinA = std::sin(angle.v()); double cosA = std::cos(angle.v()); quat.setW(cosA); quat.setX(axis.x() * sinA); quat.setY(axis.y() * sinA); quat.setZ(axis.z() * sinA); }
void mat3::makeTransform(const vec2& pos, const vec2& scale, const Radian& rot) { if (pos == vec2::zero && scale == vec2(1,1) && rot == Radian::zero) { *this = identity; return; } m[0][0] = std::cos(rot.radians()) * scale.x; m[0][1] = -std::sin(rot.radians()) * scale.y; m[0][2] = pos.x; m[1][0] = std::sin(rot.radians()) * scale.x; m[1][1] = std::cos(rot.radians()) * scale.y; m[1][2] = pos.y; m[2][0] = 0; m[2][1] = 0; m[2][2] = 1; }
//--------------------------------------------------------------------- void XMLSkeletonSerializer::writeKeyFrame(TiXmlElement* keysNode, const TransformKeyFrame* key) { TiXmlElement* keyNode = keysNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement(); keyNode->SetAttribute("time", StringConverter::toString(key->getTime())); TiXmlElement* transNode = keyNode->InsertEndChild(TiXmlElement("translate"))->ToElement(); Vector3 trans = key->getTranslate(); transNode->SetAttribute("x", StringConverter::toString(trans.x)); transNode->SetAttribute("y", StringConverter::toString(trans.y)); transNode->SetAttribute("z", StringConverter::toString(trans.z)); TiXmlElement* rotNode = keyNode->InsertEndChild(TiXmlElement("rotate"))->ToElement(); // Show Quaternion as angle / axis Radian angle; Vector3 axis; key->getRotation().ToAngleAxis(angle, axis); TiXmlElement* axisNode = rotNode->InsertEndChild(TiXmlElement("axis"))->ToElement(); rotNode->SetAttribute("angle", StringConverter::toString(angle.valueRadians())); axisNode->SetAttribute("x", StringConverter::toString(axis.x)); axisNode->SetAttribute("y", StringConverter::toString(axis.y)); axisNode->SetAttribute("z", StringConverter::toString(axis.z)); // Scale optional if (key->getScale() != Vector3::UNIT_SCALE) { TiXmlElement* scaleNode = keyNode->InsertEndChild(TiXmlElement("scale"))->ToElement(); scaleNode->SetAttribute("x", StringConverter::toString(key->getScale().x)); scaleNode->SetAttribute("y", StringConverter::toString(key->getScale().y)); scaleNode->SetAttribute("z", StringConverter::toString(key->getScale().z)); } }
//----------------------------------------------------------------------- Quaternion Quaternion::Slerp(Real fT, const Quaternion& rkP, const Quaternion& rkQ, bool shortestPath) { Real fCos = rkP.Dot(rkQ); Quaternion rkT; // 需要翻转旋转? if (fCos < 0.0f && shortestPath) { fCos = -fCos; rkT = -rkQ; } else { rkT = rkQ; } if (Math::Abs(fCos) < 1 - msEpsilon) { // 正常情况 (slerp) Real fSin = Math::Sqrt(1 - Math::Sqr(fCos)); Radian fAngle = Math::ATan2(fSin, fCos); Real fInvSin = 1.0f / fSin; Real fCoeff0 = Math::Sin((1.0f - fT) * fAngle.valueRadians()) * fInvSin; Real fCoeff1 = Math::Sin(fT * fAngle.valueRadians()) * fInvSin; return fCoeff0 * rkP + fCoeff1 * rkT; } else { // 这有两种情况 // 1. "rkP" 和 "rkQ" 是非常接近(fCos ~= +1), 所以我们能做安全的做线性插值 // 2. "rkP" 和 "rkQ" 几乎是每一个 (fCos ~= -1)的反转,这就有无数种插值的可能性。但是我们不可能有修正这个问题的方法, // 所有就在这里用线性插值 Quaternion t = (1.0f - fT) * rkP + fT * rkT; // 使这个分量重新标准化 t.normalise(); return t; } }
void KisColorSelector::mouseReleaseEvent(QMouseEvent* /*event*/) { if (!m_mouseMoved && m_clickedRing >= 0) { Radian angle = std::atan2(m_clickPos.x(), m_clickPos.y()) - RAD_90; m_selectedRing = m_clickedRing; m_selectedPiece = getHueIndex(angle, m_colorRings[m_clickedRing].getShift()); if (getNumPieces() > 1) m_selectedColor.setH(getHue(m_selectedPiece, m_colorRings[m_clickedRing].getShift())); else m_selectedColor.setH(angle.scaled(0.0f, 1.0f)); m_selectedColor.setS(getSaturation(m_selectedRing)); m_selectedColor.setX(getLight(m_light, m_selectedColor.getH(), m_relativeLight)); setSelectedColor(m_selectedColor, !(m_pressedButtons & Qt::RightButton)); } else if (m_mouseMoved) setSelectedColor(m_selectedColor, m_selectedColorIsFgColor); m_clickedRing = -1; update(); }
//----------------------------------------------------------------------- void Quaternion::FromAngleAxis(const Radian& rfAngle, const Vector3& rkAxis) { // 断言: axis[] 是单位长度 // // 这个四元数表示的旋转是 // q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k) Radian fHalfAngle(0.5*rfAngle.valueRadians()); Real fSin = Math::Sin(fHalfAngle); w = Math::Cos(fHalfAngle); x = fSin*rkAxis.x; y = fSin*rkAxis.y; z = fSin*rkAxis.z; }
inline void wrapAngle(Radian& angle) { Real rangle = angle.valueRadians(); if (rangle < -Math::PI) { rangle = fmod(rangle, -Math::TWO_PI); if (rangle < -Math::PI) { rangle += Math::TWO_PI; } angle = rangle; mChanged = true; } else if (rangle > Math::PI) { rangle = fmod(rangle, Math::TWO_PI); if (rangle > Math::PI) { rangle -= Math::TWO_PI; } angle = rangle; mChanged = true; } }