Example #1
0
Quaternion Camera::GetFaceCameraRotation(const Vector3& position, const Quaternion& rotation, FaceCameraMode mode, float minAngle)
{
    if (!node_)
        return rotation;

    switch (mode)
    {
    case FC_ROTATE_XYZ:
        return node_->GetWorldRotation();

    case FC_ROTATE_Y:
        {
            Vector3 euler = rotation.EulerAngles();
            euler.y_ = node_->GetWorldRotation().EulerAngles().y_;
            return Quaternion(euler.x_, euler.y_, euler.z_);
        }

    case FC_LOOKAT_XYZ:
        {
            Quaternion lookAt;
            lookAt.FromLookRotation(position - node_->GetWorldPosition());
            return lookAt;
        }

    case FC_LOOKAT_Y:
    case FC_LOOKAT_MIXED:
        {
            // Mixed mode needs true look-at vector
            const Vector3 lookAtVec(position - node_->GetWorldPosition());
            // While Y-only lookat happens on an XZ plane to make sure there are no unwanted transitions or singularities
            const Vector3 lookAtVecXZ(lookAtVec.x_, 0.0f, lookAtVec.z_);

            Quaternion lookAt;
            lookAt.FromLookRotation(lookAtVecXZ);

            Vector3 euler = rotation.EulerAngles();
            if (mode == FC_LOOKAT_MIXED)
            {
                const float angle = lookAtVec.Angle(rotation * Vector3::UP);
                if (angle > 180 - minAngle)
                    euler.x_ += minAngle - (180 - angle);
                else if (angle < minAngle)
                    euler.x_ -= minAngle - angle;
            }
            euler.y_ = lookAt.EulerAngles().y_;
            return Quaternion(euler.x_, euler.y_, euler.z_);
        }

    default:
        return rotation;
    }
}
Example #2
0
bool SpatialNode::LookAt(const Vector3& target, const Vector3& up, TransformSpace space)
{
    SpatialNode* parentNode = SpatialParent();
    Vector3 worldSpaceTarget;

    switch (space)
    {
    case TS_LOCAL:
        worldSpaceTarget = WorldTransform() * target;
        break;

    case TS_PARENT:
        worldSpaceTarget = !parentNode ? target : parentNode->WorldTransform() * target;
        break;

    case TS_WORLD:
        worldSpaceTarget = target;
        break;
    }

    Vector3 lookDir = worldSpaceTarget - WorldPosition();
    // Check if target is very close, in that case can not reliably calculate lookat direction
    if (lookDir.Equals(Vector3::ZERO))
        return false;
    Quaternion newRotation;
    // Do nothing if setting look rotation failed
    if (!newRotation.FromLookRotation(lookDir, up))
        return false;

    SetWorldRotation(newRotation);
    return true;
}
Example #3
0
Quaternion Camera::GetFaceCameraRotation(const Vector3& position, const Quaternion& rotation, FaceCameraMode mode)
{
    if (!node_)
        return rotation;

    switch (mode)
    {
    default:
        return rotation;

    case FC_ROTATE_XYZ:
        return node_->GetWorldRotation();

    case FC_ROTATE_Y:
        {
            Vector3 euler = rotation.EulerAngles();
            euler.y_ = node_->GetWorldRotation().EulerAngles().y_;
            return Quaternion(euler.x_, euler.y_, euler.z_);
        }

    case FC_LOOKAT_XYZ:
        {
            Quaternion lookAt;
            lookAt.FromLookRotation(position - node_->GetWorldPosition());
            return lookAt;
        }

    case FC_LOOKAT_Y:
        {
            // Make the Y-only lookat happen on an XZ plane to make sure there are no unwanted transitions
            // or singularities
            Vector3 lookAtVec(position - node_->GetWorldPosition());
            lookAtVec.y_ = 0.0f;

            Quaternion lookAt;
            lookAt.FromLookRotation(lookAtVec);

            Vector3 euler = rotation.EulerAngles();
            euler.y_ = lookAt.EulerAngles().y_;
            return Quaternion(euler.x_, euler.y_, euler.z_);
        }
    }
}
Example #4
0
bool Node::LookAt(const Vector3& target, const Vector3& up)
{
    Vector3 lookDir = target - GetWorldPosition();
    // Check if target is very close, in that case can not reliably calculate lookat direction
    if (lookDir.Equals(Vector3::ZERO))
        return false;
    Quaternion rotation;
    // Do nothing if setting look rotation failed
    if (!rotation.FromLookRotation(lookDir, up))
        return false;
    
    SetRotation((parent_ == scene_ || !parent_) ? rotation : parent_->GetWorldRotation().Inverse() * rotation);
    return true;
}
Example #5
0
void Bird::HandleUpdate(StringHash eventType, VariantMap &eventData)
{
    if (dead_ && GetPosition().y_ < -5.0f) Disable();

    float timeStep = eventData[SceneUpdate::P_TIMESTEP].GetFloat();
    if (sinceSpeciesSet_ < morphTime_){
        Morph();
    }
    sinceSpeciesSet_ += timeStep;

    if (sinceStateChange_ > stateDuration_){
        switch (state_) {
        case BirdState::Flying: {
            SetState(BirdState::Landing);
        } break;
        case BirdState::Standing: {
            SetState(BirdState::Flying);
        } break;
        default:
            break;
        }
    }
    if(!(first_ && state_ == BirdState::Standing)) sinceStateChange_ += timeStep;

    switch (state_) {
    case BirdState::Flying: {
        Fly(timeStep);
    } break;
    case BirdState::Landing: {
        Land(timeStep);
    } break;
    case BirdState::Standing: {
        Stand(timeStep);
    } break;
    default:
        break;
    }

    //Move bird
    rootNode_->Translate(velocity_*timeStep, TS_WORLD);

    //Update rotation in accordance with the birds movement.
    if (velocity_.Length() > 0.01f){
        Quaternion rotation = rootNode_->GetWorldRotation();
        Quaternion aimRotation = rotation;
        aimRotation.FromLookRotation(velocity_);
        rootNode_->SetRotation(rotation.Slerp(aimRotation, 2.0f * timeStep * velocity_.Length()));
    }
}
Example #6
0
void Player::HandleSceneUpdate(StringHash eventType, VariantMap &eventData)
{
    //Take the frame time step, which is stored as a double
    float timeStep = eventData[Update::P_TIMESTEP].GetFloat();
    //Pulse and spin the counters' apples and hearts
    UpdateGUI(timeStep);

    //Only handle input when player is active
    if (!rootNode_->IsEnabled()) return;

    Input* input = GetSubsystem<Input>();

    //Movement values
    Vector3 move = Vector3::ZERO;
    Vector3 moveJoy = Vector3::ZERO;
    Vector3 moveKey = Vector3::ZERO;
    float thrust = pilotMode_ ? 256.0f : 2323.0f;
    float maxSpeed = pilotMode_? 1.8f : 23.0f;    //Firing values
    Vector3 fire = Vector3::ZERO;
    Vector3 fireJoy = Vector3::ZERO;
    Vector3 fireKey = Vector3::ZERO;

    //Read input
    if (input->GetJoystickByIndex(0)){
        moveJoy = Vector3::RIGHT * input->GetJoystickByIndex(0)->GetAxisPosition(0) +
                Vector3::BACK * input->GetJoystickByIndex(0)->GetAxisPosition(1);
        fireJoy = Vector3::RIGHT * input->GetJoystickByIndex(0)->GetAxisPosition(2) +
                Vector3::BACK * input->GetJoystickByIndex(0)->GetAxisPosition(3);
    }
    moveKey = Vector3::LEFT * input->GetKeyDown(KEY_A) +
            Vector3::RIGHT * input->GetKeyDown(KEY_D) +
            Vector3::FORWARD * input->GetKeyDown(KEY_W) +
            Vector3::BACK * input->GetKeyDown(KEY_S);
    fireKey = Vector3::LEFT * (input->GetKeyDown(KEY_J) || input->GetKeyDown(KEY_KP_4)) +
            Vector3::RIGHT * (input->GetKeyDown(KEY_L) || input->GetKeyDown(KEY_KP_6)) +
            Vector3::FORWARD * (input->GetKeyDown(KEY_I) || input->GetKeyDown(KEY_KP_8)) +
            Vector3::BACK * (input->GetKeyDown(KEY_K) || input->GetKeyDown(KEY_KP_2) || input->GetKeyDown(KEY_KP_5)) +
            Quaternion(45.0f, Vector3::UP)*Vector3::LEFT * input->GetKeyDown(KEY_KP_7) +
            Quaternion(45.0f, Vector3::UP)*Vector3::RIGHT * input->GetKeyDown(KEY_KP_3) +
            Quaternion(45.0f, Vector3::UP)*Vector3::FORWARD * input->GetKeyDown(KEY_KP_9) +
            Quaternion(45.0f, Vector3::UP)*Vector3::BACK * input->GetKeyDown(KEY_KP_1);

    //Pick most significant input
    moveJoy.Length() > moveKey.Length() ? move = moveJoy : move = moveKey;
    fireJoy.Length() > fireKey.Length() ? fire = fireJoy : fire = fireKey;

    //Restrict move vector length
    if (move.Length() > 1.0f) move /= move.Length();
    //Deadzone
    else if (move.Length() < 0.1f) move *= 0.0f;

    if (fire.Length() < 0.1f) fire *= 0.0f;
    else fire.Normalize();

    //When in pilot mode
    if (pilotMode_){
        //Apply movement
        Vector3 force = move * thrust * timeStep;
        if (rigidBody_->GetLinearVelocity().Length() < maxSpeed ||
                (rigidBody_->GetLinearVelocity().Normalized() + force.Normalized()).Length() < 1.0f) {
            rigidBody_->ApplyForce(force);
        }

        //Update rotation according to direction of the player's movement.
        Vector3 velocity = rigidBody_->GetLinearVelocity();
        Vector3 lookDirection = velocity + 2.0f*fire;
        Quaternion rotation = rootNode_->GetWorldRotation();
        Quaternion aimRotation = rotation;
        aimRotation.FromLookRotation(lookDirection);
        rootNode_->SetRotation(rotation.Slerp(aimRotation, 7.0f * timeStep * velocity.Length()));

        //Update animation
        if (velocity.Length() > 0.05f){
            animCtrl_->PlayExclusive("Resources/Models/WalkRelax.ani", 0, true, 0.15f);
            animCtrl_->SetSpeed("Resources/Models/WalkRelax.ani", velocity.Length()*2.3f);
            animCtrl_->SetStartBone("Resources/Models/WalkRelax.ani", "MasterBone");
        }
        else {
            animCtrl_->PlayExclusive("Resources/Models/IdleRelax.ani", 0, true, 0.15f);
            animCtrl_->SetStartBone("Resources/Models/IdleRelax.ani", "MasterBone");
        }
    // When in ship mode
    } else {
        //Update shield
        Quaternion randomRotation = Quaternion(Random(360.0f),Random(360.0f),Random(360.0f));
        shieldNode_->SetRotation(shieldNode_->GetRotation().Slerp(randomRotation, Random(1.0f)));
        Color shieldColor = shieldMaterial_->GetShaderParameter("MatDiffColor").GetColor();
        Color newColor = Color(shieldColor.r_ * Random(0.6f, 0.9f),
                               shieldColor.g_ * Random(0.7f, 0.95f),
                               shieldColor.b_ * Random(0.8f, 0.9f));
        shieldMaterial_->SetShaderParameter("MatDiffColor", shieldColor.Lerp(newColor, Min(timeStep * 23.5f, 1.0f)));
        
        //Float
        ship_.node_->SetPosition(Vector3::UP *masterControl_->Sine(2.3f, -0.1f, 0.1f));
        //Apply movement
        Vector3 force = move * thrust * timeStep;
        if (rigidBody_->GetLinearVelocity().Length() < maxSpeed ||
                (rigidBody_->GetLinearVelocity().Normalized() + force.Normalized()).Length() < 1.0f) {
            rigidBody_->ApplyForce(force);
        }

        //Update rotation according to direction of the ship's movement.
        if (rigidBody_->GetLinearVelocity().Length() > 0.1f)
            rootNode_->LookAt(rootNode_->GetPosition()+rigidBody_->GetLinearVelocity());

        //Shooting
        sinceLastShot_ += timeStep;
        if (fire.Length()) {
            if (sinceLastShot_ > shotInterval_)
            {
                Shoot(fire);
            }
        }
    }
}
Example #7
0
void player::update(Input* input,float timeStep)
{
    Node* node_camera=globals::instance()->camera->GetNode();

    {
        Vector3 moveDir=Vector3::ZERO;
        Vector3 moveDir_global=Vector3::ZERO;

        if(input->GetKeyDown('D'))
            moveDir+=Vector3::RIGHT*1;
        if(input->GetKeyDown('A'))
            moveDir-=Vector3::RIGHT*1;
        if(input->GetKeyDown('W'))
            moveDir+=Vector3::FORWARD*1;
        if(input->GetKeyDown('S'))
            moveDir-=Vector3::FORWARD*1;

        if(moveDir.Length()>0.1)
            body->SetFriction(0.4);
        else
            body->SetFriction(2.0);

        if(moveDir.Length()>0.5)
            moveDir.Normalize();

        Vector3 vel=body->GetLinearVelocity()*Vector3(1,0,1);
        Quaternion rot=body->GetRotation();

        static bool on_floor;
        Vector3 moveDir_world;
        {
            static bool at_wall;
            static int jumping=0; // 0 = not jumping, 1 = jumping, 2 =
            on_floor=false;

            float height=0;
            PhysicsRaycastResult result;
            Ray ray(node->GetPosition()+Vector3(0,1.0,0),Vector3::DOWN);
            globals::instance()->physical_world->SphereCast(result,ray,0.2,2,2);
            if(result.distance_<=2)
                on_floor=true;
            if(!on_floor)
                moveDir*=0.35;

            as_stand->AddTime(timeStep/2);
            as_walk->AddTime(timeStep*vel.Length()/1.5);
            as_run->AddTime(timeStep*vel.Length()/3);
            as_jump->AddTime(timeStep);
            as_reversing->AddTime(timeStep);
            as_stand->SetWeight(1.0-Clamp(vel.Length()/2.0,0.0,1.0));
            as_stand->SetWeight(1.0);
            as_walk->SetWeight(Clamp(vel.Length()/2.0,0.0,1.0));
            as_run->SetWeight(Clamp((vel.Length()-2)/2.0,0.0,1.0));   // maybe this should be done differently, but works for this game
            if(!on_floor)
                as_jump->SetWeight(as_jump->GetWeight()+timeStep*5);
            else
            {
                as_jump->SetWeight(0.0);

                static bool sound_step1_not_played=true;    // not playing this animation cycle
                static bool sound_step2_not_played=true;
                if(as_run->GetTime()>0.1&&sound_step1_not_played&&as_reversing->GetWeight()<0.5)
                {
                    sound_source1->Play(sound_step1);
                    sound_step1_not_played=false;
                }
                if(as_run->GetTime()>0.6&&sound_step2_not_played&&as_reversing->GetWeight()<0.5)
                {
                    sound_source2->Play(sound_step2);
                    sound_step2_not_played=false;
                }
                if(as_run->GetTime()<0.1)
                {
                    sound_step1_not_played=true;
                    sound_step2_not_played=true;
                }
            }

            if(input->GetKeyDown(KEY_SPACE)&&jumping==false&&(on_floor))
                jumping=1;  // start jumping
            else if(!input->GetKeyDown(KEY_SPACE))
                jumping=0;


            static float jump_force_applied=0;
            static const float max_jump_force_applied=100;
            moveDir_world=node->GetWorldRotation()*moveDir;

            if(moveDir_world.Angle(vel)>90&&vel.Length()>3&&on_floor)   // indicate if direction change jump / side sommersault possible
                as_reversing->SetWeight(as_reversing->GetWeight()+timeStep*10);
            else
                as_reversing->SetWeight(0.0);

            if(jumping==1&&jump_force_applied<max_jump_force_applied)   // jump higher if we are jumping and the limit has not been reached
            {
                if(jump_force_applied>max_jump_force_applied)
                {
                    // do nothing if max jump force reached
                }
                else if(jump_force_applied+timeStep*800>max_jump_force_applied)
                {
                    // I want to limit the jump height more exactly by limiting the force pumped into it and applieng the remaining rest here. Doesn't fully work yet.
                    //float f=0;//(max_jump_force_applied-jump_force_applied)*timeStep*2000;
                    //moveDir+=Vector3::UP*2*f;
                    //moveDir_global=result.normal_*1*f;
                    jump_force_applied+=timeStep*900;
                }
                else
                {
                    float f=1;
                    moveDir+=Vector3::UP*0.6*f;
                    moveDir_global=result.normal_*0.3*f;
                    jump_force_applied+=timeStep*800;
                }
            }
            if(jumping!=1)
                jump_force_applied=0;
        }

        float f=0.5;    // for walking or sprinting
        if(input->GetKeyDown(KEY_SHIFT))
            f=1.0;
        Quaternion quat;
        quat.FromLookRotation(node_camera->GetDirection()*Vector3(1,0,1),Vector3::UP);
        body->SetRotation(quat);
        float speed_old=vel.Length();
        vel+=rot*moveDir*timeStep*4000*f/body->GetMass();
        float speed_new=vel.Length();
        if(speed_new>10*f&&speed_new>speed_old)   // over limit. Don't increase speed further but make direction change possible.
            vel=vel.Normalized()*speed_old;
        body->SetLinearVelocity(Vector3(vel.x_,body->GetLinearVelocity().y_+(rot*moveDir*timeStep*4500/body->GetMass()).y_,vel.z_));
        body->ApplyImpulse(moveDir_global*timeStep*4000);

        {
            auto vec_rot=body->GetLinearVelocity()*Vector3(1,0,1);
            float s=vec_rot.Length();
            vec_rot.Normalize();
            float yaw=asin(vec_rot.x_)*180/M_PI;
            if(vec_rot.z_<0)
                yaw=180-yaw;
            node_model->SetPosition(node->GetPosition());
            if(s>1&&!camera_first_person)
            {
                node_model->SetDirection(Vector3::FORWARD);
                node_model->Yaw(yaw);
            }
        }

        {   // physic raycast to avoid the player glitching through stuff when moving very fast
            Vector3 player_pos=body->GetPosition()+Vector3(0,1,0);
            PhysicsRaycastResult result;
            Ray ray(pos_last,player_pos-pos_last);
            float l=(player_pos-pos_last).Length();
            if(l>0.5)
            {
                globals::instance()->physical_world->SphereCast(result,ray,0.2,l,2);
                if(result.distance_<=l)
                    body->SetPosition(pos_last);
                pos_last=body->GetPosition()+Vector3(0,1,0);
            }
        }
    }

    IntVector2 mouseMove(0,0);
    if(!input->IsMouseVisible())
        mouseMove=input->GetMouseMove();

    camera_yaw+=mouseMove.x_*0.1;
    if(camera_yaw<0)
        camera_yaw+=360;
    if(camera_yaw>=360)
        camera_yaw-=360;
    camera_pitch+=mouseMove.y_*0.1;
    camera_pitch=Clamp(camera_pitch,-85.0f,85.0f);
    if(!camera_first_person)
    {
        camera_distance-=input->GetMouseMoveWheel();
        camera_distance=Clamp(camera_distance,2.0f,50.0f);

        node_camera->SetPosition(node->GetPosition());
        node_camera->SetDirection(Vector3::FORWARD);
        node_camera->Yaw(camera_yaw);
        node_camera->Translate(Vector3(0,1.6,0));
        node_camera->Pitch(camera_pitch);

        PhysicsRaycastResult result;
        Ray ray(node_camera->GetPosition(),-node_camera->GetDirection());
        globals::instance()->physical_world->SphereCast(result,ray,0.2,camera_distance,2);
        if(result.distance_<=camera_distance)
            node_camera->Translate(Vector3(0,0,-result.distance_+0.1));
        else
            node_camera->Translate(Vector3(0,0,-camera_distance));
    }
    else
    {
        node_camera->SetPosition(node_camera_pos->GetWorldPosition());
        node_camera->SetDirection(Vector3::FORWARD);
        node_camera->Yaw(camera_yaw);
        node_camera->Pitch(camera_pitch);
        node_camera->Translate(Vector3(0,0,0.1));
        node_model->SetDirection(Vector3::FORWARD);
        node_model->Yaw(camera_yaw);
    }

    node_light->SetPosition(node_camera_pos->GetWorldPosition());
    node_light->Translate(Vector3(0.5,-0.9,0.3));
    float yaw_360_correction=(camera_yaw+Random(-light_shaking,light_shaking))-light_yaw;
    if(yaw_360_correction>180)
        yaw_360_correction-=360;
    else if(yaw_360_correction<-180)
        yaw_360_correction+=360;
    light_yaw+=yaw_360_correction*(10*timeStep);
    light_pitch+=((camera_pitch+Random(-light_shaking,light_shaking))-light_pitch)*(10*timeStep);
    node_light->SetDirection(Vector3::FORWARD);
    node_light->Yaw(light_yaw);
    node_light->Pitch(light_pitch);
}