Threejs How to set camera for large scale objects - javascript

I am rendering a cityscape using Three.js. When attempting to view the scene I can't seem to get the camera near/far settings correct to render the whole scene. When I increase the camera's far plane - I am able to see the model, but it appears blue (image below) until I zoom into it. Is there a way to see the entire model without having to zoom super close to the scene?
var scene = new THREE.Scene()
scene.background = new THREE.Color(33,33,33);
var ambient = new THREE.AmbientLight(0xe8ecff, 1.4)
ambient.name = 'ambientLight'
scene.add(ambient)
var directionalLight1 = new THREE.DirectionalLight(0xfff1f1, 0.7)
directionalLight1.name = 'directionalLight1'
directionalLight1.position.set(-1500, 900, 1500)
directionalLight1.castShadow = true
scene.add(directionalLight1)
directionalLight1.shadow.camera.right = 2500
directionalLight1.shadow.camera.left = -2500
directionalLight1.shadow.camera.top = 2500
directionalLight1.shadow.camera.bottom = -2500
directionalLight1.shadow.camera.near = 0
directionalLight1.shadow.camera.far = 5000
var shadowCameraHelper = new THREE.CameraHelper(directionalLight1.shadow.camera)
shadowCameraHelper.visible = false
shadowCameraHelper.name = 'directionalLight1Helper'
scene.add(shadowCameraHelper)
var directionalLight2 = new THREE.DirectionalLight(0x87c0ff, 0.2)
directionalLight2.name = 'directionalLight2'
directionalLight2.position.set(1, 1, -1)
scene.add(directionalLight2)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 10000);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var canvas = document.getElementById("canvas");
canvas.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set(-400, 700, 500)
function animate (){
requestAnimationFrame( animate );
controls.update();
stats.update()
renderer.render( scene, camera );
}
animate();
var loader = new THREE.ObjectLoader
loader.load("example_mesh.json",
function(obj){
var bb = new THREE.Box3()
bb.expandByObject(obj)
var center = new THREE.Vector3()
bb.getCenter(center)
let modelSettings = { x: -center.x, y: center.y, z: -center.z }
let cameraRadius = this.boundingBox.geometry.boundingSphere.radius/2 * (1 + Math.sqrt(5))
obj.position.set(modelSettings.x, modelSettings.y, modelSettings.z)
camera.position.set(cameraRadius, cameraRadius, cameraRadius);
controls.target.set(0,modelSettings.y, 0)
controls.update()
scene.add(obj)
}, onProgress, onError)

When an object is being clipped out of the camera's focal length, you can use Object3D.scale. AFter adjusting this scaler value the entire building is visible in the camera on load and does not get clipped. You adjust the objects scale during the loading callback.
var scene = new THREE.Scene()
scene.background = new THREE.Color(33,33,33);
var ambient = new THREE.AmbientLight(0xe8ecff, 1.4)
ambient.name = 'ambientLight'
scene.add(ambient)
var directionalLight1 = new THREE.DirectionalLight(0xfff1f1, 0.7)
directionalLight1.name = 'directionalLight1'
directionalLight1.position.set(-1500, 900, 1500)
directionalLight1.castShadow = true
scene.add(directionalLight1)
directionalLight1.shadow.camera.right = 2500
directionalLight1.shadow.camera.left = -2500
directionalLight1.shadow.camera.top = 2500
directionalLight1.shadow.camera.bottom = -2500
directionalLight1.shadow.camera.near = 0
directionalLight1.shadow.camera.far = 5000
var shadowCameraHelper = new THREE.CameraHelper(directionalLight1.shadow.camera)
shadowCameraHelper.visible = false
shadowCameraHelper.name = 'directionalLight1Helper'
scene.add(shadowCameraHelper)
var directionalLight2 = new THREE.DirectionalLight(0x87c0ff, 0.2)
directionalLight2.name = 'directionalLight2'
directionalLight2.position.set(1, 1, -1)
scene.add(directionalLight2)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 10000);
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
var canvas = document.getElementById("canvas");
canvas.appendChild( renderer.domElement );
var controls = new THREE.OrbitControls( camera, renderer.domElement );
camera.position.set(-400, 700, 500)
function animate (){
requestAnimationFrame( animate );
controls.update();
stats.update()
renderer.render( scene, camera );
}
animate();
var loader = new THREE.ObjectLoader
loader.load("example_mesh.json",
function(obj){
// adjust the scale of the object in the scene.
// default scale is (1,1,1)
obj.scale.set( .1, .1, .1 );
var bb = new THREE.Box3()
bb.expandByObject(obj)
var center = new THREE.Vector3()
bb.getCenter(center)
let modelSettings = { x: -center.x, y: center.y, z: -center.z }
let cameraRadius = this.boundingBox.geometry.boundingSphere.radius/2 * (1 + Math.sqrt(5))
obj.position.set(modelSettings.x, modelSettings.y, modelSettings.z)
camera.position.set(cameraRadius, cameraRadius, cameraRadius);
controls.target.set(0,modelSettings.y, 0)
controls.update()
scene.add(obj)
}, onProgress, onError)

