Light

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Qps
Posts: 18
Joined: Thu Jan 27, 2011 2:02 pm

Light

Post by Qps »

Hi,

I have created the following draws a custom scenenode which:
  • Draws an object at the camera target which scales so the size in pixels stays the same.
    Creates a directional light

    The Light:
    • Rotates with the camera so the light is always to the left of the object
      Is always at a fixed distance in pixels from the object
      The lights rotation is set to the camera target
Now when i zoom in or out i would expect the light intensity to be constant (the lighting on the object to stay the same), however the light intensity decreases as i zoom out.

The distance in pixels of the light stays the same, which implies that the distance of the light in the scene increases as i zoom out.

The situation i would like is that the lighting on the object does not change as i:
  • Rotate (This already works)
    Zoom
I hope someone can help me out here.

I added the code below i used some pieces of code from the forum :) don't remember which posts i got them from, otherwise i would refer to the original posts for some credits ;)

.h

Code: Select all

 
#pragma once
#include <vector>
 
#include <irrlicht/ISceneNode.h>
#include <irrlicht/aabbox3d.h>
#include <irrlicht/SMaterial.h>
#include <irrlicht/vector3d.h>
 
// Forward declarations
namespace irr 
{
    namespace scene 
    { 
        class ISceneManager;
        class IAnimatedMesh;
        class IAnimatedMeshSceneNode;
        class ICameraSceneNode;
        class ILightSceneNode;
    }   
 
    namespace video
    {
        class IVideoDriver;
    }
}
 
class CTestSceneNode : public irr::scene::ISceneNode
{
public:
    CTestSceneNode(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, int id);
    ~CTestSceneNode(void);
 
    void Initialize();
 
    virtual void setMaterial(irr::video::SMaterial material);
    virtual irr::video::SMaterial getMaterial(int i);
    inline virtual irr::u32 getMaterialCount() const { return 1; }
 
    virtual const irr::core::aabbox3d<float>& getBoundingBox() const;
 
    virtual void OnRegisterSceneNode();
    virtual void render();
    
    void renderDebugData(irr::video::IVideoDriver* pDriver);
 
private:    
    
    float GetScreenScaleFactor(const irr::core::vector3df& worldpnt, irr::scene::ICameraSceneNode* camera);
    float CalculateScale(float fBoundingBoxLegth, float fSizeNeeded, float fScreenScaleFactor);
    
    irr::video::SMaterial                                       m_material;
    irr::core::aabbox3d<float>                                  m_boundingBox;
 
    irr::scene::IAnimatedMeshSceneNode*                         m_pConeTopSceneNode;
    irr::scene::ILightSceneNode*                                m_pLightTopCone;
};
 
.cpp

Code: Select all

#include "StdAfx.h"
#include "TestSceneNode.h"
 
#include <irrlicht/ISceneManager.h>
#include <irrlicht/ICameraSceneNode.h>
#include <irrlicht/IVideoDriver.h>
#include <irrlicht/IAnimatedMeshSceneNode.h>
#include <irrlicht/ILightSceneNode.h>
 
CTestSceneNode::CTestSceneNode(irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, int id)
: irr::scene::ISceneNode(parent, mgr, id)
, m_pConeTopSceneNode(NULL)
, m_pLightTopCone(NULL)
{
    m_material.Lighting = false;
    m_material.AntiAliasing = true; 
    m_material.BackfaceCulling = false;
    setAutomaticCulling(irr::scene::EAC_OFF);
}
 
CTestSceneNode::~CTestSceneNode(void)
{
}
 
void CTestSceneNode::Initialize()
{
    irr::scene::IAnimatedMesh* pConeTopMesh = SceneManager->getMesh("./resources/Objects/cone.3ds");    
    m_pConeTopSceneNode = SceneManager->addAnimatedMeshSceneNode(pConeTopMesh, this);
    m_pConeTopSceneNode->setName("Top Cone");
        
    //Add a light
    m_pLightTopCone = SceneManager->addLightSceneNode(this);
    
    irr::video::SLight sLightSettings;
    sLightSettings.Type = irr::video::E_LIGHT_TYPE::ELT_DIRECTIONAL;
    sLightSettings.CastShadows = false;
 
    m_pLightTopCone->setLightData(sLightSettings);
 
    m_pLightTopCone->setDebugDataVisible(irr::scene::E_DEBUG_SCENE_TYPE::EDS_BBOX);
}
 
