fix 3d math; d3d example is now working

This commit is contained in:
Vadim Lopatin 2016-03-25 13:14:45 +03:00
parent 6a18bde8aa
commit d27062ff63
4 changed files with 159 additions and 90 deletions

View File

@ -65,19 +65,19 @@ class UiWidget : VerticalLayout, CellVisitor {
ScrollBar { id: sbTranslationX; orientation: horizontal; minValue: -100; maxValue: 100; position: 0; minWidth: 200; alpha: 0.6 }
TextWidget { text: "Rotation X" }
TextWidget { id: lblRotationX; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbRotationX; orientation: horizontal; minValue: -100; maxValue: 100; position: 10; minWidth: 200; alpha: 0.6 }
ScrollBar { id: sbRotationX; orientation: horizontal; minValue: -180; maxValue: 180; position: 0; minWidth: 200; alpha: 0.6 }
TextWidget { text: "Translation Y" }
TextWidget { id: lblTranslationY; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbTranslationY; orientation: horizontal; minValue: -100; maxValue: 100; position: 0; minWidth: 200; alpha: 0.6 }
ScrollBar { id: sbTranslationY; orientation: horizontal; minValue: -100; maxValue: 100; position: 15; minWidth: 200; alpha: 0.6 }
TextWidget { text: "Rotation Y" }
TextWidget { id: lblRotationY; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbRotationY; orientation: horizontal; minValue: -100; maxValue: 100; position: 0; minWidth: 150; alpha: 0.6 }
ScrollBar { id: sbRotationY; orientation: horizontal; minValue: -180; maxValue: 180; position: 0; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Translation Z" }
TextWidget { id: lblTranslationZ; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbTranslationZ; orientation: horizontal; minValue: -100; maxValue: 100; position: 0; minWidth: 150; alpha: 0.6 }
ScrollBar { id: sbTranslationZ; orientation: horizontal; minValue: -100; maxValue: 100; position: 45; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Rotation Z" }
TextWidget { id: lblRotationZ; text: "0.0"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbRotationZ; orientation: horizontal; minValue: -100; maxValue: 100; position: 0; minWidth: 150; alpha: 0.6 }
ScrollBar { id: sbRotationZ; orientation: horizontal; minValue: -180; maxValue: 180; position: 0; minWidth: 150; alpha: 0.6 }
TextWidget { text: "Near" }
TextWidget { id: lblNear; text: "0.1"; minWidth: 80; backgroundColor: 0x80FFFFFF }
ScrollBar { id: sbNear; orientation: horizontal; minValue: 1; maxValue: 100; position: 1; minWidth: 150; alpha: 0.6 }
@ -102,15 +102,6 @@ class UiWidget : VerticalLayout, CellVisitor {
controlsToVars();
assignHandlers();
mat4 m;
m.translate(1, 2, -1);
Log.d("M*v=", m * vec3(0, 0, 0));
Log.d("M*v=", m * vec3(10, 10, 10));
m.translate(0, 0, -2);
Log.d("M*v=", m * vec3(0, 0, 0));
Log.d("M*v=", m * vec3(10, 10, 10));
_scene = new Scene3d();
_cam = new Camera();
@ -190,9 +181,9 @@ class UiWidget : VerticalLayout, CellVisitor {
translationX = childById!ScrollBar("sbTranslationX").position / 10.0f;
translationY = childById!ScrollBar("sbTranslationY").position / 10.0f;
translationZ = childById!ScrollBar("sbTranslationZ").position / 10.0f;
rotationX = childById!ScrollBar("sbRotationX").position * 2.5f;
rotationY = childById!ScrollBar("sbRotationY").position * 2.5f;
rotationZ = childById!ScrollBar("sbRotationZ").position * 2.5f;
rotationX = childById!ScrollBar("sbRotationX").position;
rotationY = childById!ScrollBar("sbRotationY").position;
rotationZ = childById!ScrollBar("sbRotationZ").position;
childById("lblNear").text = to!dstring(near);
childById("lblFar").text = to!dstring(far);
childById("lblTranslationX").text = to!dstring(translationX);
@ -270,9 +261,8 @@ class UiWidget : VerticalLayout, CellVisitor {
//_cam.translate(vec3(0, 0, -1.1)); // - angle/1000
//_cam.translate(vec3(0, 3, - angle/1000)); //
//_cam.rotateZ(30.0f + angle * 0.3456778);
mat4 projectionViewMatrix = _cam.projectionViewMatrix;
Log.d("projectionViewMatrix: ", projectionViewMatrix);
mat4 projectionViewMatrix = _cam.projectionViewMatrix;
// ======== Model Matrix ==================
mat4 modelMatrix;
@ -284,6 +274,46 @@ class UiWidget : VerticalLayout, CellVisitor {
//modelMatrix.rotatex(angle * 1.98765f);
mat4 projectionViewModelMatrix = projectionViewMatrix * modelMatrix;
//Log.d("projectionViewModelMatrix: ", projectionViewModelMatrix.dump);
//{
// mat4 projection;
// projection.setPerspective(45.0f, cast(float)rc.width / rc.height, near, far);
// mat4 view;
// view.translate(translationX, translationY, translationZ);
// Log.d(" .viewMatrix.trans ", view.dump);
// view.rotateX(rotationX);
// Log.d(" .viewMatrix.rx ", view.dump);
// view.rotateY(rotationY);
// Log.d(" .viewMatrix.ry ", view.dump);
// view.rotateZ(rotationZ);
// Log.d(" .viewMatrix.rz ", view.dump);
// mat4 projectionView = projection * view;
// Log.d(" .projectionMatrix: ", projection.dump);
// Log.d(" .viewMatrix: ", view.dump);
// Log.d(" .projectionViewMatrix: ", projectionView.dump);
// Log.d(" .projectionViewMMatrix: ", (projectionView * modelMatrix).dump);
//}
//{
// import gl3n.linalg;
// static string dump(mat4 m) {
// m.transpose;
// return to!string(m[0]) ~ to!string(m[1]) ~ to!string(m[2]) ~ to!string(m[3]);
// }
// static float toRad(float angle) { return angle * 2 * PI / 360; }
// mat4 projection = mat4.perspective(rc.width, rc.height, 45.0f, near, far);
// mat4 view = mat4.identity.translate(translationX, translationY, translationZ).rotatex(toRad(rotationX)).rotatey(toRad(rotationY)).rotatez(toRad(rotationZ));
// Log.d("gl3n.viewMatrix: tr ", dump(mat4.identity.translate(translationX, translationY, translationZ)));
// Log.d("gl3n.viewMatrix: rx ", dump(mat4.identity.translate(translationX, translationY, translationZ).rotatex(toRad(rotationX))));
// Log.d("gl3n.viewMatrix: ry ", dump(mat4.identity.translate(translationX, translationY, translationZ).rotatex(toRad(rotationX)).rotatey(toRad(rotationY))));
// Log.d("gl3n.viewMatrix: rz ", dump(mat4.identity.translate(translationX, translationY, translationZ).rotatex(toRad(rotationX)).rotatey(toRad(rotationY)).rotatez(toRad(rotationZ))));
// mat4 projectionView = projection * view;
// Log.d("gl3n.projectionMatrix: ", dump(projection));
// Log.d("gl3n.viewMatrix: ", dump(view));
// Log.d("gl3n.projectionViewMatrix: ", dump(projectionView));
// Log.d("gl3n.projectionViewMMatrix: ", dump(projectionView * mat4.identity));
//}
//projectionViewModelMatrix.setIdentity();
//Log.d("matrix uniform: ", projectionViewModelMatrix.m);

View File

@ -876,6 +876,11 @@ bool fuzzyNull(float v) {
struct mat4 {
float[16] m = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
@property string dump() const {
import std.conv : to;
return to!string(m[0..4]) ~ to!string(m[4..8]) ~ to!string(m[8..12]) ~ to!string(m[12..16]);
}
//alias m this;
this(float v) {
@ -883,22 +888,22 @@ struct mat4 {
}
this(const ref mat4 v) {
m[0..15] = v.m[0..15];
m[0..16] = v.m[0..16];
}
this(const float[16] v) {
m[0..15] = v[0..15];
m[0..16] = v[0..16];
}
ref mat4 opAssign(const ref mat4 v) {
m[0..15] = v.m[0..15];
m[0..16] = v.m[0..16];
return this;
}
ref mat4 opAssign(const mat4 v) {
m[0..15] = v.m[0..15];
m[0..16] = v.m[0..16];
return this;
}
ref mat4 opAssign(const float[16] v) {
m[0..15] = v[0..15];
m[0..16] = v[0..16];
return this;
}
@ -961,37 +966,6 @@ struct mat4 {
m[3*4 + 3] = 0.0f;
}
void setPerspective2(float angle, float aspect, float nearPlane, float farPlane)
{
// Bail out if the projection volume is zero-sized.
if (nearPlane == farPlane || aspect == 0.0f)
return;
// Construct the projection.
float radians = (angle / 2.0f) * PI / 180.0f;
float sine = sin(radians);
if (sine == 0.0f)
return;
float cotan = cos(radians) / sine;
float clip = farPlane - nearPlane;
m[0*4 + 0] = cotan / aspect;
m[1*4 + 0] = 0.0f;
m[2*4 + 0] = 0.0f;
m[3*4 + 0] = 0.0f;
m[0*4 + 1] = 0.0f;
m[1*4 + 1] = cotan;
m[2*4 + 1] = 0.0f;
m[3*4 + 1] = 0.0f;
m[0*4 + 2] = 0.0f;
m[1*4 + 2] = 0.0f;
m[2*4 + 2] = -(nearPlane + farPlane) / clip;
m[3*4 + 2] = -(2.0f * nearPlane * farPlane) / clip;
m[0*4 + 3] = 0.0f;
m[1*4 + 3] = 0.0f;
m[2*4 + 3] = -1.0f;
m[3*4 + 3] = 0.0f;
}
ref mat4 lookAt(const vec3 eye, const vec3 center, const vec3 up) {
vec3 forward = (center - eye).normalized();
vec3 side = vec3.crossProduct(forward, up).normalized();
@ -1021,6 +995,56 @@ struct mat4 {
return this;
}
mat4 invert() 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.
float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
mat4 inverse;
// Close to zero, can't invert.
if (fabs(det) <= 0.00000001f)
return inverse;
// Support the case where m == dst.
inverse.m[0] = m[5] * b5 - m[6] * b4 + m[7] * b3;
inverse.m[1] = -m[1] * b5 + m[2] * b4 - m[3] * b3;
inverse.m[2] = m[13] * a5 - m[14] * a4 + m[15] * a3;
inverse.m[3] = -m[9] * a5 + m[10] * a4 - m[11] * a3;
inverse.m[4] = -m[4] * b5 + m[6] * b2 - m[7] * b1;
inverse.m[5] = m[0] * b5 - m[2] * b2 + m[3] * b1;
inverse.m[6] = -m[12] * a5 + m[14] * a2 - m[15] * a1;
inverse.m[7] = m[8] * a5 - m[10] * a2 + m[11] * a1;
inverse.m[8] = m[4] * b4 - m[5] * b2 + m[7] * b0;
inverse.m[9] = -m[0] * b4 + m[1] * b2 - m[3] * b0;
inverse.m[10] = m[12] * a4 - m[13] * a2 + m[15] * a0;
inverse.m[11] = -m[8] * a4 + m[9] * a2 - m[11] * a0;
inverse.m[12] = -m[4] * b3 + m[5] * b1 - m[6] * b0;
inverse.m[13] = m[0] * b3 - m[1] * b1 + m[2] * b0;
inverse.m[14] = -m[12] * a3 + m[13] * a1 - m[14] * a0;
inverse.m[15] = m[8] * a3 - m[9] * a1 + m[10] * a0;
float mul = 1.0f / det;
inverse *= mul;
return inverse;
}
ref mat4 setLookAt(const vec3 eye, const vec3 center, const vec3 up) {
setIdentity();
lookAt(eye, center, up);
@ -1073,9 +1097,8 @@ struct mat4 {
}
/// multiply this matrix by another matrix
mat4 opOpAssign(string op : "*")(const ref mat4 m2) {
void opOpAssign(string op : "*")(const ref mat4 m2) {
this = mul(this, m2);
return this;
}
/// multiply two matrices
@ -1274,28 +1297,24 @@ struct mat4 {
/// add value to all components of matrix
ref mat4 opOpAssign(string op : "+")(float v) {
void opOpAssign(string op : "+")(float v) {
foreach(ref item; m)
item += v;
return this;
}
/// multiply all components of matrix by value
ref mat4 opOpAssign(string op : "*")(float v) {
void opOpAssign(string op : "*")(float v) {
foreach(ref item; m)
item *= v;
return this;
}
/// subtract value from all components of matrix
ref mat4 opOpAssign(string op : "-")(float v) {
void opOpAssign(string op : "-")(float v) {
foreach(ref item; m)
item -= v;
return this;
}
/// divide all components of vector by matrix
ref mat4 opOpAssign(string op : "/")(float v) {
void opOpAssign(string op : "/")(float v) {
foreach(ref item; m)
item /= v;
return this;
}
/// inplace rotate around Z axis

View File

@ -8,8 +8,10 @@ import dlangui.core.math3d;
class Camera : Node3d {
protected mat4 _projectionMatrix;
protected mat4 _viewMatrix;
protected mat4 _viewProjectionMatrix;
protected bool _dirtyViewProjection;
protected bool _dirtyViewProjection = true;
protected bool _dirtyView = true;
protected bool _enabled;
@ -39,10 +41,24 @@ class Camera : Node3d {
_dirtyViewProjection = true;
}
override protected void invalidateTransform() {
_dirtyTransform = true;
_dirtyViewProjection = true;
_dirtyView = true;
}
@property ref const(mat4) viewMatrix() {
if (_dirtyView) {
_viewMatrix = matrix.invert();
_dirtyView = false;
}
return _viewMatrix;
}
/// get projection*view matrix
@property ref const(mat4) projectionViewMatrix() {
if (_dirtyTransform || _dirtyViewProjection) {
_viewProjectionMatrix = _projectionMatrix * matrix;
_viewProjectionMatrix = _projectionMatrix * viewMatrix;
_dirtyViewProjection = false;
}
return _viewProjectionMatrix;

View File

@ -20,6 +20,10 @@ class Transform {
setIdentity();
}
protected void invalidateTransform() {
_dirtyTransform = true;
}
/// get scale vector
public @property ref const(vec3) scaling() const { return _scale; }
/// get scale X
@ -30,15 +34,15 @@ class Transform {
public @property float scalingZ() const { return _scale.z; }
/// set scale vector
public @property void scaling(const ref vec3 value) { _scale = value; _hasScale = true; _dirtyTransform = true; }
public @property void scaling(const ref vec3 value) { _scale = value; _hasScale = true; invalidateTransform(); }
/// set scale vector x, y, z to the same value
public @property void scaling(float value) { _scale.x = _scale.y = _scale.z = value; _hasScale = true; _dirtyTransform = true; }
public @property void scaling(float value) { _scale.x = _scale.y = _scale.z = value; _hasScale = true; invalidateTransform(); }
/// set scale X
public @property void scalingX(float value) { _scale.x = value; _hasScale = true; _dirtyTransform = true; }
public @property void scalingX(float value) { _scale.x = value; _hasScale = true; invalidateTransform(); }
/// set scale Y
public @property void scalingY(float value) { _scale.y = value; _hasScale = true; _dirtyTransform = true; }
public @property void scalingY(float value) { _scale.y = value; _hasScale = true; invalidateTransform(); }
/// set scale Z
public @property void scalingZ(float value) { _scale.z = value; _hasScale = true; _dirtyTransform = true; }
public @property void scalingZ(float value) { _scale.z = value; _hasScale = true; invalidateTransform(); }
/// get translation vector
public @property ref const(vec3) translation() const { return _translation; }
@ -50,44 +54,44 @@ class Transform {
public @property float translationZ() const { return _translation.z; }
/// set translation vector
public @property void translation(inout vec3 value) { _translation = value; _hasTranslation = true; _dirtyTransform = true; }
public @property void translation(inout vec3 value) { _translation = value; _hasTranslation = true; invalidateTransform(); }
/// set translation vector x, y, z to the same value
public @property void translation(float value) { _translation.x = _translation.y = _translation.z = value; _hasTranslation = true; _dirtyTransform = true; }
public @property void translation(float value) { _translation.x = _translation.y = _translation.z = value; _hasTranslation = true; invalidateTransform(); }
/// set translation x
public @property void translationX(float value) { _translation.x = value; _hasTranslation = true; _dirtyTransform = true; }
public @property void translationX(float value) { _translation.x = value; _hasTranslation = true; invalidateTransform(); }
/// set translation y
public @property void translationY(float value) { _translation.y = value; _hasTranslation = true; _dirtyTransform = true; }
public @property void translationY(float value) { _translation.y = value; _hasTranslation = true; invalidateTransform(); }
/// set translation z
public @property void translationZ(float value) { _translation.z = value; _hasTranslation = true; _dirtyTransform = true; }
public @property void translationZ(float value) { _translation.z = value; _hasTranslation = true; invalidateTransform(); }
/// translate by vector
public void translate(vec3 value) { _translation += value; _hasTranslation = true; _dirtyTransform = true; }
public void translate(vec3 value) { _translation += value; _hasTranslation = true; invalidateTransform(); }
/// translate X
public void translateX(float value) { _translation.x += value; _hasTranslation = true; _dirtyTransform = true; }
public void translateX(float value) { _translation.x += value; _hasTranslation = true; invalidateTransform(); }
/// translate Y
public void translateY(float value) { _translation.y += value; _hasTranslation = true; _dirtyTransform = true; }
public void translateY(float value) { _translation.y += value; _hasTranslation = true; invalidateTransform(); }
/// translate Z
public void translateZ(float value) { _translation.z += value; _hasTranslation = true; _dirtyTransform = true; }
public void translateZ(float value) { _translation.z += value; _hasTranslation = true; invalidateTransform(); }
/// scale by vector
public void scale(vec3 value) { _scale.x *= value.x; _scale.y *= value.y; _scale.z *= value.z; _hasScale = true; _dirtyTransform = true; }
public void scale(vec3 value) { _scale.x *= value.x; _scale.y *= value.y; _scale.z *= value.z; _hasScale = true; invalidateTransform(); }
/// scale all axis by the same values
public void scale(float value) { _scale *= value; _hasScale = true; _dirtyTransform = true; }
public void scale(float value) { _scale *= value; _hasScale = true; invalidateTransform(); }
/// scale X
public void scaleX(float value) { _scale.x *= value; _hasScale = true; _dirtyTransform = true; }
public void scaleX(float value) { _scale.x *= value; _hasScale = true; invalidateTransform(); }
/// scale Y
public void scaleY(float value) { _scale.y *= value; _hasScale = true; _dirtyTransform = true; }
public void scaleY(float value) { _scale.y *= value; _hasScale = true; invalidateTransform(); }
/// scale Z
public void scaleZ(float value) { _scale.z *= value; _hasScale = true; _dirtyTransform = true; }
public void scaleZ(float value) { _scale.z *= value; _hasScale = true; invalidateTransform(); }
/// rotate around X axis
public void rotateX(float angle) { _rotation.rotateX(angle); _hasRotation = true; _dirtyTransform = true; }
public void rotateX(float angle) { _rotation.rotateX(angle); _hasRotation = true; invalidateTransform(); }
/// rotate around Y axis
public void rotateY(float angle) { _rotation.rotateY(angle); _hasRotation = true; _dirtyTransform = true; }
public void rotateY(float angle) { _rotation.rotateY(angle); _hasRotation = true; invalidateTransform(); }
/// rotate around Z axis
public void rotateZ(float angle) { _rotation.rotateZ(angle); _hasRotation = true; _dirtyTransform = true; }
public void rotateZ(float angle) { _rotation.rotateZ(angle); _hasRotation = true; invalidateTransform(); }
/// rotate around custom axis
public void rotate(float angle, const ref vec3 axis) { _rotation.rotate(angle, axis); _hasRotation = true; _dirtyTransform = true; }
public void rotate(float angle, const ref vec3 axis) { _rotation.rotate(angle, axis); _hasRotation = true; invalidateTransform(); }
/// set transform to identity transform
public void setIdentity() {