Animating rotation of object based on new pivot in Three.js - javascript

I want to do this in Three.JS:
I did the spiral and downward movement, but I don't do the knocking motion.
var planeGeometry = new THREE.PlaneGeometry(10,10);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x828282, wireframe: false, side: THREE.DoubleSide});
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.rotation.x = 1.0 * THREE.Math.degToRad(90);
scene.add(planeMesh);
var cylinderGeometry = new THREE.CylinderGeometry(0.2, 0.2, 14);
var cylinderMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: false});
var cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinderMesh.position.set(0,7,0);
scene.add(cylinderMesh);
groupDown = new THREE.Group();
groupSpiral = new THREE.Group();
groupKnock = new THREE.Group();
var woodPeckerGeometry = new THREE.BoxGeometry(1,3,2);
var woodPeckerMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: false});
var woodPeckerMesh = new THREE.Mesh(woodPeckerGeometry , woodPeckerMaterial );
groupDown.add(woodPeckerMesh );
groupDown.position.set(0, 10, 2);
groupSpiral.add(groupDown)
groupKnock.add(groupSpiral)
scene.add(groupKnock);
and the render function:
var render = function () {
groupDown.position.y -= 0.03;
if(groupDown.position.y < 1.6) {
groupDown.position.y = 13;
}
groupSpiral.rotation.y += 0.03;
};
So the question is that how can I do knocking motion?