Related

I have having issues implementing procedural terrain generation on my three js project

Hello friends https://github.com/IceCreamYou/THREE.Terrain This is a great Library for procedural I want to add the procedural terrain generation in my code
Code goes here
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,0.01, 100000);
camera.position.set(50, 10, 50)
camera.position.z = 10
const renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.setClearColor(0xcccccc, 1.0);
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new THREE.OrbitControls( camera,renderer.domElement );
controls.screenSpacePanning = true;
const sceneMeshes = [];
const axesHelper = new THREE.AxesHelper( 1000 );
scene.add( axesHelper );
axesHelper.position.y = 0
const shadowLight = new THREE.DirectionalLight(0xffffff, 0.6);
// Set the direction of the light
shadowLight.position.set(150, 350, 350);
// Allow shadow casting
shadowLight.castShadow = true
// define the visible area of the projected shadow
shadowLight.shadow.camera.left = -400;
shadowLight.shadow.camera.right = 400;
shadowLight.shadow.camera.top = 400;
shadowLight.shadow.camera.bottom = -400;
shadowLight.shadow.camera.near = 1;
shadowLight.shadow.camera.far = 10000;
// define the resolution of the shadow; the higher the better,
// but also the more expensive and less performant
shadowLight.shadow.mapSize.width = 2048;
shadowLight.shadow.mapSize.height = 2048;
// to activate the lights, just add them to the scene
scene.add(shadowLight);
const animate = function (){
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
Normal Scene
please help me for my project
Here is a live example based on your code using the default approach of THREE.Terrain for generating a terrain mesh:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 100000);
camera.position.set(0, 250, 1000)
const renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;
renderer.setClearColor(0xcccccc, 1.0);
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.screenSpacePanning = true;
const sceneMeshes = [];
const axesHelper = new THREE.AxesHelper(1000);
scene.add(axesHelper);
axesHelper.position.y = 0
const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
scene.add(hemiLight);
const shadowLight = new THREE.DirectionalLight(0xffffff, 0.8);
// Set the direction of the light
shadowLight.position.set(0, 1000, 0);
// Allow shadow casting
shadowLight.castShadow = true
// define the visible area of the projected shadow
shadowLight.shadow.camera.left = -400;
shadowLight.shadow.camera.right = 400;
shadowLight.shadow.camera.top = 400;
shadowLight.shadow.camera.bottom = -400;
shadowLight.shadow.camera.near = 1;
shadowLight.shadow.camera.far = 10000;
// define the resolution of the shadow; the higher the better,
// but also the more expensive and less performant
shadowLight.shadow.mapSize.width = 2048;
shadowLight.shadow.mapSize.height = 2048;
// to activate the lights, just add them to the scene
scene.add(shadowLight);
//
// Generate a terrain
var xS = 63,
yS = 63;
terrainScene = THREE.Terrain({
easing: THREE.Terrain.Linear,
frequency: 2.5,
heightmap: THREE.Terrain.DiamondSquare,
material: new THREE.MeshLambertMaterial({
color: 0x654321
}),
maxHeight: 100,
minHeight: -100,
steps: 1,
xSegments: xS,
xSize: 1024,
ySegments: yS,
ySize: 1024,
});
// Assuming you already have your global scene, add the terrain to it
scene.add(terrainScene);
const animate = function() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
animate();
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.131.3/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.131.3/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three.terrain.js#2.0.0/build/THREE.Terrain.min.js"></script>

How to add env map onto gltf object

