#183 improvements

This commit is contained in:
Vadim Lopatin 2016-04-04 11:53:41 +03:00
parent b01f90c7c2
commit a48dd1d99b
7 changed files with 169 additions and 13 deletions

View File

@ -1512,9 +1512,94 @@ struct mat4 {
return res; return res;
} }
/**
* Decomposes the scale, rotation and translation components of this matrix.
*
* @param scale The scale.
* @param rotation The rotation.
* @param translation The translation.
*/
bool decompose(vec3 * scale, vec4 * rotation, vec3 * translation) const {
if (translation)
{
// Extract the translation.
translation.x = m[12];
translation.y = m[13];
translation.z = m[14];
} }
// Nothing left to do.
if (!scale && !rotation)
return true;
// Extract the scale.
// This is simply the length of each axis (row/column) in the matrix.
vec3 xaxis = vec3(m[0], m[1], m[2]);
float scaleX = xaxis.length();
vec3 yaxis = vec3(m[4], m[5], m[6]);
float scaleY = yaxis.length();
vec3 zaxis = vec3(m[8], m[9], m[10]);
float scaleZ = zaxis.length();
// Determine if we have a negative scale (true if determinant is less than zero).
// In this case, we simply negate a single axis of the scale.
float det = determinant();
if (det < 0)
scaleZ = -scaleZ;
if (scale)
{
scale.x = scaleX;
scale.y = scaleY;
scale.z = scaleZ;
}
// Nothing left to do.
if (!rotation)
return true;
//// Scale too close to zero, can't decompose rotation.
//if (scaleX < MATH_TOLERANCE || scaleY < MATH_TOLERANCE || fabs(scaleZ) < MATH_TOLERANCE)
// return false;
// TODO: support rotation
return false;
}
/**
* Gets the translational component of this matrix in the specified vector.
*
* @param translation A vector to receive the translation.
*/
void getTranslation(ref vec3 translation) const
{
decompose(null, null, &translation);
}
@property float determinant() const
{
float a0 = m[0] * m[5] - m[1] * m[4];
float a1 = m[0] * m[6] - m[2] * m[4];
float a2 = m[0] * m[7] - m[3] * m[4];
float a3 = m[1] * m[6] - m[2] * m[5];
float a4 = m[1] * m[7] - m[3] * m[5];
float a5 = m[2] * m[7] - m[3] * m[6];
float b0 = m[8] * m[13] - m[9] * m[12];
float b1 = m[8] * m[14] - m[10] * m[12];
float b2 = m[8] * m[15] - m[11] * m[12];
float b3 = m[9] * m[14] - m[10] * m[13];
float b4 = m[9] * m[15] - m[11] * m[13];
float b5 = m[10] * m[15] - m[11] * m[14];
// Calculate the determinant.
return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
}
static __gshared const mat4 IDENTITY;
}
unittest { unittest {
vec3 a, b, c; vec3 a, b, c;
a.clear(5); a.clear(5);

View File

@ -351,6 +351,15 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
checkgl!glUniformMatrix4fv(getUniformLocation(id), 1, false, matrix.m.ptr); checkgl!glUniformMatrix4fv(getUniformLocation(id), 1, false, matrix.m.ptr);
} }
/// returns true if effect has uniform
override bool hasUniform(DefaultUniform id) {
return getUniformLocation(id) >= 0;
}
/// returns true if effect has uniform
override bool hasUniform(string uniformName) {
return getUniformLocation(uniformName) >= 0;
}
/// draw mesh using this program (program should be bound by this time and all uniforms should be set) /// draw mesh using this program (program should be bound by this time and all uniforms should be set)
override void draw(Mesh mesh) { override void draw(Mesh mesh) {

View File

@ -53,7 +53,7 @@ class Camera : Node3d {
_dirtyView = true; _dirtyView = true;
} }
@property ref const(mat4) viewMatrix() { override @property ref const(mat4) viewMatrix() {
if (_dirtyView) { if (_dirtyView) {
_viewMatrix = matrix.invert(); _viewMatrix = matrix.invert();
_dirtyView = false; _dirtyView = false;
@ -62,7 +62,7 @@ class Camera : Node3d {
} }
/// get projection*view matrix /// get projection*view matrix
@property ref const(mat4) projectionViewMatrix() { override @property ref const(mat4) projectionViewMatrix() {
if (_dirtyTransform || _dirtyViewProjection) { if (_dirtyTransform || _dirtyViewProjection) {
_viewProjectionMatrix = _projectionMatrix * viewMatrix; _viewProjectionMatrix = _projectionMatrix * viewMatrix;
_dirtyViewProjection = false; _dirtyViewProjection = false;

View File

@ -75,7 +75,12 @@ class Material : RefCountedObject {
texture.texture.setSamplerParams(true); texture.texture.setSamplerParams(true);
} }
// TODO: more uniforms // TODO: more uniforms
if (_effect.hasUniform(DefaultUniform.u_worldViewProjectionMatrix))
_effect.setUniform(DefaultUniform.u_worldViewProjectionMatrix, node.projectionViewModelMatrix); _effect.setUniform(DefaultUniform.u_worldViewProjectionMatrix, node.projectionViewModelMatrix);
if (_effect.hasUniform(DefaultUniform.u_cameraPosition))
_effect.setUniform(DefaultUniform.u_cameraPosition, node.cameraPosition);
if (_effect.hasUniform(DefaultUniform.u_worldViewMatrix))
_effect.setUniform(DefaultUniform.u_worldViewMatrix, node.worldViewMatrix);
} }
void drawMesh(Mesh mesh) { void drawMesh(Mesh mesh) {

View File

@ -29,6 +29,12 @@ abstract class GraphicsEffect : RefCountedObject {
void setUniform(DefaultUniform id, vec4 vec); void setUniform(DefaultUniform id, vec4 vec);
/// returns true if effect has uniform
bool hasUniform(DefaultUniform id);
/// returns true if effect has uniform
bool hasUniform(string uniformName);
void draw(Mesh mesh); void draw(Mesh mesh);
} }
@ -51,9 +57,9 @@ enum DefaultUniform : int {
u_modulateAlpha, //uniform float u_modulateAlpha; u_modulateAlpha, //uniform float u_modulateAlpha;
u_worldViewProjectionMatrix, //uniform mat4 u_worldViewProjectionMatrix; u_worldViewProjectionMatrix, //uniform mat4 u_worldViewProjectionMatrix;
u_matrixPalette, //uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
u_inverseTransposeWorldViewMatrix, //uniform mat4 u_inverseTransposeWorldViewMatrix; u_inverseTransposeWorldViewMatrix, //uniform mat4 u_inverseTransposeWorldViewMatrix;
u_worldViewMatrix, //uniform mat4 u_worldViewMatrix; u_worldViewMatrix, //uniform mat4 u_worldViewMatrix;
u_matrixPalette, //uniform vec4 u_matrixPalette[SKINNING_JOINT_COUNT * 3];
u_cameraPosition, //uniform vec3 u_cameraPosition; u_cameraPosition, //uniform vec3 u_cameraPosition;
u_worldMatrix, //uniform mat4 u_worldMatrix; u_worldMatrix, //uniform mat4 u_worldMatrix;
u_clipPlane, //uniform vec4 u_clipPlane; u_clipPlane, //uniform vec4 u_clipPlane;

View File

@ -7,6 +7,7 @@ import dlangui.core.collections;
import dlangui.graphics.scene.scene3d; import dlangui.graphics.scene.scene3d;
import dlangui.graphics.scene.drawableobject; import dlangui.graphics.scene.drawableobject;
import dlangui.graphics.scene.light; import dlangui.graphics.scene.light;
import dlangui.graphics.scene.camera;
/// 3D scene node /// 3D scene node
class Node3d : Transform { class Node3d : Transform {
@ -97,10 +98,68 @@ class Node3d : Transform {
return this; return this;
} }
/// active camera or null of no camera
@property Camera activeCamera() {
if (!scene)
return null;
return scene.activeCamera;
}
@property vec3 cameraPosition() {
auto cam = activeCamera;
if (cam)
return cam.translationWorld;
return vec3(0, 0, 0);
}
/// get view matrix based on active camera
@property ref const(mat4) viewMatrix() {
auto cam = activeCamera;
if (cam)
return cam.viewMatrix;
return mat4.IDENTITY;
}
/// get projection*view matrix based on active camera
@property ref const(mat4) projectionViewMatrix() {
auto cam = activeCamera;
if (cam)
return cam.projectionViewMatrix;
return mat4.IDENTITY;
}
protected mat4 _projectionViewModelMatrix; protected mat4 _projectionViewModelMatrix;
/// returns projectionMatrix * viewMatrix * modelMatrix /// returns projectionMatrix * viewMatrix * modelMatrix
@property ref const(mat4) projectionViewModelMatrix() { @property ref const(mat4) projectionViewModelMatrix() {
// TODO: optimize
_projectionViewModelMatrix = _scene.projectionViewMatrix * matrix; _projectionViewModelMatrix = _scene.projectionViewMatrix * matrix;
return _projectionViewModelMatrix; return _projectionViewModelMatrix;
} }
/// returns world matrix
@property ref const(mat4) worldMatrix() {
if (!parent)
return matrix;
_worldMatrix = parent.worldMatrix * matrix;
return _worldMatrix;
}
/**
* Gets the world view matrix corresponding to this node.
*
* @return The world view matrix of this node.
*/
@property ref const(mat4) worldViewMatrix() {
static mat4 worldView;
worldView = viewMatrix * worldMatrix;
return worldView;
}
/// returns translation vector (position) of this node in world space
@property vec3 translationWorld() {
vec3 translation;
worldMatrix.getTranslation(translation);
return translation;
}
} }

View File

@ -22,7 +22,7 @@ class Scene3d : Node3d {
/// active camera /// active camera
@property Camera activeCamera() { override @property Camera activeCamera() {
if (_activeCamera) if (_activeCamera)
return _activeCamera; return _activeCamera;
// TODO: find camera in child nodes // TODO: find camera in child nodes
@ -44,14 +44,6 @@ class Scene3d : Node3d {
//ignore //ignore
} }
/// get projection*view matrix
@property ref const(mat4) projectionViewMatrix() {
if (_activeCamera)
return _activeCamera.projectionViewMatrix;
static mat4 dummyIdentityMatrix;
return dummyIdentityMatrix;
}
protected bool _wireframe; protected bool _wireframe;
void drawScene(bool wireframe) { void drawScene(bool wireframe) {
_wireframe = wireframe; _wireframe = wireframe;