adding multiple objects to a single dat.GUI slider? - three.js

I have a simple three.js scene with a car model that I want users to customize.
I have no problem manipulating the positions and rotations of single objects.
I'd like the user to be able to expand the wheelbase of the car on a single dat.Gui slider.
Front wheels move forward, rear wheels move back.
I was able to get it to work with relative positions - Just wanted to know if there was a cleaner way. dummyA and dummyC take there info from dummyB
gui.add(dummyB.position,'x').min(8).max(15).name('Wheel Base');
function animate() {
requestAnimationFrame( animate )
render();
dummyA.position.x = dummyB.position.x * -1;
dummyC.scale.x = (dummyB.position.x * 1.75)-8;
}
-Thanks

There's an example of how you can do it:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(-5, 5, 5);
var renderer = new THREE.WebGLRenderer({
antialis: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var params = {
width: 2,
length: 4,
}
// wheels
var wheels = [];
setWheel(new THREE.Vector3(-params.length * .5, 1, -params.width * 0.5));
setWheel(new THREE.Vector3(params.length * .5, 1, -params.width * 0.5));
setWheel(new THREE.Vector3(-params.length * .5, 1, params.width * 0.5));
setWheel(new THREE.Vector3(params.length * .5, 1, params.width * 0.5));
function setWheel(position) {
let wheelGeom = new THREE.CylinderGeometry(1, 1, 0.25);
wheelGeom.rotateX(-Math.PI * 0.5);
let wheel = new THREE.Mesh(wheelGeom, new THREE.MeshBasicMaterial({
color: "yellow",
wireframe: true
}));
wheel.position.copy(position);
wheels.push(wheel);
scene.add(wheel);
}
var gui = new dat.GUI();
gui.add(params, "width", 1, 3).onChange(setWidth);
gui.add(params, "length", 3, 5).onChange(setLength);
function setWidth(value) {
wheels.forEach(w => {
w.position.setZ(value * 0.5 * Math.sign(w.position.z));
});
}
function setLength(value) {
wheels.forEach(w => {
w.position.setX(value * 0.5 * Math.sign(w.position.x));
});
}
render();
function render() {
requestAnimationFrame(render);
wheels.forEach(w => {
w.rotation.z += 0.01;
});
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.1/dat.gui.min.js"></script>

Related

I need to zoom on an object upon hover

I want something like this:
https://drive.google.com/file/d/1v_4M59Ny93QwT52unfM9N_tfzo3xRAq1/view?usp=share_link
This is my code
<!DOCTYPE html>
<html>
<head>
<title>Three.js JPG Background with Custom Position</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js"></script>
<script src="./js/tween.js/dist/tween.umd.js"></script>
<!-- Css -->
<style>
body {
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
}
</style>
</head>
<body>
<script>
// Initialize Three.js scene
var scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera(window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 0.1,);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Load the Main BG texture
var mainBg = new THREE.TextureLoader().load("http://127.0.0.1:5500/img/main-bg.jpg");
// Create a full-screen plane to display the texture
var geometry1 = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);
var material1 = new THREE.MeshBasicMaterial({ map: mainBg });
var plane1 = new THREE.Mesh(geometry1, material1);
plane1.position.set(0, 0, 0)
scene.add(plane1);
// Create a full-screen plane to display the texture
var frame1 = new THREE.TextureLoader().load("http://127.0.0.1:5500/img/frame1.png");
var geometry2 = new THREE.PlaneGeometry(90, 110);
var material2 = new THREE.MeshBasicMaterial({ map: frame1 });
var plane2 = new THREE.Mesh(geometry2, material2);
plane2.position.set(-190, 130, .1);
scene.add(plane2);
// Check if mouse is over the child asset
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var zoomed = false;
// Mouse move function
function onMouseMove(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([plane2]);
if (intersects.length > 0 && !zoomed) {
zoomed = true;
camera.position.set(plane2.position.x, plane2.position.y, plane2.position.z);
camera.lookAt(plane2.position.x, plane2.position.y, plane2.position.z);
} else if (intersects.length === 0 && zoomed) {
zoomed = false;
camera.position.set(0, 0, 5);
camera.lookAt(new THREE.Vector3(0, 0, 0));
}
}
// Mouse move function calling on moving mouse
document.addEventListener('mousemove', onMouseMove, false);
window.addEventListener('mousedown', function () {
gsap.to(camera.position, {
z: 15,
duration: 15
});
})
// Render loop
function render() {
camera.position.z = 5;
requestAnimationFrame(render);
renderer.render(scene, camera);
}
render();
</script>
</body>
</html>
assets:
frame1
and
main-bg
i made frame 1 on the center of the screen by hovering it but cannot make camera to zoom in on it. I tried tween but I think there is something wrong in the basics of my code
Sorry i am new to this and this is my first threejs project
You can apply a mousemove event on the canvas and use event.clientX or event.clientY to read live mouse pointer values. These values can then be used within the the listener to update values of camera.position.z to change zoom.

Threejs How to Add in and Out curves in a custom shape?

I have a simple shape made in 3js with 8 points. The shape is without curves. I am not very good in absarc or curves in Threejs. I have tried to search online but I didn't get exact example.
My shape output:
While I need output like this:
Just an option, using .absarc():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 6);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
var grid = new THREE.GridHelper(10, 10);
grid.rotation.x = -Math.PI * 0.5;
grid.position.set(0, 0, -0.01);
scene.add(grid);
var s = new THREE.Shape();
s.absarc(0, 0, 0.5, Math.PI * 0.5, -Math.PI * 0.5, true);
s.lineTo(0, -2);
s.absarc(-1, 0, Math.sqrt(2) * 2, -Math.PI * 0.25, Math.PI * 0.25, false);
s.lineTo(0, 2);
var sGeom = new THREE.ShapeBufferGeometry(s);
var sMat = new THREE.MeshBasicMaterial({
color: "teal"
});
var shape = new THREE.Mesh(sGeom, sMat);
scene.add(shape);
var lineGeom = new THREE.BufferGeometry().setFromPoints(s.getPoints());
var lineMat = new THREE.LineBasicMaterial({
color: "orange"
});
var outline = new THREE.LineLoop(lineGeom, lineMat);
scene.add(outline);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Rendered object looks flat even with shadows

I'm a three.js newb. I've been playing around with it for a couple of days and haven't been able to figure out how to make my objects look more realistic. I suspect there's no simple answer for this question, but is there anything I can do to improve my rendering quality without going into the depth of "rendering science"? Maybe I'm missing some configs. Thank you for any advice!
Here's the relevant code used in rendering a kitchen cabinet frame.
this.renderer = new THREE.WebGLRenderer({ antialias: true })
this.renderer.setSize(this.container.offsetWidth, this.container.offsetHeight)
this.renderer.sortObjects = false
this.renderer.setClearColor(0xf0f0f0)
this.renderer.gammaFactor = 2.2
this.renderer.gammaOutput = true
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.shadowMap.enabled = true
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
const light = new THREE.AmbientLight(0xffffff, 0.8)
const light2 = new THREE.PointLight(0xffffff, 0.3)
light2.position.set(400, 400, 400)
light2.shadow.camera.near = 10
light2.shadow.camera.far = 10000
light2.shadow.mapSize.width = 2048
light2.shadow.mapSize.height = 2048
light2.castShadow = true
this.scene.add(light2)
this.scene.add(light)
const material = new THREE.MeshStandardMaterial({ color: 0xffffff, metalness: 0, roughness: 0 })
let scene, camera, controls, ambient, point, loader, renderer, container, stats;
const targetRotation = 0;
const targetRotationOnMouseDown = 0;
const mouseX = 0;
const mouseXOnMouseDown = 0;
const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;
init();
animate();
var box, b1, b2, b3;
function init() {
// Create a scene which will hold all our meshes to be rendered
scene = new THREE.Scene();
// Create and position a camera
camera = new THREE.PerspectiveCamera(
60, // Field of view
window.innerWidth / window.innerHeight, // Aspect ratio
/*window.innerWidth / -8,
window.innerWidth / 8,
window.innerHeight / 8,
window.innerHeight / -8,
*/
0.1, // Near clipping pane
1000 // Far clipping pane
);
scene.add(camera)
// Reposition the camera
camera.position.set(0, 5, 10);
// Point the camera at a given coordinate
camera.lookAt(new THREE.Vector3(0, 0, 0));
// Add orbit control
controls = new THREE.OrbitControls(camera);
controls.target.set(0, -0.5, 0);
controls.update();
// Add an ambient lights
ambient = new THREE.AmbientLight(0xffffff, 0.2);
scene.add(ambient);
// Add a point light that will cast shadows
point = new THREE.PointLight(0xffffff, 1);
point.position.set(25, 50, 25);
point.castShadow = true;
point.shadow.mapSize.width = 1024;
point.shadow.mapSize.height = 1024;
scene.add(point);
group = new THREE.Group();
group.position.y = 0;
scene.add(group);
rotationAnchor = new THREE.Object3D()
group.add(rotationAnchor);
box = new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshStandardMaterial({
color: 'grey'
}))
b1 = box.clone();
b2 = box.clone();
b3 = box.clone();
b3.material = b3.material.clone()
b3.material.color.set('red')
group.add(box);
group.add(b1);
b1.position.y += 1
group.add(b2);
b2.position.z += 1
rotationAnchor.add(b3);
rotationAnchor.position.set(0.5, 0.5, 1.5)
b3.position.set(-.5, -.5, -.5)
// Create a renderer
renderer = new THREE.WebGLRenderer({
antialias: true
});
// Set size
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Set color
renderer.setClearColor(0xf8a5c2);
renderer.gammaOutput = true;
// Enable shadow mapping
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// Append to the document
container = document.createElement("div");
document.body.appendChild(container);
document.body.appendChild(renderer.domElement);
// Add resize listener
window.addEventListener("resize", onWindowResize, false);
// Enable FPS stats
stats = new Stats();
container.appendChild(stats.dom);
var gui = new dat.GUI({
height: 5 * 32 - 1
});
let params = {
'test': 4,
'bevelThickness': 1,
'bevelSize': 1.5,
'bevelSegments': 3
}
gui.add(params, 'test', 0, 10).onChange(val => {
test = val
})
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
rotationAnchor.rotation.z = (Math.cos(performance.now() * 0.001) * Math.PI * 0.25) + (Math.PI * 1.25)
requestAnimationFrame(animate);
// Re-render scene
renderer.render(scene, camera);
// Update stats
stats.update();
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/96/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.2/dat.gui.min.js"></script>

How to create simple vertical bounce animation to a sphere

I'd like for a spinning sphere I created to also bounce vertically an infinite amount of times that looks realistic to the way a ball would bounce in real life strictly on the y axis.
The webgl examples I've found seem be a bit overloaded (multiple balls bouncing on multiple planes) and I haven't been able to deduce the core setup to achieve what I need.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, 300 / 200, 1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(300, 200);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.SphereGeometry(3, 50, 50, 0, Math.PI * 2, 0, Math.PI * 2);
var material = new THREE.MeshNormalMaterial();
var cube = new THREE.Mesh(geometry);
scene.add(cube);
camera.position.z = 10;
var render = function () {
requestAnimationFrame(render);
cube.rotation.x -= 0.10;
cube.rotation.y += 0.00;
renderer.render(scene, camera);
};
render();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
So, just an option with Math.sin():
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(2, 3, 5);
camera.lookAt(scene.position);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var plane = new THREE.Mesh(new THREE.PlaneGeometry(5, 10, 5, 10), new THREE.MeshBasicMaterial({
color: 0x00ffff,
wireframe: true
}));
plane.rotation.x = -Math.PI * 0.5;
scene.add(plane);
var ball = new THREE.Mesh(new THREE.SphereGeometry(0.5, 16, 8), new THREE.MeshBasicMaterial({
color: 0xff00ff,
wireframe: true
}));
scene.add(ball);
var clock = new THREE.Clock();
var time = 0;
var delta = 0;
render();
function render() {
requestAnimationFrame(render);
delta = clock.getDelta();
time += delta;
ball.rotation.x = time * 4;
ball.position.y = 0.5 + Math.abs(Math.sin(time * 3)) * 2;
ball.position.z = Math.cos(time) * 4;
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>

how can i modify mesh size in my scene?

First to say, I do not speak English well.
Anyway, Let's get something straight.
I want to modify mesh(cube) size when i scroll the mouse wheel to zoomin or zoomout.
I hope to increase mesh(cube) size when zoom in and Opposite case, too.
my code is below.
<script src="../lib/Three.js/build/Three.js"></script>
<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
var CANVAS_WIDTH = 400,
CANVAS_HEIGHT = 300;
var renderer = null, //웹지엘 또는 2D
scene = null, //씬 객체
camera = null; //카메라 객체
var capture = false,
start = [],
angleX = 0,
angleY = 0,
zoom = 1.0;
function initWebGL()
{
setupRenderer();
setupScene();
setupCamera();
var myColor = new THREE.Color( 0xff0000 );
myColor.setRGB(0.0, 1.0, 0.0);
var alpha = 1.0;
renderer.setClearColor(myColor, alpha);
(function animLoop(){
//camera zoom in and zomm out
renderer.render(scene, camera);
requestAnimationFrame( animLoop );
})();
/**
mouse event code for screen control about zoom, rotate
**/
$(document).ready(function() {
console.log($("#my-canvas").length);
$("#my-canvas").on("mousedown", function(e) {
capture = true;
start = [e.pageX, e.pageY];
console.log("start:" + start);
});
$("#my-canvas").on("mouseup", function(e) {
console.log(e.type);
capture = false;
console.log("end capture");
});
$("#my-canvas").mousemove(function(e) {
console.log(e.type);
if (capture)
{
var x = (e.pageX - start[0]);
var y = (e.pageY - start[1]);
//시작위치 업데이트
start[0] = e.pageX;
start[1] = e.pageY;
angleX += x;
angleY += y;
//console.log()
}
});
});
$(document).ready(function(evt) {
$("#my-canvas").on("mousewheel", function (e) {
adjustZoom(window.event.wheelData);
}).on("DOMMouseScroll", function (e) {
//파이어폭스
adjustZoom(e.originalEvent.detail * -1.0);
});
});
function adjustZoom(delta) {
if(delta > 0)
{
zoom += 0.1;
} else {
zoom -= 0.1;
if(zoom < 0.01) { zoom = 0.1;}
}
}
}
function setupRenderer()
{
renderer = new THREE.WebGLRenderer({canvas: document.createElement( 'canvas')});
renderer.setSize( CANVAS_WIDTH, CANVAS_HEIGHT );
$(renderer.domElement).attr('id','my-canvas');
//캔버스 엘리먼트를 추가하는 곳
document.body.appendChild( renderer.domElement );
}
function setupScene()
{
scene = new THREE.Scene();
addMesh();
addLight();
}
function setupCamera()
{
camera = new THREE.PerspectiveCamera(
35, //시야
CANVAS_WIDTH / CANVAS_HEIGHT, //종횡비
.1, //전방 절단면
10000 //후방 절단면
);
camera.position.set(-15, 10, 10);
camera.lookAt( scene.position );
scene.add( camera );
}
function addMesh()
{
var cube = new THREE.Mesh(
new THREE.CubeGeometry( 5, 7, 5 ),
new THREE.MeshLambertMaterial( { color: 0x0000FF} )
);
scene.add(cube);
}
function addLight()
{
var light = new THREE.PointLight( 0xFFFFFF );
light.position.set( 20, 20, 20 );
scene.add(light);
}
</script>
You wish to modify the scale value of the object. This can be done for each axis.
Each mesh object has a scale value as a vector.
So this would
mesh.scale.set( 2, 1, 1 )
Or in your case
cube.scale.set();
You can also access it this way,
cube.scale.x = 2.0;
Though the cube object is stored locally, you might want to set the globally and alter this value with the mouse action.
Hope that well.
As a note, the question provides a bit too much of the script, shorter and faster to the point is better.

Resources