Three.js setHSL() sets unexpected color - three.js

setHSL(h,s,l) - set the value of this color on the supplied HSL values. The values range from 0 to 1.
why am I getting cyan when I try material.color.setHSL( 0.5, 1, 0.5 )? I expect to have yellow instead as color picker shows
let camera, scene, renderer, material;
init();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
scene = new THREE.Scene();
const geometry = new THREE.PlaneGeometry();
material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
material.color.setHSL( 0.5, 1, 0.5 );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.render( scene, camera );
}
body {
margin: 0;
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>

Color picker goes from 0 to 360.
setHSL goes from 0 to 1.
if you want hue 50 out of 360 you set 50/360 which is 0.1388888888888889.
setHSL( 0.1388888888888889, 1, 0.5 ) is yellow.
let camera, scene, renderer, material;
init();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 1;
scene = new THREE.Scene();
const geometry = new THREE.PlaneGeometry();
material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
material.color.setHSL( 0.1388888888888889, 1, 0.5 );
const mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer.render( scene, camera );
}
body {
margin: 0;
}
<script src="//cdn.rawgit.com/mrdoob/three.js/master/build/three.min.js"></script>

Related

How to set coordination origin to top left instead of center center in ThreeJS?

When you add any object to the scene in ThreeJS it is located in the center by default. so that its position is (0,0,0) although it is drawn in the center. I need to make the default position at top left when coordinates are (0,0,0).
Here is a very simple example shows that the default coordinates are center center:
https://jsfiddle.net/qy3572dt/
var scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera( 80, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 0, 0, 50 );
var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const sprite = new THREE.Sprite( new THREE.SpriteMaterial( { color: 'red' } ) );
sprite.position.set(0,0,1);
scene.add( sprite );
camera.position.z = 5;
var animate = function () {
requestAnimationFrame( animate );
renderer.render( scene, camera );
};
animate();
Since you are working with sprites, just change Sprite.center.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 0.1, 10);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const sprite = new THREE.Sprite(new THREE.SpriteMaterial({
color: 'red'
}));
sprite.center.set(0, 1);
scene.add(sprite);
scene.add(new THREE.AxesHelper());
renderer.render(scene, camera);
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.126.1/build/three.js"></script>

Create a camera that can only stay in an orbit/dome above the ground

I have a camera
if (srims.state.staticData.cameraSettings.active) {
srims.camera = new THREE.PerspectiveCamera(
srims.state.staticData.cameraSettings.distance,
(window.innerWidth * 0.75) / window.innerHeight,
srims.state.staticData.cameraSettings.minDistance,
srims.state.staticData.cameraSettings.maxDistance
);
srims.camera.position.set(
srims.state.staticData.cameraSettings.position.x,
srims.state.staticData.cameraSettings.position.y,
srims.state.staticData.cameraSettings.position.z
);
srims.camera.up = new THREE.Vector3(0, 1, 0);
srims.camera.lookAt(new THREE.Vector3(0, 0, 0));
}
It works great, basically looks at 0, 0, 0 and i can orbit / zoom all the way around that target.
Let's say my scene has a floor placed on Y: 0 and we have a model on that floor and the model is 0, 0, 0.
Now the problem is, I don't want to see or go under the floor with my camera I want it to stay above Y.
Best example would be that the bounds of my camera are like a cut in half tennis ball placed on the floor. It's only above the floor, not a full ball translated half above and half below the floor.
Any examples or guidance would be great.
You can do this by setting OrbitControls.maxPolarAngle to Math.PI * 0.5.
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setPixelRatio( window.devicePixelRatio );
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( 20, 20, 20 );
// controls
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.maxPolarAngle = Math.PI * 0.5;
// ambient
scene.add( new THREE.AmbientLight( 0x222222 ) );
// light
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.position.set( 20,20, 0 );
scene.add( light );
// axes
scene.add( new THREE.AxesHelper( 20 ) );
// geometry
var geometry = new THREE.SphereGeometry( 5, 12, 8 );
// material
var material = new THREE.MeshPhongMaterial( {
color: 0x00ffff,
flatShading: true,
transparent: true,
opacity: 0.7,
} );
// mesh
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
<script src="https://rawcdn.githack.com/mrdoob/three.js/r112/build/three.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r112/examples/js/controls/OrbitControls.js"></script>

Animating a line in Three.js with lineTo and curveTo

