Skip to content

Commit 4a44b70

Browse files
committed
Adding portal view and related examples
Adding portal view demo, and examples to illustrate the related concepts: stencil buffer testing, clipping planes, skyboxes, and synchronizing the relative position of two objects (used for portal view cameras).
1 parent a558e63 commit 4a44b70

35 files changed

+1234
-8
lines changed

clipping-planes.html

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
<!DOCTYPE html>
2+
<head>
3+
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
4+
<title>Hello, world!</title>
5+
<script src='js/keyboard.js'></script>
6+
<!-- include three.js library -->
7+
<script src='js/three.js'></script>
8+
</head>
9+
10+
<body style='margin : 0px; overflow: hidden; font-family: Monospace;'>
11+
12+
<!--
13+
Example created by Lee Stemkoski: https://github.com/stemkoski
14+
-->
15+
16+
<script>
17+
18+
var scene, camera, renderer, clock, deltaTime, totalTime, keyboard;
19+
20+
var mover, secondMover, plane, secondPlane;
21+
22+
initialize();
23+
animate();
24+
25+
function initialize()
26+
{
27+
scene = new THREE.Scene();
28+
29+
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 1000 );
30+
camera.position.set(0, 6, 8);
31+
camera.lookAt( scene.position );
32+
scene.add( camera );
33+
34+
let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.00 );
35+
scene.add( ambientLight );
36+
37+
// let pointLight = new THREE.PointLight();
38+
// camera.add( pointLight );
39+
40+
renderer = new THREE.WebGLRenderer({
41+
antialias : true,
42+
alpha: false
43+
});
44+
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
45+
renderer.setSize( window.innerWidth, window.innerHeight );
46+
renderer.domElement.style.position = 'absolute'
47+
renderer.domElement.style.top = '0px'
48+
renderer.domElement.style.left = '0px'
49+
document.body.appendChild( renderer.domElement );
50+
window.addEventListener( 'resize', onWindowResize, false );
51+
52+
clock = new THREE.Clock();
53+
deltaTime = 0;
54+
totalTime = 0;
55+
56+
keyboard = new Keyboard();
57+
58+
let loader = new THREE.TextureLoader();
59+
60+
// floor
61+
let floorGeometry = new THREE.PlaneGeometry(20,20);
62+
let floorMaterial = new THREE.MeshBasicMaterial({
63+
map: loader.load( 'images/color-grid.png' )
64+
});
65+
let floorMesh = new THREE.Mesh( floorGeometry, floorMaterial );
66+
floorMesh.rotation.x = -Math.PI/2;
67+
scene.add( floorMesh );
68+
69+
let cubeGeometry = new THREE.BoxGeometry(1,1,1);
70+
let materialArray = [
71+
new THREE.MeshBasicMaterial( { map: loader.load("images/xpos.png") } ),
72+
new THREE.MeshBasicMaterial( { map: loader.load("images/xneg.png") } ),
73+
new THREE.MeshBasicMaterial( { map: loader.load("images/ypos.png") } ),
74+
new THREE.MeshBasicMaterial( { map: loader.load("images/yneg.png") } ),
75+
new THREE.MeshBasicMaterial( { map: loader.load("images/zpos.png") } ),
76+
new THREE.MeshBasicMaterial( { map: loader.load("images/zneg.png") } ),
77+
];
78+
let cubeMesh = new THREE.Mesh( cubeGeometry, materialArray );
79+
80+
mover = new THREE.Group();
81+
mover.add( cubeMesh );
82+
mover.position.set(-3, 0.5, 2);
83+
scene.add( mover );
84+
85+
plane = new THREE.Mesh(
86+
new THREE.PlaneGeometry(1,1),
87+
new THREE.MeshBasicMaterial({map:loader.load("images/sphere-colored.png")})
88+
);
89+
plane.position.set(-4, 0.5, 1);
90+
plane.rotation.y = Math.PI/4
91+
scene.add(plane);
92+
93+
// align clipping plane with PlaneGeometry object
94+
95+
// default normal of a plane is 0,0,1. Apply mesh rotation to it.
96+
let normal = new THREE.Vector3(0,0,1).applyQuaternion( plane.quaternion );
97+
let point = plane.position;
98+
clipPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, point);
99+
renderer.clippingPlanes = [clipPlane];
100+
}
101+
102+
function update()
103+
{
104+
keyboard.update();
105+
106+
let translateSpeed = 0.5; // units per second
107+
let distance = translateSpeed * deltaTime;
108+
let rotateSpeed = Math.PI/3; // radians per second
109+
let angle = rotateSpeed * deltaTime;
110+
111+
if (keyboard.isKeyPressed("W"))
112+
mover.translateZ( -distance );
113+
if (keyboard.isKeyPressed("S"))
114+
mover.translateZ( distance );
115+
116+
if (keyboard.isKeyPressed("A"))
117+
mover.translateX( -distance );
118+
if (keyboard.isKeyPressed("D"))
119+
mover.translateX( distance );
120+
121+
if (keyboard.isKeyPressed("R"))
122+
mover.translateY( distance );
123+
if (keyboard.isKeyPressed("F"))
124+
mover.translateY( -distance );
125+
126+
if (keyboard.isKeyPressed("Q"))
127+
mover.rotateY( angle );
128+
if (keyboard.isKeyPressed("E"))
129+
mover.rotateY( -angle );
130+
131+
if (keyboard.isKeyPressed("T"))
132+
mover.children[0].rotateX( angle );
133+
if (keyboard.isKeyPressed("G"))
134+
mover.children[0].rotateX( -angle );
135+
}
136+
137+
function render()
138+
{
139+
renderer.render( scene, camera );
140+
}
141+
142+
function animate()
143+
{
144+
requestAnimationFrame(animate);
145+
deltaTime = clock.getDelta();
146+
totalTime += deltaTime;
147+
update();
148+
render();
149+
}
150+
151+
function onWindowResize()
152+
{
153+
camera.aspect = window.innerWidth / window.innerHeight;
154+
camera.updateProjectionMatrix();
155+
renderer.setSize( window.innerWidth, window.innerHeight );
156+
}
157+
158+
</script>
159+
160+
</body>
161+
</html>