Im having quite a bit of trouble adding an environment map to a loaded GLTF / GLB file, as of now I get some sort of reflection instead of a black dot with a light point on it,
I was reading a bit of the document for three js and think I can pull it off with the standardmeshmaterial and applying it somehow to the object(gltf) and adding the mesh into the scene. I tried a similar mockup but the item disappears. I dont know how to go about it, help guys.
This is the environment map im trying to apply to it, (or something similar)
https://hdrihaven.com/files/hdri_images/tonemapped/8192/venice_sunset.jpg
here is the codepen I am working on
https://codepen.io/8AD/pen/XWpxmpO
HTML
<script src="https://unpkg.com/three#0.87.1/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/build/three.min.js"></script>
<!-- OrbitControls.js -->
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/examples/js/controls/OrbitControls.js"></script>
<!-- DRACOLoader.js -->
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/examples/js/loaders/DRACOLoader.js"></script>
<!-- GLTFLoader.js -->
<script src="https://rawcdn.githack.com/mrdoob/three.js/d9f87fb1a2c5db1ea0e2feda9bd42b39b5bedc41/examples/js/loaders/GLTFLoader.js"></script>
<div id="3dmain">
</div>
JS
var gltf = null;
var mixer = null;
var clock = new THREE.Clock();
var controls;
var camera;
init();
animate();
var renderCalls = [];
function render () {
requestAnimationFrame( render );
renderCalls.forEach((callback)=>{ callback(); });
}
render();
function init() {
width = window.innerWidth;
height = window.innerHeight;
scene = new THREE.Scene();
var light = new THREE.PointLight( 0xffffcc, 20, 200 );
light.position.set( 4, 30, 80 );
scene.add( light );
var light2 = new THREE.AmbientLight( 0x20202A, 20, 100 );
light2.position.set( 30, -10, 30 );
scene.add( light2 );
camera = new THREE.PerspectiveCamera( 60, width / height, 0.01, 10000 );
camera.position.set(0, 3, 10);
window.addEventListener( 'resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
var geometry = new THREE.BoxGeometry(100, 5, 100);
var material = new THREE.MeshLambertMaterial({
color: "#707070"
});
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
console.log( item, loaded, total );
};
var loader = new THREE.GLTFLoader();
loader.setCrossOrigin( 'anonymous' );
var scale = 0.01;
var url = "https://8ad.studio/wp-content/uploads/3D%20Assets/blimp.glb";
loader.load(url, function (data) {
gltf = data;
var object = gltf.scene;
object.scale.set(scale, scale, scale);
//object.position.y = -5;
//object.position.x = 4;
object.castShadow = true;
object.receiveShadow = true;
var animations = gltf.animations;
if ( animations && animations.length ) {
mixer = new THREE.AnimationMixer( object );
for ( var i = 0; i < animations.length; i ++ ) {
var animation = animations[ i ];
mixer.clipAction( animation ).play();
}
}
scene.add(object);
});
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true } );
renderer.setClearColor( 0x000000, 0 );
renderer.shadowMap.enabled = true;
controls = new THREE.OrbitControls( camera,);
controls.rotateSpeed = 0.3;
controls.zoomSpeed = 0.9;
controls.minDistance = 14;
controls.maxDistance = 14;
controls.minPolarAngle = 0; // radians
controls.maxPolarAngle = Math.PI /2; // radians
controls.enableDamping = true;
controls.dampingFactor = 0.05;
var renderCalls = [];
renderCalls.push(function(){
controls.update()
});
renderer.setSize( width, height );
renderer.gammaOutput = true;
document.getElementById('3dmain').appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
if (mixer) mixer.update(clock.getDelta());
controls.update();
render();
}
function render() {
renderer.render( scene, camera );
}
You have to include RGBELoader into your app for importing HDR textures and make use of PMREMGenerator in order to pre-process the environment map for the usage with a PBR material.
var gltf = null;
var mixer = null;
var clock = new THREE.Clock();
var controls;
var camera;
var renderer;
init();
animate();
var renderCalls = [];
function render() {
requestAnimationFrame(render);
renderCalls.forEach((callback) => {
callback();
});
}
render();
function init() {
width = window.innerWidth;
height = window.innerHeight;
scene = new THREE.Scene();
var light = new THREE.PointLight(0xffffcc, 20, 200);
light.position.set(4, 30, 80);
scene.add(light);
var light2 = new THREE.AmbientLight(0x20202A, 20, 100);
light2.position.set(30, -10, 30);
scene.add(light2);
camera = new THREE.PerspectiveCamera(60, width / height, 0.01, 10000);
camera.position.set(0, 3, 10);
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1;
renderer.setClearColor(0x000000, 0);
renderer.shadowMap.enabled = true;
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, false);
var geometry = new THREE.BoxGeometry(100, 5, 100);
var material = new THREE.MeshLambertMaterial({
color: "#707070"
});
var manager = new THREE.LoadingManager();
manager.onProgress = function(item, loaded, total) {
console.log(item, loaded, total);
};
var scale = 0.01;
var url = "https://8ad.studio/wp-content/uploads/3D%20Assets/blimp.glb";
var loader = new THREE.GLTFLoader();
loader.setCrossOrigin('anonymous');
const pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
const rgbeLoader = new THREE.RGBELoader();
rgbeLoader.load('https://threejs.org/examples/textures/equirectangular/venice_sunset_1k.hdr', function(texture) {
const envMap = pmremGenerator.fromEquirectangular(texture).texture;
scene.background = envMap;
scene.environment = envMap;
texture.dispose();
pmremGenerator.dispose();
loader.load(url, function(data) {
gltf = data;
var object = gltf.scene;
object.scale.set(scale, scale, scale);
//object.position.y = -5;
//object.position.x = 4;
object.castShadow = true;
object.receiveShadow = true;
var animations = gltf.animations;
if (animations && animations.length) {
mixer = new THREE.AnimationMixer(object);
for (var i = 0; i < animations.length; i++) {
var animation = animations[i];
mixer.clipAction(animation).play();
}
}
scene.add(object);
});
});
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.rotateSpeed = 0.3;
controls.zoomSpeed = 0.9;
controls.minDistance = 14;
controls.maxDistance = 14;
controls.minPolarAngle = 0; // radians
controls.maxPolarAngle = Math.PI / 2; // radians
controls.enableDamping = true;
controls.dampingFactor = 0.05;
var renderCalls = [];
renderCalls.push(function() {
controls.update()
});
renderer.setSize(width, height);
document.getElementById('3dmain').appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
if (mixer) mixer.update(clock.getDelta());
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.127/build/three.js"></script>
<!-- OrbitControls.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/controls/OrbitControls.js"></script>
<!-- DRACOLoader.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/loaders/DRACOLoader.js"></script>
<!-- GLTFLoader.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/loaders/GLTFLoader.js"></script>
<!-- RGBELoader.js -->
<script src="https://cdn.jsdelivr.net/npm/three#0.127/examples/js/loaders/RGBELoader.js"></script>
<div id="3dmain">
</div>
The example applies the environment map to Scene.environment. However, you could also traverse through the glTF object and apply it to each material's envMap property.

