SImplified the Transform usage in the gpu::api, no more pointers, just values. Improved the Transform by compressing the memory footprint

This commit is contained in:
Sam Gateau 2014-11-13 10:57:32 -08:00
parent b92a617290
commit 7e2c4c0561
9 changed files with 101 additions and 98 deletions

View file

@ -160,7 +160,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_lastQueriedViewFrustum(), _lastQueriedViewFrustum(),
_lastQueriedTime(usecTimestampNow()), _lastQueriedTime(usecTimestampNow()),
_mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)), _mirrorViewRect(QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT)),
_viewTransform(new gpu::Transform()), _viewTransform(),
_scaleMirror(1.0f), _scaleMirror(1.0f),
_rotateMirror(0.0f), _rotateMirror(0.0f),
_raiseMirror(0.0f), _raiseMirror(0.0f),
@ -2911,13 +2911,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
// Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation
// the viewTransofmr object is updatded with the correct values and saved, // the viewTransofmr object is updatded with the correct values and saved,
// this is what is used for rendering the Entities and avatars // this is what is used for rendering the Entities and avatars
gpu::Transform viewTransform; Transform viewTransform;
viewTransform.setTranslation(whichCamera.getPosition()); viewTransform.setTranslation(whichCamera.getPosition());
viewTransform.setRotation(rotation); viewTransform.setRotation(rotation);
viewTransform.postTranslate(eyeOffsetPos); viewTransform.postTranslate(eyeOffsetPos);
viewTransform.postRotate(eyeOffsetOrient); viewTransform.postRotate(eyeOffsetOrient);
if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { if (whichCamera.getMode() == CAMERA_MODE_MIRROR) {
viewTransform.setScale(gpu::Transform::Vec3(-1.0f, 1.0f, 1.0f)); viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f));
} }
setViewTransform(viewTransform); setViewTransform(viewTransform);
@ -3117,8 +3117,8 @@ void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTransl
_viewMatrixTranslation = viewMatrixTranslation; _viewMatrixTranslation = viewMatrixTranslation;
} }
void Application::setViewTransform(const gpu::Transform& view) { void Application::setViewTransform(const Transform& view) {
(*_viewTransform) = view; _viewTransform = view;
} }
void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { void Application::loadTranslatedViewMatrix(const glm::vec3& translation) {

View file

@ -232,8 +232,8 @@ public:
const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; }
void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; }
const gpu::TransformPointer& getViewTransform() const { return _viewTransform; } const Transform& getViewTransform() const { return _viewTransform; }
void setViewTransform(const gpu::Transform& view); void setViewTransform(const Transform& view);
/// if you need to access the application settings, use lockSettings()/unlockSettings() /// if you need to access the application settings, use lockSettings()/unlockSettings()
QSettings* lockSettings() { _settingsMutex.lock(); return _settings; } QSettings* lockSettings() { _settingsMutex.lock(); return _settings; }
@ -526,7 +526,7 @@ private:
QRect _mirrorViewRect; QRect _mirrorViewRect;
RearMirrorTools* _rearMirrorTools; RearMirrorTools* _rearMirrorTools;
gpu::TransformPointer _viewTransform; Transform _viewTransform;
glm::mat4 _untranslatedViewMatrix; glm::mat4 _untranslatedViewMatrix;
glm::vec3 _viewMatrixTranslation; glm::vec3 _viewMatrixTranslation;
glm::mat4 _projectionMatrix; glm::mat4 _projectionMatrix;

View file

@ -135,19 +135,19 @@ void Batch::setIndexBuffer(Type type, const BufferPointer& buffer, Offset offset
_params.push_back(type); _params.push_back(type);
} }
void Batch::setModelTransform(const TransformPointer& model) { void Batch::setModelTransform(const Transform& model) {
ADD_COMMAND(setModelTransform); ADD_COMMAND(setModelTransform);
_params.push_back(_transforms.cache(model)); _params.push_back(_transforms.cache(model));
} }
void Batch::setViewTransform(const TransformPointer& view) { void Batch::setViewTransform(const Transform& view) {
ADD_COMMAND(setViewTransform); ADD_COMMAND(setViewTransform);
_params.push_back(_transforms.cache(view)); _params.push_back(_transforms.cache(view));
} }
void Batch::setProjectionTransform(const TransformPointer& proj) { void Batch::setProjectionTransform(const Transform& proj) {
ADD_COMMAND(setProjectionTransform); ADD_COMMAND(setProjectionTransform);
_params.push_back(_transforms.cache(proj)); _params.push_back(_transforms.cache(proj));

View file

@ -50,10 +50,6 @@ enum Primitive {
NUM_PRIMITIVES, NUM_PRIMITIVES,
}; };
typedef ::Transform Transform;
typedef QSharedPointer< ::gpu::Transform > TransformPointer;
typedef std::vector< TransformPointer > Transforms;
class Batch { class Batch {
public: public:
typedef Stream::Slot Slot; typedef Stream::Slot Slot;
@ -87,9 +83,9 @@ public:
// finaly projected into the clip space by the projection transform // finaly projected into the clip space by the projection transform
// WARNING: ViewTransform transform from eye space to world space, its inverse is composed // WARNING: ViewTransform transform from eye space to world space, its inverse is composed
// with the ModelTransformu to create the equivalent of the glModelViewMatrix // with the ModelTransformu to create the equivalent of the glModelViewMatrix
void setModelTransform(const TransformPointer& model); void setModelTransform(const Transform& model);
void setViewTransform(const TransformPointer& view); void setViewTransform(const Transform& view);
void setProjectionTransform(const TransformPointer& proj); void setProjectionTransform(const Transform& proj);
// TODO: As long as we have gl calls explicitely issued from interface // TODO: As long as we have gl calls explicitely issued from interface
@ -258,35 +254,35 @@ public:
template <typename T> template <typename T>
class Cache { class Cache {
public: public:
typedef QSharedPointer<T> Pointer; typedef T Data;
Pointer _pointer; Data _data;
Cache<T>(const Pointer& pointer) : _pointer(pointer) {} Cache<T>(const Data& data) : _data(data) {}
class Vector { class Vector {
public: public:
std::vector< Cache<T> > _pointers; std::vector< Cache<T> > _items;
uint32 cache(const Pointer& pointer) { uint32 cache(const Data& data) {
uint32 offset = _pointers.size(); uint32 offset = _items.size();
_pointers.push_back(Cache<T>(pointer)); _items.push_back(Cache<T>(data));
return offset; return offset;
} }
Pointer get(uint32 offset) { Data get(uint32 offset) {
if (offset >= _pointers.size()) { if (offset >= _items.size()) {
return Pointer(); return Data();
} }
return (_pointers.data() + offset)->_pointer; return (_items.data() + offset)->_data;
} }
void clear() { void clear() {
_pointers.clear(); _items.clear();
} }
}; };
}; };
typedef Cache<Buffer>::Vector BufferCaches; typedef Cache<BufferPointer>::Vector BufferCaches;
typedef Cache<Stream::Format>::Vector StreamFormatCaches; typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
typedef Cache<Transform>::Vector TransformCaches; typedef Cache<Transform>::Vector TransformCaches;
typedef unsigned char Byte; typedef unsigned char Byte;

View file

@ -430,30 +430,18 @@ void GLBackend::do_setIndexBuffer(Batch& batch, uint32 paramOffset) {
// Transform Stage // Transform Stage
void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) { void GLBackend::do_setModelTransform(Batch& batch, uint32 paramOffset) {
TransformPointer modelTransform = batch._transforms.get(batch._params[paramOffset]._uint); _transform._model = batch._transforms.get(batch._params[paramOffset]._uint);
_transform._invalidModel = true;
if (_transform._model.isNull() || (modelTransform != _transform._model)) {
_transform._model = modelTransform;
_transform._invalidModel = true;
}
} }
void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) { void GLBackend::do_setViewTransform(Batch& batch, uint32 paramOffset) {
TransformPointer viewTransform = batch._transforms.get(batch._params[paramOffset]._uint); _transform._view = batch._transforms.get(batch._params[paramOffset]._uint);
_transform._invalidView = true;
if (_transform._view.isNull() || (viewTransform != _transform._view)) {
_transform._view = viewTransform;
_transform._invalidView = true;
}
} }
void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) { void GLBackend::do_setProjectionTransform(Batch& batch, uint32 paramOffset) {
TransformPointer projectionTransform = batch._transforms.get(batch._params[paramOffset]._uint); _transform._projection = batch._transforms.get(batch._params[paramOffset]._uint);
_transform._invalidProj = true;
if (_transform._projection.isNull() || (projectionTransform != _transform._projection)) {
_transform._projection = projectionTransform;
_transform._invalidProj = true;
}
} }
void GLBackend::updateTransform() { void GLBackend::updateTransform() {
@ -468,28 +456,28 @@ void GLBackend::updateTransform() {
} }
if (_transform._invalidModel || _transform._invalidView) { if (_transform._invalidModel || _transform._invalidView) {
if (!_transform._model.isNull()) { if (!_transform._model.isIdentity()) {
if (_transform._lastMode != GL_MODELVIEW) { if (_transform._lastMode != GL_MODELVIEW) {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
_transform._lastMode = GL_MODELVIEW; _transform._lastMode = GL_MODELVIEW;
} }
Transform::Mat4 modelView; Transform::Mat4 modelView;
if (!_transform._view.isNull()) { if (!_transform._view.isIdentity()) {
Transform mvx; Transform mvx;
Transform::inverseMult(mvx, (*_transform._view), (*_transform._model)); Transform::inverseMult(mvx, _transform._view, _transform._model);
mvx.getMatrix(modelView); mvx.getMatrix(modelView);
} else { } else {
_transform._model->getMatrix(modelView); _transform._model.getMatrix(modelView);
} }
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
} else { } else {
if (!_transform._view.isNull()) { if (!_transform._view.isIdentity()) {
if (_transform._lastMode != GL_MODELVIEW) { if (_transform._lastMode != GL_MODELVIEW) {
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
_transform._lastMode = GL_MODELVIEW; _transform._lastMode = GL_MODELVIEW;
} }
Transform::Mat4 modelView; Transform::Mat4 modelView;
_transform._view->getInverseMatrix(modelView); _transform._view.getInverseMatrix(modelView);
glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView)); glLoadMatrixf(reinterpret_cast< const GLfloat* >(&modelView));
} else { } else {
// TODO: eventually do something about the matrix when neither view nor model is specified? // TODO: eventually do something about the matrix when neither view nor model is specified?

View file

@ -86,9 +86,9 @@ protected:
void updateTransform(); void updateTransform();
struct TransformStageState { struct TransformStageState {
TransformPointer _model; Transform _model;
TransformPointer _view; Transform _view;
TransformPointer _projection; Transform _projection;
bool _invalidModel; bool _invalidModel;
bool _invalidView; bool _invalidView;
bool _invalidProj; bool _invalidProj;
@ -96,9 +96,9 @@ protected:
GLenum _lastMode; GLenum _lastMode;
TransformStageState() : TransformStageState() :
_model(0), _model(),
_view(0), _view(),
_projection(0), _projection(),
_invalidModel(true), _invalidModel(true),
_invalidView(true), _invalidView(true),
_invalidProj(true), _invalidProj(true),

View file

@ -567,11 +567,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
// Capture the view matrix once for the rendering of this model // Capture the view matrix once for the rendering of this model
if (_transforms.empty()) { if (_transforms.empty()) {
_transforms.push_back(gpu::TransformPointer(new gpu::Transform())); _transforms.push_back(Transform());
} }
(*_transforms[0]) = gpu::Transform((*Application::getInstance()->getViewTransform())); _transforms[0] = Application::getInstance()->getViewTransform();
// apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space) // apply entity translation offset to the viewTransform in one go (it's a preTranslate because viewTransform goes from world to eye space)
_transforms[0]->preTranslate(-_translation); _transforms[0].preTranslate(-_translation);
batch.setViewTransform(_transforms[0]); batch.setViewTransform(_transforms[0]);
@ -1493,10 +1493,10 @@ void Model::setupBatchTransform(gpu::Batch& batch) {
// Capture the view matrix once for the rendering of this model // Capture the view matrix once for the rendering of this model
if (_transforms.empty()) { if (_transforms.empty()) {
_transforms.push_back(gpu::TransformPointer(new gpu::Transform())); _transforms.push_back(Transform());
} }
(*_transforms[0]) = gpu::Transform((*Application::getInstance()->getViewTransform())); _transforms[0] = Application::getInstance()->getViewTransform();
_transforms[0]->preTranslate(-_translation); _transforms[0].preTranslate(-_translation);
batch.setViewTransform(_transforms[0]); batch.setViewTransform(_transforms[0]);
} }
@ -2149,10 +2149,9 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl
if (state.clusterMatrices.size() > 1) { if (state.clusterMatrices.size() > 1) {
GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false,
(const float*)state.clusterMatrices.constData()); (const float*)state.clusterMatrices.constData());
batch.setModelTransform(gpu::TransformPointer()); batch.setModelTransform(Transform());
} else { } else {
gpu::TransformPointer modelTransform(new gpu::Transform(state.clusterMatrices[0])); batch.setModelTransform(Transform(state.clusterMatrices[0]));
batch.setModelTransform(modelTransform);
} }
if (mesh.blendshapes.isEmpty()) { if (mesh.blendshapes.isEmpty()) {

View file

@ -283,7 +283,7 @@ private:
QUrl _url; QUrl _url;
gpu::Buffers _blendedVertexBuffers; gpu::Buffers _blendedVertexBuffers;
gpu::Transforms _transforms; std::vector<Transform> _transforms;
gpu::Batch _renderBatch; gpu::Batch _renderBatch;
QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures; QVector<QVector<QSharedPointer<Texture> > > _dilatedTextures;

View file

@ -20,6 +20,8 @@
#include <bitset> #include <bitset>
#include <memory>
class Transform { class Transform {
public: public:
typedef glm::mat4 Mat4; typedef glm::mat4 Mat4;
@ -30,16 +32,16 @@ public:
typedef glm::quat Quat; typedef glm::quat Quat;
Transform() : Transform() :
_translation(0),
_rotation(1.0f, 0, 0, 0), _rotation(1.0f, 0, 0, 0),
_scale(1.0f), _scale(1.0f),
_translation(0),
_flags(FLAG_CACHE_INVALID_BITSET) // invalid cache _flags(FLAG_CACHE_INVALID_BITSET) // invalid cache
{ {
} }
Transform(const Transform& transform) : Transform(const Transform& transform) :
_translation(transform._translation),
_rotation(transform._rotation), _rotation(transform._rotation),
_scale(transform._scale), _scale(transform._scale),
_translation(transform._translation),
_flags(transform._flags) _flags(transform._flags)
{ {
invalidCache(); invalidCache();
@ -49,6 +51,15 @@ public:
} }
~Transform() {} ~Transform() {}
Transform& operator=(const Transform& transform) {
_rotation = transform._rotation;
_scale = transform._scale;
_translation = transform._translation;
_flags = transform._flags;
invalidCache();
return (*this);
}
void setIdentity(); void setIdentity();
const Vec3& getTranslation() const; const Vec3& getTranslation() const;
@ -89,7 +100,6 @@ public:
// Left will be inversed before the multiplication // Left will be inversed before the multiplication
static Transform& inverseMult(Transform& result, const Transform& left, const Transform& right); static Transform& inverseMult(Transform& result, const Transform& left, const Transform& right);
protected: protected:
enum Flag { enum Flag {
@ -111,14 +121,15 @@ protected:
// TRS // TRS
Vec3 _translation;
Quat _rotation; Quat _rotation;
Vec3 _scale; Vec3 _scale;
Vec3 _translation;
mutable Flags _flags; mutable Flags _flags;
// Cached transform // Cached transform
mutable Mat4 _matrix; // TODO: replace this auto ptr by a "unique ptr" as soon as we are compiling in C++11
mutable std::auto_ptr<Mat4> _matrix;
bool isCacheInvalid() const { return _flags[FLAG_CACHE_INVALID]; } bool isCacheInvalid() const { return _flags[FLAG_CACHE_INVALID]; }
void validCache() const { _flags.set(FLAG_CACHE_INVALID, false); } void validCache() const { _flags.set(FLAG_CACHE_INVALID, false); }
@ -135,6 +146,7 @@ protected:
void flagNonUniform() { _flags.set(FLAG_NON_UNIFORM, true); } void flagNonUniform() { _flags.set(FLAG_NON_UNIFORM, true); }
void updateCache() const; void updateCache() const;
Mat4& getCachedMatrix(Mat4& result) const;
}; };
inline void Transform::setIdentity() { inline void Transform::setIdentity() {
@ -271,8 +283,25 @@ inline void Transform::postScale(const Vec3& scale) {
} }
inline Transform::Mat4& Transform::getMatrix(Transform::Mat4& result) const { inline Transform::Mat4& Transform::getMatrix(Transform::Mat4& result) const {
updateCache(); if (isRotating()) {
result = _matrix; Mat3 rot = glm::mat3_cast(_rotation);
if (isScaling()) {
rot[0] *= _scale.x;
rot[1] *= _scale.y;
rot[2] *= _scale.z;
}
result[0] = Vec4(rot[0], 0.f);
result[1] = Vec4(rot[1], 0.f);
result[2] = Vec4(rot[2], 0.f);
} else {
result[0] = Vec4(_scale.x, 0.f, 0.f, 0.f);
result[1] = Vec4(0.f, _scale.y, 0.f, 0.f);
result[2] = Vec4(0.f, 0.f, _scale.z, 0.f);
}
result[3] = Vec4(_translation, 1.0f);
return result; return result;
} }
@ -369,27 +398,18 @@ inline Transform& Transform::inverseMult( Transform& result, const Transform& le
return result; return result;
} }
inline Transform::Mat4& Transform::getCachedMatrix(Transform::Mat4& result) const {
updateCache();
result = (*_matrix);
return result;
}
inline void Transform::updateCache() const { inline void Transform::updateCache() const {
if (isCacheInvalid()) { if (isCacheInvalid()) {
if (isRotating()) { if (!_matrix.get()) {
Mat3 rot = glm::mat3_cast(_rotation); _matrix.reset(new Mat4());
if (isScaling()) {
rot[0] *= _scale.x;
rot[1] *= _scale.y;
rot[2] *= _scale.z;
}
_matrix[0] = Vec4(rot[0], 0.f);
_matrix[1] = Vec4(rot[1], 0.f);
_matrix[2] = Vec4(rot[2], 0.f);
} else {
_matrix[0] = Vec4(_scale.x, 0.f, 0.f, 0.f);
_matrix[1] = Vec4(0.f, _scale.y, 0.f, 0.f);
_matrix[2] = Vec4(0.f, 0.f, _scale.z, 0.f);
} }
getMatrix((*_matrix));
_matrix[3] = Vec4(_translation, 1.0f);
validCache(); validCache();
} }
} }