void MQuaternion::setFromVectors(const MVector3 & source, const MVector3 & destination) { MVector3 axis=source.crossProduct(destination); float angle = acosf(source.getNormalized().dotProduct(destination.getNormalized())); setFromAngleAxis((float)(angle*RAD_TO_DEG), axis); }
void MQuaternion::setFromAngleAxis(float angle, const MVector3 & axis) { const MVector3 normAxis = axis.getNormalized(); float sinHalfAngle = (float)sin((angle * DEG_TO_RAD) / 2.0); float cosHalfAngle = (float)cos((angle * DEG_TO_RAD) / 2.0); values[0] = sinHalfAngle * normAxis.x; values[1] = sinHalfAngle * normAxis.y; values[2] = sinHalfAngle * normAxis.z; values[3] = cosHalfAngle; normalize(); }
MVector3 computeTangent( const MVector3 & P1, const MVector3 & P2, const MVector3 & P3, const MVector2 & UV1, const MVector2 & UV2, const MVector2 & UV3) { MVector3 Edge1 = P2 - P1; MVector3 Edge2 = P3 - P1; MVector2 Edge1uv = UV2 - UV1; MVector2 Edge2uv = UV3 - UV1; float cp = Edge1uv.y * Edge2uv.x - Edge1uv.x * Edge2uv.y; if(cp != 0.0f) { float mul = 1.0f / cp; MVector3 tangent = (Edge1 * -Edge2uv.y + Edge2 * Edge1uv.y) * mul; return tangent.getNormalized(); } return MVector3(0.0f, 0.0f, 0.0f); }
void MBLookAt::update(void) { MEngine * engine = MEngine::getInstance(); MLevel * level = engine->getLevel(); MScene * scene = level->getCurrentScene(); MObject3d * parent = getParentObject(); const char * targetName = m_targetName.getData(); if(strcmp(targetName, "none") == 0) return; // target object MObject3d * object = scene->getObjectByName(targetName); if(! object) return; // direction MVector3 direction = object->getTransformedPosition() - parent->getTransformedPosition(); if(direction.x == 0 && direction.y == 0 && direction.z == 0) return; float angle; float roll; MVector3 axis; // compute initial roll MVector3 ZAxis = parent->getInverseRotatedVector(MVector3(0, 0, 1)).getNormalized(); ZAxis.z = 0; ZAxis.normalize(); if(ZAxis.x == 0 && ZAxis.y == 0) { MVector3 YAxis = parent->getInverseRotatedVector(MVector3(0, 1, 0)).getNormalized(); YAxis.z = 0; YAxis.normalize(); axis = MVector3(0, 1, 0).crossProduct(YAxis); roll = acosf(MVector3(0, 1, 0).dotProduct(YAxis)); if(MVector3(0, 0, 1).dotProduct(axis) < 0) roll = -roll; } else { axis = MVector3(0, 1, 0).crossProduct(ZAxis); roll = acosf(MVector3(0, 1, 0).dotProduct(ZAxis)); if(MVector3(0, 0, 1).dotProduct(axis) < 0) roll = -roll; } if(roll < 0.001f && roll > -0.001f) roll = 0; // look-at MVector3 cameraAxis = MVector3(0, 0, -1); axis = cameraAxis.crossProduct(direction); angle = acosf(cameraAxis.dotProduct(direction.getNormalized())); parent->setAxisAngleRotation(axis, (float)(angle * RAD_TO_DEG)); parent->updateMatrix(); // set roll ZAxis = parent->getInverseRotatedVector(MVector3(0, 0, 1)).getNormalized();; ZAxis.z = 0; ZAxis.normalize(); if(ZAxis.x == 0 && ZAxis.y == 0) { parent->addAxisAngleRotation(MVector3(0, 0, 1), (float)(-roll*RAD_TO_DEG)); } else { axis = MVector3(0, 1, 0).crossProduct(ZAxis); angle = acosf(MVector3(0, 1, 0).dotProduct(ZAxis)); if(angle < 0.001f && angle > -0.001f) angle = 0; if(MVector3(0, 0, 1).dotProduct(axis) < 0) angle = -angle; parent->addAxisAngleRotation(MVector3(0, 0, 1), (float)((angle-roll)*RAD_TO_DEG)); } }