You could increase the groupDown rotation on the z axis like you did with its position and the "woodpecker" would start to knock on the cylinder. The problem with this is that the pivot for the rotation is at the center of the box.
To fix this, you can add the "woodpecker" to a group (i.e. pivotGroup), set its position up relative to its height on this new group and treat pivotGroup as the new object for animation. This way, the box would rotate from its base.
See the complete example below.
var camera, scene, renderer, groupSpiral, groupDown, groupKnock;
function init() {
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 10, 10000);
camera.position.z = 30;
camera.position.y = 24;
camera.rotation.x = -0.55;
scene.add(camera);
var planeGeometry = new THREE.PlaneGeometry(10, 10);
var planeMaterial = new THREE.MeshBasicMaterial({color: 0x828282, wireframe: false, side: THREE.DoubleSide});
var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
planeMesh.rotation.x = 1.0 * THREE.Math.degToRad(90);
planeMesh.rotation.z = 1.0 * THREE.Math.degToRad(45);
scene.add(planeMesh);
var cylinderGeometry = new THREE.CylinderGeometry(0.3, 0.3, 14);
var cylinderMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00, wireframe: false});
var cylinderMesh = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
cylinderMesh.position.y = 7;
scene.add(cylinderMesh);
var coneGeometry = new THREE.ConeGeometry(0.3, 1, 32);
var coneMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: false});
var coneMesh = new THREE.Mesh(coneGeometry, coneMaterial);
coneMesh.position.set(1, 1.8, 0);
coneMesh.rotation.z = Math.PI / -2;
groupDown = new THREE.Group();
groupSpiral = new THREE.Group();
groupKnock = new THREE.Group();
var woodPeckerGeometry = new THREE.BoxGeometry(1, 3, 1.5);
var woodPeckerMaterial = new THREE.MeshBasicMaterial({color: 0xffffff, wireframe: false});
var woodPeckerMesh = new THREE.Mesh(woodPeckerGeometry, woodPeckerMaterial);
woodPeckerMesh.position.set(0, 1, 0);
woodPeckerMesh.rotation.set(0, 0, Math.PI);
groupKnock.add(coneMesh);
groupKnock.add(woodPeckerMesh);
groupDown.add(groupKnock);
groupDown.position.set(0, 12, 1.5);
groupDown.rotation.y = Math.PI / 2;
groupSpiral.add(groupDown)
scene.add(groupSpiral);
renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
$(renderer.domElement).appendTo("body");
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
groupDown.position.y -= 0.03;
if(groupDown.position.y < 1.6) {
groupDown.position.y = 12;
}
groupSpiral.rotation.y += 0.03;
groupKnock.rotation.z += 0.035;
if(groupKnock.rotation.z > Math.PI/6) {
groupKnock.rotation.z = 0;
}
renderer.render(scene, camera);
}
$(document).ready(function() {
init();
animate();
});
* {
padding: 0;
margin: 0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/109/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

How to reflect an image on a IcosahedronGeometry in three.js?

I would like to make IcosahedronGeometry in three.js and reflect an image on the front side of the geometry.
I already made a IcosahedronGeometry and made it rotate on it's axis.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// RENDERER
var renderer = new THREE.WebGLRenderer({
antialias: true
});
// RENDERER - SIZE OF CANVAS
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor('#ffffff');
document.body.appendChild(renderer.domElement);
// RESPONSIVE RENDERING
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
var groundMaterial = new THREE.MeshPhongMaterial({
shininess: 100,
color: 0xffffff,
specular: 0xffffff
});
const cubeCamera = new THREE.CubeCamera(75, 1000, 512);
scene.add(cubeCamera);
// GEOMETRY
var geometry = new THREE.IcosahedronGeometry(2, 1);
var material = new THREE.MeshStandardMaterial({
color: 0x98bbbd,
side: THREE.FrontSides,
roughness: 1,
metalness: 0.5,
envMap: cubeCamera.renderTarget
});
material.roughness = 0;
material.metalness = 1;
material.flatShading = true;
material.envMap = cubeCamera.renderTarget.texture;
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
console.log(sphere.position);
console.log(cubeCamera.position);
cubeCamera.position.copy(sphere.position);
cubeCamera.update(renderer, scene);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture('images/woman.png');
// floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
// floorTexture.repeat.set(1000, 1000);
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.BackSide
});
var floorGeometry = new THREE.PlaneGeometry(5, 5, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.position.x = 0;
floor.position.z = 3;
scene.add(floor);
cubeCamera.lookAt(floor);
// CONTROLS
var orbit = new THREE.OrbitControls(camera, renderer.Mesh);
camera.position.z = 5;
// LIGHTS
var topLeftLight = new THREE.PointLight(0xffffff, 1, 1);
topLeftLight.position.set(-50, 50, -25);
scene.add(topLeftLight);
var topRightLight = new THREE.PointLight(0xffffff, 1, 10);
topRightLight.position.set(50, 150, -25);
scene.add(topRightLight);
var lightBottomRight = new THREE.PointLight(0xffffff, 1, 100);
lightBottomRight.position.set(40, -50, 25);
scene.add(lightBottomRight);
var lightBottomLeft = new THREE.PointLight(0xffffff, 1, 100);
lightBottomLeft.position.set(-40, -50, 25);
scene.add(lightBottomLeft);
var lightTopRight = new THREE.PointLight(0xffffff, 1, 100);
lightTopRight.position.set(40, 50, 25);
scene.add(lightTopRight);
var lightTopLeft = new THREE.PointLight(0xffffff, 1, 100);
lightTopLeft.position.set(-40, 50, 25);
scene.add(lightTopLeft);
var backLight = new THREE.PointLight(0xffffff, 1, 100);
backLight.position.set(0, 0, -25);
scene.add(backLight);
var light = new THREE.AmbientLight(0x404040, 2); // soft white light
scene.add(light);
// update function
function render() {
requestAnimationFrame(render);
sphere.rotation.x += 0.005;
sphere.rotation.y += 0.005;
sphere.visible = false;
cubeCamera.update(renderer, scene);
sphere.visible = true;
renderer.render(scene, camera);
}
render();
I would like to see a rotating IcosahedronGeometry which reflects an image on the front side. I tried adding a cube camera and pointing it at the PlaneGeometry with an image texture but nothing is reflecting.
I would like to simulate something like this, but it doesn't have to be exactly the same.
The desired result.
3 issues.
you have to call cubeCamera.update before you access cubeCamera.renderTarget.texture
The parameters to CubeCamera are new CubeCamera(near, far, size).
The code had new CubeCamera(75, 1000, 512) which means only things 75 to 1000 units away from the camera would be visible. The image plane you had is 3 units away so would not be visible.
You don't call lookAt with the CubeCamera as it's always looking in all directions.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// RENDERER
var renderer = new THREE.WebGLRenderer({
antialias: true
});
// RENDERER - SIZE OF CANVAS
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor('#ffffff');
document.body.appendChild(renderer.domElement);
// RESPONSIVE RENDERING
window.addEventListener('resize', () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
var groundMaterial = new THREE.MeshPhongMaterial({
shininess: 100,
color: 0xffffff,
specular: 0xffffff
});
const cubeCamera = new THREE.CubeCamera(0.001, 10, 512);
scene.add(cubeCamera);
// GEOMETRY
var geometry = new THREE.IcosahedronGeometry(2, 1);
var material = new THREE.MeshStandardMaterial({
color: 0x98bbbd,
side: THREE.FrontSide,
roughness: 1,
metalness: 0.5,
});
cubeCamera.update(renderer, scene);
material.roughness = 0;
material.metalness = 1;
material.flatShading = true;
material.envMap = cubeCamera.renderTarget.texture;
var sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// FLOOR
var loader = new THREE.TextureLoader();
var floorTexture = loader.load('https://i.imgur.com/UKBsvV0.jpg');
var floorMaterial = new THREE.MeshBasicMaterial({
map: floorTexture,
side: THREE.BackSide
});
var floorGeometry = new THREE.PlaneGeometry(5, 5, 1, 1);
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.position.y = 0;
floor.position.x = 0;
floor.position.z = 3;
scene.add(floor);
// CONTROLS
var orbit = new THREE.OrbitControls(camera, renderer.Mesh);
camera.position.z = 5;
// LIGHTS
var topLeftLight = new THREE.PointLight(0xffffff, 1, 1);
topLeftLight.position.set(-50, 50, -25);
scene.add(topLeftLight);
var topRightLight = new THREE.PointLight(0xffffff, 1, 10);
topRightLight.position.set(50, 150, -25);
scene.add(topRightLight);
var lightBottomRight = new THREE.PointLight(0xffffff, 1, 100);
lightBottomRight.position.set(40, -50, 25);
scene.add(lightBottomRight);
var lightBottomLeft = new THREE.PointLight(0xffffff, 1, 100);
lightBottomLeft.position.set(-40, -50, 25);
scene.add(lightBottomLeft);
var lightTopRight = new THREE.PointLight(0xffffff, 1, 100);
lightTopRight.position.set(40, 50, 25);
scene.add(lightTopRight);
var lightTopLeft = new THREE.PointLight(0xffffff, 1, 100);
lightTopLeft.position.set(-40, 50, 25);
scene.add(lightTopLeft);
var backLight = new THREE.PointLight(0xffffff, 1, 100);
backLight.position.set(0, 0, -25);
scene.add(backLight);
var light = new THREE.AmbientLight(0x404040, 2); // soft white light
scene.add(light);
// update function
function render() {
sphere.rotation.x += 0.005;
sphere.rotation.y += 0.005;
sphere.visible = false;
cubeCamera.update(renderer, scene);
sphere.visible = true;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/three.min.js"></script>
<script src="https://threejsfundamentals.org/threejs/resources/threejs/r105/js/controls/OrbitControls.js"></script>

How to have two Three-JS Objects run and animate at the same time?

I've created two 3JS objects and scenes for learning purposes. Both housed in separate PHP files (not in the jsfiddle). However, I can't figure out why by adding a second object the first object stops animating and doesn't run anymore? How can I go about figuring out why my objects are canceling one another out and how to create two different or more multiple threejs items that animate at the same time?
//GRID OBJ is the first object, and the second is //BALL
When I remove the second script calling for 3js ball the grid will animate, when the ball is added the grid stops animating and only the ball animates.
http://jsfiddle.net/tdqh4jno/
//GRID OBJ
var container = document.getElementById('grid')
var vertexHeight = 90,
planeDefinition = 25,
planeSize = 900,
totalObjects = 1,
background = "#002135",
meshColor = "#ff3057";
var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;
var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer = new THREE.WebGLRenderer({alpha: true});
renderer.setClearColor( 0x000000, 0 );
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
color: meshColor,
wireframe: true
}));
plane.rotation.x -= Math.PI * .5;
scene2.add(plane);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(background, 1);
container.appendChild(renderer.domElement);
function updatePlane() {
for (var i = 0; i < planeGeo.vertices.length; i++) {
planeGeo.vertices[i].z += Math.random() * vertexHeight;
planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
}
};
var count = 0
function renderGrid() {
var gridSpeed = 0.4;
var gridInterlop = -0.4;
var gridWaveSpeed = 0.003;
var gridWaveHeight = 0.00003;
requestAnimationFrame(renderGrid);
for (var i = 0; i < planeGeo.vertices.length; i++) {
var z = +planeGeo.vertices[i].z;
planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
plane.geometry.verticesNeedUpdate = true;
count += gridInterlop
}
renderer.render(scene2, camera2);
}
updatePlane();
renderGrid();
//BALL ITEM
var camera2 = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var sceneTop = new THREE.Scene(); // initialising the scene
sceneTop.background = new THREE.Color( 0x08080c);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100,100,100);
spotLight.castShadow = false;
sceneTop.add(spotLight);
function Mat(){
var material = new THREE.MeshPhongMaterial({
color : new THREE.Color(0xff3266),
emissive : new THREE.Color(0x08080c),
specular : new THREE.Color(0x08080c),
shininess : 0,
wireframe : true,
transparent: 0.5,
opacity : 0.55
});
return material;
}
var geometry = new THREE.IcosahedronGeometry(45 , 1);
var obj = new THREE.Mesh(geometry, Mat());
sceneTop.add(obj);
camera2.position.z = 90;
function myrender(){
renderer.setClearColor( 0x000000, 0 );
obj.rotation.x += 0.0004;
obj.rotation.y += 0.0006;
obj.rotation.z += Math.random() * 0.0005;
renderer.render(sceneTop, camera2);
requestAnimationFrame(myrender);
}
window.addEventListener('resize', onWindowResize, true);
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera2.updateProjectionMatrix();
};
myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>
You create 2 THREE.WebGLRenderer objects, but both assigned to the variable renderer. This breaks down the animation of the first (grid) object in the function renderGrid.
In your code are created 2 different scenes referenced by 2 different variables (sceneTop, scene2). Create 2 different render objects, referenced by 2 different variables (renderer, renderer2), too:
var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );
// [...]
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);
function renderGrid() {
// [...]
renderer2.render(scene2, camera2);
}
In the following you have to respect, that renderer corresponds to camera respectively sceneTop, but renderer2 corresponds to scene2 and camera2:
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
[...]
camera.position.z = 90;
function myrender(){
// [...]
renderer.render(sceneTop, camera);
requestAnimationFrame(myrender);
}
See the example, where I applied the suggested changes to your original code:
//GRID OBJ
var container = document.getElementById('grid')
var vertexHeight = 90,
planeDefinition = 25,
planeSize = 900,
totalObjects = 1,
background = "#002135",
meshColor = "#ff3057";
var camera2 = new THREE.PerspectiveCamera( 110, 1, 5)
camera2.position.y = 500;
var scene2 = new THREE.Scene();
scene2.background = new THREE.Color( 0x08080c);
var renderer2 = new THREE.WebGLRenderer({alpha: true});
renderer2.setClearColor( 0x000000, 0 );
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
color: meshColor,
wireframe: true
}));
plane.rotation.x -= Math.PI * .5;
scene2.add(plane);
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.setClearColor(background, 1);
container.appendChild(renderer2.domElement);
function updatePlane() {
for (var i = 0; i < planeGeo.vertices.length; i++) {
planeGeo.vertices[i].z += Math.random() * vertexHeight;
planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
}
};
var count = 0
function renderGrid() {
var gridSpeed = 0.4;
var gridInterlop = -0.4;
var gridWaveSpeed = 0.003;
var gridWaveHeight = 0.00003;
requestAnimationFrame(renderGrid);
for (var i = 0; i < planeGeo.vertices.length; i++) {
var z = +planeGeo.vertices[i].z;
planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
plane.geometry.verticesNeedUpdate = true;
count += gridInterlop
}
renderer2.render(scene2, camera2);
}
updatePlane();
renderGrid();
//BALL ITEM
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.autoClear = false;
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var sceneTop = new THREE.Scene(); // initialising the scene
sceneTop.background = new THREE.Color( 0x08080c);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100,100,100);
spotLight.castShadow = false;
sceneTop.add(spotLight);
function Mat(){
var material = new THREE.MeshPhongMaterial({
color : new THREE.Color(0xff3266),
emissive : new THREE.Color(0x08080c),
specular : new THREE.Color(0x08080c),
shininess : 0,
wireframe : true,
transparent: 0.5,
opacity : 0.55
});
return material;
}
var geometry = new THREE.IcosahedronGeometry(45 , 1);
var obj = new THREE.Mesh(geometry, Mat());
sceneTop.add(obj);
camera.position.z = 90;
function myrender(){
renderer.setClearColor( 0x000000, 0 );
obj.rotation.x += 0.0004;
obj.rotation.y += 0.0006;
obj.rotation.z += Math.random() * 0.0005;
renderer.render(sceneTop, camera);
requestAnimationFrame(myrender);
}
window.addEventListener('resize', onWindowResize, true);
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
renderer2.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
camera2.aspect = window.innerWidth / window.innerHeight;
camera2.updateProjectionMatrix();
};
myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<div id="grid"></div>
Alternatively both scenes can be rendered to different parts of the viewport.
Create 1 THREE.WebGLRenderer, with the .autoClear property set to false:
var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
Render both scenes 2 different parts of the viewport. The viewport rectangle can be changed by .setViewport:
function myrender(){
// [...]
renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
renderer.clear();
renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
renderer.render(sceneTop, camera, 0, false);
renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
renderer.render(scene2, camera2, 0, false);
requestAnimationFrame(myrender);
}
Ensure that the .background property is only set for the THREE.Scene which is rendered first.
See the example:
//GRID OBJ
var container = document.getElementById('grid')
var vertexHeight = 90,
planeDefinition = 25,
planeSize = 900,
totalObjects = 1,
background = "#002135",
meshColor = "#ff3057";
var renderer = new THREE.WebGLRenderer({alpha: true, preserveDrawingBuffer: true});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor( 0x000000, 0 );
renderer.autoClear = false;
document.body.appendChild(renderer.domElement);
var camera2 = new THREE.PerspectiveCamera( 110, window.innerWidth/2/window.innerHeight, 5)
camera2.position.y = 500;
var scene2 = new THREE.Scene();
var planeGeo = new THREE.PlaneGeometry(planeSize, planeSize, planeDefinition, planeDefinition);
var plane = new THREE.Mesh(planeGeo, new THREE.MeshBasicMaterial({
color: meshColor,
wireframe: true
}));
plane.rotation.x -= Math.PI * .5;
scene2.add(plane);
function updatePlane() {
for (var i = 0; i < planeGeo.vertices.length; i++) {
planeGeo.vertices[i].z += Math.random() * vertexHeight;
planeGeo.vertices[i]._myZ = planeGeo.vertices[i].z
}
};
var count = 0
updatePlane();
//BALL ITEM
var camera = new THREE.PerspectiveCamera(100, window.innerWidth/2/window.innerHeight, 0.1, 1000);
var sceneTop = new THREE.Scene(); // initialising the scene
sceneTop.background = new THREE.Color( 0x08080c);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(100,100,100);
spotLight.castShadow = false;
sceneTop.add(spotLight);
function Mat(){
var material = new THREE.MeshPhongMaterial({
color : new THREE.Color(0xff3266),
emissive : new THREE.Color(0x08080c),
specular : new THREE.Color(0x08080c),
shininess : 0,
wireframe : true,
transparent: 0.5,
opacity : 0.55
});
return material;
}
var geometry = new THREE.IcosahedronGeometry(45 , 1);
var obj = new THREE.Mesh(geometry, Mat());
sceneTop.add(obj);
camera.position.z = 90;
function myrender(){
var gridSpeed = 0.4;
var gridInterlop = -0.4;
var gridWaveSpeed = 0.003;
var gridWaveHeight = 0.00003;
for (var i = 0; i < planeGeo.vertices.length; i++) {
var z = +planeGeo.vertices[i].z;
planeGeo.vertices[i].z = Math.sin(( i + count * gridWaveHeight)) * (planeGeo.vertices[i]._myZ - (planeGeo.vertices[i]._myZ * gridWaveSpeed))
plane.geometry.verticesNeedUpdate = true;
count += gridInterlop
}
obj.rotation.x += 0.0004;
obj.rotation.y += 0.0006;
obj.rotation.z += Math.random() * 0.0005;
renderer.setViewport(0,0,window.innerWidth, window.innerHeight);
renderer.clear();
renderer.setViewport(window.innerWidth/2,0,window.innerWidth/2, window.innerHeight);
renderer.render(sceneTop, camera, 0, false);
renderer.setViewport(0,0,window.innerWidth/2, window.innerHeight);
renderer.render(scene2, camera2, 0, false);
requestAnimationFrame(myrender);
}
window.addEventListener('resize', onWindowResize, true);
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / 2 / window.innerHeight;
camera.updateProjectionMatrix();
camera2.aspect = window.innerWidth / 2 / window.innerHeight;
camera2.updateProjectionMatrix();
};
myrender();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>