create a 3D object by adding a default height javascript

I have this code which should create a 3D form. The idea is that I have whatever coordinates stored into a vector in the same plan to which I should add a default height in order to make it 3D. As you can see I am a beginner in programming and this is the first time I use ThreeJS so can you tell me what am I doing wrong? Honestly I have no clue and I would like to know if there is another way of adding the default height to my 2D vector coordinates in order to make it 3D without using ThreeJS. Thank you!
$(document).ready(function(){
function storeCoordinate(x, y, array) {
array.push(x);
array.push(y);
}
var coords = [];
var z=500;
storeCoordinate(3, 5, coords);
storeCoordinate(10, 100, coords);
storeCoordinate(30, 120, coords);
storeCoordinate(3, 5, coords);
for (var i = 0; i < coords.length; i+=2) {
var x = coords[i];
var y = coords[i+1];
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var shape = new THREE.Shape( coords );
ctx.moveTo(coords[i],coords[i+1]);
ctx.lineTo(coords[i+2],coords[i+3]);
ctx.stroke();
}
var render,mycanvas,scene,camera,renderer,light;
init();
animate();
function init(){
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 1, 1000 );
var extrudedGeometry = new THREE.ExtrudeGeometry(shape, {amount: 5, bevelEnabled: false});
var extrudedMesh = new THREE.Mesh(extrudedGeometry, new THREE.MeshPhongMaterial({color: 0xff0000}));
scene.add(extrudedMesh);
document.body.onmousemove = function(e){
extrudedMesh.rotation.z = e.pageX / 100;
extrudedMesh.rotation.x = e.pageY / 100;
}
//lights
dirLight = new THREE.DirectionalLight(0xffffff);
dirLight.intensity = .9;
dirLight.position.set(500, 140, 500);
dirLight.castShadow = true;
dirLight.shadowMapHeight = 2048
dirLight.shadowMapWidth = 2048
dirLight.shadowDarkness = .15
spotLight = new THREE.PointLight( 0xffffff );
spotLight.intensity = .5
spotLight.position.set( -500, 140, -500 );
camera.add( spotLight)
camera.add(dirLight);
lighthelper = new THREE.DirectionalLightHelper(dirLight, 20);
lighthelper.children[1].material.color.set(0,0,0)
lighthelper.visible = false;
scene.add(lighthelper);
ambientLight = new THREE.AmbientLight( 0x020202, 1 );
scene.add( ambientLight );
light = new THREE.PointLight(0xffffff);
light.position.set(-100,200,100);
scene.add(light);
renderer = new THREE.WebGLRenderer({canvas: mycanvas});
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.enableZoom = true;
controls.enablePan = true;
controls.rotateSpeed = 3.0;
controls.zoomSpeed = 1.0;
controls.panSpeed = 2.0;
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.minDistance = 1.1;
controls.maxDistance = 1000;
controls.keys = [65, 83, 68]; // [ rotateKey, zoomKey, panKey ]
}
function animate() {
window.requestAnimationFrame( animate );
render();
}
function render() {
renderer.render( scene, camera );
}
var loader = new THREE.OBJLoader();
});
Just an option of how you can do it, using THREE.ExtrudeGeometry():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 3);
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 grid = new THREE.GridHelper(5, 10, "white", "gray");
grid.geometry.rotateX(Math.PI * 0.5);
scene.add(grid);
var points = [
new THREE.Vector2(0, 1),
new THREE.Vector2(1, 1),
new THREE.Vector2(1, 0)
]
var shape = new THREE.Shape(points);
var extrudeGeom = new THREE.ExtrudeGeometry(shape, {
amount: 0.5,
bevelEnabled: false
});
var mesh = new THREE.Mesh(extrudeGeom, 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/92/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Changing z rotation in three.js animation

I need to add an additional function to change the Z rotation value of the teapot from within the updateTeapot function. I saw this answer Three.js camera tilt up or down and keep horizon level, but how do I incorporate a z rotation function within this function?
function updateTeapot() {
if (teapot != null) {
teaPotHeight+=1;
teapot.position.y = teaPotHeight%200;
}
}
(function ( lab3 , $, undefined) {
lab3.init = function(hook) {
// Create a renderer
var WIDTH = 600,
HEIGHT = 500;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(WIDTH, HEIGHT);
hook.append(renderer.domElement);
var scene = new THREE.Scene();
// Create lights
var pointLight =
new THREE.PointLight(0xFFFFFF);
pointLight.position = new THREE.Vector3(-10, 100, 100);
scene.add(pointLight);
// Add ambient light
var ambient = new THREE.AmbientLight( 0x555555 );
scene.add( ambient );
// Create a camera
var VIEW_ANGLE = 65, //65 FOV is most 'natural' FOV
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1, //these elements are needed for cameras to
FAR = 10000; //partition space correctly
var camera = new THREE.PerspectiveCamera(
VIEW_ANGLE,
ASPECT,
NEAR,
FAR);
camera.position.z = 300;
scene.add(camera);
// Create and add controls
var controls = new THREE.TrackballControls( camera );
controls.target.set( 0, 0, 0 );
// Create a cube
var material =
new THREE.MeshLambertMaterial(
{
color: 0x00bbcc
});
var cube = new THREE.Mesh(
new THREE.CubeGeometry(
40, 55, 30),
material);
scene.add(cube);
// Animation
function renderLoop() {
renderer.render(scene, camera);
controls.update();
window.requestAnimationFrame(renderLoop);
updateTeapot();
}
window.requestAnimationFrame(renderLoop);
////////////////////////////////////////////////
var teapot = null;
var teaPotHeight=0;
loader = new THREE.JSONLoader();
loader.load( "models/utah-teapot.json", function( geometry ) {
teapot = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial({
color: 0x00bb00,
side: THREE.DoubleSide
}));
teapot.scale.set( 20, 20, 20 );
teapot.position = new THREE.Vector3(-30, 100, 20);
function updateTeapot() {
if (teapot != null) {
teaPotHeight+=1;
teapot.position.y = teaPotHeight%200;
}
}
//add it to the scene
scene.add(teapot);
});
}
})(window.lab3 = window.lab3 || {} , jQuery)
Add
teapot.rotation.z = numInRadians;

