Browse Source

Caching light position relative to camera.

Saves one matrix*vector multiplication per object per frame. The
position can be now Vector3 like before, because it won't be multiplied
with anything on draw call. Added unit test.
vectorfields
Vladimír Vondruš 14 years ago
parent
commit
0443bbe286
  1. 9
      src/CMakeLists.txt
  2. 15
      src/Light.cpp
  3. 15
      src/Light.h
  4. 1
      src/Test/CMakeLists.txt
  5. 63
      src/Test/LightTest.cpp
  6. 32
      src/Test/LightTest.h

9
src/CMakeLists.txt

@ -42,6 +42,15 @@ install(TARGETS Magnum DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
if(BUILD_TESTS)
enable_testing()
# Library with graceful assert for testing
add_library(MagnumTestLib SHARED ${Magnum_SRCS})
if(WIN32)
set_target_properties(MagnumTestLib PROPERTIES COMPILE_FLAGS -DMAGNUM_EXPORTING)
endif()
set_target_properties(MagnumTestLib PROPERTIES COMPILE_FLAGS -DCORRADE_GRACEFUL_ASSERT)
target_link_libraries(MagnumTestLib ${CORRADE_UTILITY_LIBRARY} ${CORRADE_PLUGINMANAGER_LIBRARY} ${OPENGL_gl_LIBRARY} ${GLEW_LIBRARY})
include_directories(${QT_INCLUDE_DIR})
add_subdirectory(Test)
endif()

15
src/Light.cpp

@ -14,12 +14,25 @@
*/
#include "Light.h"
#include "Camera.h"
namespace Magnum {
Vector3 Light::position(Camera* camera) {
CORRADE_ASSERT(scene() && camera->scene() == scene(), "Light: camera and light aren't in the same scene!", Vector3())
if(camera != _camera) {
_camera = camera;
setDirty();
}
setClean();
return _position;
}
void Light::setClean() {
if(!isDirty()) return;
_position = absoluteTransformation()[3];
_position = (absoluteTransformation()*_camera->cameraMatrix())[3].xyz();
Object::setClean();
}

15
src/Light.h

@ -34,15 +34,15 @@ class Light: public Object {
* @brief Constructor
* @param parent Parent object
*/
inline Light(Object* parent = nullptr): Object(parent) {}
inline Light(Object* parent = nullptr): Object(parent), _camera(nullptr) {}
/**
* @brief Light position relative to root object (scene)
* @brief Light position relative to given camera
*
* The position is cached until the camera is changed to another or
* the light dirty bit is set.
*/
inline Vector4 position() {
setClean();
return _position;
}
Vector3 position(Camera* camera);
/**
* Recomputes light position.
@ -50,7 +50,8 @@ class Light: public Object {
void setClean();
private:
Vector4 _position;
Camera* _camera;
Vector3 _position;
};
}

1
src/Test/CMakeLists.txt

@ -1,3 +1,4 @@
corrade_add_test(ObjectTest ObjectTest.h ObjectTest.cpp Magnum)
corrade_add_test(CameraTest CameraTest.h CameraTest.cpp Magnum)
corrade_add_test(LightTest LightTest.h LightTest.cpp MagnumTestLib)
corrade_add_test(SceneTest SceneTest.h SceneTest.cpp Magnum)

63
src/Test/LightTest.cpp

@ -0,0 +1,63 @@
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "LightTest.h"
#include <sstream>
#include <QtTest/QTest>
#include "Camera.h"
#include "Light.h"
#include "Scene.h"
QTEST_APPLESS_MAIN(Magnum::Test::LightTest)
using namespace std;
using namespace Corrade::Utility;
namespace Magnum { namespace Test {
void LightTest::positionWrongCamera() {
stringstream ss;
Error::setOutput(&ss);
Camera c;
Light l;
QVERIFY(l.position(&c) == Vector3());
QVERIFY(ss.str() == "Light: camera and light aren't in the same scene!\n");
}
void LightTest::position() {
Scene s;
Object lightParent(&s);
lightParent.translate(Vector3::zAxis(3));
Light light(&lightParent);
Object cameraParent(&s);
cameraParent.rotate(deg(90.0f), Vector3::xAxis());
Camera camera(&cameraParent);
QVERIFY(light.position(&camera) == (Matrix4::translation(Vector3::zAxis(3))*
Matrix4::rotation(deg(90.0f), Vector3::xAxis()).inversed())[3].xyz());
/* Set another camera */
Camera another(&cameraParent);
another.scale(Vector3(3.0f));
QVERIFY(light.position(&another) == (Matrix4::translation(Vector3::zAxis(3))*
(Matrix4::scaling(Vector3(3.0f))*Matrix4::rotation(deg(90.0f), Vector3::xAxis())).inversed())[3].xyz());
}
}}

32
src/Test/LightTest.h

@ -0,0 +1,32 @@
#ifndef Magnum_Test_LightTest_h
#define Magnum_Test_LightTest_h
/*
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <QtCore/QObject>
namespace Magnum { namespace Test {
class LightTest: public QObject {
Q_OBJECT
private slots:
void positionWrongCamera();
void position();
};
}}
#endif
Loading…
Cancel
Save