void CTestSceneNode::OnRegisterSceneNode()
{
    if (IsVisible)
        SceneManager->registerNodeForRendering(this);
 
    ISceneNode::OnRegisterSceneNode();
    
    irr::scene::ICameraSceneNode* pActiveCamera = SceneManager->getActiveCamera();
    irr::core::vector3df vCameraPosition = pActiveCamera->getAbsolutePosition();
    irr::core::vector3df vCameraTarget = pActiveCamera->getTarget();
    
    float fScreenScaleFactor = GetScreenScaleFactor(vCameraTarget, pActiveCamera);
    
    //Calculate the position and scale of the cone
    if(m_pConeTopSceneNode)
    {
        m_pConeTopSceneNode->setPosition(vCameraTarget);
        
        float fScale = CalculateScale(m_pConeTopSceneNode->getBoundingBox().MinEdge.getLength(), 15, fScreenScaleFactor);
        m_pConeTopSceneNode->setScale(irr::core::vector3df(fScale, fScale, fScale));
    }
 
    //Calculate the position of the light
    if(m_pLightTopCone)
    {
        float fLightDistance = 0.200f * fScreenScaleFactor;
 
        irr::core::vector3df vLightTopCone(vCameraTarget.X - fLightDistance, vCameraTarget.Y, vCameraTarget.Z);
 
        irr::core::vector3df vDirectionStartToCamera = vCameraTarget - vCameraPosition;
        irr::core::vector3df vHorizontalAngle = vDirectionStartToCamera.getHorizontalAngle();
 
        vLightTopCone.rotateXZBy(-vHorizontalAngle.Y, vCameraTarget);
        m_pLightTopCone->setPosition(vLightTopCone);
 
        irr::core::vector3df diff = vCameraTarget - vLightTopCone;
        m_pLightTopCone->setRotation(diff.getHorizontalAngle());
 
    }
}
 
float CTestSceneNode::CalculateScale(float fBoundingBoxLegth, float fSizeNeeded, float fScreenScaleFactor)
{
    float pixels = fBoundingBoxLegth / fScreenScaleFactor;
    
    return fSizeNeeded / (pixels * 1000);
}
 
void CTestSceneNode::render()
{
    irr::video::IVideoDriver* pDriver = SceneManager->getVideoDriver();
    irr::scene::ICameraSceneNode* pCurrentCamera = SceneManager->getActiveCamera();
    
    pDriver->setMaterial(m_material);
    pDriver->setTransform(irr::video::ETS_WORLD, AbsoluteTransformation);
    
    //Start rendering the light 
    //NOTE: The light is not set to invisible until all the nodes
    //have been rendered onto which the light should be applied
    if(m_pLightTopCone)
    {
        m_pLightTopCone->setVisible(true);      
        m_pLightTopCone->updateAbsolutePosition();
        m_pLightTopCone->render();      
    }
 
    if(m_pConeTopSceneNode)
    {
        m_pConeTopSceneNode->setVisible(true);      
        m_pConeTopSceneNode->updateAbsolutePosition();
        m_pConeTopSceneNode->render();
        m_pConeTopSceneNode->setVisible(false);
    }
 
    //All nodes were rendered set the light to invisible so it doesnt affect any other nodes
    if(m_pLightTopCone)
        m_pLightTopCone->setVisible(false);
}
 
float CTestSceneNode::GetScreenScaleFactor(const irr::core::vector3df& worldpnt, irr::scene::ICameraSceneNode* camera)
{
        irr::core::vector3df viewpnt = worldpnt;
        camera->getViewMatrix().transformVect(viewpnt);
        return  2 * viewpnt.Z / camera->getProjectionMatrix()[0];
}
 
void CTestSceneNode::setMaterial(irr::video::SMaterial material)
{   
    m_material = material;
}
 
irr::video::SMaterial CTestSceneNode::getMaterial(int i)
{   
    irr::video::SMaterial material = m_material;
 
    return material;
}
 
const irr::core::aabbox3d<float>& CTestSceneNode::getBoundingBox() const 
{ 
    irr::core::aabbox3d<float> boundingBox = m_boundingBox;
 
    return boundingBox;
}
 
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Light

Post by hybrid »

This effect is expected, as you also scale the normals of the mesh. These are taken into account on light calculations, and are expected to be normalized. So enable EMF_NORMALIZE_NORMALS in your materials as well.
Qps
Posts: 18
Joined: Thu Jan 27, 2011 2:02 pm

Re: Light

Post by Qps »

Thank you, this was indeed the case.
Post Reply