Skip to content

Commit c0bfb6a

Browse files
committed
Added basic Camera and Frustum
1 parent 3baa34b commit c0bfb6a

5 files changed

Lines changed: 384 additions & 1 deletion

File tree

src/layer3d/cameras/Camera.js

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/**
2+
* @author Richard Davey <rich@photonstorm.com>
3+
* @copyright 2020 Photon Storm Ltd.
4+
* @license {@link https://opensource.org/licenses/MIT|MIT License}
5+
*/
6+
7+
var Class = require('../../utils/Class');
8+
var CONST = require('../const');
9+
var GameObject3D = require('../GameObject3D');
10+
var Frustum = require('./Frustum');
11+
var Vector3 = require('../../math/Vector3');
12+
var Vector4 = require('../../math/Vector4');
13+
var Matrix4 = require('../../math/Matrix4');
14+
15+
var tempMatrix = new Matrix4();
16+
17+
var Camera = new Class({
18+
19+
Extends: GameObject3D,
20+
21+
initialize:
22+
23+
function Camera ()
24+
{
25+
GameObject3D.call(this);
26+
27+
this.type = CONST.OBJECT_TYPE.CAMERA;
28+
29+
/**
30+
* This is the inverse of worldMatrix.
31+
*/
32+
this.viewMatrix = new Matrix4();
33+
34+
/**
35+
* This is the matrix which contains the projection.
36+
*/
37+
this.projectionMatrix = new Matrix4();
38+
39+
/**
40+
* This is the matrix which contains the projection.
41+
*/
42+
this.projectionMatrixInverse = new Matrix4();
43+
44+
/**
45+
* The frustum of the camera.
46+
*/
47+
this.frustum = new Frustum();
48+
49+
/**
50+
* The factor of gamma.
51+
*/
52+
this.gammaFactor = 2.0;
53+
54+
/**
55+
* Output pixel encoding.
56+
* @type {TEXEL_ENCODING_TYPE}
57+
*/
58+
this.outputEncoding = 'linear';
59+
60+
/**
61+
* Where on the screen is the camera rendered in normalized coordinates.
62+
* @type {Vector4}
63+
*/
64+
this.rect = new Vector4(0, 0, 1, 1);
65+
66+
/**
67+
* When this is set, it checks every frame if objects are in the frustum of the camera before rendering objects.
68+
* Otherwise objects gets rendered every frame even if it isn't visible.
69+
*/
70+
this.frustumCulled = true;
71+
},
72+
73+
/**
74+
* Set view by look at, this func will set quaternion of this camera.
75+
*
76+
* @method
77+
* @param {zen3d.Vector3} target - The target that the camera look at.
78+
* @param {zen3d.Vector3} up - The up direction of the camera.
79+
*/
80+
lookAt: function (target, up)
81+
{
82+
tempMatrix.lookAtRH(this.position, target, up);
83+
84+
this.quaternion.setFromRotationMatrix(tempMatrix);
85+
},
86+
87+
/**
88+
* Set orthographic projection matrix.
89+
*
90+
* @param {number} left — Camera frustum left plane.
91+
* @param {number} right — Camera frustum right plane.
92+
* @param {number} bottom — Camera frustum bottom plane.
93+
* @param {number} top — Camera frustum top plane.
94+
* @param {number} near — Camera frustum near plane.
95+
* @param {number} far — Camera frustum far plane.
96+
*/
97+
setOrtho: function (left, right, bottom, top, near, far)
98+
{
99+
this.projectionMatrix.set([
100+
2 / (right - left), 0, 0, -(right + left) / (right - left),
101+
0, 2 / (top - bottom), 0, -(top + bottom) / (top - bottom),
102+
0, 0, -2 / (far - near), -(far + near) / (far - near),
103+
0, 0, 0, 1
104+
]);
105+
106+
this.projectionMatrixInverse.getInverse(this.projectionMatrix);
107+
},
108+
109+
/**
110+
* Set perspective projection matrix.
111+
* @param {number} fov — Camera frustum vertical field of view.
112+
* @param {number} aspect — Camera frustum aspect ratio.
113+
* @param {number} near — Camera frustum near plane.
114+
* @param {number} far — Camera frustum far plane.
115+
*/
116+
setPerspective: function (fov, aspect, near, far)
117+
{
118+
this.projectionMatrix.set([
119+
1 / (aspect * Math.tan(fov / 2)), 0, 0, 0,
120+
0, 1 / (Math.tan(fov / 2)), 0, 0,
121+
0, 0, -(far + near) / (far - near), -2 * far * near / (far - near),
122+
0, 0, -1, 0
123+
]);
124+
125+
this.projectionMatrixInverse.getInverse(this.projectionMatrix);
126+
},
127+
128+
getWorldDirection: function (optionalTarget)
129+
{
130+
optionalTarget = optionalTarget || new Vector3();
131+
132+
var e = this.worldMatrix.val;
133+
134+
return optionalTarget.set(-e[8], -e[9], -e[10]).normalize();
135+
},
136+
137+
updateMatrix: function (force)
138+
{
139+
GameObject3D.prototype.updateMatrix.call(this, force);
140+
141+
this.viewMatrix.getInverse(this.worldMatrix);
142+
143+
tempMatrix.multiplyMatrices(this.projectionMatrix, this.viewMatrix);
144+
145+
this.frustum.setFromMatrix(tempMatrix);
146+
}
147+
148+
});
149+
150+
module.exports = Camera;