I'm a three.js newbie and I'm coming from Processing/p5.js (so I'm a bit spoiled on animating loops). I'm trying to create something like this simple stretching pill shape:
Stretching pill shape
This is what I cobbled together from some things I found online. I just have the 'O' shape. I'm trying to get the variable oHeight to be the variable that causes the fluxing back and forth with a Math.sin.
Do I need to update the path? Or the bufferGeometry? Or the THREE.path?
Sorry this code is so messy. Just starting out!
var camera, scene, renderer;
var curve;
var path;
var oHeight = 0;
var delta = 0;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 600;
scene = new THREE.Scene();
path = new THREE.Path();
path.lineTo( 0, 0 );
path.quadraticCurveTo( 0, 20, 20, 20 );
path.lineTo( 40, 20 );
path.quadraticCurveTo( 60,20, 60,0);
path.lineTo(60,-40-oHeight);
path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
path.lineTo(20,-60-oHeight);
path.quadraticCurveTo(0,-60,0,-40-oHeight);
path.lineTo(0,0);
var points = path.getPoints();
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color: 0xffffff } );
curve = new THREE.Line( geometry, material );
scene.add( curve );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
delta +=.1;
oHeight = Math.sin(delta)*20;
line.needUpdate = true; //is this where I went wrong?
renderer.render( scene, camera );
}
There is no object line in your code and there is no mystic reference from the object geometry to the oHeight. The THREE.Path is only a temporary object, which contains the information, that is needed to create the BufferGeoemtry. Note, at the end the vertices of the geometry are stored in an array buffer on the GPU.
You have to create the path in the animate function and to set it to the BufferGeoemtry. So the geometry is recreated in every frame:
function animate() {
requestAnimationFrame( animate );
delta +=.1;
oHeight = Math.sin(delta)*20;
path = new THREE.Path();
path.lineTo( 0, 0 );
path.quadraticCurveTo( 0, 20, 20, 20 );
path.lineTo( 40, 20 );
path.quadraticCurveTo( 60,20, 60,0);
path.lineTo(60,-40-oHeight);
path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
path.lineTo(20,-60-oHeight);
path.quadraticCurveTo(0,-60-oHeight,0,-40-oHeight);
path.lineTo(0,0);
geometry.dispose();
geometry.setFromPoints( path.getPoints() );
renderer.render( scene, camera );
}
var camera, scene, renderer;
var curve;
var path;
var oHeight = 0;
var delta = 0;
var geometry;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 600;
scene = new THREE.Scene();
geometry = new THREE.BufferGeometry();
var material = new THREE.LineBasicMaterial( { color: 0xffffff } );
curve = new THREE.Line( geometry, material );
scene.add( curve );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.onresize = resize;
}
function animate() {
requestAnimationFrame( animate );
delta +=.1;
oHeight = Math.sin(delta)*20;
path = new THREE.Path();
path.lineTo( 0, 0 );
path.quadraticCurveTo( 0, 20, 20, 20 );
path.lineTo( 40, 20 );
path.quadraticCurveTo( 60,20, 60,0);
path.lineTo(60,-40-oHeight);
path.quadraticCurveTo( 60,-60-oHeight, 40,-60-oHeight);
path.lineTo(20,-60-oHeight);
path.quadraticCurveTo(0,-60-oHeight,0,-40-oHeight);
path.lineTo(0,0);
geometry.dispose();
geometry.setFromPoints( path.getPoints() );
renderer.render( scene, camera );
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
<script src="https://threejs.org/build/three.min.js"></script>

Three.js material isn't applied correctly to hexagonal faces

I have a mesh, created in blender and exported to .obj. The mesh looks valid and has UV map applied and exported into the same .obj as well. For some reason, when I try to apply a texture material, or even basic material to the mesh, only half of the hexagon is actually painted.
This is a mesh
This is the code
var container;
var camera, scene, renderer;
init();
animate();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 55, window.innerWidth / window.innerHeight, 0.5, 3000000 );
camera.position.set( 2000, 750, 2000 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.userPan = false;
controls.userPanSpeed = 0.0;
controls.maxDistance = 5000.0;
controls.maxPolarAngle = Math.PI * 0.495;
controls.center.set( 0, 1, 0 );
var light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
light.position.set( - 1, 1, - 1 );
scene.add( light );
waterNormals = new THREE.ImageUtils.loadTexture( 'textures/waternormals.jpg' );
waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
water = new THREE.Water( renderer, camera, scene, {
textureWidth: 512,
textureHeight: 512,
waterNormals: waterNormals,
alpha: 1.0,
sunDirection: light.position.clone().normalize(),
sunColor: 0xffffff,
waterColor: 0x001e0f,
distortionScale: 50.0,
} );
var loader = new THREE.OBJMTLLoader();
loader.load( "models/world.obj", "models/world.mtl", function(object)
{
console.log(object.children[0].children[1].geometry);
var mesh = new THREE.Mesh(
object.children[0].children[1].geometry,
new THREE.MeshBasicMaterial
);
scene.add(mesh);
});
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
controls.update();
renderer.render( scene, camera );
}
And this is how it looks:
When I split the hexagons into 2 quads it works perfectly, thing is, I need faces to stay hexagons for picking, the faces I want to be selected are hexagons.

THREE.js Texture is not visible with SVGRenderer

We've tried the next code:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.0001, 999);
camera.position.set( 0, 0, 3 );
scene.add( camera );
var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
var image = $('#tmp')[0]
var texture = new THREE.Texture(image);
texture.needsUpdate = true;
var img_material = new THREE.MeshBasicMaterial({color: 0x000000, map: texture });
var plane_geometry = new THREE.PlaneGeometry(2, 2);
var imageMesh = new THREE.Mesh(plane_geometry, img_material);
imageMesh.doubleSided = true;
scene.add(imageMesh);
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
$('#container').append( renderer.domElement );
renderer.render(scene, camera);
but when we switched to:
renderer = new THREE.SVGRenderer();
it stop rendering texture over image geometry. Can anybody say why so?
THREE.SVGRenderer doesn't support textures.

Resources