hole-box.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@
117117
// the inside of the hole
118118
let geometry1 = new THREE.CubeGeometry(2,2,2);
119119
let loader = new THREE.TextureLoader();
120-
let texture = loader.load( 'images/tiles.jpg', render );
120+
let texture = loader.load( 'images/tiles.jpg' );
121121
let material1 = new THREE.MeshLambertMaterial({
122122
transparent : true,
123123
map: texture,

images/beach/negx.jpg

1.06 MB
Loading

images/beach/negy.jpg

1.3 MB
Loading

images/beach/negz.jpg

1.01 MB
Loading

images/beach/posx.jpg

942 KB
Loading

images/beach/posy.jpg

712 KB
Loading

images/beach/posz.jpg

1020 KB
Loading

images/beach/readme.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Author
2+
======
3+
4+
This is the work of Emil Persson, aka Humus.
5+
http://www.humus.name
6+
7+
8+
9+
License
10+
=======
11+
12+
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
13+
http://creativecommons.org/licenses/by/3.0/

images/church/negx.jpg

806 KB
Loading

images/church/negy.jpg

874 KB
Loading

images/church/negz.jpg

895 KB
Loading

images/church/posx.jpg

957 KB
Loading

images/church/posy.jpg

533 KB
Loading

images/church/posz.jpg

849 KB
Loading

images/church/readme.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Author
2+
======
3+
4+
This is the work of Emil Persson, aka Humus.
5+
http://www.humus.name
6+
7+
8+
9+
License
10+
=======
11+
12+
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
13+
http://creativecommons.org/licenses/by/3.0/

images/demo/clipping-planes.png

38 KB
Loading

images/demo/portal-view-large.png

1.42 MB
Loading

images/demo/portal-view.png

107 KB
Loading

images/demo/stencil-test.png

25.6 KB
Loading

images/mountain/negx.jpg

551 KB
Loading

images/mountain/negy.jpg

875 KB
Loading

images/mountain/negz.jpg

559 KB
Loading

images/mountain/posx.jpg

676 KB
Loading

images/mountain/posy.jpg

209 KB
Loading

images/mountain/posz.jpg

665 KB
Loading

images/mountain/readme.txt

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Author
2+
======
3+
4+
This is the work of Emil Persson, aka Humus.
5+
http://www.humus.name
6+
7+
8+
9+
License
10+
=======
11+
12+
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
13+
http://creativecommons.org/licenses/by/3.0/
File renamed without changes.

images/scene-sphere-room.jpg

185 KB
Loading

index.html

+31-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<html>
22
<head>
3-
<title>AR.js - examples</title>
3+
<title>Three.js and AR.js - examples</title>
44
<link rel=stylesheet href="css/index.css"/>
55
</head>
66
<body>
77

8-
<div class="bigTitle">AR.js Examples</div>
8+
<div class="bigTitle">Three.js and AR.js Examples</div>
99
<hr>
10-
The goal of this collection is to provide a set of basic and instructive examples that introduce the various features in the Javascript-based Augmented Reality library,
11-
<a class="toc" href="https://github.com/jeromeetienne/AR.js">AR.js</a>.
10+
The goal of this collection is to provide a set of basic and instructive examples that introduce the various features in the Javascript-based Augmented Reality (AR) library,
11+
<a class="toc" href="https://github.com/jeromeetienne/AR.js">AR.js</a>. Advanced <a class="toc" href="https://threejs.org/">three.js</a> examples are also included.
1212
<br/><br/>
13-
Viewing these examples will require a device with a camera and one or both of the <a class="toc" href="markers/hiro.png">Hiro</a> and <a class="toc" href="markers/kanji.png">Kanji</a> marker patterns (either printed or displayed on a second device).
13+
Viewing the AR examples will require a device with a camera and one or both of the <a class="toc" href="markers/hiro.png">Hiro</a> and <a class="toc" href="markers/kanji.png">Kanji</a> marker patterns (either printed or displayed on a second device).
1414
<br/><br/>
1515
Source code hosted at <a class="toc" href="https://github.com/stemkoski/AR-Examples">GitHub</a>.
1616

@@ -145,7 +145,32 @@
145145
<a href="portal-half-keyboard-test.html" target="_blank">
146146
<img src="images/demo/portal-half-keyboard-test.png" class="superImage" />
147147
<br/>Portal Test</a>
148-
<p class ="superText"> Creating a "portal to another world" effect. Camera moves using same controls as Object Movement example. Only visible from one side. </p>
148+
<p class ="superText"> Creating a "portal to another world" effect. Camera moves using same controls as Object Movement example. Only visible from one side.
149+
<br/>Not very robust -- see the following portal examples instead.</p>
150+
</div>
151+
152+
<div class="fancy">
153+
<a href="stencil-test.html" target="_blank">
154+
<img src="images/demo/stencil-test.png" class="superImage" />
155+
<br/>Stencil Buffer Test</a>
156+
<p class ="superText"> A simple example that uses layers and the stencil buffer to render part of the scene
157+
onto a plane in the scene. Camera moves using same controls as Object Movement example. Useful for understanding portal view example. </p>
158+
</div>
159+
160+
<div class="fancy">
161+
<a href="clipping-planes.html" target="_blank">
162+
<img src="images/demo/clipping-planes.png" class="superImage" />
163+
<br/>Clipping Planes</a>
164+
<p class ="superText"> A simple example that sets up a clipping plane (aligned with a plane mesh) to limit the volume of the scene that is rendered. Useful for understanding portal view example. </p>
165+
</div>
166+
167+
<div class="fancy">
168+
<a href="portal-view.html" target="_blank">
169+
<img src="images/demo/portal-view.png" class="superImage" />
170+
<br/>Portal View</a>
171+
<p class ="superText"> A "portal to another world" effect. Portal visible through both sides.
172+
<br/>Camera moves using same controls as Object Movement example; also, press 1, 2, or 3 to see the view from different cameras.
173+
<br/>Uses stencil buffer and clipping planes for accurate rendering. </p>
149174
</div>
150175

151176
<!--

portal-half-keyboard-test.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484

8585
let cloakTexture = loader.load("images/color-grid.png");
8686
cloakMaterial = new THREE.MeshBasicMaterial({ map: cloakTexture, side: THREE.FrontSide, colorWrite: false }); // change colorWrite: true to see the cloak
87-
let sceneTexture = loader.load("images/scene-sphere.jpg");
87+
let sceneTexture = loader.load("images/scene-sphere-outside.jpg");
8888
sceneTexture.offset.x = 0.5;
8989
sceneTexture.repeat.set(0.5, 1);
9090

0 commit comments

Comments
 (0)