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

📄 maphorizon.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 
MapHorizon.cpp
@brief
Utility that pre-calculate horizon mapping for real-time
light mapping of terrain
*/
#include "MapUtil.h"
#include "MapHorizon.h"
#include "OgrePagingLandScapeOptions.h"

#include <iostream>

namespace Ogre
{

MapHorizon::MapHorizon()
{   
    hMap = 0;
}
MapHorizon::~MapHorizon()
{
   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 *MapHorizon::getElevationCubeMap(uint sample)
{
    return mElevation[sample];
}
Image *MapHorizon::getHorizon3DMap(uint sample)
{
    return mHorizon[sample];
}

Vector3 MapHorizon::GetCubeVector(int side, uint x, uint y)
{
    Real s, t, sc, tc;

    s = (x + 0.5) / mElevationSize;
    t = (y + 0.5) / mElevationSize;
    sc = s*2 - 1;
    tc = t*2 - 1;

    Vector3 CubeVector;
    switch (side) 
    {
        case 0: //CUBE_MAP_POSITIVE_X
            CubeVector = Vector3(1, -tc, -sc);
            break;
        case 1: //CUBE_MAP_NEGATIVE_X
            CubeVector = Vector3(-1, -tc, sc);
            break;
        case 2: //CUBE_MAP_POSITIVE_Y
            CubeVector = Vector3(sc, 1, tc);
            break;
        case 3: //CUBE_MAP_NEGATIVE_Y
            CubeVector = Vector3(sc, -1, -tc);
            break;
        case 4: //CUBE_MAP_POSITIVE_Z
            CubeVector = Vector3(sc, -tc, 1);
            break;
        case 5: //CUBE_MAP_NEGATIVE_Z
            CubeVector = Vector3(-sc, -tc, -1);
            break;
    }

    CubeVector.normalise ();
    return CubeVector;
}

void MapHorizon::calcElevationCubeMap(uint size)
{
    mElevationSize = size;
    mElevation.reserve (mElevationSize);

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

    uint eBpp = 3;   //2 only are used...
    DataChunk dc;
    dc.allocate (mElevationSize * mElevationSize * eBpp);
    uchar*     pixels = dc.getPtr();

    for (uint i = 0; i < 6; i++) 
    {
        //ui3 CubeFace = CubeFaces[i];
        uint row_count = 0;
        DEBUG_PROGRESS_OUTPUT(".")
        for (uint y = 0 ; y < mElevationSize; y++)
        {
            //Real cube_t = (y + 0.5)  * twoBysSize - 1;    
            for (uint x = 0 ; x < mElevationSize; x++)
            {
                Vector3 cubeVector;

                cubeVector = GetCubeVector(i, x, y);

                // Calculate elevation:
                Vector3 e0 = Vector3 (cubeVector.x, cubeVector.y, 0);
                e0.normalise ();

                Real elevation = 1 - e0.dotProduct (cubeVector);

                // Calculate heading:
                Real heading = Math::ACos (e0.x).valueRadians();

                if (e0.y < 0)
                    heading = Math::PI + (Math::PI - heading);

                // Write them to the cube map.
                pixels[(row_count + x) * eBpp + 0] = uchar ((heading/(2*Math::PI))*255);
                pixels[(row_count + x) * eBpp + 1] = uchar (elevation * 255);
                if (eBpp > 2)
                    pixels[(row_count + x) * eBpp + 2] = uchar (0);
            }
            row_count += mElevationSize;
        }

        Image *elevationImage = new Image();
        elevationImage->loadRawData (dc, mElevationSize, mElevationSize,  PF_R8G8B8);
        mElevation.push_back (elevationImage);
    }
    dc.clear ();
    std::cout << "\n";
}

uint MapHorizon::CalcHorizonAtPoint (uint localx, uint localy,
                                    Vector3 direction,
                                    Real origin)
{

  
    // Scale the direction vector such that the largest component is 1.
    Vector3 dir = direction;

    // Trace a ray through the heightmap 
    // and keep track of the horizon elevation. 
    int w = (int) mW;
    int h = (int) mH;

    int x = (int) localx;
    int y = (int) localy;

    // Move one step further along the ray.
    Vector3 curr_pos = Vector3 (x, y, 0.0f);
    curr_pos += dir; 
    int i = int (Math::Ceil (curr_pos.x));
    int j = int (Math::Ceil  (curr_pos.y));
    uint maxH = 0;
    //Real vscalefactor = vscale / 255;
    //Real originheight = origin * vscalefactor;

    while ((i >= 0) && (i < w) && 
            (j >= 0) && (j < h))
    {
        // Height of the current sample point:
        uint curH = uint (hMap[j*w + i]);

        // If the current sample point is lower than the ray origin, it can't affect
        //   our horizon, so skip it. 
        if (curH > origin) 
        {
            // Calculate the elevation angle of the current sample point:
            Vector3 flat = Vector3 (i - x, 
                                    j - y, 
                                    0); //originheight);
            flat.normalise ();

            Vector3 elev = Vector3 (i - x, 
                                    j - y, 
                                     //curH*vscalefactor - originheight);
                                     curH - origin);
            elev.normalise ();

            // Output: [0=horizontal, 1=vertical].
            curH = int (Math::Ceil ( (1 - flat.dotProduct (elev)) * 255.0f));

            maxH = ((curH < maxH) ? maxH : curH);

            // If the current sample value is 255, no point beyond it can possibly be
            //   higher, so stop here. 
            if (mHeightMapData[j*w+i] == 255)  
                i = w;
        }
        // Move one step further along the ray.
        curr_pos += dir;
        i = int (Math::Ceil (curr_pos.x));
        j = int (Math::Ceil (curr_pos.y));
    }

    return maxH;
}


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

    uint w = mW;
    uint h = mH;
    uint size = w * h;

    mElevationHeight = vscale* 256;

    hMap = new Real[size];
    Real *dest = hMap;
    uchar *src = mHeightMapData;
    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++) 
     {
        DataChunk dc;
        dc.allocate (size);
        uchar *horizonmap2d = dc.getPtr();
        uint row_countj = 0; 
        std::cout << k << " : ";

        Vector3 dir;

      
        dir = Vector3 (Math::Sin (rotationAmountSum), 
                        Math::Cos (rotationAmountSum), 
                        0.0f);
           
        dir *= 1 / (fabs (dir.x) > fabs (dir.y) ? fabs (dir.x) : fabs (dir.y));

        for (uint j = 0; j <  h; j++)
         {  
            DEBUG_PROGRESS_OUTPUT(".")
            for (uint i = 0; i < w; i++) 
            {
                horizonmap2d[row_countj + i] = 
                    CalcHorizonAtPoint (i, 
                                        j, 
                                        dir, 
                                        hMap[ row_countj + i]);
            }
            row_countj += w;            
        }
        rotationAmountSum += rotationAmount;

        Image *horizonImage = new Image();
        horizonImage->loadRawData (dc, w, h, PF_L8);
        mHorizon.push_back (horizonImage);
        dc.clear ();
        std::cout << "\n";
     }
}


}//ogre namespace

⌨️ 快捷键说明

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