示例#1
0
//-----------------------------------------------------------------------------
//! Returns an aiBone ptr if name exists, or null if it doesn't
const SLMat4f SLAssimpImporter::getOffsetMat(const SLstring& name)
{
	if(_jointOffsets.find(name) != _jointOffsets.end())
		return _jointOffsets[name];

	return SLMat4f();
}
示例#2
0
/*!
Applies the view transform to the modelview matrix depending on the eye:
eye=-1 for left, eye=1 for right
*/
void SLCamera::setView(const SLEye eye)
{  
   SLSceneView* sv = SLScene::current->activeSV();
   
   if (eye == centerEye)
   {  stateGL->modelViewMatrix.identity();
      stateGL->modelViewMatrix.multiply(_vm); 
   } 
   else // stereo viewing
   {
      if (_projection == stereoSideBySideD)
      {  
         // half interpupilar distance
         _eyeSeparation = sv->oculus()->eyeSeparation();
         SLfloat halfIPD = (SLfloat)eye * _eyeSeparation * -0.5f;

         // get the oculus orientation
         SLMat4f rotation(sv->oculus()->orientation().toMat4());
         SLMat4f vmEye(SLMat4f(halfIPD, 0.0f, 0.f) * rotation * _vm);
         stateGL->modelViewMatrix = vmEye;
         stateGL->viewMatrix = vmEye;
      }
      else
      {
         // Get central camera vectors eye, lookAt, lookUp out of the view matrix vm
         SLVec3f EYE, LA, LU, LR;
         _vm.lookAt(&EYE, &LA, &LU, &LR);
   
         // Shorten LR to half of the eye dist (eye=-1 for left, eye=1 for right)
         LR *= _eyeSeparation * 0.5f * (SLfloat)eye;
      
         // Set the OpenGL view matrix for the left eye
         SLMat4f vmEye;
         vmEye.lookAt(EYE+LR, EYE + _focalDist*LA+LR, LU);
         stateGL->modelViewMatrix = vmEye;
         stateGL->viewMatrix = vmEye;
      }
   } 
}
示例#3
0
/*!
Applies the view transform to the modelview matrix depending on the eye:
eye=-1 for left, eye=1 for right
*/
void SLCamera::setView(SLSceneView* sv, const SLEye eye)
{  
    SLScene* s = SLScene::current;
   
    SLMat4f vm = updateAndGetWMI();

    if (eye == centerEye)
    {   _stateGL->modelViewMatrix.identity();
        _stateGL->viewMatrix.setMatrix(vm);
    } 
    else // stereo viewing
    {
        if (_projection == stereoSideBySideD)
        {  
            // half interpupilar disqtance
            //_eyeSeparation = s->oculus()->interpupillaryDistance(); update old rift code
            SLfloat halfIPD = (SLfloat)eye * _eyeSeparation * -0.5f;
            
            SLMat4f trackingPos;
            if (_useDeviceRot)
            {
                // get the oculus or mobile device orientation
                SLQuat4f rotation;
                if (s->oculus()->isConnected())
                {
                    rotation = s->oculus()->orientation(eye);
                    trackingPos.translate(-s->oculus()->position(eye));
                }
                else rotation = sv->deviceRotation();

                SLfloat rotX, rotY, rotZ;
                rotation.toMat4().toEulerAnglesZYX(rotZ, rotY, rotX);
                //SL_LOG("rotx : %3.1f, roty: %3.1f, rotz: %3.1f\n", rotX*SL_RAD2DEG, rotY*SL_RAD2DEG, rotZ*SL_RAD2DEG);
                SLVec3f viewAdjust = s->oculus()->viewAdjust(eye) * _unitScaling;
                SLMat4f vmEye(SLMat4f(viewAdjust.x, viewAdjust.y, viewAdjust.z) * rotation.inverted().toMat4() * trackingPos * vm);
                _stateGL->modelViewMatrix = vmEye;
                _stateGL->viewMatrix = vmEye;
            } 
            else
            {      
                SLMat4f vmEye(SLMat4f(halfIPD, 0.0f, 0.f) * vm);
                _stateGL->modelViewMatrix = vmEye;
                _stateGL->viewMatrix = vmEye;
            }
        }
        else
        {
            // Get central camera vectors eye, lookAt, lookUp out of the view matrix vm
            SLVec3f EYE, LA, LU, LR;
            vm.lookAt(&EYE, &LA, &LU, &LR);
   
            // Shorten LR to half of the eye dist (eye=-1 for left, eye=1 for right)
            LR *= _eyeSeparation * 0.5f * (SLfloat)eye;
      
            // Set the OpenGL view matrix for the left eye
            SLMat4f vmEye;
            vmEye.lookAt(EYE+LR, EYE + _focalDist*LA+LR, LU);
            _stateGL->modelViewMatrix = vmEye;
            _stateGL->viewMatrix = vmEye;
        }
    } 
}
示例#4
0
/*!
SLAssimpImporter::loadAnimation loads the scene graph node tree recursively.
*/
SLAnimation* SLAssimpImporter::loadAnimation(aiAnimation* anim)
{
    int animCount = 0;
    if (_skeleton) animCount = _skeleton->numAnimations();
    ostringstream oss;
    oss << "unnamed_anim_" << animCount;
    SLstring animName = oss.str();
    SLfloat animTicksPerSec = (anim->mTicksPerSecond == 0) ? 30.0f : (SLfloat)anim->mTicksPerSecond;
    SLfloat animDuration = (SLfloat)anim->mDuration / animTicksPerSec;

    if (anim->mName.length > 0)
        animName = anim->mName.C_Str();

    // log
    logMessage(LV_minimal, "\nLoading animation %s\n", animName.c_str());
    logMessage(LV_normal, " Duration(seconds): %f \n", animDuration);
    logMessage(LV_normal, " Duration(ticks): %f \n", anim->mDuration);
    logMessage(LV_normal, " Ticks per second: %f \n", animTicksPerSec);
    logMessage(LV_normal, " Num channels: %d\n", anim->mNumChannels);
                
    // exit if we didn't load a skeleton but have animations for one
    if (_skinnedMeshes.size() > 0)
        assert(_skeleton != nullptr && "The skeleton wasn't impoted correctly."); 
    
    // create the animation
    SLAnimation* result;
    if (_skeleton)
        result = _skeleton->createAnimation(animName, animDuration);
    else
    {
        result = SLScene::current->animManager().createNodeAnimation(animName, animDuration);
        _nodeAnimations.push_back(result);
    }


    SLbool isSkeletonAnim = false;
    for (SLuint i = 0; i < anim->mNumChannels; i++)
    {
        aiNodeAnim* channel = anim->mChannels[i];

        // find the node that is animated by this channel
        SLstring nodeName = channel->mNodeName.C_Str();
        SLNode* affectedNode = _sceneRoot->find<SLNode>(nodeName);
        SLuint id = 0;
        SLbool isJointNode = (affectedNode == nullptr);

        // @todo: this is currently a work around but it can happen that we receive normal node animationtracks and joint animationtracks
        //        we don't allow node animation tracks in a skeleton animation, so we should split an animation in two seperate 
        //        animations if this happens. for now we just ignore node animation tracks if we already have joint tracks
        //        ofc this will crash if the first track is a node anim but its just temporary
        if (!isJointNode && isSkeletonAnim)
            continue;

        // is there a skeleton and is this animation channel not affecting a normal node?
        if (_skeletonRoot && !affectedNode)
        {
            isSkeletonAnim = true;
            SLJoint* affectedJoint = _skeleton->getJoint(nodeName);
            if (affectedJoint == nullptr)
                break;

            id = affectedJoint->id();
            // @todo warn if we find an animation with some node channels and some joint channels
            //       this shouldn't happen!

            /// @todo [high priority!] Address the problem of some bones not containing an animation channel
            ///         when importing. Current workaround is to set their reset position to their bind pose.
            ///         This will however fail if we have multiple animations affecting a single model and fading
            ///         some of them out or in. This will require us to provide animations that have a channel
            ///         for all bones even if they're just positional.
            // What does this next line do?
            //   
            //   The testimportfile we used (Astroboy.dae) has the following properties:
            //      > It has joints in the skeleton that aren't animated by any channel.
            //      > The joints need a reset position of (0, 0, 0) to work properly 
            //          because the joint position is contained in a single keyframe for every joint
            //
            //      Since some of the joints don't have a channel that animates them, they also lack
            //      the joint position that the other joints get from their animation channel.
            //      So we need to set the initial state for all joints that have a channel
            //      to identity.
            //      All joints that arent in a channel will receive their local joint bind pose as
            //      reset position.
            //
            //      The problem stems from the design desicion to reset a whole skeleton before applying 
            //      animations to it. If we were to reset each joint just before applying a channel to it
            //      we wouldn't have this problem. But we coulnd't blend animations as easily.
            //
            SLMat4f prevOM = affectedJoint->om();
            affectedJoint->om(SLMat4f());
            affectedJoint->setInitialState();
            affectedJoint->om(prevOM);
        }
                            
        // log
        logMessage(LV_normal, "\n  Channel %d %s", i, (isJointNode) ? "(joint animation)\n" : "\n");
        logMessage(LV_normal, "   Affected node: %s\n", channel->mNodeName.C_Str());
        logMessage(LV_detailed, "   Num position keys: %d\n", channel->mNumPositionKeys);
        logMessage(LV_detailed, "   Num rotation keys: %d\n", channel->mNumRotationKeys);
        logMessage(LV_detailed, "   Num scaling keys: %d\n", channel->mNumScalingKeys);

        
        // joint animation channels should receive the correct node id, normal node animations just get 0
        SLNodeAnimTrack* track = result->createNodeAnimationTrack(id);

        
        // this is a node animation only, so we add a reference to the affected node to the track
        if (affectedNode && !isSkeletonAnim) {
            track->animatedNode(affectedNode);
        }

        KeyframeMap keyframes;

        // add position keys
        for (SLuint i = 0; i < channel->mNumPositionKeys; i++)
        {
            SLfloat time = (SLfloat)channel->mPositionKeys[i].mTime; 
            keyframes[time] = SLImportKeyframe(&channel->mPositionKeys[i], nullptr, nullptr);
        }
        
        // add rotation keys
        for (SLuint i = 0; i < channel->mNumRotationKeys; i++)
        {
            SLfloat time = (SLfloat)channel->mRotationKeys[i].mTime;

            if (keyframes.find(time) == keyframes.end())
                keyframes[time] = SLImportKeyframe(nullptr, &channel->mRotationKeys[i], nullptr);
            else
            {
                // @todo this shouldn't abort but just throw an exception
                assert(keyframes[time].rotation == nullptr && "There were two rotation keys assigned to the same timestamp.");
                keyframes[time].rotation = &channel->mRotationKeys[i];
            }
        }
        
        // add scaleing keys
        for (SLuint i = 0; i < channel->mNumScalingKeys; i++)
        {
            SLfloat time = (SLfloat)channel->mScalingKeys[i].mTime; 

            if (keyframes.find(time) == keyframes.end())
                keyframes[time] = SLImportKeyframe(nullptr, nullptr, &channel->mScalingKeys[i]);
            else
            {
                // @todo this shouldn't abort but just throw an exception
                assert(keyframes[time].scaling == nullptr && "There were two scaling keys assigned to the same timestamp.");
                keyframes[time].scaling = &channel->mScalingKeys[i];
            }
        }

        logMessage(LV_normal, "   Found %d distinct keyframe timestamp(s).\n", 
                              keyframes.size());

        for (auto it : keyframes)
        {   SLTransformKeyframe* kf = track->createNodeKeyframe(it.first);         
            kf->translation(getTranslation(it.first, keyframes));
            kf->rotation(getRotation(it.first, keyframes));
            kf->scale(getScaling(it.first, keyframes));

            // log
            logMessage(LV_detailed, "\n   Generating keyframe at time '%.2f'\n", 
                       it.first);
            logMessage(LV_detailed, "    Translation: (%.2f, %.2f, %.2f) %s\n", 
                       kf->translation().x, 
                       kf->translation().y, 
                       kf->translation().z, 
                       (it.second.translation != nullptr) ? "imported" : "generated");
            logMessage(LV_detailed, "    Rotation: (%.2f, %.2f, %.2f, %.2f) %s\n", 
                       kf->rotation().x(), 
                       kf->rotation().y(), 
                       kf->rotation().z(), 
                       kf->rotation().w(), 
                       (it.second.rotation != nullptr) ? "imported" : "generated");
            logMessage(LV_detailed, "    Scale: (%.2f, %.2f, %.2f) %s\n", 
                       kf->scale().x, 
                       kf->scale().y, 
                       kf->scale().z, 
                       (it.second.scaling != nullptr) ? "imported" : "generated");
        }
    }
    
    return result;
}