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

📄 heightmaploader.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
字号:
/*****************************************************************************

	File: HeightmapLoader
	Desc: Simple patch loader that loads data from a heightmap
	Date: 2003/03/02

	Author: Martin Persson
	Modified by Mike Prosser

*****************************************************************************/

#include <OgreConfigFile.h>
#include <OgreMaterialManager.h>
#include <OgreStringConverter.h>
#include <OgreImage.h>
#include <OgreSceneNode.h>
#include <OgreTechnique.h>
#include <OgrePass.h>
#include <OgreTextureUnitState.h>
#include <OgreSceneManager.h>

#include "HeightmapLoader.h"

namespace Ogre
{

//----------------------------------------------------------------------------

HeightmapLoader::HeightmapLoader(SceneNode *sceneRoot)
    : NaturePatchLoader(sceneRoot)
{
    mInited = false;

    mMapSizeX  = mMapSizeY = 0;
    mHeightMap = 0;

    // get default material
    mMaterial = reinterpret_cast<Material *>
	(MaterialManager::getSingleton().getByName("BaseWhite"));
}

//----------------------------------------------------------------------------

HeightmapLoader::~HeightmapLoader()
{
    if (mHeightMap != 0) delete mHeightMap;
}

//----------------------------------------------------------------------------

unsigned char* HeightmapLoader::loadRAWHeightmap(const char *filename,
			   			 unsigned int realSize,
						 unsigned int requestSize,
						 unsigned int xoff,
						 unsigned int yoff)
{
    unsigned char *heightMap;
    unsigned int readBytes = 0;
    unsigned int off = 0;

    FILE *fp;

    // allocate memory for the heightmap 
    if ((heightMap = new unsigned char[requestSize*requestSize]) == 0)
	return 0;

    // open the mapfile in read-only mode
    if ((fp = fopen(filename, "rb")) == 0)
	return 0;

    // seek to start offset
    fseek(fp, (yoff*realSize) + xoff, SEEK_SET);

    while (readBytes < (requestSize * requestSize))
    {
		// read 1 row of data
		fread(&heightMap[off], requestSize, 1, fp);
		off += requestSize;
		readBytes += requestSize;

		// seek to the next row
		fseek(fp, (realSize - requestSize), SEEK_CUR);
    }

    fclose(fp);
    return heightMap;
}

//----------------------------------------------------------------------------

bool HeightmapLoader::initialise(const String& filename)
{
    ConfigFile config;
    config.load(filename);

    String heightmap = config.getSetting("HeightMap");

    mHeightMap = new Image();
    mHeightMap->load(heightmap);

    mScale.x = atof(config.getSetting("Scale.x").c_str());
    mScale.y = atof(config.getSetting("Scale.y").c_str());
    mScale.z = atof(config.getSetting("Scale.z").c_str());
    if (mScale.x == 0) mScale.x = 1.0;
    if (mScale.y == 0) mScale.y = 0.25;
    if (mScale.z == 0) mScale.z = 1.0;

    int sx = mHeightMap->getWidth() / PATCH_SIZE;
    int sy = mHeightMap->getHeight() / PATCH_SIZE;
    
    // check that heightmap is of correct size
    if ((sx * PATCH_SIZE) + 1 != mHeightMap->getWidth() || 
		(sy * PATCH_SIZE) + 1 != mHeightMap->getHeight())
    {
		mMapSizeX = mMapSizeY = 0;

			String err = "Error: Invalid heightmap size : "
			+ StringConverter::toString(mHeightMap->getWidth())
			+ "," + StringConverter::toString(mHeightMap->getHeight()) 
			+ ". Should be 64*n+1, 64*n+1";
		
		std::cout << err << std::endl;
		return false;
    }

    if (mHeightMap->getFormat() != PF_L8)
    {
		std::cout << "Error: Heightmap is not a grayscale image." << std::endl;
		return false;
    }

    mMapSizeX = sx;
    mMapSizeY = sy;

#if USE_TEXTURES
    // create the material
    String texture = config.getSetting("WorldTexture");
    if (texture != "")
    {
		// get material
		mMaterial = mSceneRoot->getCreator()->getMaterial("NaturePatchMaterial");
		if (mMaterial != 0) MaterialManager::getSingleton().unload(mMaterial);

		mMaterial = mSceneRoot->getCreator()->createMaterial("NaturePatchMaterial");
	    
		TextureUnitState *layer;
		layer = mMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(texture, 1);

	#if USE_NORMALS
		mMaterial->setLightingEnabled(true);
	#endif

		String detail_texture = config.getSetting("DetailTexture");
		if (detail_texture != "")
		{
			layer = mMaterial->getTechnique(0)->getPass(0)->createTextureUnitState(detail_texture, 0);
			layer->setTextureScale(0.2, 0.2);
		}
    }
#endif

    mMaterial->load();

    mInited = true;
    return true;
}

//----------------------------------------------------------------------------

NaturePatch::NaturePatchData *HeightmapLoader::requestData(int x, int y,
    Vector3 *worldPos, Vector3 *zonePos, Vector3 *scale)
{
    NaturePatch::NaturePatchData *data = 0;

    // return null if patch requested is out of bounds
    if (!mInited || x < 0 || x >= mMapSizeX || y < 0 || y >= mMapSizeY)
	return 0;

    // create and fill the patch data structure
    data = new NaturePatch::NaturePatchData;
    data->type = NaturePatch::TYPE_TERRAIN;

    data->terrain.pHeightMap     = mHeightMap->getData()
				 + (y * PATCH_SIZE * mHeightMap->getWidth())
				 + (x * PATCH_SIZE);
    data->terrain.heightMapWidth = mHeightMap->getWidth();
    data->terrain.pMaterial	 = mMaterial;
    data->terrain.numBlendMaps   = 0;

    // set world/zone position and scaling info
    zonePos->x = (x % 16) * PATCH_SIZE;
    zonePos->y = 0;
    zonePos->z = (y % 16) * PATCH_SIZE;

    worldPos->x = x * PATCH_SIZE;
    worldPos->y = 0;
    worldPos->z = y * PATCH_SIZE;

    scale->x = mScale.x;
    scale->y = mScale.y;
    scale->z = mScale.z;

    return data;
}

//----------------------------------------------------------------------------

int HeightmapLoader::getZoneSize()
{
    if (!mInited) return 0;

    return  (mHeightMap->getWidth()<(16*PATCH_SIZE))
	   ? mHeightMap->getWidth():(16*PATCH_SIZE);
}

//----------------------------------------------------------------------------

int HeightmapLoader::getMapSize()
{
    if (!mInited) return 0;

    return  mHeightMap->getWidth();
}

//----------------------------------------------------------------------------

void HeightmapLoader::releaseData(NaturePatch::NaturePatchData *data)
{
    if (!mInited) return;

    // for now just delete the data
    delete data;
}

//----------------------------------------------------------------------------

void HeightmapLoader::getPatchAtPosition(const Vector3& pos, int *px, int *py)
{
    // get patch x/y for position
    *px = pos.x / (EDGE_LENGTH * mScale.x);
    *py = pos.z / (EDGE_LENGTH * mScale.z);

}
} // namespace Ogre

⌨️ 快捷键说明

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