#include "LBBCBillboardCloudIndirectTextureViewMode.h" #include "LBBCLeaves.h" #include "LBBCManager.h" namespace LBBC { BillboardCloudIndirectTextureViewMode::BillboardCloudIndirectTextureViewMode(Ogre::RenderWindow* win, unsigned int ogreFrameListenerModeHandle, bool useBufferedInputKeys, bool useBufferedInputMouse) :OBA::OgreFrameListenerMode(win, ogreFrameListenerModeHandle, useBufferedInputKeys, useBufferedInputMouse) { mFrame = 0; mCurrentBillboardGroup = 0; mCurrentBillboard = 0; showDebugOverlay(false); mDebugBillboardGeneration = false; mDebugTextureAtlasGeneration = false; } BillboardCloudIndirectTextureViewMode::~BillboardCloudIndirectTextureViewMode() { } void BillboardCloudIndirectTextureViewMode::setBillboardCloudGroupedTextureAtlasDebug(bool debugTextureAtlasGeneration) { mDebugTextureAtlasGeneration = debugTextureAtlasGeneration; } void BillboardCloudIndirectTextureViewMode::configureBillboardOrthogonalAlignedCamera(unsigned int iBillboard) { BBC::BillboardPtr billboardPtr = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getBillboard(iBillboard); Ogre::Vector3 vTopLeft = billboardPtr->getBillboardClusterData()->getQuadTopLeftCorner(); Ogre::Vector3 vTopRight = billboardPtr->getBillboardClusterData()->getQuadTopRightCorner(); Ogre::Vector3 vBottomLeft = billboardPtr->getBillboardClusterData()->getQuadBottomLeftCorner(); Ogre::Vector3 vBottomRight = billboardPtr->getBillboardClusterData()->getQuadBottomRightCorner(); Ogre::Vector3 vMidPoint = vTopLeft.midPoint(vBottomRight); Ogre::Vector3 vWidth(vTopRight - vTopLeft); Ogre::Vector3 vHeight(vBottomLeft - vTopLeft); Ogre::Real w = vWidth.length(); Ogre::Real h = vHeight.length(); Ogre::Real aspect = w / h; Ogre::Radian fovy = Ogre::Radian(Ogre::Degree(90.0)); Ogre::Real nearPlane = h / Ogre::Math::Tan(fovy/2.0,false); Ogre::Real farPlane = 100000; Ogre::Vector3 vUp = vTopLeft - vBottomLeft; vUp.normalise(); Ogre::Vector3 vI(vTopRight-vTopLeft); vI.normalise(); Ogre::Vector3 vJ(vBottomLeft-vTopLeft); vJ.normalise(); Ogre::Vector3 vDir = -vI.crossProduct(vJ); vDir.normalise(); Ogre::Vector3 vRight = vDir.crossProduct(vUp); vRight.normalise(); Ogre::Quaternion qOrientation(vRight, vUp, -vDir); mCamera->setNearClipDistance(nearPlane); mCamera->setOrientation(qOrientation); mCamera->setPosition(vMidPoint - (vDir * (nearPlane*nearPlane))); if (Ogre::Root::getSingleton().getRenderSystem()->getName() != "Direct3D9 Rendering SubSystem") { Ogre::Radian thetaY (fovy / 2.0f); Ogre::Real tanThetaY = Ogre::Math::Tan(thetaY); Ogre::Real tanThetaX = tanThetaY * aspect; Ogre::Real half_w,half_h; half_w = w / 2.0; half_h = h / 2.0; Ogre::Real iw = 1.0 / half_w; Ogre::Real ih = 1.0 / half_h; Ogre::Real q; if (farPlane == 0) { q = 0; } else { q = 2.0 / (farPlane - nearPlane); } mCustomProjMatrix = Ogre::Matrix4::ZERO; mCustomProjMatrix[0][0] = iw; mCustomProjMatrix[1][1] = ih; mCustomProjMatrix[2][2] = -q; mCustomProjMatrix[2][3] = - (farPlane + nearPlane)/(farPlane - nearPlane); mCustomProjMatrix[3][3] = 1; } else { Ogre::Radian thetaY (fovy / 2.0f); Ogre::Real tanThetaY = Ogre::Math::Tan(thetaY); //Real thetaX = thetaY * aspect; Ogre::Real tanThetaX = tanThetaY * aspect; //Math::Tan(thetaX); Ogre::Real half_w = w / 2; Ogre::Real half_h = h / 2; Ogre::Real iw = 1.0 / half_w; Ogre::Real ih = 1.0 / half_h; Ogre::Real q; if (farPlane == 0) { q = 0; } else { q = 1.0 / (farPlane - nearPlane); } mCustomProjMatrix = Ogre::Matrix4::ZERO; mCustomProjMatrix[0][0] = iw; mCustomProjMatrix[1][1] = ih; mCustomProjMatrix[2][2] = q; mCustomProjMatrix[2][3] = -nearPlane / (farPlane - nearPlane); mCustomProjMatrix[3][3] = 1; mCustomProjMatrix[2][2] = -mCustomProjMatrix[2][2]; } } void BillboardCloudIndirectTextureViewMode::saveTextureAtlas() { if (mBitRange == 32) { mDestPixelFormat = Ogre::PF_FLOAT32_RGBA; } else if (mBitRange == 16) { mDestPixelFormat = Ogre::PF_FLOAT16_RGBA; } else // mBitRange == 8 { mDestPixelFormat = Ogre::PF_BYTE_RGBA; } Ogre::String textureAtlasFileName = BBC::Util::getBaseName(mTextureAtlasName) + Ogre::StringConverter::toString(mCurrentBillboardGroup) + "." + BBC::Util::getExtensionName(mTextureAtlasName); mTextureAtlas->save(mTextureAtlasFolder, textureAtlasFileName, mDestPixelFormat); } void BillboardCloudIndirectTextureViewMode::configureTexture() { mTextureAtlas->getRectangle2D()->setVisible(false); //mClusterTexture->getRectangle2D()->setVisible(true); //mClusterTexture->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("customNormalMap128x128.png"); //mClusterTexture->setCorners(-1.0, 1.0, 1.0, -1.0); mBillboardCloudPointClusters->getSubEntity((mCurrentTexture-1) % mBillboardCloudPointClusters->getNumSubEntities())->setVisible(false); mBillboardCloudPointClusters->getSubEntity(mCurrentTexture % mBillboardCloudPointClusters->getNumSubEntities())->setVisible(true); configureBillboardOrthogonalAlignedCamera(mCurrentTexture % mBillboardCloudSplitted->getNumSubEntities()); mCamera->setCustomProjectionMatrix(true,mCustomProjMatrix); Ogre::GpuProgramParametersSharedPtr fragParams; if (mDebugTextureAtlasGeneration) { mClusterTexture->getMaterial()->getTechnique(0)->getPass(0)->setAmbient(Ogre::Math::RangeRandom(0.0,1.0), Ogre::Math::RangeRandom(0.0,1.0), Ogre::Math::RangeRandom(0.0,1.0)); mClusterTexture->getMaterial()->getTechnique(0)->getPass(0)->setDiffuse(Ogre::Math::RangeRandom(0.0,1.0), Ogre::Math::RangeRandom(0.0,1.0), Ogre::Math::RangeRandom(0.0,1.0), 1.0); } } void BillboardCloudIndirectTextureViewMode::generateTexture() { configureTexture(); mClusterTexture->update(); //mClusterTexture->debug(); } void BillboardCloudIndirectTextureViewMode::setEntityClustersGroupedName(Ogre::String entityClustersGroupedName) { mEntityClustersGroupedName = entityClustersGroupedName; } void BillboardCloudIndirectTextureViewMode::initializeEntityClustersGrouped() { if (mFrame == 1) { for (unsigned int iSubEntity = 0; iSubEntity < mBillboardCloudPointClusters->getNumSubEntities(); iSubEntity++) { mEntityClustersGrouped->getSubEntity(iSubEntity)->setVisible(false); } } } void BillboardCloudIndirectTextureViewMode::initializeBillboardCloudPointClusters() { if (mFrame == 1) { for (unsigned int iSubEntity = 0; iSubEntity < mBillboardCloudPointClusters->getNumSubEntities(); iSubEntity++) { mBillboardCloudPointClusters->getSubEntity(iSubEntity)->setVisible(false); } } } void BillboardCloudIndirectTextureViewMode::initializeBillboardCloudSplitted() { if (mFrame == 1) { ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->loadBillboardCloudGroupedIndirectTexturingXML(); for (unsigned int iSubEntity = 0; iSubEntity < mBillboardCloudSplitted->getNumSubEntities(); iSubEntity++) { mBillboardCloudSplitted->getSubEntity(iSubEntity)->setVisible(false); } } } bool BillboardCloudIndirectTextureViewMode::processUnbufferedKeyInput(const Ogre::FrameEvent& evt) { if (mInputDevice->isKeyDown(Ogre::KC_SPACE)) { mCurrentTexture++; } return OgreFrameListenerMode::processUnbufferedKeyInput(evt); } void BillboardCloudIndirectTextureViewMode::configureTextureAtlas() { mBillboardCloudPointClusters->getSubEntity(mCurrentTexture % mBillboardCloudPointClusters->getNumSubEntities())->setVisible(false); mTextureAtlas->getRectangle2D()->setVisible(true); Ogre::Vector2 uvMapMax = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getBillboard(mCurrentTexture % mBillboardCloudPointClusters->getNumSubEntities())->getBillboardClusterData()->getBillboardUVMapMax(0); Ogre::Vector2 uvMapMin = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getBillboard(mCurrentTexture % mBillboardCloudPointClusters->getNumSubEntities())->getBillboardClusterData()->getBillboardUVMapMin(0); mClusterTexture->setCorners(uvMapMin[0], uvMapMax[1], uvMapMax[0], uvMapMin[1]); mClusterTexture->getRectangle2D()->setVisible(true); //mClusterTexture->getMaterial()->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName(mClusterTexture->getTextureName()); } void BillboardCloudIndirectTextureViewMode::generateTextureAtlas() { configureTextureAtlas(); mTextureAtlas->update(); //mTextureAtlas->debug(); mClusterTexture->getRectangle2D()->setVisible(false); } bool BillboardCloudIndirectTextureViewMode::frameStarted(const Ogre::FrameEvent& evt, Ogre::InputReader *inputReader) { showDebugOverlay(false); initializeEntityClustersGrouped(); initializeBillboardCloudSplitted(); initializeBillboardCloudPointClusters(); if (mFrame > 1) { if (!mDebugBillboardGeneration) { mWindow->getViewport(0)->setBackgroundColour(Ogre::ColourValue(1.0, 1.0, 1.0, 1.0)); if (mCurrentTexture < mNumTextures) { generateTexture(); generateTextureAtlas(); mCurrentTexture++; mCurrentBillboard++; unsigned int numBillboardsCurrentGroups = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getBillboardGroup(mCurrentBillboardGroup)->getNumBillboards(); if (mCurrentBillboard == numBillboardsCurrentGroups) { saveTextureAtlas(); unsigned int numBillboardGroups = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getNumBillboardGroups(); if (mCurrentBillboardGroup < numBillboardGroups) { mCurrentBillboard = 0; mCurrentBillboardGroup++; mTextureAtlas->getRectangle2D()->setVisible(false); mTextureAtlas->update(); //mTextureAtlas->debug(); } } } if (mCurrentTexture == mNumTextures) { mDebugBillboardGeneration = true; mWindow->getViewport(0)->setBackgroundColour(Ogre::ColourValue(0.0, 0.0, 0.0, 1.0)); mTextureAtlas->getRectangle2D()->setVisible(false); mCurrentTexture = 0; } } else { mWindow->getViewport(0)->setBackgroundColour(Ogre::ColourValue(0.0, 0.0, 0.0, 1.0)); configureBillboard(); configureTexture(); mCurrentTexture = mCurrentTexture % mNumTextures; } } mFrame++; return OgreFrameListenerMode::frameStarted(evt, inputReader); } void BillboardCloudIndirectTextureViewMode::configureBillboard() { mEntityClustersGrouped->getSubEntity((mCurrentTexture-1) % mEntityClustersGrouped->getNumSubEntities())->setVisible(false); mEntityClustersGrouped->getSubEntity(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities())->setVisible(true); mBillboardCloudSplitted->getSubEntity((mCurrentTexture-1) % mBillboardCloudPointClusters->getNumSubEntities())->setVisible(false); mBillboardCloudSplitted->getSubEntity(mCurrentTexture % mBillboardCloudPointClusters->getNumSubEntities())->setVisible(true); } void BillboardCloudIndirectTextureViewMode::setTextureAtlasSize(unsigned int size) { mTextureAtlasSize = size; } void BillboardCloudIndirectTextureViewMode::setBillboardCloudPointClustersName(Ogre::String billboardCloudPointClustersName) { mBillboardCloudPointClustersName = billboardCloudPointClustersName; } void BillboardCloudIndirectTextureViewMode::setBillboardCloudSplittedName(Ogre::String billboardCloudSplittedName) { mBillboardCloudSplittedName = billboardCloudSplittedName; } void BillboardCloudIndirectTextureViewMode::setTextureAtlasBitRange(unsigned int bitRange) { mBitRange = bitRange; } void BillboardCloudIndirectTextureViewMode::setTextureSize(unsigned int size) { mTextureSize = size; } void BillboardCloudIndirectTextureViewMode::setTextureAtlasFolder(Ogre::String textureAtlasFolder) { mTextureAtlasFolder = textureAtlasFolder; } void BillboardCloudIndirectTextureViewMode::setTextureAtlasName(Ogre::String textureAtlasName) { mTextureAtlasName = textureAtlasName; } void BillboardCloudIndirectTextureViewMode::createScene() { if (mBitRange == 32) { mSrcPixelFormat = Ogre::PF_FLOAT32_RGBA; } else if (mBitRange == 16) { mSrcPixelFormat = Ogre::PF_FLOAT16_RGBA; } else // mBitRange == 8 { mSrcPixelFormat = Ogre::PF_A8R8G8B8; } mWindow->getViewport(0)->setBackgroundColour(Ogre::ColourValue(1.0, 1.0, 1.0, 1.0)); mBillboardCloudPointClustersSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mBillboardCloudSplittedSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mBillboardCloudPointClusters = mSceneMgr->createEntity(mBillboardCloudPointClustersName, mBillboardCloudPointClustersName); mBillboardCloudPointClustersSceneNode->attachObject(mBillboardCloudPointClusters); mBillboardCloudSplitted = mSceneMgr->createEntity(mBillboardCloudSplittedName, mBillboardCloudSplittedName); mBillboardCloudSplittedSceneNode->attachObject(mBillboardCloudSplitted); mEntityClustersGroupedSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mEntityClustersGrouped = mSceneMgr->createEntity(mEntityClustersGroupedName, mEntityClustersGroupedName); mEntityClustersGroupedSceneNode->attachObject(mEntityClustersGrouped); mTextureAtlas = IMG::TextureAtlasPtr( new IMG::TextureAtlas() ); mTextureAtlas->create("IndirectTextureAtlas", mTextureAtlasSize, mTextureAtlasSize, mSrcPixelFormat, mCamera, Ogre::ColourValue(0.0, 0.0, 0.0, 0.0)); mTextureAtlas->setTextureAtlasSceneNode(mBillboardCloudPointClustersSceneNode); Ogre::MaterialPtr materialPtr1 = Ogre::MaterialManager::getSingleton().create("IndirectTextureAtlasMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); materialPtr1->getTechnique(0)->getPass(0)->setAlphaRejectSettings(Ogre::CMPF_GREATER_EQUAL, 10); materialPtr1->getTechnique(0)->getPass(0)->createTextureUnitState("transparent.png"); materialPtr1->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::FO_NONE, Ogre::FO_NONE, Ogre::FO_NONE); materialPtr1->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); materialPtr1->getTechnique(0)->getPass(0)->setLightingEnabled(false); mTextureAtlas->setMaterial(materialPtr1.getPointer()); mTextureAtlas->setCorners(-1.0, 1.0, 1.0, -1.0); mClusterTexture = IMG::TexturePtr( new IMG::Texture() ); mClusterTexture->create("ClusterIndirectTexture", mTextureSize, mTextureSize, mSrcPixelFormat, mCamera, Ogre::ColourValue(0.0, 0.0, 0.0, 0.0)); Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().create("IndirectTextureMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (!mDebugTextureAtlasGeneration) { materialPtr->getTechnique(0)->getPass(0)->createTextureUnitState("customNormalMap128x128.png", 0); materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureFiltering(Ogre::FO_NONE, Ogre::FO_NONE, Ogre::FO_NONE); materialPtr->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); materialPtr->getTechnique(0)->createPass(); materialPtr->getTechnique(0)->getPass(1)->setSceneBlending(Ogre::SBT_ADD); materialPtr->getTechnique(0)->getPass(1)->setDepthWriteEnabled(false); materialPtr->getTechnique(0)->getPass(1)->setAlphaRejectSettings(Ogre::CMPF_GREATER_EQUAL, 10); materialPtr->getTechnique(0)->getPass(1)->createTextureUnitState("ClusterIndirectTexture", 0); materialPtr->getTechnique(0)->getPass(1)->getTextureUnitState(0)->setTextureFiltering(Ogre::FO_NONE, Ogre::FO_NONE, Ogre::FO_NONE); materialPtr->getTechnique(0)->getPass(1)->getTextureUnitState(0)->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); materialPtr->getTechnique(0)->getPass(0)->setLightingEnabled(false); } mClusterTexture->setMaterial(materialPtr.getPointer()); mTextureAtlas->addTexture(mClusterTexture); mNumTextures = mBillboardCloudPointClusters->getNumSubEntities(); mCurrentTexture = 0; } void BillboardCloudIndirectTextureViewMode::destroyScene() { } }