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.
pull/279/head
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) if(BUILD_TESTS)
enable_testing() 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}) include_directories(${QT_INCLUDE_DIR})
add_subdirectory(Test) add_subdirectory(Test)
endif() endif()

15
src/Light.cpp

@ -14,12 +14,25 @@
*/ */
#include "Light.h" #include "Light.h"
#include "Camera.h"
namespace Magnum { 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() { void Light::setClean() {
if(!isDirty()) return; if(!isDirty()) return;
_position = absoluteTransformation()[3]; _position = (absoluteTransformation()*_camera->cameraMatrix())[3].xyz();
Object::setClean(); Object::setClean();
} }

15
src/Light.h

@ -34,15 +34,15 @@ class Light: public Object {
* @brief Constructor * @brief Constructor
* @param parent Parent object * @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() { Vector3 position(Camera* camera);
setClean();
return _position;
}
/** /**
* Recomputes light position. * Recomputes light position.
@ -50,7 +50,8 @@ class Light: public Object {
void setClean(); void setClean();
private: 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(ObjectTest ObjectTest.h ObjectTest.cpp Magnum)
corrade_add_test(CameraTest CameraTest.h CameraTest.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) 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