Integrating three.js and plotly.js - javascript

I am trying to plot a 3d network using three.js. The nodes of
the three.js graph network is associated with array of values. I want these
values to be plotted using plotly.js when nodes are clicked.
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Three.js & Plotly integration</title>
<style>
#three-js-container {
width: 70%;
height: 400px;
float: left;
}
#plotly-container {
width: 30%;
height: 400px;
float: right;
}
</style>
</head>
<body>
<div id="three-js-container"></div>
<div id="plotly-container"></div>
<script src="https://cdn.jsdelivr.net/npm/three#0.117.0/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/plotly.js#1.55.3/dist/plotly.min.js"></script>
<script>
// Three.js code for network graph
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth * 0.7, 400);
document.querySelector("#three-js-container").appendChild(renderer.domElement);
// Values of nodes
var values = [
[10, 15, 20, 25],
[5, 10, 15, 20]
];
// Create node1
var node1 = new THREE.SphereGeometry(5, 32, 32);
var node1Material = new THREE.MeshBasicMaterial({color: 0x00ff00});
var node1Mesh = new THREE.Mesh(node1, node1Material);
node1Mesh.position.set(-10, 0, 0);
scene.add(node1Mesh);
// Create node2
var node2 = new THREE.SphereGeometry(5, 32, 32);
var node2Material = new THREE.MeshBasicMaterial({color: 0xff0000});
var node2Mesh = new THREE.Mesh(node2, node2Material);
node2Mesh.position.set(10, 0, 0);
scene.add(node2Mesh);
// Create edge
var edge = new THREE.Line(
new THREE.BufferGeometry().setFromPoints( [
new THREE.Vector3( node1Mesh.position.x, node1Mesh.position.y, node1Mesh.position.z ),
new THREE.Vector3( node2Mesh.position.x, node2Mesh.position.y, node2Mesh.position.z )
] ),
new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } )
);
scene.add(edge);
camera.position.z = 20;
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
// Event listener to detect click on edge
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
document.querySelector("#three-js-container").addEventListener("click", function(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects([edge]);
if (intersects.length > 0) {
// Show plotly graph on side panel
Plotly.newPlot('side-panel', [{
x: [0, 1, 2, 3],
y: values[0],
type: 'scatter'
}, {
x: [0, 1, 2, 3],
y: values[1],
type: 'scatter'
}], {
title: 'Values of Nodes'
});
}
});
</script>
</body>
</html>
But the plotly line graph is not visible when the three.js nodes are clicked.
Suggestions on how to fix this will be really helpful.

Related

Plotting 3d network in three.js

I am trying to generate a 3d graph using three.js
Code:
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/three#0.119.0/build/three.min.js"></script>
<style>
body { margin: 0; }
canvas { display: block; }
</style>
</head>
<body>
<script>
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var node1_geometry = new THREE.BoxGeometry( 1, 1, 1 );
var node1_material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
var node1 = new THREE.Mesh( node1_geometry, node1_material );
node1.position.set(-2, 4, 1);
var node2_geometry = new THREE.BoxGeometry( 1, 1, 1 );
var node2_material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
var node2 = new THREE.Mesh( node2_geometry, node2_material );
node2.position.set(2, 4, 1);
var edge_geometry = new THREE.Geometry();
edge_geometry.vertices.push( node1.position, node2.position );
var edge_material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
var edge = new THREE.Line( edge_geometry, edge_material );
scene.add( node1 );
scene.add( node2 );
scene.add( edge );
camera.position.z = 5;
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
</script>
</body>
</html>
But this only gives a black window and the graph is not displayed.
Suggestions on how to fix this will be really helpful.
To get the snippet to run you have a small problem with you line
var edge_material = new THREE.LineBasicMaterial( { color: 0xffffff, linewidth: 2 } );
You can change this to:
var edge_material = new THREE.LineDashedMaterial({
color: 0xffffff,
dashSize: 2,
gapSize: 2
});
It should now render, but a black background still shows up. The problem now is that your camera is not angled at the content you have created, so add a line with a camera position below.
camera.position.y = 5;
Now you should be able to see your two boxes, and the line.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.background = new THREE.Color(0x333333);
var node1_geometry = new THREE.BoxGeometry(1, 1, 1);
var node1_material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
var node1 = new THREE.Mesh(node1_geometry, node1_material);
node1.position.set(-2, 4, 1);
var node2_geometry = new THREE.BoxGeometry(1, 1, 1);
var node2_material = new THREE.MeshBasicMaterial({
color: 0xff00ff
});
var node2 = new THREE.Mesh(node2_geometry, node2_material);
node2.position.set(2, 4, 1);
var edge_geometry = new THREE.Geometry();
edge_geometry.vertices.push(node1.position, node2.position);
var edge_material = new THREE.LineDashedMaterial({
color: 0xffffff,
dashSize: 2,
gapSize: 2
});
var edge = new THREE.Line(edge_geometry, edge_material);
scene.add(node1);
scene.add(node2);
scene.add(edge);
camera.position.z = 5;
camera.position.y = 5;
var animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/three#0.119.0/build/three.min.js"></script>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
</body>
</html>

