Skip to content

Commit caea24d

Browse files
committed
Add CombinedCamera from examples
1 parent 4ab0c3c commit caea24d

File tree

4 files changed

+372
-0
lines changed

4 files changed

+372
-0
lines changed

js/scripts/generate-wrappers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var JS_AUTOGEN_EXT = '.' + AUTOGEN_EXT + '.js';
3333
var CUSTOM_CLASSES = [
3434
'textures/ImageTexture.js',
3535
'textures/TextTexture.js',
36+
'cameras/CombinedCamera.js',
3637
'controls/Controls.js',
3738
'controls/OrbitControls.js',
3839
'controls/TrackballControls.js',

js/scripts/three-class-config.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,25 @@ module.exports = {
110110
cameraR: new Types.ThreeType('PerspectiveCamera'),
111111
},
112112
},
113+
CombinedCamera: {
114+
relativePath: './cameras/CombinedCamera',
115+
superClass: 'Camera',
116+
properties: {
117+
fov: new Types.Float(),
118+
119+
far: new Types.Float(),
120+
near: new Types.Float(),
121+
orthoFar: new Types.Float(),
122+
orthoNear: new Types.Float(),
123+
124+
width: new Types.Float(),
125+
height: new Types.Float(),
126+
127+
zoom: new Types.Float(1),
128+
// view: new Types.ViewOffset()
129+
},
130+
constructorArgs: [ 'width', 'height', 'fov', 'near', 'far', 'orthoNear', 'orthoFar' ],
131+
},
113132
Controls: {
114133
relativePath: './controls/Controls',
115134
properties: {

js/src/cameras/CombinedCamera.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
var _ = require('underscore');
2+
var CombinedCameraAutogen = require('./CombinedCamera.autogen');
3+
4+
var CombinedCameraModel = CombinedCameraAutogen.CombinedCameraModel.extend({
5+
6+
createPropertiesArrays: function() {
7+
CombinedCameraAutogen.prototype.createPropertiesArrays.call(this);
8+
9+
this.property_mappers['CombinedCamera'] = 'mapCombinedCamera';
10+
delete this.property_converters['width'];
11+
delete this.property_converters['height'];
12+
delete this.property_converters['near'];
13+
delete this.property_converters['far'];
14+
delete this.property_converters['orthoNear'];
15+
delete this.property_converters['orthoFar'];
16+
},
17+
18+
mapCombinedCameraModelToThree: function() {
19+
20+
var width = this.convertFloatModelToThree(this.get('width'));
21+
var height = this.convertFloatModelToThree(this.get('height'));
22+
this.obj.left = - width / 2;
23+
this.obj.right = width / 2;
24+
this.obj.top = height / 2;
25+
this.obj.bottom = - height / 2;
26+
27+
this.obj.aspect = width / height;
28+
this.obj.cameraP.near = this.convertFloatModelToThree(this.get('near'));
29+
this.obj.cameraP.far = this.convertFloatModelToThree(this.get('far'));
30+
this.obj.cameraO.near = this.convertFloatModelToThree(this.get('orthoNear'));
31+
this.obj.cameraO.far = this.convertFloatModelToThree(this.get('orthoFar'));
32+
33+
// Always update the projection matrix after setting the attributes:
34+
this.obj.updateProjectionMatrix();
35+
},
36+
37+
mapCombinedCameraThreeToModel: function() {
38+
39+
var toSet = {};
40+
toSet.width = this.convertFloatThreeToModel(this.obj.right - this.obj.left);
41+
toSet.height = this.convertFloatThreeToModel(this.obj.top - this.obj.bottom);
42+
43+
toSet.near = this.convertFloatThreeToModel(this.obj.cameraP.near);
44+
toSet.near = this.convertFloatThreeToModel(this.obj.cameraP.far);
45+
toSet.orthoNear = this.convertFloatThreeToModel(this.obj.cameraO.near);
46+
toSet.orthoFar = this.convertFloatThreeToModel(this.obj.cameraO.far);
47+
48+
this.set(toSet, 'pushFromThree');
49+
50+
},
51+
});
52+
53+
module.exports = {
54+
CombinedCameraModel: CombinedCameraModel,
55+
};
Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
/**
2+
* @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
3+
*
4+
* A general perpose camera, for setting FOV, Lens Focal Length,
5+
* and switching between perspective and orthographic views easily.
6+
* Use this only if you do not wish to manage
7+
* both a Orthographic and Perspective Camera
8+
*
9+
*/
10+
11+
12+
var THREE = require('three');
13+
14+
15+
var CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoFar ) {
16+
17+
THREE.Camera.call( this );
18+
19+
this.fov = fov;
20+
21+
this.far = far;
22+
this.near = near;
23+
24+
this.left = - width / 2;
25+
this.right = width / 2;
26+
this.top = height / 2;
27+
this.bottom = - height / 2;
28+
29+
this.aspect = width / height;
30+
this.zoom = 1;
31+
this.view = null;
32+
// We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
33+
34+
this.cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, orthoNear, orthoFar );
35+
this.cameraP = new THREE.PerspectiveCamera( fov, width / height, near, far );
36+
37+
this.toPerspective();
38+
39+
};
40+
41+
CombinedCamera.prototype = Object.create( THREE.Camera.prototype );
42+
CombinedCamera.prototype.constructor = CombinedCamera;
43+
44+
CombinedCamera.prototype.toPerspective = function () {
45+
46+
// Switches to the Perspective Camera
47+
48+
this.near = this.cameraP.near;
49+
this.far = this.cameraP.far;
50+
51+
this.cameraP.aspect = this.aspect;
52+
this.cameraP.fov = this.fov / this.zoom ;
53+
this.cameraP.view = this.view;
54+
55+
this.cameraP.updateProjectionMatrix();
56+
57+
this.projectionMatrix = this.cameraP.projectionMatrix;
58+
59+
this.inPerspectiveMode = true;
60+
this.inOrthographicMode = false;
61+
62+
this.type = 'PerspectiveCamera'; // Act as a perspective camera
63+
64+
};
65+
66+
CombinedCamera.prototype.toOrthographic = function () {
67+
68+
// Switches to the Orthographic camera estimating viewport from Perspective
69+
70+
var fov = this.fov;
71+
var aspect = this.cameraP.aspect;
72+
var near = this.cameraP.near;
73+
var far = this.cameraP.far;
74+
75+
// The size that we set is the mid plane of the viewing frustum
76+
77+
var hyperfocus = ( near + far ) / 2;
78+
79+
var halfHeight = Math.tan( fov * Math.PI / 180 / 2 ) * hyperfocus;
80+
var halfWidth = halfHeight * aspect;
81+
82+
halfHeight /= this.zoom;
83+
halfWidth /= this.zoom;
84+
85+
this.cameraO.left = - halfWidth;
86+
this.cameraO.right = halfWidth;
87+
this.cameraO.top = halfHeight;
88+
this.cameraO.bottom = - halfHeight;
89+
this.cameraO.view = this.view;
90+
91+
this.cameraO.updateProjectionMatrix();
92+
93+
this.near = this.cameraO.near;
94+
this.far = this.cameraO.far;
95+
this.projectionMatrix = this.cameraO.projectionMatrix;
96+
97+
this.inPerspectiveMode = false;
98+
this.inOrthographicMode = true;
99+
100+
this.type = 'OrthographicCamera'; // Act as an orthographic camera
101+
102+
};
103+
104+
CombinedCamera.prototype.copy = function ( source ) {
105+
106+
THREE.Camera.prototype.copy.call( this, source );
107+
108+
this.fov = source.fov;
109+
this.far = source.far;
110+
this.near = source.near;
111+
112+
this.left = source.left;
113+
this.right = source.right;
114+
this.top = source.top;
115+
this.bottom = source.bottom;
116+
117+
this.zoom = source.zoom;
118+
this.view = source.view === null ? null : Object.assign( {}, source.view );
119+
this.aspect = source.aspect;
120+
121+
this.cameraO.copy( source.cameraO );
122+
this.cameraP.copy( source.cameraP );
123+
124+
this.inOrthographicMode = source.inOrthographicMode;
125+
this.inPerspectiveMode = source.inPerspectiveMode;
126+
127+
return this;
128+
129+
};
130+
131+
CombinedCamera.prototype.setViewOffset = function( fullWidth, fullHeight, x, y, width, height ) {
132+
133+
this.view = {
134+
fullWidth: fullWidth,
135+
fullHeight: fullHeight,
136+
offsetX: x,
137+
offsetY: y,
138+
width: width,
139+
height: height
140+
};
141+
142+
if ( this.inPerspectiveMode ) {
143+
144+
this.aspect = fullWidth / fullHeight;
145+
146+
this.toPerspective();
147+
148+
} else {
149+
150+
this.toOrthographic();
151+
152+
}
153+
154+
};
155+
156+
CombinedCamera.prototype.clearViewOffset = function() {
157+
158+
this.view = null;
159+
this.updateProjectionMatrix();
160+
161+
};
162+
163+
CombinedCamera.prototype.setSize = function( width, height ) {
164+
165+
this.cameraP.aspect = width / height;
166+
this.left = - width / 2;
167+
this.right = width / 2;
168+
this.top = height / 2;
169+
this.bottom = - height / 2;
170+
171+
};
172+
173+
174+
CombinedCamera.prototype.setFov = function( fov ) {
175+
176+
this.fov = fov;
177+
178+
if ( this.inPerspectiveMode ) {
179+
180+
this.toPerspective();
181+
182+
} else {
183+
184+
this.toOrthographic();
185+
186+
}
187+
188+
};
189+
190+
// For maintaining similar API with PerspectiveCamera
191+
192+
CombinedCamera.prototype.updateProjectionMatrix = function() {
193+
194+
if ( this.inPerspectiveMode ) {
195+
196+
this.toPerspective();
197+
198+
} else {
199+
200+
this.toPerspective();
201+
this.toOrthographic();
202+
203+
}
204+
205+
};
206+
207+
/*
208+
* Uses Focal Length (in mm) to estimate and set FOV
209+
* 35mm (full frame) camera is used if frame size is not specified;
210+
* Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
211+
*/
212+
CombinedCamera.prototype.setLens = function ( focalLength, filmGauge ) {
213+
214+
if ( filmGauge === undefined ) filmGauge = 35;
215+
216+
var vExtentSlope = 0.5 * filmGauge /
217+
( focalLength * Math.max( this.cameraP.aspect, 1 ) );
218+
219+
var fov = THREE.Math.RAD2DEG * 2 * Math.atan( vExtentSlope );
220+
221+
this.setFov( fov );
222+
223+
return fov;
224+
225+
};
226+
227+
228+
CombinedCamera.prototype.setZoom = function( zoom ) {
229+
230+
this.zoom = zoom;
231+
232+
if ( this.inPerspectiveMode ) {
233+
234+
this.toPerspective();
235+
236+
} else {
237+
238+
this.toOrthographic();
239+
240+
}
241+
242+
};
243+
244+
CombinedCamera.prototype.toFrontView = function() {
245+
246+
this.rotation.x = 0;
247+
this.rotation.y = 0;
248+
this.rotation.z = 0;
249+
250+
// should we be modifing the matrix instead?
251+
252+
};
253+
254+
CombinedCamera.prototype.toBackView = function() {
255+
256+
this.rotation.x = 0;
257+
this.rotation.y = Math.PI;
258+
this.rotation.z = 0;
259+
260+
};
261+
262+
CombinedCamera.prototype.toLeftView = function() {
263+
264+
this.rotation.x = 0;
265+
this.rotation.y = - Math.PI / 2;
266+
this.rotation.z = 0;
267+
268+
};
269+
270+
CombinedCamera.prototype.toRightView = function() {
271+
272+
this.rotation.x = 0;
273+
this.rotation.y = Math.PI / 2;
274+
this.rotation.z = 0;
275+
276+
};
277+
278+
CombinedCamera.prototype.toTopView = function() {
279+
280+
this.rotation.x = - Math.PI / 2;
281+
this.rotation.y = 0;
282+
this.rotation.z = 0;
283+
284+
};
285+
286+
CombinedCamera.prototype.toBottomView = function() {
287+
288+
this.rotation.x = Math.PI / 2;
289+
this.rotation.y = 0;
290+
this.rotation.z = 0;
291+
292+
};
293+
294+
295+
module.exports = {
296+
CombinedCamera: CombinedCamera
297+
}

0 commit comments

Comments
 (0)