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

📄 ogrepaginglandscaperayscenequery.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
字号:
/***************************************************************************
OgrePagingLandScapeRaySceneQuery.cpp  -  description
-------------------
begin                : Fri Sep 10 2003
copyright            : (C) 2003 by Jose A Milan
email                : spoke2@supercable.es
***************************************************************************/
 
/***************************************************************************
*                                                                         *
*   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.                       *
*                                                                         *
***************************************************************************/

#include <OgreEntity.h>

#include "OgrePagingLandScapeRaySceneQuery.h"
#include "OgrePagingLandScapePrerequisites.h"

namespace Ogre
{

//----------------------------------------------------------------------------
// This function return the vertex interpolated height.
// Supplied by Praetor. Thanks a lot. ]:)
void PagingLandScapeRaySceneQuery::execute(RaySceneQueryListener* listener) 
{ 
	clearFragmentList();

	unsigned long mask = getQueryMask();
	SceneQuery::WorldFragment* frag;

	if(mask & RSQ_Height)
	{
		// we don't want to bother checking for entities because a 
		// UNIT_Y ray is assumed to be a height test, not a ray test
		frag = new SceneQuery::WorldFragment();
		fragmentList.push_back(frag);

		frag->fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION; 
		Vector3 origin = mRay.getOrigin();
		origin.y = 0; // ensure that it's within bounds
		frag->singleIntersection = getHeightAt(origin);
		listener->queryResult(frag, 0);
	}
	else
	{
		// Check for entity contacts
		if(mask & RSQ_Entities)
		{
			DefaultRaySceneQuery::execute(listener);
		}

		if(mask & RSQ_AllTerrain || mask & RSQ_FirstTerrain)
		{
			Vector3 ray = mRay.getOrigin();
			Vector3 land = getHeightAt(ray);
			Real dist = 0, resFactor = 1;

			// Only bother if the non-default mask has been set
			if((mask & RSQ_1xRes) == 0)
			{
				if(mask & RSQ_2xRes)
				{
					resFactor = 0.5;
				}
				else if(mask & RSQ_4xRes)
				{
					resFactor = 0.25;
				}
				else if(mask & RSQ_8xRes)
				{
					resFactor = 0.125;
				}
			}

			while(land.y != -1)
			{
				ray += mRay.getDirection() * resFactor;
				dist += 1 * resFactor;

				land = getHeightAt(ray);
				if(ray.y < land.y)
				{
					frag = new SceneQuery::WorldFragment();
					fragmentList.push_back(frag);

					frag->fragmentType = SceneQuery::WFT_SINGLE_INTERSECTION; 
					frag->singleIntersection = land;
					listener->queryResult(frag, dist);

					if(mask & RSQ_FirstTerrain)
					{
						return;
					}
				}
			} 
		}
	}             
} 

//----------------------------------------------------------------------------
Vector3 PagingLandScapeRaySceneQuery::getHeightAt(const Vector3& origin)
{
	return Vector3(origin.x, static_cast<PagingLandScapeSceneManager*>(mParentSceneMgr) -> getRealWorldHeight (origin.x, origin.z), origin.z);
}
/*
	PagingLandScapeSceneManager* sceneMgr = static_cast<PagingLandScapeSceneManager*>(mParentSceneMgr); 
	Real nearest[4] = {0, 0, 0, 0}, alpha, beta, gamma;
	int  xBase, zBase; 
	Real xFactor, zFactor;
	PagingLandScapePage* page;
	HardwareVertexBufferSharedPtr vertexBuffer, neighborBuffer;
	RenderOperation rOp, rOp1, rOp2, rOp3;
	Real *vertexData, *neighborData;
	PagingLandScapeTile *tile, *base, *neighborX, *neighborZ, *neighborSE;

	//////////////////////////////////////////////// 
	//  Iterate through all of the page rows 
	for(int pz = 0;pz < mOptions->world_height;pz++) 
	{ 
		//////////////////////////////////////////////// 
		//  Iterate through all of the page columns 
		for(int px = 0;px < mOptions->world_width;px++) 
		{ 
			//////////////////////////////// 
			// Check if the page is loaded 
			page = sceneMgr->mPages[px][pz]; 
			if(page->isLoaded() == true) 
			{
				//////////////////////////////////////////// 
				// Check if the camera is within the page 
				if(page->isCameraIn(origin) != PAGE_OUTSIDE) 
				{ 
					// Iterate through all of the tile columns 
					for(unsigned int tx = 0;tx < page->mTiles.size();tx++) 
					{														
						////////////////////////////////////////////////////////// 
						// Iterate through all of the tile rows 
						for(unsigned int tz = 0;tz < page->mTiles[tx].size();tz++) 
						{ 
							base = tile = page->mTiles[tx][tz]; 

							///////////////////////////////////////////// 
							// Determine if the point is within the tile 
							const AxisAlignedBox& box = tile->getBoundingBox(); 
							const Vector3& vMin = box.getMinimum(); 
							const Vector3& vMax = box.getMaximum(); 

							//if(vectorIsInside(origin, vMin, vMax)) 
							if (((AxisAlignedBox)tile->getBoundingBox()).intersects(origin))
							{ 
								//////////////////////////////////////////// 
								// If we don't find a valid tile, then just 
								// default to the old nearest vertex result 
								if((tile = getNonDividedTile(tile, origin)) == 0) 
								{ 
									return Vector3(origin.x, page->_getWorldHeight((int)origin.x, (int)origin.z), origin.z); 
								} 

								///////////////////////////// 
								// Localize the coordinates 
								const AxisAlignedBox& box2 = tile->getBoundingBox(); 
								const Vector3& tMin = box2.getMinimum(); 
								const Vector3& tMax = box2.getMaximum(); 
								////////////////////////////////////////// 
								// Get the dimensions of the tile and the 
								// relative coordinates 
								Vector3 tSize = tMax - tMin; 
								Vector3 relPos = origin - tMin; 
								/////////////////////////////////////////////////// 
								// Find out the relative dimensions of each vertex 
								// *Note: there is only a 5x5 grid of vertices 
								Vector3 relSize = tSize / 5; 
								///////////////////////////////////////////// 
								// Finally, we can assign the vertex offsets 
								Vector3 localPos; 
								localPos.x = relPos.x / relSize.x; 
								localPos.z = relPos.z / relSize.z; 
								xBase = (int)localPos.x; 
								zBase = (int)localPos.z; 
								xFactor = localPos.x - (xBase); 
								zFactor = localPos.z - (zBase); 

								//////////////////////////////////////// 
								// Okay, we finally have a valid tile, 
								// now we can finally query the vertex 
								// data and get on with life 
								tile->mRenderable->getRenderOperation(rOp); 
								vertexBuffer = rOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
								if(vertexBuffer->isLocked()) 
								{ 
									return Vector3(origin.x, page->_getWorldHeight((int)origin.x, (int)origin.z), origin.z);
								} 

								vertexData = static_cast<Real*>(vertexBuffer->lock(HardwareBuffer::HBL_NORMAL)); 

								if(xFactor == 0 && zFactor == 0) 
								{ 
									// We're on top of a vertex, so we'll just use that data 
									Real tHeight = vertexData[1 + ((xBase + (zBase * 5)) * 3)];
									vertexBuffer->unlock(); 
									return Vector3(origin.x, tHeight, origin.z); 
								} 

								////////////////////////////////// 
								// Get the nearest four vertices 
								// First, we need to see if we're in a border region and 
								// if so we need to load a neighboring tile 
								nearest[0] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 

								///////////////////////////////// 
								// If xBase >= 4 then it means that we need to load the next 
								// tile from the X-axis 
								if(xBase >= 4) 
								{ 
									neighborX = getNonDividedTile(base, Vector3(origin.x + relSize.x, origin.y, origin.z)); 
									if(neighborX != 0) 
									{                                      
										neighborX->mRenderable->getRenderOperation(rOp1); 
										neighborBuffer = rOp1.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
										if(neighborBuffer->isLocked()) 
										{ 
											nearest[1] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 
										}
										else
										{
											neighborData = static_cast<Real*>(neighborBuffer->lock(HardwareBuffer::HBL_NORMAL)); 
											nearest[1] = neighborData[(zBase * 15) + 1];
										}

										// If we're not in a corner, we'll need another vertex 
										// from here 
										if(zBase < 4) 
										{ 
											nearest[2] = neighborData[((zBase + 1) * 15) + 1]; 
										} 
											neighborBuffer->unlock(); 
										}
										else
										{ 
											nearest[1] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 
										} 
									}
									else
									{
										nearest[1] = vertexData[1 + (((xBase + 1) + (zBase * 5)) * 3)]; 
									} 

									///////////////////////////////// 
									// If zBase >= 4 then we need to load the next tile down the Z axis 
									if(zBase >= 4) 
									{ 
										neighborZ = getNonDividedTile(base, Vector3(origin.x, origin.y, origin.z + relSize.z)); 
										if(neighborZ != 0) 
										{ 
											neighborZ->mRenderable->getRenderOperation(rOp2); 
											neighborBuffer = rOp2.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
											if(neighborBuffer->isLocked()) 
											{ 
												nearest[3] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 
											}
											else
											{
												neighborData = static_cast<Real*>(neighborBuffer->lock(HardwareBuffer::HBL_NORMAL)); 
												nearest[3] = neighborData[(xBase * 3) + 1]; 
											}

											// If we're not in a corner, we'll need another vertex 
											// from here 
											if(xBase < 4) 
											{ 
												nearest[2] = neighborData[((xBase + 1) * 3) + 1]; 
											} 

											neighborBuffer->unlock(); 
										}
										else
										{ 
											nearest[3] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 
										} 
									}
									else
									{
										nearest[3] = vertexData[1 + ((xBase + ((zBase + 1) * 5)) * 3)]; 
									} 

									///////////////////////////////// 
									// If they both are 4 that means we're in a corner and need 
									// to load the tile to the southeast.  We'll just move east from 
									// the southern loaded tile since both should exist 
									if(xBase >= 4 && zBase >= 4) 
									{ 
										neighborSE = getNonDividedTile(base, Vector3(origin.x + relSize.x, origin.y, origin.z + relSize.z)); 
										if(neighborSE != 0) 
										{ 
											neighborSE->mRenderable->getRenderOperation(rOp3); 
											neighborBuffer = rOp3.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
											if(neighborBuffer->isLocked())
											{ 
												nearest[2] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 
											}
											else
											{
												neighborData = static_cast<Real*>(neighborBuffer->lock(HardwareBuffer::HBL_NORMAL)); 
												nearest[2] = neighborData[1]; 
											}

											neighborBuffer->unlock(); 
										}
										else
										{ 
											nearest[2] = vertexData[1 + ((xBase + (zBase * 5)) * 3)]; 
										} 
									}
									else if(xBase < 4 && zBase < 4)
									{ 
										nearest[2] = vertexData[1 + (((xBase + 1) + ((zBase + 1) * 5)) * 3)]; 
									} 
									vertexBuffer->unlock(); 

									///////////////////////////////// 
									// Interpolate along the x axis 
									alpha = nearest[0] + ((nearest[1] - nearest[0]) * xFactor); 
									beta = nearest[3] + ((nearest[2] - nearest[3]) * xFactor); 

									///////////////////////////////// 
									// Interpolate along the z axis 
									gamma = alpha + ((beta - alpha) * zFactor); 

									///////////////////////////////// 
									// Return the results 
									return Vector3(origin.x, gamma, origin.z); 
							} 
						} 
					}
				} 
			} 
		} 
	}

	return Vector3(-1, -1, -1);
}
*/
/*
//----------------------------------------------------------------------------
PagingLandScapeTile* PagingLandScapeRaySceneQuery::getNonDividedTile(PagingLandScapeTile* tile, const Vector3& origin) 
{ 
	PagingLandScapeTile* retTile = 0; 

	////////////////////////////////////////////////// 
	// Determine if the camera is within the tile. 
	if (((AxisAlignedBox)tile->getBoundingBox()).intersects(origin))
	{ 
		/////////////////////////////////////////////// 
		// Check to see if this tile is divided. 
		if(tile->isDivided()) 
		{ 
			/////////////////////////////////////////// 
			// If the tile is divided, recurse through 
			// its children 
			for(int i = 0;i < 4;i++) 
			{ 
				/////////////////////////////////////// 
				// If we find the tile, return it 
				if((retTile = getNonDividedTile(tile->mTile[i], origin)) != 0) 
				{ 
					return retTile; 
				} 
			} 
			/////////////////////////////////////// 
			// If we ever get here, it means we 
			// didn't find a suitable tile 
			return 0; 
			} 
			else
			{ 
				return tile; 
			}
		}
		/////////////////////////////////////////////////// 
		// Otherwise if the point is not in this tile 
		// return an invalid pointer 
		else 
		{ 
			return 0; 
		} 
	/////////////////////////// 
	// Should never reach here 
	return 0; 
}
*/
} // namespace Ogre

⌨️ 快捷键说明

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