Three.js Animated curve

I try to animate a 2D curve in Three.js over time.
I'll need more than 4 control points, so I'm not using Bezier curves.
I created a Three.Line based on a SplineCurve.
If I log the geometry.vertices position of my line they'll change over time, but geometry.attributes.position remains the same. Is it possible to animate the line based on the curve animation ? I managed to do this with Bezier Curves, but can't find a way with SplineCurve.
Thank you for your help, here's my code :
First I create the line :
var curve = new THREE.SplineCurve( [
new THREE.Vector3( -10, 0, 10 ),
new THREE.Vector3( -5, 5, 5 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 5, -5, 5 ),
new THREE.Vector3( 10, 0, 10 )
] );
var points = curve.getPoints( 50 );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
// Create the final object to add to the scene
curveObject = new THREE.Line( geometry, material );
scene.add( curveObject );
curveObject.curve = curve;
Then I try to update it :
curveObject.curve.points[0].x += 1;
curveObject.geometry.vertices = curveObject.curve.getPoints( 50 );
curveObject.geometry.verticesNeedUpdate = true;
curveObject.geometry.attributes.needsUpdate = true;
You can do it like that:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(8, 13, 25);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
var canvas = renderer.domElement;
document.body.appendChild(canvas);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(20, 40));
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-10, 0, 10),
new THREE.Vector3(-5, 5, 5),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(5, -5, 5),
new THREE.Vector3(10, 0, 10)
]);
var points = curve.getPoints(50);
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var material = new THREE.LineBasicMaterial({
color: 0x00ffff
});
var curveObject = new THREE.Line(geometry, material);
scene.add(curveObject);
var clock = new THREE.Clock();
var time = 0;
render();
function resize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render() {
if (resize(renderer)) {
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
time += clock.getDelta();
curve.points[1].y = Math.sin(time) * 2.5;
geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(50));
curveObject.geometry.dispose();
curveObject.geometry = geometry;
requestAnimationFrame(render);
}
html,
body {
height: 100%;
margin: 0;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
display;
block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Round Corners Box Geometry - threejs

This question is more about Math, than about threejs but maybe there are usable Alternatives for my issue.
So what I want to do, is to go through every vertice in a Box Geometry and check weither it has to be moved down/up and move it then by a specific value. (it is only about the y-values of each vertice)
var width = 200,
height = 100,
depth = 50;
var roundCornerWidth = var roundCornerHeight = 10;
var helpWidth = width - 2*roundCornerWidth,
helpHeight = height - 2*roundCornerHeight;
var boxGeometry = new THREE.BoxGeometry(width, height, depth, 100, 50, 10);
boxGeometry.vertices.forEach(v => {
if(Math.abs(v.x)>helpWidth/2){
if(Math.abs(v.y)>helpHeight/2){
let helper = Math.abs(v.x)-helperWidth/2;
v.y = Math.sign(v.y)*(helperHeight + Math.cos(helper/roundWidth * Math.PI/2)*roundHeight);
}
}
});
The code above creates corners like you can see on the example image. Those aren't kind of beautiful! :( Another "function" than cos() is needed.
I've used a method without trigonometrical functions, as we can manipulate with vectors:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(50, 50, 150);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var radius = 10;
var width = 200,
height = 100;
var geometry = new THREE.BoxGeometry(width, height, 50, 100, 50, 10);
var v1 = new THREE.Vector3();
var w1 = (width - (radius * 2)) * 0.5,
h1 = (height - (radius * 2)) * 0.5;
var vTemp = new THREE.Vector3(),
vSign = new THREE.Vector3(),
vRad = new THREE.Vector3();
geometry.vertices.forEach(v => {
v1.set(w1, h1, v.z);
vTemp.multiplyVectors(v1, vSign.set(Math.sign(v.x), Math.sign(v.y), 1));
vRad.subVectors(v, vTemp);
if (Math.abs(v.x) > v1.x && Math.abs(v.y) > v1.y && vRad.length() > radius) {
vRad.setLength(radius).add(vTemp);
v.copy(vRad);
}
});
var mesh = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
scene.add(mesh);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/90/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Disadvantage: you can't control the smoothness of the roundness without increasing the amount of width or height or depth segments.
EDIT: copied surrounding Code Blocks from prisoner849 to make result visbile for everyone.
I wanted to stay with the box Geometry, because I also deform the Geometry on the z-axis, so this is my solution:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(50, 50, 150);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var width = 200,
height = 100,
depth = 50;
var roundCornerWidth = roundCornerHeight = 10;
var helpWidth = width - 2*roundCornerWidth,
helpHeight = height - 2*roundCornerHeight;
var boxGeometry = new THREE.BoxGeometry(width, height, depth, 100, 50, 10);
boxGeometry.vertices.forEach(v => {
if(Math.abs(v.x)>helpWidth/2){
if(Math.abs(v.y)>helpHeight/2){
let helperX = Math.abs(v.x)-helpWidth/2;
let helperY2 = (Math.abs(v.y)-helpHeight/2)/roundCornerHeight;
let helperY = (1-helperX/roundCornerWidth) * roundCornerHeight * helperY2;
v.y = Math.sign(v.y)*((helpHeight/2 + helperY)+(Math.sin(helperX/roundCornerWidth * Math.PI)*(roundCornerHeight/4))*helperY2);
v.x = Math.sign(v.x)*(Math.abs(v.x)+(Math.sin(helperX/roundCornerWidth * Math.PI)*(roundCornerWidth/4))*helperY2);
}
}
});
var mesh = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({
color: 0xffce00,
wireframe: true
}));
scene.add(mesh);
render();
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/90/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
This worked for me perfectly and seems to be the simplest solution for my issue.

