/////////////////////////////////////////////////////////////////////////// // // Realistic rain real-time simulation program // // Pierre Rousseau // /////////////////////////////////////////////////////////////////////////// // // Light Handling // /////////////////////////////////////////////////////////////////////////// #include "RainLight.h" RainLight::RainLight(SceneManager *sceneMgr, int lightNumber, ColourValue col, Vector3 LightPos, float LightAttenuation) {String name; mSceneMgr = sceneMgr; Vector3 decalage_ampoule(-5.5, 38, 0); Entity *mStreetLight = mSceneMgr->createEntity("Street_light_" + StringConverter::toString(lightNumber), "lampadaire.mesh"); mStreetLight->setMaterialName("lampMat"); mConeNode = NULL; SceneNode *mStreetLightNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(); mStreetLightNode->setPosition(LightPos); mStreetLightNode->setScale(0.8, 0.8, 0.8); mStreetLightNode->attachObject(mStreetLight); mLightNode = mStreetLightNode->createChildSceneNode(decalage_ampoule); name = "billboardSet_for_light" + StringConverter::toString(lightNumber); mBillboardSet = sceneMgr->createBillboardSet(name); mLightNode->attachObject(mBillboardSet); mBillboardSet->setMaterialName("Examples/Flare"); mBillboard = mBillboardSet->createBillboard(Vector3(0, 0, 0)); mBillboard->setDimensions(8, 8); mBillboard->setColour(col); mColour = col; mLightPos = mLightNode->getWorldPosition(); mLightDir = Vector3(-0.2, -1, 0).normalisedCopy(); mLightCutoff = 35; mLightAttenuation = LightAttenuation; } void RainLight::animate() { static Vector3 pos; static Vector3 dir; if (isAnimated) { h1 += stepH1 / 10.0; h2 += stepH2 / 10.0; h3 += stepH3 / 10.0; v1 += stepV1 / 10.0; v2 += stepV2 / 10.0; /* pos = Vector3(sin(h1) * sin(h2) * 10.0, sin(v1) * sin(v2) * 3.0, (cos(h1) - 1.0) * (cos(h3) - 1.0) * 10.0); mLightPos = mLightInitialPos + pos; mLightNode->setPosition(mLightPos); mLightCutoff = sin(h3) * 60.0 + 30; if (mLightCutoff < 45) { //the cone is narrow, we scale over x and z mConeNode->setScale(tan(mLightCutoff * _PI / 180.0) * 2.0, 1.0, tan(mLightCutoff * _PI / 180.0) * 2.0); } else { mConeNode->setScale(1.0, 1.0 / (tan(mLightCutoff * _PI / 180.0) * 2.0), 1.0); } */ dir = Vector3(sin(h1) * sin(h2), cos(h1), sin(h1) * cos(h2)).normalisedCopy(); if (mConeNode) { mConeNode->resetOrientation(); mConeNode->rotate(Vector3(0, 1, 0).getRotationTo(dir)); mLightDir = dir; } } } ////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////// ////////// ////////// RainLightManager class ////////// ////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////// RainLightManager::RainLightManager(SceneManager *sceneMgr) { mSceneMgr = sceneMgr; lightCount = 0; lightVector.clear(); } RainLightManager::~RainLightManager() {} void RainLightManager::addStreetLight(ColourValue col, Vector3 LightPos, float LightAttenuation) { lightVector.push_back(new RainLight(mSceneMgr, lightCount, col, LightPos, LightAttenuation)); ++lightCount; } /* light info texture will contain information about a light source : - first pixel : color - second pixel : position - third pixel : direction (if spot) - fourth pixel : spot cutoff angle (180 for omnidirectional), distance attenuation (% / m) */ //void RainLightManager::createLightInfoTexture(int lightIndex, ColourValue col, Vector3 lightPosition, Vector3 lightDirection) void RainLightManager::createLightInfoTexture() { std::cout << std::endl << " Creating light information texture " << std::endl << std::endl; TexturePtr DynamicLightInfoTexture = TextureManager::getSingleton().createManual( LIGHT_INFO_TEXTURE_NAME, // name ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, // type 4, lightCount, // width & height 0, // number of mipmaps PF_FLOAT32_RGBA, // pixel format TU_DYNAMIC_WRITE_ONLY_DISCARDABLE); // Get the pixel buffer HardwarePixelBufferSharedPtr pixelBuffer = DynamicLightInfoTexture->getBuffer(); // Lock the pixel buffer and get a pixel box pixelBuffer->lock(HardwareBuffer::HBL_DISCARD); const PixelBox& pixelBox = pixelBuffer->getCurrentLock(); float* pDest = static_cast(pixelBox.data); // Fill in some pixel data. for (int i = 0 ; i < lightCount ; i++ ) { // we search for the data of each light ColourValue col = lightVector[i]->getColour(); Vector3 pos = lightVector[i]->getPosition(); Vector3 dir = lightVector[i]->getDirection(); float cutoff = lightVector[i]->getCutoff(); float att = lightVector[i]->getAttenuation(); // first pixel : light color *pDest++ = col.r; *pDest++ = col.g; *pDest++ = col.b; *pDest++ = 1.0; // second pixel : light position *pDest++ = pos.x; *pDest++ = pos.y; *pDest++ = pos.z; *pDest++ = 1.0; // third pixel : light direction *pDest++ = dir.x; *pDest++ = dir.y; *pDest++ = dir.z; *pDest++ = 1.0; // fourth pixel : cutoff and attenuation *pDest++ = cutoff; *pDest++ = att; *pDest++ = 1.0; *pDest++ = 1.0; } // Unlock the pixel buffer pixelBuffer->unlock(); DynamicLightInfoTexture->load(); } void RainLightManager::updateLightInfoTexture() { TexturePtr DynamicLightInfoTexture = TextureManager::getSingleton().getByName(LIGHT_INFO_TEXTURE_NAME); // Get the pixel buffer HardwarePixelBufferSharedPtr pixelBuffer = DynamicLightInfoTexture->getBuffer(); // Lock the pixel buffer and get a pixel box pixelBuffer->lock(HardwareBuffer::HBL_DISCARD); const PixelBox& pixelBox = pixelBuffer->getCurrentLock(); float* pDest = static_cast(pixelBox.data); // Fill in some pixel data. for (int i = 0 ; i < lightCount ; i++ ) { // we search for the data of each light ColourValue col = lightVector[i]->getColour(); Vector3 pos = lightVector[i]->getPosition(); Vector3 dir = lightVector[i]->getDirection(); float cutoff = lightVector[i]->getCutoff(); float att = lightVector[i]->getAttenuation(); // first pixel : light color *pDest++ = col.r; *pDest++ = col.g; *pDest++ = col.b; *pDest++ = 1.0; // second pixel : light position *pDest++ = pos.x; *pDest++ = pos.y; *pDest++ = pos.z; *pDest++ = 1.0; // third pixel : light direction *pDest++ = dir.x; *pDest++ = dir.y; *pDest++ = dir.z; *pDest++ = 1.0; // fourth pixel : cutoff and attenuation *pDest++ = cutoff; *pDest++ = att; *pDest++ = 1.0; *pDest++ = 1.0; } // Unlock the pixel buffer pixelBuffer->unlock(); DynamicLightInfoTexture->load(); } void RainLightManager::updateLights() { for (int i = 0 ; i < lightCount ; i++ ) { if (lightVector[i]->getIsAnimated()) { lightVector[i]->animate(); } } updateLightInfoTexture(); } void RainLightManager::finalizeLights() { createLightInfoTexture(); }