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

📄 maptexturetoquad.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// http://www.wild-magic.com
// Copyright (c) 2003.  All Rights Reserved
//
// The Wild Magic Library (WML) source code is supplied under the terms of
// the license agreement http://www.magic-software.com/License/WildMagic.pdf
// and may not be copied or disclosed except in accordance with the terms of
// that agreement.

#include "MapTextureToQuad.h"
#include "WmlContPointInPolygon2.h"

MapTextureToQuad g_kTheApp;

//----------------------------------------------------------------------------
MapTextureToQuad::MapTextureToQuad ()
    :
    Application2("MapTextureToQuad",0,0,256,256,ColorRGB(1.0f,1.0f,1.0f))
{
    m_pkMap = NULL;
    m_pkImage = NULL;
    m_bMouseDown = false;
    m_iSelected = -1;
}
//----------------------------------------------------------------------------
MapTextureToQuad::~MapTextureToQuad ()
{
}
//----------------------------------------------------------------------------
bool MapTextureToQuad::OnInitialize ()
{
    if ( !Application2::OnInitialize() )
        return false;

    // source bitmap
    m_pkImage = Image::Load("butterfly.mif",false);
    assert( m_pkImage );
    if ( !m_pkImage )
        return false;

    // The quadrilateral to which the image is perspectively mapped.  The
    // default is the original image rectangle (the initial mapping is the
    // identity).
    m_akVertex[0] = Vector2f(0.0f,0.0f);
    m_akVertex[1] = Vector2f(m_pkImage->GetWidth()-1.0f,0.0f);
    m_akVertex[2] = Vector2f(m_pkImage->GetWidth()-1.0f,
        m_pkImage->GetHeight()-1.0f);
    m_akVertex[3] = Vector2f(0.0f,m_pkImage->GetHeight()-1.0f);

    Vector2f kOffset(0.5f*(GetWidth()-m_pkImage->GetWidth()),
        0.5f*(GetHeight()-m_pkImage->GetHeight()));
    for (int i = 0; i < 4; i++)
        m_akVertex[i] += kOffset;

    CreateMapping();
    return true;
}
//----------------------------------------------------------------------------
void MapTextureToQuad::OnTerminate ()
{
    delete m_pkImage;
    delete m_pkMap;
    Application2::OnTerminate();
}
//----------------------------------------------------------------------------
void MapTextureToQuad::OnDisplay ()
{
    Application2::OnDisplay();
}
//----------------------------------------------------------------------------
void MapTextureToQuad::OnKeyDown (unsigned char ucKey, int, int)
{
    if ( ucKey == 'q' || ucKey == 'Q' || ucKey == KEY_ESCAPE )
    {
        RequestTermination();
        return;
    }
}
//----------------------------------------------------------------------------
void MapTextureToQuad::OnMouseClick (int iButton, int iState, int iX,
    int iY, unsigned int)
{
    if ( iButton != MOUSE_LEFT_BUTTON )
        return;

    if ( iState == MOUSE_DOWN )
    {
        m_bMouseDown = true;
        SelectVertex(Vector2f((float)iX,(float)iY));
    }
    else if ( iState == MOUSE_UP )
    {
        m_bMouseDown = false;
        if ( m_iSelected >= 0
        &&   0 <= iX && iX < GetWidth()
        &&   0 <= iY && iY < GetHeight() )
        {
            UpdateQuadrilateral(Vector2f((float)iX,(float)iY));
        }
    }
}
//----------------------------------------------------------------------------
void MapTextureToQuad::OnMotion (int iX, int iY, unsigned int)
{
    if ( m_bMouseDown )
    {
        if ( m_iSelected >= 0
        &&   0 <= iX && iX < GetWidth()
        &&   0 <= iY && iY < GetHeight() )
        {
            UpdateQuadrilateral(Vector2f((float)iX,(float)iY));
        }
    }
}
//----------------------------------------------------------------------------
void MapTextureToQuad::CreateMapping ()
{
    // Create the new perspective mapping from the *target* quadrilateral to
    // the *source* square bitmap.  The mapping is in this direction to avoid
    // holes in the drawn quadrilateral.
    delete m_pkMap;
    m_pkMap = new HmQuadToSqrf(m_akVertex[0],m_akVertex[1],m_akVertex[2],
        m_akVertex[3]);

    // compute axis-aligned bounding box
    int iXMin = GetWidth(), iXMax = 0, iYMin = GetWidth(), iYMax = 0;
    for (int i = 0; i < 4; i++)
    {
        if ( iXMin > (int)m_akVertex[i].X() )
            iXMin = (int)m_akVertex[i].X();

        if ( iXMax < (int)m_akVertex[i].X() )
            iXMax = (int)m_akVertex[i].X();

        if ( iYMin > (int)m_akVertex[i].Y() )
            iYMin = (int)m_akVertex[i].Y();

        if ( iYMax < (int)m_akVertex[i].Y() )
            iYMax = (int)m_akVertex[i].Y();
    }

    // draw perspective mapping of image (...inefficient drawing...)
    ClearScreen();
    int iXSize = m_pkImage->GetWidth();
    int iYSize = m_pkImage->GetHeight();
    unsigned char* aucData = m_pkImage->GetData();
    for (int iTrgY = iYMin; iTrgY <= iYMax; iTrgY++)
    {
        Vector2f kQuad;
        kQuad.Y() = (float)iTrgY;

        int iXStart = iXMin;
        while ( iXStart <= iXMax )
        {
            kQuad.X() = (float)iXStart;
            if ( PointInConvex4(m_akVertex,kQuad) )
                break;
            iXStart++;
        }

        int iXFinal = iXMax;
        while ( iXFinal >= iXMin )
        {
            kQuad.X() = (float)iXFinal;
            if ( PointInConvex4(m_akVertex,kQuad) )
                break;
            iXFinal--;
        }

        for (int iTrgX = iXStart; iTrgX <= iXFinal; iTrgX++)
        {
            // transform point to unit square
            kQuad.X() = (float)iTrgX;
            Vector2f kSquare = m_pkMap->Transform(kQuad);

            // convert to bitmap coordinates (using clamping)
            int iSrcX = (int)((iXSize-1)*kSquare.X());
            if ( iSrcX < 0 )
                iSrcX = 0;
            else if ( iSrcX >= iXSize )
                iSrcX = iXSize-1;

            int iSrcY = (int)((iYSize-1)*kSquare.Y());
            if ( iSrcY < 0 )
                iSrcY = 0;
            else if ( iSrcY >= iYSize )
                iSrcY = iYSize-1;

            int iSrcIndex = 3*(iSrcX+iXSize*iSrcY);
            unsigned char* aucSrcRGB = aucData + iSrcIndex;
            int iTrgIndex = iTrgX + GetWidth()*iTrgY;
            unsigned char* aucTrgRGB =
                (unsigned char*)(m_akScreen + iTrgIndex);
            for (int i = 0; i < 3; i++)
                aucTrgRGB[i] = aucSrcRGB[2-i];
        }
    }
    OnDisplay();
}
//----------------------------------------------------------------------------
void MapTextureToQuad::SelectVertex (const Vector2f& rkPos)
{
    // identify vertex within 5 pixels of mouse click
    const float fPixels = 5.0f;
    m_iSelected = -1;
    for (int i = 0; i < 4; i++)
    {
        Vector2f kDiff = rkPos - m_akVertex[i];
        if ( kDiff.Length() <= fPixels )
        {
            m_iSelected = i;
            break;
        }
    }
}
//----------------------------------------------------------------------------
void MapTextureToQuad::UpdateQuadrilateral (const Vector2f& rkPos)
{
    // quadrilateral must remain convex
    int iPrev = (m_iSelected > 0 ? m_iSelected - 1 : 3);
    int iNext = (m_iSelected < 3 ? m_iSelected + 1 : 0);
    Vector2f kDiff1 = rkPos - m_akVertex[iPrev];
    Vector2f kDiff2 = m_akVertex[iNext] - rkPos;
    float fDet = kDiff1.X()*kDiff2.Y() - kDiff1.Y()*kDiff2.X();
    if ( fDet > 0.0f )
    {
        m_akVertex[m_iSelected] = rkPos;
        CreateMapping();
    }
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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