ThreeJS, How to use CSS3Renderer and WebGLRenderer to render 2 objects on the same scene and have them overlap?

JSFiddle :
http://jsfiddle.net/ApoG/50y32971/2/
I am rendering an image as a background using CSS3Renderer, projected as a cube in the app.
I want to have objects, rendered using WebGLRenderer in the middle (later I will make them clickable using ray detection).
It looks like (from my code below), that WebGlrendered wireframe (the wireframe of the randomly generated square in the middle) only shows up when you rotate the view to have white background, when the background is turned to the CSS3Rendered clouds, the wireframe rendered by WebGLRenderer disappears. Is there a way to keep the wireframe in the view?
My ultimate goal is to have several floating objects (3d text for example) with links as an object property, which will be later made clickable (using rays). I want to use CSS3 renderer because it renders well on mobile vs canvasrenderer, ideas and suggestions would greatly appreciated, I am officially stuck. My fiddle:
http://jsfiddle.net/ApoG/50y32971/2/
var camera, scene, renderer;
var scene2, renderer2;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(200, 200, 200);
controls = new THREE.TrackballControls(camera);
scene = new THREE.Scene();
scene2 = new THREE.Scene();
var material = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
wireframeLinewidth: 1,
side: THREE.DoubleSide
});
//
//
for (var i = 0; i < 1; i++) {
var element = document.createElement('div');
element.style.width = '100px';
element.style.height = '100px';
element.style.opacity = 0.5;
element.style.background = new THREE.Color(Math.random() * 0xffffff).getStyle();
var object = new THREE.CSS3DObject(element);
object.position.x = Math.random() * 200 - 100;
object.position.y = Math.random() * 200 - 100;
object.position.z = Math.random() * 200 - 100;
object.rotation.x = Math.random();
object.rotation.y = Math.random();
object.rotation.z = Math.random();
object.scale.x = Math.random() + 0.5;
object.scale.y = Math.random() + 0.5;
scene2.add(object);
var geometry = new THREE.PlaneGeometry(100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(object.position);
mesh.rotation.copy(object.rotation);
mesh.scale.copy(object.scale);
scene.add(mesh);
}
//
var sides = [{
url: 'http://threejs.org/examples/textures/cube/skybox/px.jpg',
position: [-1024, 0, 0],
rotation: [0, Math.PI / 2, 0]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/nx.jpg',
position: [1024, 0, 0],
rotation: [0, -Math.PI / 2, 0]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/py.jpg',
position: [0, 1024, 0],
rotation: [Math.PI / 2, 0, Math.PI]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/ny.jpg',
position: [0, -1024, 0],
rotation: [-Math.PI / 2, 0, Math.PI]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/pz.jpg',
position: [0, 0, 1024],
rotation: [0, Math.PI, 0]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/nz.jpg',
position: [0, 0, -1024],
rotation: [0, 0, 0]
}];
for (var i = 0; i < sides.length - 1; i++) {
var side = sides[i];
var element = document.createElement('img');
element.width = 2050; // 2 pixels extra to close the gap.
element.src = side.url;
var object = new THREE.CSS3DObject(element);
object.position.fromArray(side.position);
object.rotation.fromArray(side.rotation);
scene2.add(object);
}
//
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xf0f0f0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer2 = new THREE.CSS3DRenderer();
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.top = 0;
document.body.appendChild(renderer2.domElement);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
renderer2.render(scene2, camera);
}
You are using CSS3DRenderer and WebGLRenderer in overlapping canvas elements.
You you need to make sure the WebGLRenderer's background is transparent. Follow this pattern:
renderer = new THREE.WebGLRenderer( { alpha: true } ); // required
renderer.setClearColor( 0x000000, 0 ); // the default
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer2 = new THREE.CSS3DRenderer();
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.top = 0;
document.body.appendChild( renderer2.domElement );
three.js r.120

THREE.js: calling lookAt method after rendering does not work

The script below isn't working properly. (It just needs jquery and three.js to run). The troublesome lines are these two:
// change the view so looking at the top of the airplane
views[1].camera.position.set( 0,5,0 );
views[1].camera.lookAt(objectManager.airplane.position);
Strangely, if those two lines are commented out, it can be seen that the two similar preceeding lines below do run as expected:
views[1].camera.lookAt(objectManager.airplane.position);
and
view.camera.position.set( 5,0,0 );
For some reason it seems that the call to camera.lookAt only works the first time. After that, the camera no longer follows the airplane object. I'd be extremely grateful if someone can figure out what I'm doing wrong!
The full script is below.
Thanks
$(function(){
var scene, renderer, viewPort, objectManager, views;
init();
animate();
function init() {
viewPort = $('body');
scene = new THREE.Scene();
// construct the two cameras
initialiseViews();
// construct airplane, lights and floor grid
objectManager = new ObjectManager();
objectManager.construct();
objectManager.addToScene(scene);
// make the second camera's position
// stay fixed relative to the airplane
objectManager.airplane.add(views[1].camera);
// make the second camera stay looking
// at the airplane
views[1].camera.lookAt(objectManager.airplane.position);
renderer = new THREE.WebGLRenderer();
renderer.setClearColorHex(0x000000, 1);
renderer.setSize( viewPort.innerWidth(), viewPort.innerHeight() );
viewPort.get(0).appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
objectManager.tick();
for (var i in views){
views[i].render(scene, renderer);
}
}
function initialiseViews(){
views = [];
// ----------------------------------------------------
// Create the first view, static with respect to ground
// ----------------------------------------------------
views[0] = new View(viewPort, objectManager, scene);
var view = views[0];
view.fov = 40;
view.proportions.height = 0.5;
view.proportions.bottom = 0.5;
view.init();
view.camera.position.y = 1;
view.camera.position.z = 4;
// ----------------------------------------------------
// Create the second view, which follows the airplane
// ----------------------------------------------------
views[1] = new View(viewPort, objectManager, scene);
var view = views[1];
view.fov = 20;
view.proportions.height = 0.5;
view.init();
// set the initial position of the camera
// with respect to the airplane. Views from behind
view.camera.position.set( 5,0,0 );
view.updateCamera = function(){
// change the view so looking at the top of the airplane
views[1].camera.position.set( 0,5,0 );
views[1].camera.lookAt(objectManager.airplane.position);
views[1].camera.updateProjectionMatrix();
};
}
});
function View(viewport, om, scene){
this.scene = scene;
this.camera;
this.objectManager = om;
this.viewPort = viewport;
this.fov = 30;
// default: full width and height
this.proportions = { left: 0, bottom: 0, height: 1, width: 1 };
this.pixels = { left: 0, bottom: 0, height: 0, width: 0, aspect: 0 };
this.aspect;
this.init = function(){
this.pixels.left = Math.floor(this.proportions.left * this.viewPort.innerWidth());
this.pixels.width = Math.floor(this.proportions.width * this.viewPort.innerWidth());
this.pixels.bottom = Math.floor(this.proportions.bottom * this.viewPort.innerHeight());
this.pixels.height = Math.floor(this.proportions.height * this.viewPort.innerHeight());
this.pixels.aspect = this.pixels.width / this.pixels.height;
this.makeCamera();
};
this.makeCamera = function(){
this.camera = new THREE.PerspectiveCamera(
this.fov,
this.pixels.aspect,
0.1, 10000
);
this.camera.updateProjectionMatrix();
this.scene.add(this.camera);
};
this.render = function(scene, renderer){
this.updateCamera();
pixels = this.pixels;
renderer.setViewport(pixels.left, pixels.bottom, pixels.width, pixels.height);
renderer.setScissor(pixels.left, pixels.bottom, pixels.width, pixels.height);
renderer.enableScissorTest(true);
renderer.render( scene, this.camera );
};
this.updateCamera = function(){};
}
function ObjectManager(){
// manages all visible 3d objects (including lights)
this.airplane;
var grid;
var ambientLight;
var pointLight;
this.construct = function(){
this.constructAirplane();
this.constructLights();
this.constructFloorGrid();
};
this.constructAirplane = function(){
this.airplane = new THREE.Object3D();
var fuselage = newCube(
{x: 1, y: 0.1, z: 0.1},
{x: 0, y: 0, z: 0},
[0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
[0, 1, 2, 3, 4, 5]
);
this.airplane.add(fuselage);
var tail = newCube(
{x: 0.15, y: 0.2, z: 0.03},
{x: 0.5, y: 0.199, z: 0},
[0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
[0, 1, 2, 3, 4, 5]
);
this.airplane.add(tail);
var wings = newCube(
{x: 0.3, y: 0.05, z: 1},
{x: -0.05, y: 0, z: 0},
[0xffff00, 0x808000, 0x0000ff, 0xff00000, 0xffffff, 0x808080],
[0, 1, 2, 3, 4, 5]
);
this.airplane.add(wings);
};
this.constructLights = function(){
ambientLight = new THREE.AmbientLight(0x808080);
pointLight = new THREE.PointLight(0x808080);
pointLight.position = {x: 100, y: 100, z: 100};
};
this.constructFloorGrid = function(){
grid = new THREE.Object3D();
var geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3( - 200, 0, 0 ) );
geometry.vertices.push(new THREE.Vector3( 200, 0, 0 ) );
linesMaterial = new THREE.LineBasicMaterial( { color: 0x00ff00, opacity: 1, linewidth: .1 } );
for ( var i = 0; i <= 200; i ++ ) {
var line = new THREE.Line( geometry, linesMaterial );
line.position.z = ( i * 2 ) - 200;
grid.add( line );
var line = new THREE.Line( geometry, linesMaterial );
line.position.x = ( i * 2 ) - 200;
line.rotation.y = 90 * Math.PI / 180;
grid.add( line );
}
};
this.addToScene = function(scene){
scene.add( this.airplane );
scene.add( grid );
scene.add( ambientLight );
scene.add( pointLight );
};
this.tick = function(){
this.airplane.rotation.x += 0.005;
this.airplane.rotation.y += 0.01;
this.airplane.position.x -= 0.05;
};
};
function newCube(dims, pos, cols, colAss){
var mesh;
var geometry;
var materials = [];
geometry = new THREE.CubeGeometry( dims.x, dims.y, dims.z );
for (var i in cols){
materials[i] = new THREE.MeshLambertMaterial( { color: cols[i], ambient: cols[i], overdraw: true } );
}
geometry.materials = materials;
for (var i in colAss){
geometry.faces[i].materialIndex = colAss[i];
}
mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
mesh.position = pos;
return mesh;
}
You need to do this:
views[1].camera.position.set( 0, 5, 0 );
views[1].camera.lookAt( new THREE.Vector3() );
and not this:
views[1].camera.position.set( 0, 5, 0 );
views[1].camera.lookAt( objectManager.airplane.position );
Your camera is a child of the airplane. It needs to lookAt ( 0, 0, 0 ) in it's local coordinate system -- not the airplane's position in world space.
Your calls to updateProjectionMatrix() are not necessary. Copy the three.js examples.

Categories

Resources