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

📄 mgccontbox.cpp

📁 3D Game Engine Design Source Code非常棒
💻 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/free.pdf

#include "MgcContBox.h"
#include "MgcGaussPointsFit.h"
#include "MgcQuaternion.h"

//----------------------------------------------------------------------------
void MgcContAlignedBox (int iQuantity, const MgcVector2* akPoint,
    MgcVector2& rkMin, MgcVector2& rkMax)
{
    rkMin = akPoint[0];
    rkMax = rkMin;

    for (int i = 1; i < iQuantity; i++)
    {
        if ( akPoint[i].x < rkMin.x )
            rkMin.x = akPoint[i].x;
        else if ( akPoint[i].x > rkMax.x )
            rkMax.x = akPoint[i].x;

        if ( akPoint[i].y < rkMin.y )
            rkMin.y = akPoint[i].y;
        else if ( akPoint[i].y > rkMax.y )
            rkMax.y = akPoint[i].y;
    }
}
//----------------------------------------------------------------------------
void MgcContAlignedBox (int iQuantity, const MgcVector3* akPoint,
    MgcVector3& rkMin, MgcVector3& rkMax)
{
    rkMin = akPoint[0];
    rkMax = rkMin;

    for (int i = 1; i < iQuantity; i++)
    {
        if ( akPoint[i].x < rkMin.x )
            rkMin.x = akPoint[i].x;
        else if ( akPoint[i].x > rkMax.x )
            rkMax.x = akPoint[i].x;

        if ( akPoint[i].y < rkMin.y )
            rkMin.y = akPoint[i].y;
        else if ( akPoint[i].y > rkMax.y )
            rkMax.y = akPoint[i].y;

        if ( akPoint[i].z < rkMin.z )
            rkMin.z = akPoint[i].z;
        else if ( akPoint[i].z > rkMax.z )
            rkMax.z = akPoint[i].z;
    }
}
//----------------------------------------------------------------------------
MgcBox2 MgcContOrientedBox (int iQuantity, const MgcVector2* akPoint)
{
    MgcBox2 kBox;

    MgcGaussPointsFit(iQuantity,akPoint,kBox.Center(),kBox.Axes(),
        kBox.Extents());

    // Let C be the box center and let U0 and U1 be the box axes.  Each input
    // point is of the form X = C + y0*U0 + y1*U1.  The following code
    // computes min(y0), max(y0), min(y1), and max(y1).  The box center is
    // then adjusted to be
    //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1

    MgcVector2 kDiff = akPoint[0] - kBox.Center();
    MgcReal fY0Min = kDiff.Dot(kBox.Axis(0)), fY0Max = fY0Min;
    MgcReal fY1Min = kDiff.Dot(kBox.Axis(1)), fY1Max = fY1Min;

    for (int i = 1; i < iQuantity; i++)
    {
        kDiff = akPoint[i] - kBox.Center();

        MgcReal fY0 = kDiff.Dot(kBox.Axis(0));
        if ( fY0 < fY0Min )
            fY0Min = fY0;
        else if ( fY0 > fY0Max )
            fY0Max = fY0;

        MgcReal fY1 = kDiff.Dot(kBox.Axis(1));
        if ( fY1 < fY1Min )
            fY1Min = fY1;
        else if ( fY1 > fY1Max )
            fY1Max = fY1;
    }

    kBox.Center() += (0.5*(fY0Min+fY0Max))*kBox.Axis(0) +
        (0.5*(fY1Min+fY1Max))*kBox.Axis(1);

    kBox.Extent(0) = 0.5*(fY0Max - fY0Min);
    kBox.Extent(1) = 0.5*(fY1Max - fY1Min);

    return kBox;
}
//----------------------------------------------------------------------------
MgcBox3 MgcContOrientedBox (int iQuantity, const MgcVector3* akPoint)
{
    MgcBox3 kBox;

    MgcGaussPointsFit(iQuantity,akPoint,kBox.Center(),kBox.Axes(),
        kBox.Extents());

    // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
    // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
    // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
    // and max(y2).  The box center is then adjusted to be
    //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
    //        0.5*(min(y2)+max(y2))*U2

    MgcVector3 kDiff = akPoint[0] - kBox.Center();
    MgcReal fY0Min = kDiff.Dot(kBox.Axis(0)), fY0Max = fY0Min;
    MgcReal fY1Min = kDiff.Dot(kBox.Axis(1)), fY1Max = fY1Min;
    MgcReal fY2Min = kDiff.Dot(kBox.Axis(2)), fY2Max = fY2Min;

    for (int i = 1; i < iQuantity; i++)
    {
        kDiff = akPoint[i] - kBox.Center();

        MgcReal fY0 = kDiff.Dot(kBox.Axis(0));
        if ( fY0 < fY0Min )
            fY0Min = fY0;
        else if ( fY0 > fY0Max )
            fY0Max = fY0;

        MgcReal fY1 = kDiff.Dot(kBox.Axis(1));
        if ( fY1 < fY1Min )
            fY1Min = fY1;
        else if ( fY1 > fY1Max )
            fY1Max = fY1;

        MgcReal fY2 = kDiff.Dot(kBox.Axis(2));
        if ( fY2 < fY2Min )
            fY2Min = fY2;
        else if ( fY2 > fY2Max )
            fY2Max = fY2;
    }

    kBox.Center() += (0.5*(fY0Min+fY0Max))*kBox.Axis(0) +
        (0.5*(fY1Min+fY1Max))*kBox.Axis(1) +
        (0.5*(fY2Min+fY2Max))*kBox.Axis(2);

    kBox.Extent(0) = 0.5*(fY0Max - fY0Min);
    kBox.Extent(1) = 0.5*(fY1Max - fY1Min);
    kBox.Extent(2) = 0.5*(fY2Max - fY2Min);

    return kBox;
}
//----------------------------------------------------------------------------
bool MgcContOrientedBox (int iQuantity, const MgcVector2* akPoint,
    const bool* abValid, MgcBox2& rkBox)
{
    if ( !MgcGaussPointsFit(iQuantity,akPoint,abValid,rkBox.Center(),
         rkBox.Axes(),rkBox.Extents()) )
    {
        return false;
    }

    // Let C be the box center and let U0 and U1 be the box axes.  Each input
    // point is of the form X = C + y0*U0 + y1*U1.  The following code
    // computes min(y0), max(y0), min(y1), and max(y1).  The box center is
    // then adjusted to be
    //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1

    // get first valid vertex
    MgcVector2 kDiff;
    MgcReal fY0Min, fY0Max, fY1Min, fY1Max;
    int i;
    for (i = 0; i < iQuantity; i++)
    {
        if ( abValid[i] )
        {
            kDiff = akPoint[i] - rkBox.Center();
            fY0Min = kDiff.Dot(rkBox.Axis(0));
            fY0Max = fY0Min;
            fY1Min = kDiff.Dot(rkBox.Axis(1));
            fY1Max = fY1Min;
            break;
        }
    }

    for (i++; i < iQuantity; i++)
    {
        if ( abValid[i] )
        {
            kDiff = akPoint[i] - rkBox.Center();

            MgcReal fY0 = kDiff.Dot(rkBox.Axis(0));
            if ( fY0 < fY0Min )
                fY0Min = fY0;
            else if ( fY0 > fY0Max )
                fY0Max = fY0;

            MgcReal fY1 = kDiff.Dot(rkBox.Axis(1));
            if ( fY1 < fY1Min )
                fY1Min = fY1;
            else if ( fY1 > fY1Max )
                fY1Max = fY1;
        }
    }

    rkBox.Center() += (0.5*(fY0Min+fY0Max))*rkBox.Axis(0)
        + (0.5*(fY1Min+fY1Max))*rkBox.Axis(1);

    rkBox.Extent(0) = 0.5*(fY0Max - fY0Min);
    rkBox.Extent(1) = 0.5*(fY1Max - fY1Min);

    return true;
}
//----------------------------------------------------------------------------
bool MgcContOrientedBox (int iQuantity, const MgcVector3* akPoint,
    const bool* abValid, MgcBox3& rkBox)
{
    if ( !MgcGaussPointsFit(iQuantity,akPoint,abValid,rkBox.Center(),
         rkBox.Axes(),rkBox.Extents()) )
    {
        return false;
    }

    // Let C be the box center and let U0, U1, and U2 be the box axes.  Each
    // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2.  The
    // following code computes min(y0), max(y0), min(y1), max(y1), min(y2),
    // and max(y2).  The box center is then adjusted to be
    //   C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 +
    //        0.5*(min(y2)+max(y2))*U2

    // get first valid vertex
    MgcVector3 kDiff;
    MgcReal fY0Min, fY0Max, fY1Min, fY1Max, fY2Min, fY2Max;
    int i;
    for (i = 0; i < iQuantity; i++)
    {
        if ( abValid[i] )
        {
            kDiff = akPoint[i] - rkBox.Center();
            fY0Min = kDiff.Dot(rkBox.Axis(0));
            fY0Max = fY0Min;
            fY1Min = kDiff.Dot(rkBox.Axis(1));
            fY1Max = fY1Min;
            fY2Min = kDiff.Dot(rkBox.Axis(2));
            fY2Max = fY2Min;
            break;
        }
    }

    for (i++; i < iQuantity; i++)
    {
        if ( abValid[i] )
        {
            kDiff = akPoint[i] - rkBox.Center();

            MgcReal fY0 = kDiff.Dot(rkBox.Axis(0));
            if ( fY0 < fY0Min )
                fY0Min = fY0;
            else if ( fY0 > fY0Max )
                fY0Max = fY0;

            MgcReal fY1 = kDiff.Dot(rkBox.Axis(1));
            if ( fY1 < fY1Min )
                fY1Min = fY1;
            else if ( fY1 > fY1Max )
                fY1Max = fY1;

            MgcReal fY2 = kDiff.Dot(rkBox.Axis(2));
            if ( fY2 < fY2Min )
                fY2Min = fY2;
            else if ( fY2 > fY2Max )
                fY2Max = fY2;
        }
    }

    rkBox.Center() += (0.5*(fY0Min+fY0Max))*rkBox.Axis(0)
        + (0.5*(fY1Min+fY1Max))*rkBox.Axis(1) +
        (0.5*(fY2Min+fY2Max))*rkBox.Axis(2);

    rkBox.Extent(0) = 0.5*(fY0Max - fY0Min);
    rkBox.Extent(1) = 0.5*(fY1Max - fY1Min);
    rkBox.Extent(2) = 0.5*(fY2Max - fY2Min);

    return true;
}
//----------------------------------------------------------------------------
MgcBox3 MgcMergeBoxes (const MgcBox3& rkBox0, const MgcBox3& rkBox1)
{
    MgcBox3 kBox;
    kBox.Center() = 0.5*(rkBox0.Center() + rkBox1.Center());

    MgcQuaternion kQ0, kQ1;
    kQ0.FromAxes(rkBox0.Axes());
    kQ1.FromAxes(rkBox1.Axes());
    if ( kQ0.Dot(kQ1) < 0.0 )
        kQ1 = -kQ1;

    MgcQuaternion kQ = kQ0 + kQ1;
    MgcReal fInvLength = 1.0/MgcMath::Sqrt(kQ.Norm());
    kQ = fInvLength*kQ;
    kQ.ToAxes(kBox.Axes());

    int i, j;
    MgcVector3 akVertex[8], kDiff;
    MgcReal fADot;

    kBox.Extent(0) = 0.0;
    kBox.Extent(1) = 0.0;
    kBox.Extent(2) = 0.0;

    rkBox0.ComputeVertices(akVertex);
    for (i = 0; i < 8; i++)
    {
        kDiff = akVertex[i] - kBox.Center();
        for (j = 0; j < 3; j++)
        {
            fADot = MgcMath::Abs(kDiff.Dot(rkBox0.Axis(j)));
            if ( fADot > kBox.Extent(j) )
                kBox.Extent(j) = fADot;
        }
    }

    rkBox1.ComputeVertices(akVertex);
    for (i = 0; i < 8; i++)
    {
        kDiff = akVertex[i] - kBox.Center();
        for (j = 0; j < 3; j++)
        {
            fADot = MgcMath::Abs(kDiff.Dot(rkBox1.Axis(j)));
            if ( fADot > kBox.Extent(j) )
                kBox.Extent(j) = fADot;
        }
    }

    return kBox;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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