src/layer3d/cameras/Frustum.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* @author Richard Davey <rich@photonstorm.com>
3+
* @copyright 2020 Photon Storm Ltd.
4+
* @license {@link https://opensource.org/licenses/MIT|MIT License}
5+
*/
6+
7+
var Class = require('../../utils/Class');
8+
var Plane = require('../math/Plane');
9+
var Vector3 = require('../../math/Vector3');
10+
11+
var tempVec = new Vector3();
12+
13+
var Frustum = new Class({
14+
15+
initialize:
16+
17+
function Frustum (p0, p1, p2, p3, p4, p5)
18+
{
19+
if (p0 === undefined) { p0 = new Plane(); }
20+
if (p1 === undefined) { p1 = new Plane(); }
21+
if (p2 === undefined) { p2 = new Plane(); }
22+
if (p3 === undefined) { p3 = new Plane(); }
23+
if (p4 === undefined) { p4 = new Plane(); }
24+
if (p5 === undefined) { p5 = new Plane(); }
25+
26+
this.planes = [ p0, p1, p2, p3, p4, p5 ];
27+
},
28+
29+
set: function (p0, p1, p2, p3, p4, p5)
30+
{
31+
var planes = this.planes;
32+
33+
planes[0].copy(p0);
34+
planes[1].copy(p1);
35+
planes[2].copy(p2);
36+
planes[3].copy(p3);
37+
planes[4].copy(p4);
38+
planes[5].copy(p5);
39+
40+
return this;
41+
},
42+
43+
setFromMatrix: function (mat4)
44+
{
45+
var m = mat4.val;
46+
47+
var m0 = m[0];
48+
var m1 = m[1];
49+
var m2 = m[2];
50+
var m3 = m[3];
51+
var m4 = m[4];
52+
var m5 = m[5];
53+
var m6 = m[6];
54+
var m7 = m[7];
55+
var m8 = m[8];
56+
var m9 = m[9];
57+
var m10 = m[10];
58+
var m11 = m[11];
59+
var m12 = m[12];
60+
var m13 = m[13];
61+
var m14 = m[14];
62+
var m15 = m[15];
63+
64+
var planes = this.planes;
65+
66+
planes[0].setComponents(m3 - m0, m7 - m4, m11 - m8, m15 - m12).normalize();
67+
planes[1].setComponents(m3 + m0, m7 + m4, m11 + m8, m15 + m12).normalize();
68+
planes[2].setComponents(m3 + m1, m7 + m5, m11 + m9, m15 + m13).normalize();
69+
planes[3].setComponents(m3 - m1, m7 - m5, m11 - m9, m15 - m13).normalize();
70+
planes[4].setComponents(m3 - m2, m7 - m6, m11 - m10, m15 - m14).normalize();
71+
planes[5].setComponents(m3 + m2, m7 + m6, m11 + m10, m15 + m14).normalize();
72+
73+
return this;
74+
},
75+
76+
intersectsSphere: function (sphere)
77+
{
78+
var planes = this.planes;
79+
var center = sphere.center;
80+
var negRadius = -sphere.radius;
81+
82+
for (var i = 0; i < 6; i++)
83+
{
84+
var distance = planes[i].distanceToPoint(center);
85+
86+
if (distance < negRadius)
87+
{
88+
return false;
89+
}
90+
}
91+
92+
return true;
93+
},
94+
95+
intersectsBox: function (box)
96+
{
97+
var planes = this.planes;
98+
99+
for (var i = 0; i < 6; i++)
100+
{
101+
var plane = planes[i];
102+
103+
// corner at max distance
104+
105+
tempVec.x = (plane.normal.x > 0) ? box.max.x : box.min.x;
106+
tempVec.y = (plane.normal.y > 0) ? box.max.y : box.min.y;
107+
tempVec.z = (plane.normal.z > 0) ? box.max.z : box.min.z;
108+
109+
// if both outside plane, no intersection
110+
111+
if (plane.distanceToPoint(tempVec) < 0)
112+
{
113+
return false;
114+
}
115+
}
116+
117+
return true;
118+
}
119+
120+
});
121+
122+
module.exports = Frustum;

src/layer3d/cameras/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* @author Richard Davey <rich@photonstorm.com>
3+
* @copyright 2020 Photon Storm Ltd.
4+
* @license {@link https://opensource.org/licenses/MIT|MIT License}
5+
*/
6+
7+
/**
8+
* @namespace Phaser.Layer3D.Cameras
9+
*/
10+
11+
module.exports = {
12+
13+
Camera: require('./Camera'),
14+
Frustum: require('./Frustum')
15+
16+
};

src/layer3d/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010

1111
module.exports = {
1212

13+
Cameras: require('./cameras'),
14+
Geometry: require('./geometry'),
1315
Lights: require('./lights'),
1416
Materials: require('./materials'),
1517
Math: require('./math'),
18+
1619
GameObject3D: require('./GameObject3D'),
17-
Layer3DScene: require('./Layer3DScene')
20+
Layer3DScene: require('./Layer3DScene'),
21+
Mesh: require('./Mesh')
1822

1923
};

src/layer3d/math/Plane.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* @author Richard Davey <rich@photonstorm.com>
3+
* @copyright 2020 Photon Storm Ltd.
4+
* @license {@link https://opensource.org/licenses/MIT|MIT License}
5+
*/
6+
7+
var Class = require('../../utils/Class');
8+
var Matrix3 = require('../../math/Matrix3');
9+
var Vector3 = require('../../math/Vector3');
10+
11+
var tempVec3 = new Vector3();
12+
var tempMat3 = new Matrix3();
13+
14+
var Plane = new Class({
15+
16+
initialize:
17+
18+
function Plane (normal, constant)
19+
{
20+
if (normal === undefined) { normal = new Vector3(1, 0, 0); }
21+
if (constant === undefined) { constant = 0; }
22+
23+
this.normal = normal;
24+
this.constant = console;
25+
},
26+
27+
set: function (normal, constant)
28+
{
29+
this.normal.copy(normal);
30+
this.constant = constant;
31+
32+
return this;
33+
},
34+
35+
setComponents: function (x, y, z, w)
36+
{
37+
this.normal.set(x, y, z);
38+
this.constant = w;
39+
40+
return this;
41+
},
42+
43+
setFromNormalAndCoplanarPoint: function (normal, point)
44+
{
45+
this.normal.copy(normal);
46+
this.constant = -point.dot(this.normal);
47+
48+
return this;
49+
},
50+
51+
normalize: function ()
52+
{
53+
// Note: will lead to a divide by zero if the plane is invalid.
54+
55+
var inverseNormalLength = 1 / this.normal.length();
56+
57+
this.normal.scale(inverseNormalLength);
58+
59+
this.constant *= inverseNormalLength;
60+
61+
return this;
62+
},
63+
64+
distanceToPoint: function (point)
65+
{
66+
return this.normal.dot(point) + this.constant;
67+
},
68+
69+
coplanarPoint: function (optionalTarget)
70+
{
71+
var result = optionalTarget || new Vector3();
72+
73+
return result.copy(this.normal).scale(-this.constant);
74+
},
75+
76+
applyMatrix4: function (matrix, optionalNormalMatrix)
77+
{
78+
var normalMatrix = optionalNormalMatrix || tempMat3.fromMat4(matrix).invert().transpose();
79+
80+
var referencePoint = this.coplanarPoint(tempVec3).applyMatrix4(matrix);
81+
82+
var normal = this.normal.applyMatrix3(normalMatrix).normalize();
83+
84+
this.constant = -referencePoint.dot(normal);
85+
86+
return this;
87+
}
88+
89+
});
90+
91+
module.exports = Plane;

0 commit comments

Comments
 (0)