Skip to content

Commit c10b1b2

Browse files
committed
Finish initial implementation of CombinedCamera
Also adds a notebook showing its use
1 parent caea24d commit c10b1b2

File tree

5 files changed

+152
-18
lines changed

5 files changed

+152
-18
lines changed

examples/Combined Camera.ipynb

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# Combined Camera\n",
8+
"\n",
9+
"A combined camera allows you to easily switch between a perspective camera and an orthographic camera."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": null,
15+
"metadata": {},
16+
"outputs": [],
17+
"source": [
18+
"from pythreejs import *\n",
19+
"from IPython.display import display"
20+
]
21+
},
22+
{
23+
"cell_type": "code",
24+
"execution_count": null,
25+
"metadata": {},
26+
"outputs": [],
27+
"source": [
28+
"mesh1 = Mesh(SphereBufferGeometry(20, 16, 16), MeshPhysicalMaterial(color='red'), position=[-20, 0, 0])\n",
29+
"mesh2 = Mesh(SphereBufferGeometry(20, 16, 16), MeshPhysicalMaterial(color='green'), position=[20, 0, 0])"
30+
]
31+
},
32+
{
33+
"cell_type": "code",
34+
"execution_count": null,
35+
"metadata": {},
36+
"outputs": [],
37+
"source": [
38+
"view_width = 600\n",
39+
"view_height = 400\n",
40+
"camera = CombinedCamera(position=[0, 0, 60], width=view_width, height=view_height)"
41+
]
42+
},
43+
{
44+
"cell_type": "code",
45+
"execution_count": null,
46+
"metadata": {},
47+
"outputs": [],
48+
"source": [
49+
"key_light = PointLight(position=[-100, 100, 100])\n",
50+
"ambient_light = AmbientLight(intensity=0.4)\n",
51+
"scene = Scene(children=[mesh1, mesh2, key_light, ambient_light, camera])\n",
52+
"renderer = Renderer(scene=scene, camera=camera, controls=[OrbitControls(controlling=camera)],\n",
53+
" width=view_width, height=view_height)\n",
54+
"display(renderer)"
55+
]
56+
},
57+
{
58+
"cell_type": "code",
59+
"execution_count": null,
60+
"metadata": {},
61+
"outputs": [],
62+
"source": [
63+
"camera.mode = 'orthographic'"
64+
]
65+
},
66+
{
67+
"cell_type": "code",
68+
"execution_count": null,
69+
"metadata": {},
70+
"outputs": [],
71+
"source": [
72+
"camera.mode = 'perspective'"
73+
]
74+
},
75+
{
76+
"cell_type": "code",
77+
"execution_count": null,
78+
"metadata": {},
79+
"outputs": [],
80+
"source": []
81+
}
82+
],
83+
"metadata": {
84+
"kernelspec": {
85+
"display_name": "Python 3",
86+
"language": "python",
87+
"name": "python3"
88+
},
89+
"language_info": {
90+
"codemirror_mode": {
91+
"name": "ipython",
92+
"version": 3
93+
},
94+
"file_extension": ".py",
95+
"mimetype": "text/x-python",
96+
"name": "python",
97+
"nbconvert_exporter": "python",
98+
"pygments_lexer": "ipython3",
99+
"version": "3.5.4"
100+
}
101+
},
102+
"nbformat": 4,
103+
"nbformat_minor": 2
104+
}

js/scripts/three-class-config.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,17 @@ module.exports = {
114114
relativePath: './cameras/CombinedCamera',
115115
superClass: 'Camera',
116116
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(),
117+
fov: new Types.Float(50.0),
118+
zoom: new Types.Float(1.0),
119+
near: new Types.Float(0.1),
120+
far: new Types.Float(2000),
121+
orthoNear: new Types.Float(0.1),
122+
orthoFar: new Types.Float(2000),
123123

124-
width: new Types.Float(),
125-
height: new Types.Float(),
124+
width: new Types.Float(),
125+
height: new Types.Float(),
126126

127-
zoom: new Types.Float(1),
127+
mode: new Types.Enum("['perspective', 'orthographic']", 'perspective'),
128128
// view: new Types.ViewOffset()
129129
},
130130
constructorArgs: [ 'width', 'height', 'fov', 'near', 'far', 'orthoNear', 'orthoFar' ],

js/src/cameras/CombinedCamera.js

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
var _ = require('underscore');
2-
var CombinedCameraAutogen = require('./CombinedCamera.autogen');
2+
var CombinedCamera = require("../examples/cameras/CombinedCamera.js").CombinedCamera;
3+
var CombinedCameraAutogen = require('./CombinedCamera.autogen').CombinedCameraModel;
34