How to create an infinite floor (skyline) in Three.js?

QUESTION:
So I came across this:
https://skin-tracker.com/pubg/outfit?no=000000000000000000000000000&set=1&char=1
I have the central ground area which is textured already in my code. But I have no idea how to make it extend up to the horizon like seen in the link.
It seems the person who coded what you see in the link hit some kind of limitation and had to use a single color for what extends beyond the central floor area.
How can I make my floor extend to the horizon/ create a skyline ?
CODE:
var floorTexture = new THREE.ImageUtils.loadTexture( '../../public/assets/grassTile.jpg' );
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set( 10, 10 );
var floorMaterial = new THREE.MeshBasicMaterial({ map: floorTexture, side: THREE.DoubleSide });
var floorGeometry = new THREE.PlaneGeometry(1000, 1000, 10, 10);
var mesh = new THREE.Mesh(floorGeometry, floorMaterial);
mesh.rotation.x = - Math.PI / 2;
mesh.receiveShadow = true;
scene.add( mesh );
You can simply create an enormous textured plane. I found no limitations with the example below. If you implement something like this and encounter errors/problems, update your question with the errors you're seeing.
// prepare the renderer
let WIDTH
let HEIGHT
let aspectRatio = function() {
return WIDTH / HEIGHT
}
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
})
document.body.appendChild(renderer.domElement)
const camera = new THREE.PerspectiveCamera(32, aspectRatio(), 1, 1000)
camera.position.set(0, 10, 50)
function resize() {
WIDTH = window.innerWidth
HEIGHT = window.innerHeight
renderer.setSize(WIDTH, HEIGHT)
camera.aspect = aspectRatio()
camera.updateProjectionMatrix()
}
resize()
window.addEventListener("resize", resize)
const scene = new THREE.Scene()
const light = new THREE.DirectionalLight(0xffffff, 1, Infinity)
light.position.set(0, 0, 1)
camera.add(light)
scene.add(camera)
const sun = new THREE.DirectionalLight(0xffffcc)
sun.position.set(0, 1, 0)
scene.add(sun)
// populate the scene
let geo = new THREE.BoxBufferGeometry(10, 10, 10)
let mat = new THREE.MeshLambertMaterial({
color: "red"
})
let mesh = new THREE.Mesh(geo, mat)
scene.add(mesh)
let tex = new THREE.TextureLoader().load("https://upload.wikimedia.org/wikipedia/commons/4/4c/Grass_Texture.png")
tex.anisotropy = 32
tex.repeat.set(100, 100)
tex.wrapT = THREE.RepeatWrapping
tex.wrapS = THREE.RepeatWrapping
geo = new THREE.PlaneBufferGeometry(10000, 10000)
mat = new THREE.MeshLambertMaterial({
map: tex
})
mesh = new THREE.Mesh(geo, mat)
mesh.position.set(0, -5, 0)
mesh.rotation.set(Math.PI / -2, 0, 0)
scene.add(mesh)
let axis = new THREE.Vector3(0, 1, 0)
function updateCamera() {
camera.position.applyAxisAngle(axis, 0.01)
}
// rendering functions
function render() {
renderer.render(scene, camera)
camera.lookAt(scene.position)
}
let animationLoopId = null
function animationLoop() {
animationLoopId = requestAnimationFrame(animationLoop)
updateCamera()
render()
}
animationLoop()
html,
body {
padding: 0;
margin: 0;
overflow: hidden;
background: skyBLue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.js"></script>

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>

Object on camera rotation isn't centered three js

I've created a 3D marquee by bending two meshes into a circle, however I'm having trouble getting them to center to the camera.
Please reference https://jsfiddle.net/siiiick/1jh49e1u/
var text = "EXPRESS FREE SHIPPING WORLDWIDE OVER 200€ / 200% 150$ ";
var geoParams = {
size: 208,
height: 1,
curveSegments: 4,
font: "junicode",
// bevelEnabled: false,
// bevelThickness: 1,
// bevelSize: 1,
}
var textMaterial = new THREE.MeshPhongMaterial({
color: 0x000000
});
var deg = Math.PI / 4.8;
var geoTop = new THREE.TextGeometry(text, geoParams);
var textTop = new THREE.Mesh(geoTop, textMaterial);
geoTop.computeBoundingBox();
textWidth = geoTop.boundingBox.max.x - geoTop.boundingBox.min.x;
controls.target.set(-textWidth * .1 - 10, 0, -textWidth / 3.8);
textTop.rotation.y = Math.PI;
modifier.set(new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, 1, 0), deg).modify(textTop.geometry);
modifier.set(new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, 1, 0), deg).modify(textTop.geometry);
textTop.position.set(-0.5 * textWidth + textWidth * .867, 0, -textWidth * .577);
var geoBot = new THREE.TextGeometry(text, geoParams);
var textBot = new THREE.Mesh(geoBot, textMaterial);
modifier.set(new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, 1, 0), deg).modify(textBot.geometry);
modifier.set(new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, 1, 0), deg).modify(textBot.geometry);
textBot.position.set(-0.5 * textWidth, 0, 0);
scene.add(textTop);
scene.add(textBot);
As you can see after a few seconds the the marquee isn't centered. Do you think it's as a result of the camera positioning or the mesh positioning?
Thanks
//Testing some easy camera centering code...
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 light2 = new THREE.PointLight(0x00FFFF);
light2.position.set(-20, 20, -20);
scene.add(light2);
var light3 = new THREE.PointLight(0xFF00FF);
light3.position.set(-20, -20, -20);
scene.add(light3);
var sphereGeom = new THREE.SphereGeometry(5, 16, 16);
var material = new THREE.MeshLambertMaterial({
color: 0x808080
});
var mesh = new THREE.Mesh(sphereGeom, material);
scene.add(mesh);
var mesh1 = new THREE.Mesh(sphereGeom, material);
mesh1.position.x += 5;
mesh.add(mesh1);
var mesh2 = new THREE.Mesh(sphereGeom, material);
mesh2.position.y += 5;
mesh2.position.x += 9;
mesh.add(mesh2);
var grp0 = mesh;
var mesh = new THREE.Mesh(sphereGeom, material);
scene.add(mesh);
mesh.position.x += 30;
var mesh1 = new THREE.Mesh(sphereGeom, material);
mesh1.position.x += 15;
mesh.add(mesh1);
var mesh2 = new THREE.Mesh(sphereGeom, material);
mesh2.position.y += 12;
mesh2.position.x += 9;
mesh.add(mesh2);
renderer.setClearColor(0xdddddd, 1);
var grp1 = mesh;
var curGrp;
var targPos;
var targLook;
var tmp = new THREE.Vector3();
var vbox;
function focusCam(targ) {
const boundingBox = new THREE.Box3();
boundingBox.setFromObject(targ)
var center = boundingBox.getCenter(new THREE.Vector3())
var sz = boundingBox.getSize(new THREE.Vector3());
var minZ = sz.length() + camera.near;
var lookOffset = new THREE.Vector3(0, 0, 1);
lookOffset.applyQuaternion(camera.quaternion);
lookOffset.multiplyScalar(minZ)
targLook = center.clone();
targPos = new THREE.Vector3().copy(center).add(lookOffset)
if (!vbox) {
vbox = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), material.clone())
vbox.material.transparent = true;
vbox.material.opacity = 0.15;
scene.add(vbox)
}
vbox.scale.copy(sz);
vbox.position.copy(center);
}
renderer.domElement.onclick = (evt) => {
if (!curGrp) {
curGrp = grp0;
} else if (curGrp === grp0) {
curGrp = grp1
} else if (curGrp === grp1) {
curGrp = grp0
}
focusCam(curGrp);
}
(function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
if (targPos) {
tmp.copy(targPos).sub(camera.position).multiplyScalar(0.01)
if (tmp.length() > 0.01) {
camera.position.add(tmp)
controls.target.add(tmp);//copy(targLook);
//camera.lookAt(targLook);
} else targPos = undefined;
}
})();
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>

Categories