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

📄 maphorizon2.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
字号:
/***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU Lesser General Public License as        *
*   published by the Free Software Foundation; either version 2 of the    *
*   License, or (at your option) any later version.                       *
*                                                                         *
***************************************************************************/
/**
@file
MapHorizon2.cpp
@brief
Utility that pre-calculate horizon mapping for real-time
light mapping of terrain
*/
#include "MapUtil.h"
#include "MapHorizon2.h"
#include "OgrePagingLandScapeOptions.h"

#include <iostream>

namespace Ogre
{

MapHorizon2::MapHorizon2()
{
   hMap = 0;
}


MapHorizon2::~MapHorizon2()
{
   if(mHorizon.size())
   {
       for (uint k = 0; k < mSamples; k++)
       {
            delete mHorizon[k];
       }
   }
    mHorizon.clear ();

    if(mElevation.size())
    {
        for (uint k = 0; k < 6; k++)
        {
            delete mElevation[k];
        }
    }
    mElevation.clear ();
    if (hMap)
        delete[] hMap;
}
Image *MapHorizon2::getElevationCubeMap(uint sample)
{
    return mElevation[sample];
}
Image *MapHorizon2::getHorizon3DMap(uint sample)
{
    return mHorizon[sample];
}


Vector3 MapHorizon2::getCubeVector(int i,int size,int x,int y)
{
    Real s = ((Real)x + 0.5) / (Real)size * 2.0 - 1.0;
    Real t = ((Real)y + 0.5) / (Real)size * 2.0 - 1.0;
    Vector3 v;
    switch(i)
    {
        case 0: v = Vector3(1.0,-t,-s); break;
        case 1: v = Vector3(-1.0,-t,s); break;
        case 2: v = Vector3(s,1.0,t); break;
        case 3: v = Vector3(s,-1.0,-t); break;
        case 4: v = Vector3(s,-t,1.0); break;
        case 5: v = Vector3(-s,-t,-1.0); break;
    }
    v.normalise();
    return v;
}
void MapHorizon2::calcElevationCubeMap(uint size)
{
    mElevationSize = size;
    mElevation.reserve (mElevationSize);

    std::cout << "Calculating Elevation map";

    DataChunk dc;
    dc.allocate (mElevationSize * mElevationSize * 2);
    uchar*     data = dc.getPtr();
    for(uint i = 0; i < 6; i++)
    {
        DEBUG_PROGRESS_OUTPUT(".")
        uchar *d = data;
        for(uint y = 0; y < mElevationSize; y++)
        {
            for(uint x = 0; x < mElevationSize; x++)
            {
                Vector3 dir = getCubeVector (i, mElevationSize, x, y);
                Vector3 vec (dir.x, dir.y, 0.0f);
                vec.normalise ();

                Real h =  Math::ACos (Vector3(0,1,0).dotProduct (vec)).valueRadians() / (2.0 * Math::PI);
                if (vec.x < 0)
                    h = 1.0 - h;

                *d++ = (uchar) (h * 255.0);
                *d++ = (uchar) ((1.0 - vec.dotProduct (dir)) * 255.0);
            }
        }
        Image *elevationImage = new Image();
        elevationImage->loadRawData (dc, mElevationSize, mElevationSize,  PF_L16);
        mElevation.push_back (elevationImage);
      }
    dc.clear ();
    std::cout << "\n";
}



void MapHorizon2::create_layer (uchar *dest, const Vector3 &dir)
{
    Vector3 d = dir;
    Real step = fabs (d.x) > fabs (d.y) ? fabs (d.x) : fabs (d.y);
    d /= step;
    int length = (int) Math::Sqrt ((Real)mW * d.x *
                                     (Real)mW * d.x +
                                     (Real)mH * d.y *
                                     (Real)mH * d.y);
    Real dlen =  d.length ();
    for(uint y = 0; y < mH; y++)
    {
        DEBUG_PROGRESS_OUTPUT(".")
        for(uint x = 0; x < mW; x++)
        {
            Vector3 v (x, y, 0.0f);
            *dest = 0;
            Real height_start = height_wrap (x, y);
            Real len = 0;
            Real angle = 0;
            int i = 0;
            int nx = 0;
            int ny = 0;

            const int w = (int)mW;
            const int h = (int)mH;

            while ( i < length &&
                    (nx < w) &&
                    (ny < h))
            {
                v += d;
                len += dlen;
                nx = (int)(v.x + 0.5);
                ny = (int)(v.y + 0.5);
                Real height = height_wrap (nx, ny);
                // If the current sample value is mElevation,
                // no point beyond it can possibly be
                //   higher, so stop here.
                if (height == mElevationHeight)
                    i = length;
                height = (height - height_start) / len;
                if (height > angle)
                    angle = h;
                i++;
            }
            *dest++ = (uchar)((1.0 - Math::Cos (Math::ATan (angle))) * 255.0);
        }
    }
    std::cout << "\n";
}



Real MapHorizon2::height_wrap(int x, int y)
{
    int w = (int) mW;
    int h = (int) mH;

    while (x < 0)
        x += w;
    while (y < 0)
        y += h;
    if (x >= w)
        x = x % w;
    if (y >= h)
        y = y % h;
    return hMap[y * w + x];
}

void MapHorizon2::calcHorizon3DMap(Real vscale,
                                    uint samples,
                                    Real step)
{
    mHeightMapData = MapUtil::getSingleton().getHeightMapData ();
    mW = MapUtil::getSingleton().getMapWidth ();
    mH = MapUtil::getSingleton().getMapHeight ();
    mSamples = samples;
    mVscale = vscale;

    mElevationHeight = vscale* 256;

    uchar *h = mHeightMapData;
    uint size = mW * mH;
    hMap = new Real[size];
    Real *dest = hMap;
    uchar *src = h;
    for (uint i = 0; i < size; i++)
    {
        *dest++ = (Real)*src / 255.0 * mElevationHeight / step;
        src += 1;
    }

    std::cout << "Calculating horizon map" << "\n";

    mHorizon.reserve (mSamples);
    double rotationAmount = 2 * Math::PI / mSamples;
    double rotationAmountSum = 0;
    for (uint k = 0; k < mSamples; k++)
    {
        std::cout << k << " : ";
        DataChunk dc;
        dc.allocate (size);
        uchar *horizonmap2d = dc.getPtr();

        create_layer (horizonmap2d,
                        Vector3 (Math::Sin (rotationAmountSum),
                                 Math::Cos (rotationAmountSum),
                                 0.0f));

        Image *horizonImage = new Image();
        horizonImage->loadRawData (dc, mW, mH, PF_L8);
        mHorizon.push_back (horizonImage);
        dc.clear ();
        rotationAmountSum += rotationAmount;
    }
    std::cout << "\n";
}


}//ogre namespace

⌨️ 快捷键说明

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