4-
var CombinedCameraModel = CombinedCameraAutogen.CombinedCameraModel.extend({
5+
var CombinedCameraModel = CombinedCameraAutogen.extend({
56

67
createPropertiesArrays: function() {
78
CombinedCameraAutogen.prototype.createPropertiesArrays.call(this);
@@ -13,6 +14,22 @@ var CombinedCameraModel = CombinedCameraAutogen.CombinedCameraModel.extend({
1314
delete this.property_converters['far'];
1415
delete this.property_converters['orthoNear'];
1516
delete this.property_converters['orthoFar'];
17+
delete this.property_converters['mode'];
18+
},
19+
20+
constructThreeObject: function() {
21+
22+
var result = new CombinedCamera(
23+
this.convertFloatModelToThree(this.get('width'), 'width'),
24+
this.convertFloatModelToThree(this.get('height'), 'height'),
25+
this.convertFloatModelToThree(this.get('fov'), 'fov'),
26+
this.convertFloatModelToThree(this.get('near'), 'near'),
27+
this.convertFloatModelToThree(this.get('far'), 'far'),
28+
this.convertFloatModelToThree(this.get('orthoNear'), 'orthoNear'),
29+
this.convertFloatModelToThree(this.get('orthoFar'), 'orthoFar')
30+
);
31+
return Promise.resolve(result);
32+
1633
},
1734

1835
mapCombinedCameraModelToThree: function() {
@@ -30,8 +47,11 @@ var CombinedCameraModel = CombinedCameraAutogen.CombinedCameraModel.extend({
3047
this.obj.cameraO.near = this.convertFloatModelToThree(this.get('orthoNear'));
3148
this.obj.cameraO.far = this.convertFloatModelToThree(this.get('orthoFar'));
3249

33-
// Always update the projection matrix after setting the attributes:
34-
this.obj.updateProjectionMatrix();
50+
// This update projection matrix, and sets correct mode
51+
this.obj.toPerspective();
52+
if (this.get('mode') === 'orthographic') {
53+
this.obj.toOrthographic();
54+
}
3555
},
3656

3757
mapCombinedCameraThreeToModel: function() {
@@ -41,10 +61,12 @@ var CombinedCameraModel = CombinedCameraAutogen.CombinedCameraModel.extend({
4161
toSet.height = this.convertFloatThreeToModel(this.obj.top - this.obj.bottom);
4262

4363
toSet.near = this.convertFloatThreeToModel(this.obj.cameraP.near);
44-
toSet.near = this.convertFloatThreeToModel(this.obj.cameraP.far);
64+
toSet.far = this.convertFloatThreeToModel(this.obj.cameraP.far);
4565
toSet.orthoNear = this.convertFloatThreeToModel(this.obj.cameraO.near);
4666
toSet.orthoFar = this.convertFloatThreeToModel(this.obj.cameraO.far);
4767

68+
toSet.mode = this.obj.inPerspectiveMode ? 'perspective' : 'orthographic';
69+
4870
this.set(toSet, 'pushFromThree');
4971

5072
},

js/src/examples/cameras/CombinedCamera.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ var CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoF
2121
this.far = far;
2222
this.near = near;
2323

24+
// The default focus is the mid plane of the viewing frustum
25+
this.focus = ( near + far ) / 2;
26+
2427
this.left = - width / 2;
2528
this.right = width / 2;
2629
this.top = height / 2;
@@ -72,11 +75,9 @@ CombinedCamera.prototype.toOrthographic = function () {
7275
var near = this.cameraP.near;
7376
var far = this.cameraP.far;
7477

75-
// The size that we set is the mid plane of the viewing frustum
76-
77-
var hyperfocus = ( near + far ) / 2;
78+
// The size that we set is the plane of the viewing frustum at the focus
7879

79-
var halfHeight = Math.tan( fov * Math.PI / 180 / 2 ) * hyperfocus;
80+
var halfHeight = Math.tan( fov * Math.PI / 180 / 2 ) * this.focus;
8081
var halfWidth = halfHeight * aspect;
8182

8283
halfHeight /= this.zoom;

js/src/examples/controls/OrbitControls.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@ var OrbitControls = function ( object, domElement ) {
172172

173173
scope.object.lookAt( scope.target );
174174

175+
if ( scope.object.focus !== undefined ) {
176+
177+
// Set focus for those cameras that support it
178+
scope.object.focus = scope.object.position.distanceTo( scope.target );
179+
180+
}
181+
175182
if ( scope.enableDamping === true ) {
176183

177184
sphericalDelta.theta *= ( 1 - scope.dampingFactor );

0 commit comments

Comments
 (0)