Three.js skybox seems broken after rotating camera

js and I'm trying to create a simple skybox based on this demo. Everything seems ok so far except 1 thing when I rotate my camera (I'm using orbitControls.js) and the z value is not the minimum possible then textures act weird and seem broken.
Source:
var camera, scene, renderer, controls, skybox;
var toRadians = function(deg) {
return deg * Math.PI / 180
}
var toDegrees = function(radians) {
return radians * (180 / Math.PI);
}
var init = function() {
// scene
scene = new THREE.Scene();
scene.fog = new THREE.FogExp2( 0xffffff, 0.00010);
// camera
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 20000 );
camera.position.z = 5000;
scene.add( camera );
// skydome
var urlPrefix = "http://three.dev/skybox/textures/";
var urls = [urlPrefix + "px.png", urlPrefix + "nx.png",
urlPrefix + "py.png", urlPrefix + "ny.png",
urlPrefix + "pz.png", urlPrefix + "nz.png"];
var textureCube = THREE.ImageUtils.loadTextureCube( urls );
var shader = THREE.ShaderLib[ "cube" ];
shader.uniforms[ "tCube" ].value = textureCube;
var material = new THREE.ShaderMaterial( {
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
depthWrite: false,
side: THREE.BackSide
} ),
skybox = new THREE.Mesh( new THREE.BoxGeometry( 10000, 10000, 10000 ), material );
scene.add( skybox );
//var texture = THREE.ImageUtils.loadTexture( 'http://three.dev/skybox/textures/wood.jpg')
//var paintMaterial = new THREE.MeshBasicMaterial({map: textureCube})
// var lightAmb = new THREE.AmbientLight(0x333333);
// lightAmb.position.set( 0,0,0 );
// scene.add(lightAmb);
// var directionalLightTop = new THREE.DirectionalLight( 0xffffff, 1 );
// directionalLightTop.position.set( 0, 0, 0 ).normalize();
// scene.add( directionalLightTop );
// var color = new THREE.Color("rgb(255,0,0)");
// var pointLightRed = new THREE.PointLight(color, 1, 8000);
// pointLightRed.position.set( 0, 0, 0);
// camera.add( pointLightRed );
// renderer
renderer = new THREE.WebGLRenderer( {alpha: true, antialias: true} );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff, 1 );
renderer.autoClear = false;
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.rotateSpeed = 0.5;
controls.minDistance = 500;
controls.maxDistance = 6000;
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
// start rendering
render();
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
var update = function() {
}
var render = function() {
update();
controls.update();
requestAnimationFrame( render );
renderer.render(scene, camera);
}
window.onload = function(){
init();
}
You're adding a skybox in the 'main' scene. A better way to accomplish a skydome would be to create a new scene. this will be the 'background' to your 'main' scene. There's also a discussion about skydomes v.s. skyboxes, simply put, a box saves polys, a dome looks better. in this example i'll be using a dome/sphere.
var renderer = new THREE.WebGLRenderer( {alpha: true, antialias: true} );
var mainScene = new THREE.Scene();
var mainCamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 20000 );
var skydome = {
scene: new THREE.Scene(),
camera: new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 20000 );
};
skydome.material = new THREE.MeshBasicMaterial({color: 0x0F0F0F}) //the material for the skydome, for sake of lazyness i took a MeshBasicMaterial.
skydome.mesh = new THREE.Mesh(new THREE.SphereGeometry(100, 20, 20), skydome.material);
skydome.scene.add(skydome.mesh);
now, during the render function you adjust only the rotation of the skydome camera, not the position.
var render = function(){
requestAnimationFrame( render );
skydome.camera.quaternion = mainCamera.quaternion;
renderer.render(skydome.scene, skydome.camera); //first render the skydome
renderer.render(mainScene, mainCamera);//then render the rest over the skydome
};
renderer.autoclear = false; //otherwise only the main scene will be rendered.

Categories