void MergeBounds(Ogre::SceneNode* node, Ogre::SceneNode* rootNode, const Ogre::Matrix4& parentTransform, Ogre::AxisAlignedBox& aabb) { // Get this nodes current transform Ogre::Matrix4 currentTransform = parentTransform; if (node != rootNode) { Ogre::Matrix4 localTransform(node->getOrientation()); localTransform.setTrans(node->getPosition()); currentTransform = currentTransform * localTransform; } // Merge this nodes objects Ogre::SceneNode::ObjectIterator object = node->getAttachedObjectIterator(); while (object.hasMoreElements()) { Ogre::AxisAlignedBox localAABB = object.getNext()->getBoundingBox(); localAABB.transform(currentTransform); aabb.merge(localAABB); } // Iterate through all children and call this function on them Ogre::SceneNode::ChildNodeIterator child = node->getChildIterator(); while (child.hasMoreElements()) { MergeBounds(static_cast<Ogre::SceneNode*>(child.getNext()), rootNode, currentTransform, aabb); } }
void SelectionHandler::updateTrackedBoxes() { M_HandleToBox::iterator it = boxes_.begin(); M_HandleToBox::iterator end = boxes_.end(); for (; it != end; ++it) { V_AABB aabbs; Picked p(it->first.first); p.extra_handles.insert(it->first.second); getAABBs(Picked(it->first.first), aabbs); if (!aabbs.empty()) { Ogre::AxisAlignedBox combined; V_AABB::iterator aabb_it = aabbs.begin(); V_AABB::iterator aabb_end = aabbs.end(); for (; aabb_it != aabb_end; ++aabb_it) { combined.merge(*aabb_it); } createBox(std::make_pair(p.handle, it->first.second), combined, "RVIZ/Cyan"); } } }
Ogre::AxisAlignedBox GPUBillboardSet::calculateBillboardsBoundingBox(const std::vector<PhotoSynth::Vertex>& vertices) { Ogre::AxisAlignedBox box; for (std::size_t i=0; i<vertices.size(); ++i) box.merge(vertices[i].position); return box; }
void RenderBoxScene::updateViewport() { // пр?нуле вылетает if ((mCanvas->getWidth() <= 1) || (mCanvas->getHeight() <= 1)) return; if ((nullptr != mEntity) && (nullptr != mCamera)) { // не ¤сн? нужн?ли раст¤гивать камеру, установленну?юзером mCamera->setAspectRatio((float)mCanvas->getWidth() / (float)mCanvas->getHeight()); // вычисл¤ем рассто¤ни? чтоб?бы?виде?весь объект Ogre::AxisAlignedBox box; box.merge(mEntity->getBoundingBox().getMinimum() + mEntity->getParentSceneNode()->_getDerivedPosition()); box.merge(mEntity->getBoundingBox().getMaximum() + mEntity->getParentSceneNode()->_getDerivedPosition()); if (box.isNull()) return; Ogre::Vector3 vec = box.getSize(); float width = sqrt(vec.x*vec.x + vec.z*vec.z); // само?длинно?- диагонал?(если крутит?модель) float len2 = width / mCamera->getAspectRatio(); float height = vec.y; float len1 = height; if (len1 < len2) len1 = len2; len1 /= 0.86; // [sqrt(3)/2] for 60 degrees field of view // цент?объект?по вертикал?+ отъехать та? чтоб?влезла ближ?¤ гран?BoundingBox'?+ чуть ввер??ещ?наза?дл¤ красот? Ogre::Vector3 result = box.getCenter() + Ogre::Vector3(0, 0, vec.z/2 + len1) + Ogre::Vector3(0, height*0.1, len1*0.2); Ogre::Vector3 look = Ogre::Vector3(0, box.getCenter().y /*+ box.getCenter().y * (1-mCurrentScale)*/, 0); mCameraNode->setPosition(result); mCameraNode->lookAt(look, Ogre::Node::TS_WORLD); } }
void SelectionHandler::onSelect(const Picked& obj) { ROS_DEBUG("Selected 0x%08x", obj.handle); V_AABB aabbs; getAABBs(obj, aabbs); if (!aabbs.empty()) { Ogre::AxisAlignedBox combined; V_AABB::iterator it = aabbs.begin(); V_AABB::iterator end = aabbs.end(); for (; it != end; ++it) { combined.merge(*it); } createBox(std::make_pair(obj.handle, 0ULL), combined, "RVIZ/Cyan"); } }
bool MiniMapMaker::outputTextures(void) { // 如果需要(纹理大小改变了或第一次输出文件时),就重建render texture if (mNeedRecreate) { destroy(); init(); } mTempOutputFileNames.clear(); static const String TEMP_GROUP_NAME = "#TEMP#"; // 创建临时的资源组 Ogre::ResourceGroupManager& rgm = Ogre::ResourceGroupManager::getSingleton(); rgm.addResourceLocation(mPath, "FileSystem", TEMP_GROUP_NAME, false); // 合并所有物体的包围盒 Ogre::AxisAlignedBox aabb; Ogre::SceneManager::MovableObjectIterator itm = mManipulator->getSceneManager()->getMovableObjectIterator(Ogre::EntityFactory::FACTORY_TYPE_NAME); while (itm.hasMoreElements()) { Ogre::MovableObject* movable = itm.getNext(); aabb.merge(movable->getWorldBoundingBox(true)); } mCamera->setFarClipDistance(mCamera->getNearClipDistance() + 2 * (aabb.getMaximum().y - aabb.getMinimum().y )); mCamera->setNearClipDistance(mTileSize/2); // 设置摄像机的高度 Real yPos = mCamera->getNearClipDistance() + aabb.getMaximum().y; TerrainData* terrainData = mManipulator->getTerrainData(); assert (terrainData); float terrainHeight = terrainData->mMaxZ - terrainData->mMinZ; float terrainWidth = terrainData->mMaxX - terrainData->mMinX; // 投影的真正面积 Real projectSize = 0.0f; // 最终切割成小块纹理的块数 int xIndex = 0; int zIndex = 0; Ogre::Vector3 originPoint(Ogre::Vector3::ZERO); if (mUseRealCameraAngle) { float outerSquareWidth = 0.0f; float outerSquareHeight = 0.0f; Ogre::Radian alphaAngle = Ogre::Math::ATan( Ogre::Math::Abs(mMoveZDir.z / mMoveZDir.x) ); switch (mCameraDirQuadrant) { case WestNorth : { float leftWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; float rightWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; float bottomHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMinX,0,terrainData->mMinZ) + (-mMoveZDir * leftWidth); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } case EastNorth : { float leftWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; float rightWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; float bottomHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMaxX,0,terrainData->mMinZ) + (-mMoveZDir * leftWidth); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } case EastSouth : { float leftWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; float rightWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; float bottomHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMaxX,0,terrainData->mMaxZ) + (-mMoveZDir * topHeight); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } case WestSouth : { float leftWidth = Ogre::Math::Sin(alphaAngle) * terrainHeight; float rightWidth = Ogre::Math::Cos(alphaAngle) * terrainWidth; outerSquareWidth = leftWidth + rightWidth; float topHeight = Ogre::Math::Sin(alphaAngle) * terrainWidth; float bottomHeight = Ogre::Math::Cos(alphaAngle) * terrainHeight; outerSquareHeight = topHeight + bottomHeight; originPoint = Ogre::Vector3(terrainData->mMinX,0,terrainData->mMaxZ) + (-mMoveZDir * rightWidth); float projectOffset = yPos / Ogre::Math::Tan(mCamDirAngle); originPoint.x += (mInvertCameraDir * projectOffset ).x; originPoint.z += (mInvertCameraDir * projectOffset ).z; break; } default: { OGRE_EXCEPT(Ogre::Exception::ERR_INTERNAL_ERROR, " wrong camera dir " + Ogre::StringConverter::toString(mCameraDir), "MiniMapMaker::outputTextures"); break; } } // 计算投影的长度 Real factor = Ogre::Math::Sin(mCamDirAngle); if (factor > 0.0f && factor != 1.0f) projectSize = mTileSize / factor; // 根据当前场景的大小,计算需要的分块数 xIndex = Ogre::Math::Ceil( (outerSquareWidth) / mTileSize ) + 1; zIndex = Ogre::Math::Ceil( (outerSquareHeight) / projectSize ) + 1; } else { xIndex = Ogre::Math::Ceil( (terrainData->mMaxX - terrainData->mMinX) / mTileSize ) + 1; zIndex = Ogre::Math::Ceil( (terrainData->mMaxZ - terrainData->mMinZ) / mTileSize ) + 1; originPoint.x = terrainData->mMinX; originPoint.z = terrainData->mMinZ; } // 计算最终的mini map的大小 uint miniMapWidth = xIndex * mTexWidth; uint miniMapHeight = zIndex * mTexHeight; if ( miniMapWidth > 10000 || miniMapHeight > 10000 ) { mLastErrorString = "texture size is out of range!"; return false; } // 创建mini map所需的内存空间 uchar* miniMapData = new uchar[miniMapWidth * miniMapHeight * Ogre::PixelUtil::getNumElemBytes(mOutPutFormat)]; //// 初始的摄像机位置 Real xPos = originPoint.x; Real zPos = originPoint.z; for ( int i=0; i<xIndex; ++i ) { for ( int j=0; j<zIndex; ++j ) { // 设置摄像机位置,并更新render texture的内容 mCamera->setPosition(xPos, yPos, zPos); mRenderTexture->update(); String fileName = mPath + mSceneBaseName + Ogre::StringConverter::toString(i) + "_" + Ogre::StringConverter::toString(j) + "." + mTexExtension; // 输出小纹理文件 mRenderTexture->writeContentsToFile(fileName); mTempOutputFileNames.push_back(fileName); // 读取刚创建的纹理 Ogre::Image* tempImage = new Ogre::Image; tempImage->load(mSceneBaseName + Ogre::StringConverter::toString(i) + "_" + Ogre::StringConverter::toString(j) + "." + mTexExtension, TEMP_GROUP_NAME); // 获取render texture中的内容 uchar* tempImageData = tempImage->getData(); // 定位在mini map中的左上角 uint miniMapIndex = ( j * mTexHeight * miniMapWidth + i * mTexWidth ) * Ogre::PixelUtil::getNumElemBytes(mOutPutFormat); uchar* startData = miniMapData + miniMapIndex; for ( size_t height = 0; height < tempImage->getHeight(); ++height ) { for ( size_t width = 0; width < tempImage->getWidth(); ++width ) { memcpy(startData, tempImageData, Ogre::PixelUtil::getNumElemBytes(mOutPutFormat)); startData += Ogre::PixelUtil::getNumElemBytes(mOutPutFormat); tempImageData += Ogre::PixelUtil::getNumElemBytes( tempImage->getFormat() ); } startData += (miniMapWidth - tempImage->getWidth()) * Ogre::PixelUtil::getNumElemBytes(mOutPutFormat); } delete tempImage; // 移动摄像机的z坐标 if (mUseRealCameraAngle) { zPos += (mInvertCameraDir * (projectSize)).z; xPos += (mInvertCameraDir * (projectSize)).x; } else zPos += mTileSize; } if (mUseRealCameraAngle) { xPos = originPoint.x; zPos = originPoint.z; xPos += (mMoveZDir * (mTileSize) * (i+1)).x; zPos += (mMoveZDir * (mTileSize) * (i+1)).z; } else { // 操作完每一列之后,重置摄像机的z坐标 zPos = terrainData->mMinZ; // 移动摄像机的x坐标 xPos += mTileSize; } } // 保存mini map并输出 Ogre::Image* miniMapImage = new Ogre::Image; miniMapImage->loadDynamicImage(miniMapData, miniMapWidth, miniMapHeight, 1, mOutPutFormat, true); miniMapImage->save(mPath + mOutFileName + "." + mTexExtension); delete miniMapImage; rgm.destroyResourceGroup(TEMP_GROUP_NAME); return true; }
void RenderBoxWrap::updateViewport() { // при нуле вылетает if ((mRenderBox->getWidth() <= 1) || (mRenderBox->getHeight() <= 1) ) return; if ((nullptr != mEntity) && (nullptr != mRttCam)) { // не ¤сно, нужно ли раст¤гивать камеру, установленную юзером mRttCam->setAspectRatio((float)mRenderBox->getWidth() / (float)mRenderBox->getHeight()); //System::Console::WriteLine("Width {0}, Height {1}", getWidth(), getHeight()); // вычисл¤ем рассто¤ние, чтобы был виден весь объект Ogre::AxisAlignedBox box;// = mNode->_getWorldAABB();//mEntity->getBoundingBox(); VectorEntity::iterator iter = mVectorEntity.begin(); while (iter != mVectorEntity.end()) { box.merge((*iter)->getBoundingBox().getMinimum() + (*iter)->getParentSceneNode()->_getDerivedPosition()); box.merge((*iter)->getBoundingBox().getMaximum() + (*iter)->getParentSceneNode()->_getDerivedPosition()); iter++; } if (box.isNull()) return; //box.scale(Ogre::Vector3(1.41f,1.41f,1.41f)); //System::Console::WriteLine("Minimum({0}), Maximum({1})", // gcnew System::String(Ogre::StringConverter::toString(box.getMinimum()).c_str()), // gcnew System::String(Ogre::StringConverter::toString(box.getMaximum()).c_str())); //box.getCenter(); Ogre::Vector3 vec = box.getSize(); // коррекци¤ под левосторонюю систему координат с осью Z направленную вверх #ifdef LEFT_HANDED_CS_UP_Z float width = sqrt(vec.x*vec.x + vec.y*vec.y); // самое длинное - диагональ (если крутить модель) float len2 = width; // mRttCam->getAspectRatio(); float height = vec.z; float len1 = height; if (len1 < len2) len1 = len2; len1 /= 0.86; // [sqrt(3)/2] for 60 degrees field of view // центр объекта по вертикали + отъехать так, чтобы влезла ближн¤¤ грань BoundingBox'а + чуть вверх и еще назад дл¤ красоты Ogre::Vector3 result = box.getCenter() - Ogre::Vector3(vec.y/2 + len1, 0, 0) - Ogre::Vector3(len1*0.2, 0, -height*0.1); result.x *= mCurrentScale; mCamNode->setPosition(result); Ogre::Vector3 x = Ogre::Vector3(0, 0, box.getCenter().z + box.getCenter().z * (1-mCurrentScale)) - mCamNode->getPosition(); Ogre::Vector3 y = Ogre::Vector3(Ogre::Vector3::UNIT_Z).crossProduct(x); Ogre::Vector3 z = x.crossProduct(y); mCamNode->setOrientation(Ogre::Quaternion( x.normalisedCopy(), y.normalisedCopy(), z.normalisedCopy())); #else float width = sqrt(vec.x*vec.x + vec.z*vec.z); // самое длинное - диагональ (если крутить модель) float len2 = width / mRttCam->getAspectRatio(); float height = vec.y; float len1 = height; if (len1 < len2) len1 = len2; len1 /= 0.86; // [sqrt(3)/2] for 60 degrees field of view // центр объекта по вертикали + отъехать так, чтобы влезла ближн¤¤ грань BoundingBox'а + чуть вверх и еще назад дл¤ красоты Ogre::Vector3 result = box.getCenter() + Ogre::Vector3(0, 0, vec.z/2 + len1) + Ogre::Vector3(0, height*0.1, len1*0.2); result.z *= mCurrentScale; Ogre::Vector3 look = Ogre::Vector3(0, box.getCenter().y /*+ box.getCenter().y * (1-mCurrentScale)*/, 0); mCamNode->setPosition(result); mCamNode->lookAt(look, Ogre::Node::TS_WORLD); #endif } }
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) { Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, NULL, mesh); for(size_t i = 0;i < entities.mEntities.size();i++) { const Ogre::AxisAlignedBox &tmp = entities.mEntities[i]->getBoundingBox(); bounds.merge(Ogre::AxisAlignedBox(insert->_getDerivedPosition() + tmp.getMinimum(), insert->_getDerivedPosition() + tmp.getMaximum()) ); } Ogre::Vector3 extents = bounds.getSize(); extents *= insert->getScale(); float size = std::max(std::max(extents.x, extents.y), extents.z); bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && Settings::Manager::getBool("limit small object distance", "Viewing distance"); // do not fade out doors. that will cause holes and look stupid if (ptr.getTypeName().find("Door") != std::string::npos) small = false; if (mBounds.find(ptr.getCell()) == mBounds.end()) mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; mBounds[ptr.getCell()].merge(bounds); bool transparent = false; for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; for (unsigned int i=0; i<ent->getNumSubEntities(); ++i) { Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); while (techIt.hasMoreElements()) { Ogre::Technique* tech = techIt.getNext(); Ogre::Technique::PassIterator passIt = tech->getPassIterator(); while (passIt.hasMoreElements()) { Ogre::Pass* pass = passIt.getNext(); if (pass->getDepthWriteEnabled() == false) transparent = true; } } } } if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) { for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } } else { Ogre::StaticGeometry* sg = 0; if (small) { if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometrySmall[ptr.getCell()] = sg; sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); } else sg = mStaticGeometrySmall[ptr.getCell()]; } else { if( mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometry[ptr.getCell()] = sg; } else sg = mStaticGeometry[ptr.getCell()]; } // This specifies the size of a single batch region. // If it is set too high: // - there will be problems choosing the correct lights // - the culling will be more inefficient // If it is set too low: // - there will be too many batches. sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); sg->setCastShadows(true); sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; insert->detachObject(ent); sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); mRenderer.getScene()->destroyEntity(ent); } } }
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh, bool light) { Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; NifOgre::ObjectList objects = NifOgre::Loader::createObjects(insert, mesh); for(size_t i = 0;i < objects.mEntities.size();i++) bounds.merge(objects.mEntities[i]->getWorldBoundingBox(true)); Ogre::Vector3 extents = bounds.getSize(); extents *= insert->getScale(); float size = std::max(std::max(extents.x, extents.y), extents.z); bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && Settings::Manager::getBool("limit small object distance", "Viewing distance"); // do not fade out doors. that will cause holes and look stupid if (ptr.getTypeName().find("Door") != std::string::npos) small = false; if (mBounds.find(ptr.getCell()) == mBounds.end()) mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; mBounds[ptr.getCell()].merge(bounds); bool anyTransparency = false; for(size_t i = 0;!anyTransparency && i < objects.mEntities.size();i++) { Ogre::Entity *ent = objects.mEntities[i]; for(unsigned int i=0;!anyTransparency && i < ent->getNumSubEntities(); ++i) { anyTransparency = ent->getSubEntity(i)->getMaterial()->isTransparent(); } } if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || anyTransparency || objects.mParticles.size() > 0) { for(size_t i = 0;i < objects.mEntities.size();i++) { Ogre::Entity *ent = objects.mEntities[i]; for(unsigned int i=0; i < ent->getNumSubEntities(); ++i) { Ogre::SubEntity* subEnt = ent->getSubEntity(i); subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); } ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); } for(size_t i = 0;i < objects.mParticles.size();i++) { Ogre::ParticleSystem *part = objects.mParticles[i]; // TODO: Check the particle system's material for actual transparency part->setRenderQueueGroup(RQG_Alpha); part->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); part->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); } } else { Ogre::StaticGeometry* sg = 0; if (small) { if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometrySmall[ptr.getCell()] = sg; sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); } else sg = mStaticGeometrySmall[ptr.getCell()]; } else { if( mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometry[ptr.getCell()] = sg; } else sg = mStaticGeometry[ptr.getCell()]; } // This specifies the size of a single batch region. // If it is set too high: // - there will be problems choosing the correct lights // - the culling will be more inefficient // If it is set too low: // - there will be too many batches. sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); sg->setCastShadows(true); sg->setRenderQueueGroup(RQG_Main); std::vector<Ogre::Entity*>::reverse_iterator iter = objects.mEntities.rbegin(); while(iter != objects.mEntities.rend()) { Ogre::Node *node = (*iter)->getParentNode(); sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale()); (*iter)->detachFromParent(); mRenderer.getScene()->destroyEntity(*iter); iter++; } } if (light) { insertLight(ptr, objects.mSkelBase, bounds.getCenter() - insert->_getDerivedPosition()); } }
void AssetLoader::readModel(Ogre::SceneManager* sceneMgr, Ogre::SceneNode* scnNode, const aiScene* scene, aiNode* nd) { for (size_t n = 0; n < nd->mNumChildren; n++) { aiNode* cnd = nd->mChildren[n]; Ogre::SceneNode* cnode = createChildSceneNodeWithTransform(scnNode, cnd); for (size_t i = 0; i < cnd->mNumMeshes; i++) { aiMesh* m = scene->mMeshes[cnd->mMeshes[i]]; aiMaterial* mat = scene->mMaterials[m->mMaterialIndex]; std::string nodeName = getFullPathName(cnd); Ogre::MaterialPtr omat = createMaterial(Ogre::String(nodeName), m->mMaterialIndex, mat); aiVector3D* vec = m->mVertices; aiVector3D* norm = m->mNormals; aiVector3D* uv = m->mTextureCoords[0]; aiColor4D* vcol = NULL; if (m->HasVertexColors(0)) vcol = m->mColors[0]; // 頂点情報の読み込み Ogre::AxisAlignedBox aab; Ogre::ManualObject* mobj = new Ogre::ManualObject(nodeName+"_MObj"); mobj->begin(omat->getName()); //mobj->begin("Ogre/Skin"); for (size_t n = 0; n < m->mNumVertices; n ++) { Ogre::Vector3 position(vec->x, vec->y, vec->z); aab.merge(position); mobj->position(vec->x, vec->y, vec->z); vec++; mobj->normal(norm->x, norm->y, norm->z); norm++; if (uv) { mobj->textureCoord(uv->x, uv->y); uv++; } if (vcol) { mobj->colour(vcol->r, vcol->g, vcol->b, vcol->a); vcol++; } } // ポリゴンの構築 for (size_t n = 0; n < m->mNumFaces; n++) { aiFace* face = &m->mFaces[n]; for (size_t k = 0; k < face->mNumIndices; k++) { mobj->index(face->mIndices[k]); } } mobj->end(); mobj->setBoundingBox(aab); Ogre::String meshName(nodeName+"_Mesh"); mobj->convertToMesh(meshName); delete mobj; Ogre::String entityName(nodeName+"_Entity"); std::cout << "entity: " << entityName << std::endl; Ogre::Entity* ent = sceneMgr->createEntity(entityName, meshName); cnode->attachObject(ent); } readModel(sceneMgr, cnode, scene, cnd); } }
void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScenePtr objlist, const ESM::Light *light) { const MWWorld::Fallback *fallback = MWBase::Environment::get().getWorld()->getFallback(); const int clr = light->mData.mColor; Ogre::ColourValue color(((clr >> 0) & 0xFF) / 255.0f, ((clr >> 8) & 0xFF) / 255.0f, ((clr >> 16) & 0xFF) / 255.0f); const float radius = float(light->mData.mRadius); if((light->mData.mFlags&ESM::Light::Negative)) color *= -1; objlist->mLights.push_back(sceneMgr->createLight()); Ogre::Light *olight = objlist->mLights.back(); olight->setDiffuseColour(color); Ogre::ControllerValueRealPtr src(Ogre::ControllerManager::getSingleton().getFrameTimeSource()); Ogre::ControllerValueRealPtr dest(OGRE_NEW OEngine::Render::LightValue(olight, color)); Ogre::ControllerFunctionRealPtr func(OGRE_NEW OEngine::Render::LightFunction( (light->mData.mFlags&ESM::Light::Flicker) ? OEngine::Render::LT_Flicker : (light->mData.mFlags&ESM::Light::FlickerSlow) ? OEngine::Render::LT_FlickerSlow : (light->mData.mFlags&ESM::Light::Pulse) ? OEngine::Render::LT_Pulse : (light->mData.mFlags&ESM::Light::PulseSlow) ? OEngine::Render::LT_PulseSlow : OEngine::Render::LT_Normal )); objlist->mControllers.push_back(Ogre::Controller<Ogre::Real>(src, dest, func)); bool interior = !(mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior()); bool quadratic = fallback->getFallbackBool("LightAttenuation_OutQuadInLin") ? !interior : fallback->getFallbackBool("LightAttenuation_UseQuadratic"); // with the standard 1 / (c + d*l + d*d*q) equation the attenuation factor never becomes zero, // so we ignore lights if their attenuation falls below this factor. const float threshold = 0.03; if (!quadratic) { float r = radius * fallback->getFallbackFloat("LightAttenuation_LinearRadiusMult"); float attenuation = fallback->getFallbackFloat("LightAttenuation_LinearValue") / r; float activationRange = 1.0f / (threshold * attenuation); olight->setAttenuation(activationRange, 0, attenuation, 0); } else { float r = radius * fallback->getFallbackFloat("LightAttenuation_QuadraticRadiusMult"); float attenuation = fallback->getFallbackFloat("LightAttenuation_QuadraticValue") / std::pow(r, 2); float activationRange = std::sqrt(1.0f / (threshold * attenuation)); olight->setAttenuation(activationRange, 0, 0, attenuation); } // If there's an AttachLight bone, attach the light to that, otherwise put it in the center, if(objlist->mSkelBase && objlist->mSkelBase->getSkeleton()->hasBone("AttachLight")) objlist->mSkelBase->attachObjectToBone("AttachLight", olight); else { Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; for(size_t i = 0;i < objlist->mEntities.size();i++) { Ogre::Entity *ent = objlist->mEntities[i]; bounds.merge(ent->getBoundingBox()); } Ogre::SceneNode *node = bounds.isFinite() ? mInsert->createChildSceneNode(bounds.getCenter()) : mInsert->createChildSceneNode(); node->attachObject(olight); } }
void operator()(Ogre::MovableObject *obj) { mBounds->merge(obj->getWorldBoundingBox(true)); }