#include "LBBCBillboardCloudDiffuseColorTextureViewMode.h" #include "LBBCLeaves.h" #include "LBBCManager.h" namespace LBBC { BillboardCloudDiffuseColorTextureViewMode::BillboardCloudDiffuseColorTextureViewMode(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; } BillboardCloudDiffuseColorTextureViewMode::~BillboardCloudDiffuseColorTextureViewMode() { } void BillboardCloudDiffuseColorTextureViewMode::setBillboardCloudGroupedTextureAtlasDebug(bool debugTextureAtlasGeneration) { mDebugTextureAtlasGeneration = debugTextureAtlasGeneration; } void BillboardCloudDiffuseColorTextureViewMode::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 BillboardCloudDiffuseColorTextureViewMode::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 BillboardCloudDiffuseColorTextureViewMode::disableEntityClusterCustomOrthogonalCameraMaterial(unsigned int iEntityClusterGrouped) { //mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram(""); //mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram(""); //mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->reload(); } void BillboardCloudDiffuseColorTextureViewMode::enableEntityClusterCustomOrthogonalCameraMaterial(unsigned int iEntityClusterGrouped) { //mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->getTechnique(0)->getPass(0)->setVertexProgram("diffuseTextureScreenAligned_VP20"); mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->getTechnique(0)->getPass(0)->setFragmentProgram("diffuseTextureScreenAligned_FP20"); //Ogre::GpuProgramParametersSharedPtr vertParams; //Ogre::GpuProgramParametersSharedPtr fragParams; //vertParams = mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->getTechnique(0)->getPass(0)->getVertexProgramParameters(); //fragParams = mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->getTechnique(0)->getPass(0)->getFragmentProgramParameters(); //vertParams->setNamedConstant("projectionmatrix", mCamera->getProjectionMatrixWithRSDepth()); //vertParams->setNamedAutoConstant("worldmatrix", Ogre::GpuProgramParameters::ACT_WORLD_MATRIX); //vertParams->setNamedAutoConstant("viewmatrix", Ogre::GpuProgramParameters::ACT_VIEW_MATRIX); //mEntityClustersGrouped->getSubEntity(iEntityClusterGrouped)->getMaterial()->reload(); } void BillboardCloudDiffuseColorTextureViewMode::configureTexture() { mTextureAtlas->getRectangle2D()->setVisible(false); mEntityClustersGrouped->getSubEntity((mCurrentTexture-1) % mEntityClustersGrouped->getNumSubEntities())->setVisible(false); mEntityClustersGrouped->getSubEntity(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities())->setVisible(true); configureBillboardOrthogonalAlignedCamera(mCurrentTexture % mBillboardCloudSplitted->getNumSubEntities()); mCamera->setCustomProjectionMatrix(true,mCustomProjMatrix); 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 BillboardCloudDiffuseColorTextureViewMode::generateTexture() { configureTexture(); enableEntityClusterCustomOrthogonalCameraMaterial(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities()); mClusterTexture->update(); disableEntityClusterCustomOrthogonalCameraMaterial(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities()); } void BillboardCloudDiffuseColorTextureViewMode::initializeEntityClustersGrouped() { if (mFrame == 1) { for (unsigned int iSubEntity = 0; iSubEntity < mEntityClustersGrouped->getNumSubEntities(); iSubEntity++) { mEntityClustersGrouped->getSubEntity(iSubEntity)->setVisible(false); } } } void BillboardCloudDiffuseColorTextureViewMode::initializeBillboardCloudSplitted() { if (mFrame == 1) { ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->loadBillboardCloudGroupedDiffuseColorXML(); for (unsigned int iSubEntity = 0; iSubEntity < mBillboardCloudSplitted->getNumSubEntities(); iSubEntity++) { mBillboardCloudSplitted->getSubEntity(iSubEntity)->setVisible(false); } } } bool BillboardCloudDiffuseColorTextureViewMode::processUnbufferedKeyInput(const Ogre::FrameEvent& evt) { if (mInputDevice->isKeyDown(Ogre::KC_SPACE)) { mCurrentTexture++; } return OgreFrameListenerMode::processUnbufferedKeyInput(evt); } void BillboardCloudDiffuseColorTextureViewMode::configureTextureAtlas() { mEntityClustersGrouped->getSubEntity(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities())->setVisible(false); mClusterTexture->getRectangle2D()->setVisible(true); mTextureAtlas->getRectangle2D()->setVisible(true); Ogre::Vector2 uvMapMax = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getBillboard(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities())->getBillboardClusterData()->getBillboardUVMapMax(0); Ogre::Vector2 uvMapMin = ((LBBC::LBBCManager*)LBBC::LBBCManager::getSingletonPtr())->getLeaves()->getBillboardCloud()->getBillboard(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities())->getBillboardClusterData()->getBillboardUVMapMin(0); mClusterTexture->setCorners(uvMapMin[0], uvMapMax[1], uvMapMax[0], uvMapMin[1]); } void BillboardCloudDiffuseColorTextureViewMode::generateTextureAtlas() { configureTextureAtlas(); mTextureAtlas->update(); //mTextureAtlas->debug(); mClusterTexture->getRectangle2D()->setVisible(false); } bool BillboardCloudDiffuseColorTextureViewMode::frameStarted(const Ogre::FrameEvent& evt, Ogre::InputReader *inputReader) { showDebugOverlay(false); initializeEntityClustersGrouped(); initializeBillboardCloudSplitted(); 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 BillboardCloudDiffuseColorTextureViewMode::configureBillboard() { mBillboardCloudSplitted->getSubEntity((mCurrentTexture-1) % mEntityClustersGrouped->getNumSubEntities())->setVisible(false); mBillboardCloudSplitted->getSubEntity(mCurrentTexture % mEntityClustersGrouped->getNumSubEntities())->setVisible(true); } void BillboardCloudDiffuseColorTextureViewMode::setTextureAtlasSize(unsigned int size) { mTextureAtlasSize = size; } void BillboardCloudDiffuseColorTextureViewMode::setEntityClustersGroupedName(Ogre::String entityClustersGroupedName) { mEntityClustersGroupedName = entityClustersGroupedName; } void BillboardCloudDiffuseColorTextureViewMode::setBillboardCloudSplittedName(Ogre::String billboardCloudSplittedName) { mBillboardCloudSplittedName = billboardCloudSplittedName; } void BillboardCloudDiffuseColorTextureViewMode::setTextureAtlasBitRange(unsigned int bitRange) { mBitRange = bitRange; } void BillboardCloudDiffuseColorTextureViewMode::setTextureSize(unsigned int size) { mTextureSize = size; } void BillboardCloudDiffuseColorTextureViewMode::setTextureAtlasFolder(Ogre::String textureAtlasFolder) { mTextureAtlasFolder = textureAtlasFolder; } void BillboardCloudDiffuseColorTextureViewMode::setTextureAtlasName(Ogre::String textureAtlasName) { mTextureAtlasName = textureAtlasName; } void BillboardCloudDiffuseColorTextureViewMode::setTextureName(Ogre::String textureName) { mTextureName = textureName; } void BillboardCloudDiffuseColorTextureViewMode::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; } IMG::TexturePtr texturePtr ( new IMG::Texture() ); texturePtr->bind(mTextureName); Ogre::ColourValue avgColour = texturePtr->getAvgColour(); mWindow->getViewport(0)->setBackgroundColour(Ogre::ColourValue(1.0, 1.0, 1.0, 1.0)); mEntityClustersGroupedSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mBillboardCloudSplittedSceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mEntityClustersGrouped = mSceneMgr->createEntity(mEntityClustersGroupedName, mEntityClustersGroupedName); mEntityClustersGroupedSceneNode->attachObject(mEntityClustersGrouped); mBillboardCloudSplitted = mSceneMgr->createEntity(mBillboardCloudSplittedName, mBillboardCloudSplittedName); mBillboardCloudSplittedSceneNode->attachObject(mBillboardCloudSplitted); mTextureAtlas = IMG::TextureAtlasPtr( new IMG::TextureAtlas() ); mTextureAtlas->create("TextureAtlasDiffuseColor", mTextureAtlasSize, mTextureAtlasSize, mSrcPixelFormat, mCamera, avgColour); mTextureAtlas->setTextureAtlasSceneNode(mEntityClustersGroupedSceneNode); Ogre::MaterialPtr materialPtr1 = Ogre::MaterialManager::getSingleton().create("DiffuseColorTextureAtlasMaterial", 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("ClusterTextureDiffuseColor", mTextureSize, mTextureSize, mSrcPixelFormat, mCamera, avgColour); Ogre::MaterialPtr materialPtr = Ogre::MaterialManager::getSingleton().create("DiffuseColorTextureMaterial", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (!mDebugTextureAtlasGeneration) { materialPtr->getTechnique(0)->getPass(0)->setAlphaRejectSettings(Ogre::CMPF_GREATER_EQUAL, 10); materialPtr->getTechnique(0)->getPass(0)->createTextureUnitState("ClusterTextureDiffuseColor", 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)->getPass(0)->setLightingEnabled(false); } mClusterTexture->setMaterial(materialPtr.getPointer()); mTextureAtlas->addTexture(mClusterTexture); mNumTextures = mEntityClustersGrouped->getNumSubEntities(); mCurrentTexture = 0; } void BillboardCloudDiffuseColorTextureViewMode::destroyScene() { } }