mirror of https://github.com/buggins/dlangui.git
#183 improvements
This commit is contained in:
parent
b01f90c7c2
commit
a48dd1d99b
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue