⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 testik.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License.html/free.pdf

#include "TestIK.h"

//---------------------------------------------------------------------------
MgcApplication* MgcApplication::Create ()
{
    return new TestIK;
}
//---------------------------------------------------------------------------
TestIK::TestIK ()
    :
    MgcApplication("TestIK",640,480,0,1)
{
    // set up bindings for camera turret
    m_fTrnSpeed = 1.0;
    m_fRotSpeed = 0.1;
    m_kTurret.BindKeysToTranslateRight('[',']',m_fTrnSpeed);
    m_kTurret.BindKeysToTranslateUp('{','}',m_fTrnSpeed);
    m_kTurret.BindKeysToTranslateDirection(VK_DOWN,VK_UP,m_fTrnSpeed);
    m_kTurret.BindKeysToRotateRight(VK_PRIOR,VK_NEXT,0.1*m_fRotSpeed);
    m_kTurret.BindKeysToRotateUp(VK_RIGHT,VK_LEFT,0.1*m_fRotSpeed);

    // initialize 'last time'
    MeasureTime();
}
//---------------------------------------------------------------------------
void TestIK::CreateAlphaState ()
{
    m_spkAlphaState = new MgcAlphaState;
    m_spkAlphaState->Test() = MgcAlphaState::TF_LEQUAL;
    m_spkAlphaState->BlendEnabled() = true;

    m_spkScene->SetRenderState(m_spkAlphaState);
}
//---------------------------------------------------------------------------
void TestIK::CreateTextureState ()
{
    unsigned int uiYMax = 256, uiXMax = 8;
    unsigned int* auiData = new unsigned int[uiXMax*uiYMax];
    for (unsigned int uiY = 0, uiI = 0; uiY < uiYMax; uiY++)
    {
        unsigned int uiColor = (uiY | (uiYMax-1-uiY) << 16 | 0x80 << 24);
        for (unsigned int uiX = 0; uiX < uiXMax; uiX++)
            auiData[uiI++] = uiColor;
    }

    MgcImage* pkImage = new MgcImage(MgcImage::IT_RGBA8888,uiXMax,uiYMax,
        (unsigned char*)auiData);

    MgcTexture* pkTexture = new MgcTexture;
    pkTexture->SetImage(pkImage);
    pkTexture->Mipmap() = MgcTexture::MM_LINEAR_LINEAR;

    m_spkTextureState = new MgcTextureState;
    m_spkTextureState->Set(0,pkTexture);

    m_spkScene->SetRenderState(m_spkTextureState);
}
//---------------------------------------------------------------------------
void TestIK::CreateWireframeState ()
{
    m_spkWireframeState = new MgcWireframeState;

    m_spkScene->SetRenderState(m_spkWireframeState);
}
//---------------------------------------------------------------------------
void TestIK::CreateZBufferState ()
{
    m_spkZBufferState = new MgcZBufferState;
    m_spkZBufferState->Enabled() = true;
    m_spkZBufferState->Writeable() = true;
    m_spkZBufferState->Compare() = MgcZBufferState::CF_LEQUAL;

    m_spkScene->SetRenderState(m_spkZBufferState);
}
//---------------------------------------------------------------------------
MgcTriMesh* TestIK::CreateCylinder (MgcReal fRadius, MgcReal fHalfHeight)
{
    unsigned int uiN = 16;
    unsigned int uiVertexQuantity = 2*uiN+2;
    unsigned int uiTriangleQuantity = 4*uiN;
    MgcReal fAlpha = 0.1;

    MgcVector3* akVertex = new MgcVector3[uiVertexQuantity];
    MgcVector3* akNormal = new MgcVector3[uiVertexQuantity];
    MgcVector2* akTexture = new MgcVector2[uiVertexQuantity];
    unsigned int* auiConnect = new unsigned int[3*uiTriangleQuantity];

    unsigned int uiV, uiVP;
    for (uiV = 0, uiVP = uiN; uiV < uiN; uiV++, uiVP++)
    {
        MgcReal fAngle = MgcMath::TWO_PI*uiV/uiN;
        MgcReal fSin = MgcMath::Sin(fAngle);
        MgcReal fCos = MgcMath::Cos(fAngle);

        akVertex[uiV] = MgcVector3(fRadius*fCos,fRadius*fSin,-fHalfHeight);
        akNormal[uiV] = akVertex[uiV];
        akNormal[uiV].Unitize();
        akTexture[uiV] = MgcVector2(fSin,0.25);

        akVertex[uiVP] = MgcVector3(fRadius*fCos,fRadius*fSin,+fHalfHeight);
        akNormal[uiVP] = akVertex[uiVP];
        akNormal[uiVP].Unitize();
        akTexture[uiVP] = MgcVector2(fSin,0.75);
    }

    akVertex[2*uiN] = MgcVector3(0.0,0.0,-fHalfHeight);
    akNormal[2*uiN] = akVertex[2*uiN];
    akTexture[2*uiN] = MgcVector2(0.5,0.0);
    akVertex[2*uiN+1] = MgcVector3(0.0,0.0,+fHalfHeight);
    akNormal[2*uiN+1] = akVertex[2*uiN+1];
    akTexture[2*uiN+1] = MgcVector2(0.5,1.0);

    unsigned int uiI = 0;
    for (uiV = 0; uiV < uiN; uiV++)
    {
        auiConnect[uiI++] = (uiV+1) % uiN;
        auiConnect[uiI++] = uiV;
        auiConnect[uiI++] = 2*uiN;
    }
    for (uiVP = uiN; uiVP < 2*uiN; uiVP++)
    {
        auiConnect[uiI++] = uiVP;
        auiConnect[uiI++] = (uiVP == 2*uiN-1 ? uiN : uiVP+1);
        auiConnect[uiI++] = 2*uiN+1;
    }
    for (uiV = 0, uiVP = uiN; uiV < uiN; uiV++, uiVP++)
    {
        auiConnect[uiI++] = uiVP;
        auiConnect[uiI++] = uiV;
        auiConnect[uiI++] = (uiV+1) % uiN;

        auiConnect[uiI++] = uiVP;
        auiConnect[uiI++] = (uiV+1) % uiN;
        auiConnect[uiI++] = (uiVP == 2*uiN-1 ? uiN : uiVP+1);
    }

    MgcTriMesh* pkCylinder = new MgcTriMesh(uiVertexQuantity,akVertex,
        akNormal,0,akTexture,uiTriangleQuantity,auiConnect);
    pkCylinder->UpdateModelBound();

    return pkCylinder;
}
//---------------------------------------------------------------------------
MgcNode* TestIK::CreateJointAndArm ()
{
    // joint
    MgcNode* pkNode = new MgcNode;

    // cylinder of joint
    MgcTriMesh* pkCylinder = CreateCylinder(1.0,0.5);
    pkNode->AttachChild(pkCylinder);

    // arm connected to joint
    MgcTriMesh* pkArm = CreateCylinder(0.4,2.0);
    pkArm->Rotate().FromAxisAngle(MgcVector3::UNIT_Y,MgcMath::HALF_PI);
    pkArm->Translate() = MgcVector3(2.0,0.0,0.0);
    pkNode->AttachChild(pkArm);

    return pkNode;
}
//---------------------------------------------------------------------------
bool TestIK::Initialize ()
{
    m_spkRenderer = new MgcOglRenderer(GetWindowHandle(),640,480);
    m_spkRenderer->SetBackgroundColor(MgcColor(0.5f,0.0f,1.0f));
    m_spkCamera = new MgcOglCamera(640,480);
    m_spkCamera->SetFrustum(1.0,1000.0,-0.55,0.55,0.4125,-0.4125);
    m_spkCamera->SetFrame(MgcVector3(0.0,0.0,-26.0),MgcMatrix3::IDENTITY);
    m_spkRenderer->SetCamera(m_spkCamera);

    m_spkScene = new MgcNode;
    MgcIKJoint** apkJoint = new MgcIKJoint*[3];

    MgcNode* pkNode0 = CreateJointAndArm();
    apkJoint[0] = new MgcIKJoint(pkNode0);
    apkJoint[0]->AllowRotation(2) = true;
    apkJoint[0]->RotationMin(2) = 0.0;
    apkJoint[0]->RotationMax(2) = 0.25*MgcMath::PI;

    MgcNode* pkNode1 = CreateJointAndArm();
    //pkNode1->Rotate().FromAxisAngle(MgcVector3::UNIT_Z,MgcMath::HALF_PI);
    pkNode1->Translate() = MgcVector3(4.0,0.0,0.0);
    pkNode0->AttachChild(pkNode1);
    apkJoint[1] = new MgcIKJoint(pkNode1);
    apkJoint[1]->AllowRotation(2) = true;
    apkJoint[1]->RotationMin(2) = 0.0;
    apkJoint[1]->RotationMax(2) = 0.25*MgcMath::PI;

    MgcNode* pkNode2 = CreateJointAndArm();
    //pkNode2->Rotate().FromAxisAngle(MgcVector3::UNIT_Z,-MgcMath::HALF_PI);
    pkNode2->Translate() = MgcVector3(4.0,0.0,0.0);
    pkNode1->AttachChild(pkNode2);
    apkJoint[2] = new MgcIKJoint(pkNode2);
    apkJoint[2]->AllowRotation(2) = true;
    apkJoint[2]->RotationMin(2) = 0.0;
    apkJoint[2]->RotationMax(2) = 0.25*MgcMath::PI;

    MgcNode* pkTarget = new MgcNode;
    pkTarget->Translate() = MgcVector3(16.0,0.0,0.0);

    MgcIKGoal** apkGoal = new MgcIKGoal*[1];
    apkGoal[0] = new MgcIKGoal(pkTarget,pkNode2,1.0);

    MgcIKController* pkIK = new MgcIKController;
    pkIK->JointQuantity() = 3;
    pkIK->Joints() = apkJoint;
    pkIK->GoalQuantity() = 1;
    pkIK->Goals() = apkGoal;
    pkNode0->AttachControl(pkIK);

    m_spkScene->AttachChild(pkTarget);
    m_spkScene->AttachChild(pkNode0);

    CreateAlphaState();
    CreateTextureState();
    CreateWireframeState();
    CreateZBufferState();

    m_spkScene->UpdateGS(0.0);
    m_spkScene->UpdateRS();

    m_pkObject = m_spkScene;

    return true;
}
//---------------------------------------------------------------------------
void TestIK::Terminate ()
{
    m_spkAlphaState = 0;
    m_spkTextureState = 0;
    m_spkWireframeState = 0;
    m_spkZBufferState = 0;

    m_spkCamera = 0;
    m_spkRenderer = 0;
    m_spkScene = 0;
}
//---------------------------------------------------------------------------
void TestIK::OnIdle ()
{
    MeasureTime();

    if ( GetFocus() == GetWindowHandle() )
    {
        if ( m_kTurret.ReadKeyboard() )
        {
            m_spkRenderer->GetCamera()->SetFrame(m_kTurret.GetTranslate(),
                m_kTurret.GetRotate());
        }
    }

    m_spkRenderer->ClearBuffers();
    m_spkRenderer->Draw(m_spkScene);
    m_spkRenderer->DisplayBackBuffer();

    DrawFrameRate();
    UpdateClicks();
}
//---------------------------------------------------------------------------
bool TestIK::Transform (char cCharCode, long lKeyData)
{
    MgcVector3 trn;
    MgcMatrix3 rot, incr;

    switch ( cCharCode )
    {
        case 'x':
            m_pkObject->Translate().x -= m_fTrnSpeed;
            break;
        case 'X':
            m_pkObject->Translate().x += m_fTrnSpeed;
            break;
        case 'y':
            m_pkObject->Translate().y -= m_fTrnSpeed;
            break;
        case 'Y':
            m_pkObject->Translate().y += m_fTrnSpeed;
            break;
        case 'z':
            m_pkObject->Translate().z -= m_fTrnSpeed;
            break;
        case 'Z':
            m_pkObject->Translate().z += m_fTrnSpeed;
            break;
        case 'r':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_X,m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'R':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_X,-m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'a':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Y,m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'A':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Y,-m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'p':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Z,m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        case 'P':
            rot = m_pkObject->Rotate();
            incr.FromAxisAngle(MgcVector3::UNIT_Z,-m_fRotSpeed);
            m_pkObject->Rotate() = incr*rot;
            break;
        default:
            return false;
    }

    m_pkObject->UpdateGS(0.0f);
    return true;
}
//---------------------------------------------------------------------------
bool TestIK::WmChar (char cCharCode, long lKeyData)
{
    if ( Transform(cCharCode,lKeyData) )
        return true;

    switch ( cCharCode )
    {
    case '0':  // reset frame rate measurements
        ResetTime();
        return true;
    case 'w':
        m_spkWireframeState->Enabled() = !m_spkWireframeState->Enabled();
        return true;
    case 'q':
    case 'Q':
    case VK_ESCAPE:
        PostMessage(GetWindowHandle(),WM_DESTROY,0,0);
        return true;
    }

    return false;
}
//---------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -