I have created a pie chart object using 3js ExtrudeGeometry. My requirement is to move out a slice from the piechart object as shown in the following image.
Here is the code I have tried.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
font-family: Monospace;
background-color: #f0f0f0;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="js/three.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/Detector.js" type="text/javascript"></script>
<script src="js/renderers/CanvasRenderer.js"></script>
<script src="js/renderers/Projector.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"> </script>
<script>
var container, scene, camera, renderer, controls;
var segments = [];
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(5, 10, -10);
scene.add(camera);
var dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(100, 100, 100);
camera.add(dirLight);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var i;
var startAngle=0;
var color="blue";
for(i=0;i<4;i++){
var smallSegment=createSegment(1, THREE.Math.degToRad(startAngle) ,THREE.Math.degToRad(startAngle+90), color);
if(color=="blue"){
color="red"
}else{
color="blue"
}
startAngle=startAngle+90;
scene.add(smallSegment);
segments.push(smallSegment);
}
//segments[0].position.x=segments[0].position.x+0.5;
//segments[1].position.x=segments[1].position.x+0.5;
//segments[2].position.x=segments[2].position.x+0.5;
segments[3].position.x=segments[3].position.x+0.5;
}
function createSegment(radius, angleStart, angleEnd, color) {
var extrOpt = {
curveSegments: 32,
steps: 1,
amount: 0.1,
bevelEnabled: false,
};
var Shape = new THREE.Shape();
Shape.moveTo(0, 0);
Shape.absarc(0, 0, radius, angleStart, angleEnd, false);
Shape.lineTo(0, 0);
var SegmentGeom = new THREE.ExtrudeGeometry( Shape, extrOpt );
SegmentGeom.rotateX(-Math.PI / 2);
var SegmentMat = new THREE.MeshLambertMaterial({
color: color
});
var Segment = new THREE.Mesh(SegmentGeom, SegmentMat);
return Segment;
}
function animate() {
var time = new Date() * 0.001;
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
</html>
I tried to change the x position of the slices which I need to move out. But that did not workout. When I change the x positions some slices have overlapped with each other.
Are there any solutions to make this work correctly?
To move the slice outward, you need to figure out the angle in radians of the direction that you want to move it..
var renderer = new THREE.WebGLRenderer();
var w = 300;
var h = 200;
renderer.setSize(w, h);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
45, // Field of view
w / h, // Aspect ratio
0.1, // Near
10000 // Far
);
camera.position.set(15, 10, 15);
camera.lookAt(scene.position);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var light = new THREE.PointLight(0xFFFF00);
light.position.set(20, 20, 20);
scene.add(light);
var light1 = new THREE.AmbientLight(0x808080);
light1.position.set(20, 20, 20);
scene.add(light1);
var i;
var startAngle = 0;
var rnd = (rng) => {
return Math.random() * rng
}
var color = "blue";
//Make a random pie chart...
for (startAngle = 0; startAngle < 360;) {
var ang = rnd(40) + 5;
if (ang + startAngle > 360) ang = 360 - startAngle;
var smallSegment = createSegment(1, THREE.Math.degToRad(startAngle), THREE.Math.degToRad(startAngle + ang), color);
if (color == "blue") {
color = "red"
} else {
color = "blue"
}
scene.add(smallSegment);
startAngle += ang;
}
console.log("start!")
var time = 0;
function createSegment(radius, angleStart, angleEnd, color) {
var extrOpt = {
curveSegments: 32,
steps: 1,
depth: 0.1,
bevelEnabled: false,
};
var Shape = new THREE.Shape();
Shape.moveTo(0, 0);
Shape.absarc(0, 0, radius, angleStart, angleEnd, false);
Shape.lineTo(0, 0);
var SegmentGeom = new THREE.ExtrudeGeometry(Shape, extrOpt);
SegmentGeom.rotateX(-Math.PI / 2);
var SegmentMat = new THREE.MeshLambertMaterial({
color: color
});
var Segment = new THREE.Mesh(SegmentGeom, SegmentMat);
Segment.userData.angleStart = angleStart;
Segment.userData.angleEnd = angleEnd;
Segment.onBeforeRender = function() {
//degrees is the angle of the direction you want to move the slice
//We do the average of startAngle+endAngle to get the center angle of the slice
var radians = (this.userData.angleEnd + this.userData.angleStart) * 0.5; //45;
var vx = Math.cos(radians);
var vz = -Math.sin(radians);
//This is just some values I fake up to make it animate
var tmp = this.userData.angleStart * 0.2;
var sinTime = Math.abs(Math.sin(tmp + (time * 0.001)));
//Move the actual piece
this.position.x = sinTime * vx;
this.position.z = sinTime * vz;
}
return Segment;
}
renderer.setClearColor(0xdddddd, 1);
(function animate(dt) {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
time = dt;
})();
<script src="https://threejs.org/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
Related
I have a piece of code from 3 years ago that appears to not be working anymore from Three.js.
I have updated all of the other issues of the migration to ES6 for Three.js, but when I try to add as I did in the past more than 1 place marker on the planet surface, only 1 place marker is displayed, with only the last added place marker being successfully displayed in the desired position... with all other place markers being erased.
Problem example -> https://jsfiddle.net/jhL6s579/6/
Complete code:
HTML
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://s3-eu-west-2.amazonaws.com/bckld/lab/loading.js"></script>
JS
// ------ Marker object ------------------------------------------------
function Marker() {
var radius = 0.005;
var sphereRadius = 0.02;
var height = 0.05;
var material = new THREE.MeshPhongMaterial({ color: 0xbab68f });
var cone = new THREE.Mesh(new THREE.ConeBufferGeometry(radius, height, 8, 1, true), material);
cone.position.y = height * 0.5;
cone.rotation.x = Math.PI;
var sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(sphereRadius, 16, 8), material);
sphere.position.y = height * 0.95 + sphereRadius;
this.add(cone, sphere);
}
Marker.prototype = Object.create(new THREE.Object3D());
// ------ Earth object -------------------------------------------------
function Earth(radius, texture) {
this.userData.radius = radius;
var earth = new THREE.Mesh(
new THREE.SphereBufferGeometry(radius, 64.0, 48.0),
new THREE.MeshPhongMaterial({
map: texture
})
);
this.add(earth);
}
Earth.prototype = Object.create(new THREE.Object3D());
Earth.prototype.createMarker = function (lat,lon ) {
var marker = new Marker();
var lonRad = -lon * (Math.PI / 180);
var latRad = lat * (Math.PI / 180);
var r = this.userData.radius;
marker.position.set(Math.cos(latRad) * Math.cos(lonRad) * r, Math.sin(latRad) * r, Math.cos(latRad) * Math.sin(lonRad) * r);
marker.rotation.set(0.0, -lonRad, latRad - Math.PI * 0.5);
this.attach(marker);
};
// ------ Three.js code ------------------------------------------------
var scene, camera, renderer;
var controls;
init();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, 4 / 3, 0.1, 100);
camera.position.set(0.0, 1.5, 3.0);
renderer = new THREE.WebGLRenderer({ antialias: true });
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.autoRotateSpeed = -1.0;
controls.enablePan = false;
var ambient = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambient);
var direcitonal = new THREE.DirectionalLight(0xffffff, 0.5);
direcitonal.position.set(5.0, 2.0, 5.0).normalize();
scene.add(direcitonal);
// just some code for the loading
var manager = createLoader(renderer.domElement, animate);
var texLoader = new THREE.TextureLoader(manager).setCrossOrigin(true);
var texture = texLoader.load('https://s3-eu-west-2.amazonaws.com/bckld/lab/textures/earth_latlon.jpg');
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
var earth = new Earth(1.0, texture);
earth.createMarker(48.856700, 2.350800); // Paris
earth.createMarker(28.524167, -80.650833); // Paris
scene.add(earth);
window.addEventListener('resize', onResize);
onResize();
document.body.appendChild(renderer.domElement);
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
CSS
body {
background: #000;
margin: 0;
overflow: hidden;
}
I have also tried doing this.attach(marker) but still not working...
You have to derive your custom classes Marker and Earth in ES6 now. Meaning you have to use the class syntax like below since Object3D is now a class, too.
// ------ Marker object ------------------------------------------------
class Marker extends THREE.Object3D {
constructor() {
super();
var radius = 0.005;
var sphereRadius = 0.02;
var height = 0.05;
var material = new THREE.MeshPhongMaterial({
color: 0xbab68f
});
var cone = new THREE.Mesh(new THREE.ConeBufferGeometry(radius, height, 8, 1, true), material);
cone.position.y = height * 0.5;
cone.rotation.x = Math.PI;
var sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(sphereRadius, 16, 8), material);
sphere.position.y = height * 0.95 + sphereRadius;
this.add(cone, sphere);
}
}
// ------ Earth object -------------------------------------------------
class Earth extends THREE.Object3D {
constructor(radius, texture) {
super();
this.userData.radius = radius;
var earth = new THREE.Mesh(
new THREE.SphereBufferGeometry(radius, 64.0, 48.0),
new THREE.MeshPhongMaterial({
map: texture
})
);
this.add(earth);
}
createMarker(lat, lon) {
var marker = new Marker();
var lonRad = -lon * (Math.PI / 180);
var latRad = lat * (Math.PI / 180);
var r = this.userData.radius;
marker.position.set(Math.cos(latRad) * Math.cos(lonRad) * r, Math.sin(latRad) * r, Math.cos(latRad) * Math.sin(lonRad) * r);
marker.rotation.set(0.0, -lonRad, latRad - Math.PI * 0.5);
this.attach(marker);
}
}
// ------ Three.js code ------------------------------------------------
var scene, camera, renderer;
var controls;
init();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, 4 / 3, 0.1, 100);
camera.position.set(0.0, 1.5, 3.0);
renderer = new THREE.WebGLRenderer({
antialias: true
});
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.autoRotateSpeed = -1.0;
controls.enablePan = false;
var ambient = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambient);
var direcitonal = new THREE.DirectionalLight(0xffffff, 0.5);
direcitonal.position.set(5.0, 2.0, 5.0).normalize();
scene.add(direcitonal);
// just some code for the loading
var manager = createLoader(renderer.domElement, animate);
var texLoader = new THREE.TextureLoader(manager).setCrossOrigin(true);
var texture = texLoader.load('https://s3-eu-west-2.amazonaws.com/bckld/lab/textures/earth_latlon.jpg');
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
var earth = new Earth(1.0, texture);
earth.createMarker(48.856700, 2.350800); // Paris
earth.createMarker(28.524167, -80.650833); // Paris
scene.add(earth);
window.addEventListener('resize', onResize);
onResize();
document.body.appendChild(renderer.domElement);
}
function onResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.137.5/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.137.5/examples/js/controls/OrbitControls.js"></script>
<script src="https://s3-eu-west-2.amazonaws.com/bckld/lab/loading.js"></script>
How can I preserve constant size of meshes regardless of perspective using Three.js?
Lets assume I have multiple meshes of the same size. I want them to always have the same on screen size. I also have to use perspective camera.
I have found some related answers, but seems that I miss something:
First approach is to use Euclidean distance to objects from
camera and scale them respectively every animation frame.
Three JS Keep Label Size On Zoom
I have tried to modify jsfiddle given in the answer to apply scale to meshes instead of sprites, but that doesn't work for me. The result looks as follows https://jsfiddle.net/a2ogz9vx/258/
var camera, scene, renderer, controls;
var planets = [];
var timestamp = 0;
var scaleVector = new THREE.Vector3();
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 100, 100);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var createPlanet = function(name, radius, orbit, speed) {
var geom = new THREE.SphereGeometry(radius, 32, 16);
var mat = new THREE.MeshBasicMaterial({
color: Math.random() * 0xFFFFFF,
});
var planet = new THREE.Mesh(geom, mat);
planet.userData.orbit = orbit;
planet.userData.speed = speed;
var canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
var tex = new THREE.Texture(canvas);
tex.needsUpdate = true;
var spriteMat = new THREE.SpriteMaterial({
map: tex
});
var sprite = new THREE.Sprite(spriteMat);
planet.add(sprite);
planets.push(planet);
scene.add(planet);
};
createPlanet("One", 11, -10, 5);
createPlanet("Two", 11, 5, 5);
createPlanet("Three", 11, 10, 5);
}
function animate() {
requestAnimationFrame(animate);
planets.forEach(function(planet) {
var scaleFactor = 100;
var scale = scaleVector.subVectors(planet.position, camera.position).length() / scaleFactor;
planet.scale.set(scale, scale, scale);
var orbit = planet.userData.orbit;
var speed = planet.userData.speed;
planet.position.x = speed * orbit;
planet.position.z = speed * orbit;
});
render();
}
function render() {
renderer.render(scene, camera);
}
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
Second approach is to use on screen width calculation. https://stackoverflow.com/a/13351534/8465699
Result also doesn't look right https://jsfiddle.net/a2ogz9vx/260/
var camera, scene, renderer, controls;
var planets = [];
var timestamp = 0;
var scaleVector = new THREE.Vector3();
init();
animate();
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(90, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(0, 100, 100);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
controls = new THREE.OrbitControls(camera, renderer.domElement);
var createPlanet = function(name, radius, orbit, speed) {
var geom = new THREE.SphereGeometry(radius, 32, 16);
var mat = new THREE.MeshBasicMaterial({
color: Math.random() * 0xFFFFFF,
});
var planet = new THREE.Mesh(geom, mat);
planet.userData.orbit = orbit;
planet.userData.speed = speed;
var canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
var tex = new THREE.Texture(canvas);
tex.needsUpdate = true;
var spriteMat = new THREE.SpriteMaterial({
map: tex
});
var sprite = new THREE.Sprite(spriteMat);
planet.add(sprite);
planets.push(planet);
scene.add(planet);
};
createPlanet("One", 11, -10, 5);
createPlanet("Two", 11, 0, 5);
createPlanet("Three", 11, 10, 5);
}
function animate() {
requestAnimationFrame(animate);
planets.forEach(function(planet) {
const dist = planet.position.distanceTo(camera.position);
const vFOV = THREE.Math.degToRad(camera.fov);
const size = 2 * Math.tan(vFOV / 2) * dist;
const scaleFactor = 130;
const scale = size / scaleFactor;
planet.scale.set(scale, scale, scale);
var orbit = planet.userData.orbit;
var speed = planet.userData.speed;
planet.position.x = speed * orbit;
planet.position.z = speed * orbit;
});
render();
}
function render() {
renderer.render(scene, camera);
}
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
Any suggestions how to fix the code or other approaches are welcome!
I'm new at three.js.
In my work, I have to made 3d graphical website.
So after searched in google, I found that three.js is suitable to manipulate WebGL conveniently.
In three.js document(https://threejs.org/docs/#api/en/geometries/TextGeometry),
TextGeometry is API for draw text in the scene.
[src.js]
init = () => {
window.addEventListener('resize', resizeWindow);
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
var controls = new THREE.OrbitControls( camera );
controls.update();
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xdd3b56);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set shadow
renderer.shadowMap.enabled = true;
// Show Axis
var axes = new THREE.AxisHelper(5);
scene.add(axes);
// Text
var loader = new THREE.FontLoader();
loader.load( './helvetiker_regular.typeface.json', function ( font ) {
var geometry = new THREE.TextGeometry( 'Hello three.js!', {
font: font,
size: 80,
height: 5,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
bevelSegments: 5
} );
} );
var textMaterial = new THREE.MeshPhongMaterial({color: 0xFE98A0});
var text = new THREE.Mesh(geometry, textMaterial);
text.position.x = 0;
text.position.y = 10;
text.position.z = 10;
scene.add(text);
// Light
var spotLight = new THREE.SpotLight(0xFFFFFF);
spotLight.position.set(-40, 60, 30);
spotLight.castShadow = true;
spotLight.shadow.mapSize.width = 5120;
spotLight.shadow.mapSize.height = 5120;
scene.add(spotLight);
// Camera Setting
camera.position.x = 0;
camera.position.y = 30;
camera.position.z = 30;
camera.lookAt(scene.position);
document.getElementById("threejs_scene").appendChild(renderer.domElement);
renderScene();
function renderScene() {
requestAnimationFrame(renderScene);
controls.update();
renderer.render(scene, camera);
}
}
window.onload = init();
[index.html]
<html>
<head>
<script src="three.js"></script>
<script src="OrbitControls.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div id="threejs_scene"></div>
<script src="src.js"></script>
</body>
</html>
When I execute my code, it throws [.WebGL-0x7fb612852000]RENDER WARNING: Render count or primcount is 0. and WebGL: too many errors, no more errors will be reported to the console for this context. errors.
So I searched it at google, it occured when Three.js is trying to render an object that does not exist yet.
But in my code, I already defined it.
var textMaterial = new THREE.MeshPhongMaterial({color: 0xFE98A0});
var text = new THREE.Mesh(geometry, textMaterial);
text.position.x = 0;
text.position.y = 10;
text.position.z = 10;
How can I solve this issue?
My last goal is display text in the scene.
Thanks.
window.onload = function(params) {
/*
*
* SET UP THE WORLD
*
*/
//set up the ratio
var gWidth = window.innerWidth;
var gHeight = window.innerHeight;
var ratio = gWidth / gHeight;
var borders = [40, 24] //indicate where the ball needs to move in mirror position
var light = new THREE.AmbientLight(0xffffff, 0.5);
var light1 = new THREE.PointLight(0xffffff, 0.5);
light1.position.set(0, 5, 0);
light1.castShadow = true;
// set the renderer
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera();
camera.position.set(10, 10, 10);
camera.lookAt(new THREE.Vector3(0, 0, 0));
//properties for casting shadow
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(gWidth, gHeight);
document.body.appendChild(renderer.domElement);
var scene = new THREE.Scene();
scene.add(light);
scene.add(light1);
var ground = new THREE.Mesh(new THREE.BoxGeometry(10, 0.5, 10), new THREE.MeshLambertMaterial())
ground.receiveShadow = true;
scene.add(ground)
var geometry;
var loader = new THREE.FontLoader();
var mesh;
requestAnimationFrame(render);
function render() {
if (mesh) {
mesh.rotation.y += 0.01;
mesh.rotation.z += 0.007;
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
loader.load('https://cdn.rawgit.com/mrdoob/three.js/master/examples/fonts/helvetiker_regular.typeface.json', function(font) {
var geometry = new THREE.TextGeometry('Hello three.js!', {
font: font,
size: 80,
height: 5,
curveSegments: 12,
bevelEnabled: true,
bevelThickness: 10,
bevelSize: 8,
bevelSegments: 5
});
var material = new THREE.MeshLambertMaterial({
color: 0xF3FFE2
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, 2, 0);
mesh.scale.multiplyScalar(0.01)
mesh.castShadow = true;
scene.add(mesh);
var canv = document.createElement('canvas')
canv.width = canv.height = 256;
var ctx = canv.getContext('2d')
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canv.width, canv.height);
ctx.fillStyle = 'black'
ctx.fillText("HERE IS SOME 2D TEXT", 20, 20);
var tex = new THREE.Texture(canv);
tex.needsUpdate = true;
var mat = new THREE.MeshBasicMaterial({
map: tex
});
var plane = new THREE.Mesh(new THREE.PlaneGeometry(10, 10), mat);
scene.add(plane)
});
}
body {
padding: 0;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<html>
<head>
</head>
<body>
</body>
</html>
Here is my code which has embedded html page in three.js . I want to click the html page and make a popup. So is there any way i can do that because i think ray casting can only be done to three.js elements and not the html one.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ADN CSS3D Demo</title>
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/master/examples/js/controls/TrackballControls.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/master/examples/js/renderers/CSS3DRenderer.js"></script>
<script>
var controls, camera, glScene, cssScene, glRenderer, cssRenderer;
///////////////////////////////////////////////////////////////////
// Creates WebGL Renderer
//
///////////////////////////////////////////////////////////////////
function createGlRenderer() {
var glRenderer = new THREE.WebGLRenderer({alpha:true});
glRenderer.setClearColor(0xECF8FF);
glRenderer.setPixelRatio(window.devicePixelRatio);
glRenderer.setSize(window.innerWidth, window.innerHeight);
glRenderer.domElement.style.position = 'absolute';
glRenderer.domElement.style.zIndex = 1;
glRenderer.domElement.style.top = 0;
return glRenderer;
}
///////////////////////////////////////////////////////////////////
// Creates CSS Renderer
//
///////////////////////////////////////////////////////////////////
function createCssRenderer() {
var cssRenderer = new THREE.CSS3DRenderer();
cssRenderer.setSize(window.innerWidth, window.innerHeight);
cssRenderer.domElement.style.position = 'absolute';
glRenderer.domElement.style.zIndex = 0;
cssRenderer.domElement.style.top = 0;
return cssRenderer;
}
///////////////////////////////////////////////////////////////////
// Creates plane mesh
//
///////////////////////////////////////////////////////////////////
function createPlane(w, h, position, rotation) {
var material = new THREE.MeshBasicMaterial({
color: 0x000000,
opacity: 0.0,
side: THREE.DoubleSide
});
var geometry = new THREE.PlaneGeometry(w, h);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.x = position.x;
mesh.position.y = position.y;
mesh.position.z = position.z;
mesh.rotation.x = rotation.x;
mesh.rotation.y = rotation.y;
mesh.rotation.z = rotation.z;
return mesh;
}
///////////////////////////////////////////////////////////////////
// Creates CSS object
//
///////////////////////////////////////////////////////////////////
function createCssObject(w, h, position, rotation, url) {
var html = [
'<div style="width:' + w + 'px; height:' + h + 'px;">',
'<iframe src="' + url + '" width="' + w + '" height="' + h + '">',
'</iframe>',
'</div>'
].join('\n');
var div = document.createElement('div');
$(div).html(html);
var cssObject = new THREE.CSS3DObject(div);
cssObject.position.x = position.x;
cssObject.position.y = position.y;
cssObject.position.z = position.z;
cssObject.rotation.x = rotation.x;
cssObject.rotation.y = rotation.y;
cssObject.rotation.z = rotation.z;
return cssObject;
}
///////////////////////////////////////////////////////////////////
// Creates 3d webpage object
//
///////////////////////////////////////////////////////////////////
function create3dPage(w, h, position, rotation, url) {
var plane = createPlane(
w, h,
position,
rotation);
glScene.add(plane);
var cssObject = createCssObject(
w, h,
position,
rotation,
url);
cssScene.add(cssObject);
}
///////////////////////////////////////////////////////////////////
// Creates material with random color
//
///////////////////////////////////////////////////////////////////
function createColoredMaterial() {
var material = new THREE.MeshBasicMaterial({
color: Math.floor(Math.random() * 16777215),
shading: THREE.FlatShading,
side: THREE.DoubleSide
});
return material;
}
///////////////////////////////////////////////////////////////////
// Creates 3D geometry to place in the scene
//
///////////////////////////////////////////////////////////////////
function create3dGeometry() {
var mesh1 = new THREE.Mesh(
new THREE.CylinderGeometry(0, 200, 300, 20, 4),
createColoredMaterial());
mesh1.position.x = 0;
mesh1.position.y = -300;
mesh1.position.z = 400;
glScene.add(mesh1);
var mesh2 = new THREE.Mesh(
new THREE.BoxGeometry(200, 200, 200),
createColoredMaterial());
mesh2.position.x = -300;
mesh2.position.y = -300;
mesh2.position.z = 400;
glScene.add(mesh2);
var mesh3 = new THREE.Mesh(
new THREE.SphereGeometry(100, 128, 128),
createColoredMaterial());
mesh3.position.x = 500;
mesh3.position.y = -300;
mesh3.position.z = 400;
glScene.add(mesh3);
}
///////////////////////////////////////////////////////////////////
// Initializes scene
//
///////////////////////////////////////////////////////////////////
function initialize() {
camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
10000);
camera.position.set(0, 100, 3000);
controls = new THREE.TrackballControls(camera);
glRenderer = createGlRenderer();
cssRenderer = createCssRenderer();
//document.body.appendChild(glRenderer.domElement);
document.body.appendChild(cssRenderer.domElement);
cssRenderer.domElement.appendChild(glRenderer.domElement);
glScene = new THREE.Scene();
cssScene = new THREE.Scene();
var ambientLight = new THREE.AmbientLight(0x555555);
glScene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xffffff);
directionalLight.position.set( -.5, .5, -1.5 ).normalize();
glScene.add(directionalLight);
create3dPage(
1000, 1000,
new THREE.Vector3(-1050, 0, 400),
new THREE.Vector3(0, 45 * Math.PI / 180, 0),
'http://viewer.autodesk.io/node/ng-gallery/#/home');
create3dPage(
900, 1000,
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 0, 0),
'http://adndevblog.typepad.com/cloud_and_mobile');
create3dPage(
1000, 1000,
new THREE.Vector3(1050, 0, 400),
new THREE.Vector3(0, -45 * Math.PI / 180, 0),
'http://mongo.autodesk.io');
create3dGeometry();
update();
}
///////////////////////////////////////////////////////////////////
// Updates scene
//
///////////////////////////////////////////////////////////////////
function update() {
controls.update();
glRenderer.render(glScene, camera);
cssRenderer.render(cssScene, camera);
requestAnimationFrame(update);
}
///////////////////////////////////////////////////////////////////
// On document ready
//
///////////////////////////////////////////////////////////////////
$(document ).ready(function() {
initialize();
});
</script>
</body>
</html>
I have tried raycasting using the description given on three.js site but the browser is not showing an results. Can somebody help me with my code
I'm trying to add a lamp to my scene with an OBJLoader object. The object is exported from Blender. If I set its children[i].castShadow property to true the following errors show up but still it appears and its shadow can be seen on the wall:
What am I doing wrong? If and when I add some other object to my scene and set its castShadow property to true I get no error messages whatsoever. This is the only problematic object I have currently.
One more thing. My project won't work in Firefox, but it displays in Edge or Chrome for example. What is so special about Firefox?
<!DOCTYPE html>
<html>
<head>
<title>Jaj de jó</title>
<script type="text/javascript" src="libs/three.js"></script>
<script type="text/javascript" src="libs/OBJLoader.js"></script>
<script type="text/javascript" src="libs/MTLLoader.js"></script>
<script type="text/javascript" src="libs/OBJMTLLoader.js"></script>
<script type="text/javascript" src="libs/OrbitControls.js"></script>
<script type="text/javascript" src="libs/ThreeBSP.js"></script>
<script type="text/javascript" src="libs/stats.js"></script>
<script type="text/javascript" src="libs/dat.gui.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
<meta charset="UTF-8">
</head>
<body>
<div id="WebGL-output"></div>
<script type="text/javascript">
var webGLRenderer;
function init() {
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
webGLRenderer = new THREE.WebGLRenderer();
webGLRenderer.setClearColor(new THREE.Color(0x666666, 1.0));
webGLRenderer.setSize(window.innerWidth, window.innerHeight);
webGLRenderer.shadowMapEnabled = true;
webGLRenderer.shadowMapType = THREE.PCFShadowMap;
camera.position.x = -30;
camera.position.y = 40;
camera.position.z = 50;
camera.lookAt(new THREE.Vector3(0, 0, 0));
var orbitControls = new THREE.OrbitControls(camera);
orbitControls.autoRotate = false;
var clock = new THREE.Clock();
document.getElementById("WebGL-output").appendChild(webGLRenderer.domElement);
/* prepare, load textures and add geometries to the scene */
var planeGeometry = new THREE.PlaneBufferGeometry(200, 200, 1, 1);
var texture = THREE.ImageUtils.loadTexture("textures/floor_wood.jpg");
var planeMaterial = new THREE.MeshPhongMaterial();
planeMaterial.map = texture;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.x = 200 / 100;
texture.repeat.y = 200 / 100;
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.receiveShadow = true;
plane.rotation.x = -0.5 * Math.PI;
plane.position.x = 0;
plane.position.y = 0;
plane.position.z = -20;
scene.add(plane);
/* FLOOR ADDED */
/* WALLS START */
var wallGeometry = new THREE.BoxGeometry(150, 100, 175);
texture = THREE.ImageUtils.loadTexture("textures/brick-wall.jpg");
var material = new THREE.MeshPhongMaterial();
material.map = texture;
var wall = new THREE.Mesh(wallGeometry, material);
wall.receiveShadow = true;
wall.material.side = THREE.BackSide;
wall.material.map.repeat.set(200 / 100, 175 / 100);
wall.material.map.wrapS = THREE.RepeatWrapping;
wall.material.map.wrapT = THREE.RepeatWrapping;
wall.material.needsUpdate = true;
wall.position.y = 25;
wall.position.z -= 25;
scene.add(wall);
/* WALLS END */
/* LAMP */
var loader = new THREE.OBJLoader();
loader.load("models/lamp.obj", function (object) {
console.log("LAMP");
console.log(object);
var blackMaterial = new THREE.MeshPhongMaterial({ color: 0x222222 });
for(var i = 0; i < object.children.length; i++) {
object.children[i].material = blackMaterial;
object.children[i].castShadow = true;
}
object.scale.set(5, 5, 5);
object.position.x = -14.5;
object.position.y = 40;
object.position.z = -17;
scene.add(object);
});
/* LAMP END */
// add spotlight for the shadows
var spotLight = new THREE.SpotLight(0xffffff, 1);
spotLight.position.set(75, 75, 15);
spotLight.castShadow = true;
spotLight.shadowCameraNear = 20;
spotLight.shadowDarkness = .6;
spotLight.shadowMapWidth = 512;
spotLight.shadowMapHeight = 512;
spotLight.shadowCameraFov = 64;
scene.add(spotLight);
render();
function render() {
var delta = clock.getDelta();
orbitControls.update(delta);
requestAnimationFrame(render);
webGLRenderer.render(scene, camera);
}
}
window.onload = init;
</script>
</body>
</html>