THREE.js PlaneGeometry Converting a triangle drawing to a square - javascript

In the link below there is an animation created with triangles. How can I convert triangular areas into squares? A line runs through the middle when using "PlaneGeometry". When this line is deleted, the triangles turn into squares.
https://codepen.io/UIUXLab/pen/pBRzRZ
I want it like in the picture.
( function( $ ) {
"use strict";
$( function() {
var $window = $( window ),
windowWidth = window.innerWidth,
windowHeight = window.innerHeight,
rendererCanvasID = '3D-background-three-canvas5';
// Generate one plane geometries mesh to scene
//-------------------------------------
var camera,
scene,
material,
group,
lights = [],
renderer,
shaderSprite,
clock = new THREE.Clock();
var geometry, plane, simplex;
var factor = 300,
speed = 0.0005, // terrain size
cycle = 0, //move speed
scale = 30; // smoothness
init();
render();
function init() {
//camera
camera = new THREE.PerspectiveCamera( 60, windowWidth / windowHeight, 1, 10000 );
camera.position.set( 0, 0, 100 );
//Scene
scene = new THREE.Scene();
//HemisphereLight
lights[ 0 ] = new THREE.PointLight( 0xff0000, 1, 0 );
lights[ 1 ] = new THREE.PointLight( 0x0000ff, 1, 0 );
lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 0 ].position.set( 0, 200, 0 );
lights[ 1 ].position.set( 100, 200, 100 );
lights[ 2 ].position.set( - 100, - 200, - 100 );
scene.add( lights[ 0 ] );
scene.add( lights[ 1 ] );
scene.add( lights[ 2 ] );
//WebGL Renderer
renderer = new THREE.WebGLRenderer( {
canvas : document.getElementById( rendererCanvasID ), //canvas
alpha : true,
antialias: true
} );
renderer.setSize( windowWidth, windowHeight );
// Immediately use the texture for material creation
group = new THREE.Object3D();
group.position.set(0,-300,-1000);
group.rotation.set(29.8,0,0);
geometry = new THREE.PlaneGeometry(4000, 2000, 128, 64);
material = new THREE.MeshLambertMaterial({
color: 0xffffff,
opacity: 1,
blending: THREE.NoBlending,
side: THREE.FrontSide,
transparent: false,
depthTest: false,
wireframe: true
});
plane = new THREE.Mesh(geometry, material);
plane.position.set(0, 0, 0);
simplex = new SimplexNoise();
moveNoise();
group.add(plane);
scene.add(group);
// Fires when the window changes
window.addEventListener( 'resize', onWindowResize, false );
}
function render() {
requestAnimationFrame( render );
var delta = clock.getDelta();
//To set a background color.
renderer.setClearColor( 0x000000 );
//change noise values over time
moveNoise();
//update sprite
cycle -= delta * 0.5;
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function moveNoise() {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = geometry.vertices[Symbol.iterator](), _step2; ! (_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var vertex = _step2.value;
var xoff = vertex.x / factor;
var yoff = vertex.y / factor + cycle;
var rand = simplex.noise2D(xoff, yoff) * scale;
vertex.z = rand;
}
} catch(err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2.
return != null) {
_iterator2.
return ();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
geometry.verticesNeedUpdate = true;
cycle += speed;
}
} );
} ) ( jQuery );
The middle line should disappear.
https://threejs.org/docs/#api/en/geometries/PlaneGeometry

You can change index of a plane geometry, and then use the geometry with LineSegments.
See this forum topic: Wireframe of quads
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three#0.136.0/examples/jsm/controls/OrbitControls";
import { ImprovedNoise } from 'https://cdn.skypack.dev/three#0.136.0/examples/jsm/math/ImprovedNoise.js';
let perlin = new ImprovedNoise()
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 5, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", event => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
let controls = new OrbitControls(camera, renderer.domElement);
let g = new THREE.PlaneGeometry(20, 20, 50, 50);
let pos = g.attributes.position;
let uvs = g.attributes.uv;
let uv = new THREE.Vector2();
for(let i = 0; i < pos.count; i++){pos
uv.fromBufferAttribute(uvs, i);
uv.multiplyScalar(5);
let z = perlin.noise(uv.x, uv.y, 0) * 3;
pos.setZ(i, z);
}
g.rotateX(-Math.PI * 0.5);
ToQuads(g); // change the index
let m = new THREE.LineBasicMaterial({color: "magenta"});
let o = new THREE.LineSegments(g, m);
scene.add(o);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
function ToQuads(g) {
let p = g.parameters;
let segmentsX = (g.type == "TorusBufferGeometry" ? p.tubularSegments : p.radialSegments) || p.widthSegments || p.thetaSegments || (p.points.length - 1) || 1;
let segmentsY = (g.type == "TorusBufferGeometry" ? p.radialSegments : p.tubularSegments) || p.heightSegments || p.phiSegments || p.segments || 1;
let indices = [];
for (let i = 0; i < segmentsY + 1; i++) {
let index11 = 0;
let index12 = 0;
for (let j = 0; j < segmentsX; j++) {
index11 = (segmentsX + 1) * i + j;
index12 = index11 + 1;
let index21 = index11;
let index22 = index11 + (segmentsX + 1);
indices.push(index11, index12);
if (index22 < ((segmentsX + 1) * (segmentsY + 1) - 1)) {
indices.push(index21, index22);
}
}
if ((index12 + segmentsX + 1) <= ((segmentsX + 1) * (segmentsY + 1) - 1)) {
indices.push(index12, index12 + segmentsX + 1);
}
}
g.setIndex(indices);
}
</script>

Related

Three.js - How to update a PlaneBufferGeometry?

I'm trying to create an ocean for my Three.js application. I took the example from this site:
https://codepen.io/RemiRuc/pen/gJMwOe?fbclid=IwAR2caTQL-AOPE2Gv6x4rzSWBrOmAh2j-raqesOO0XbYQAuSG37imbMszSis
var params = {
res : 32,
speed : 8,
amp : 2,
wireframe : true,
backgroundColor : 0x9c81e3,
planeColor : 0x4a4a4a
}
var scene = new THREE.Scene();
scene.background = new THREE.Color(params.backgroundColor)
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 )
let canvas = document.getElementById("webgl")
var renderer = new THREE.WebGLRenderer({canvas:canvas, antialias: true})
renderer.setSize( window.innerWidth, window.innerHeight )
var simplex = new SimplexNoise()
var light = new THREE.AmbientLight( 0xcccccc ); // soft white light
scene.add( light );
var pointLight = new THREE.PointLight( 0xeeeeee, 1, 100 );
pointLight.position.set( 0, 20, -20 );
scene.add( pointLight );
let geometry, material, plane
createPlane()
camera.position.z = 5;
camera.position.y = 3;
camera.lookAt(new THREE.Vector3( 0, 3, 0 ))
var animate = function () {
requestAnimationFrame( animate );
for (var i = 0; i < geometry.vertices.length; i++) {
var z = (i + Date.now() * params.speed/100000)
geometry.vertices[i].z = simplex.noise4D(z,z,z,z) * params.amp
plane.geometry.verticesNeedUpdate = true;
}
scene.background = new THREE.Color(params.backgroundColor)
material.color = new THREE.Color(params.planeColor)
material.wireframe = params.wireframe
camera.rotation.y += 0.001
renderer.render( scene, camera );
};
animate();
function createPlane(){
geometry = new THREE.PlaneGeometry( 200, 200, params.res,params.res );
material = new THREE.MeshLambertMaterial( {color: params.planeColor, side: THREE.DoubleSide, wireframe: params.wireframe} );
plane = new THREE.Mesh( geometry, material );
scene.add( plane );
plane.rotation.x = Math.PI/2
}
/***RESIZE***/
window.addEventListener('resize', ()=>{
document.querySelector('canvas').style.width = window.innerWidth + "px"
document.querySelector('canvas').style.height = window.innerHeight + "px"
renderer.setSize( window.innerWidth, window.innerHeight )
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
})
var gui = new dat.GUI()
var controller = gui.add(params, "res", 0, 100).name("Plane resolution")
gui.add(params, "speed", 0, 500).name("Wave speed")
gui.add(params, "amp", 0, 20).name("Wave amplitude")
gui.add(params, "wireframe", 0, 20).name("Wireframe")
gui.addColor(params, "backgroundColor").name("Background color")
gui.addColor(params, "planeColor").name("Plane color")
controller.onChange(()=>{
scene.remove(plane)
createPlane()
})
Issue is, I'm using PlaneBufferGeometry instead of PlaneGeometry, and it seems there are some differences
My code in render after creating the waterPlane
for (var i = 0; i < waterGeometry.attributes.position.count; i++) {
var z = (i + Date.now() * params.speed/100000);
waterGeometry.attributes.position[i] = simplex.noise4D(z,z,z,z) * params.amp;
}
waterGeometry.attributes.position.needsUpdate = true;
waterPlaneMesh.attributes.position.needsUpdate = true;
I'm not getting any errors, but no matter what I do, all I get is a flat wireframe plane geometry that doesn't move or anything. I think issue is in the updating of the plane?
This is an example of how you can displace vertices of a buffer geometry, using that SimplexNoise library:
body {
margin: 0;
background-color: #000;
color: #fff;
font-family: Monospace;
font-size: 13px;
line-height: 24px;
overscroll-behavior: none;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.136.0";
import { OrbitControls } from "https://cdn.skypack.dev/three#0.136.0/examples/jsm/controls/OrbitControls";
import { createNoise3D } from "https://cdn.skypack.dev/simplex-noise";
let simplex = createNoise3D();
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 2000);
camera.position.set(0, 0.5, 1).setLength(12);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", onWindowResize);
//scene.add(new THREE.GridHelper())
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 0.5);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let v3 = new THREE.Vector3();
let v2 = new THREE.Vector2();
let g = new THREE.PlaneGeometry(200, 200, 100, 100);
g.rotateX(-Math.PI *0.5);
let m = new THREE.MeshLambertMaterial({color: "aqua", wireframe: false});
let o = new THREE.Mesh(g, m);
scene.add(o);
let clock = new THREE.Clock();
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
let t = clock.getElapsedTime();
for(let i = 0; i < g.attributes.position.count; i++){
v2.fromBufferAttribute(g.attributes.uv, i).addScalar(t * 0.01).multiplyScalar(20);
let h = simplex(v2.x, v2.y, t * 0.1);
g.attributes.position.setY(i, h);
}
g.computeVertexNormals();
g.attributes.position.needsUpdate = true;
});
function onWindowResize() {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
}
</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>

Three js lookAt function failing

I have the following scene visable here: http://gravient.thomashoek.com/drag_example/
In the initial mode the text looks at the mouse. but when you make sertain mouse movements the text seems to flip the direct of looking at the mouse. As far as i figured out this happens when the mouse crosses the middle of the canvas.
A quick in depth explanation of the problem: So when the mouse is at the top of the screen the mesh looks at the bottom of the screen. And this is the same for all directions.
But when you move the mouse again in a certain undefined manner the problem fixes it self.
So my question is: How can i prevent this from happening?
My code to do the lookAt is as following:
var data = {
text : ["THE NEXT","POINT","OF VIEW"],
size : 5,
height : 2,
curveSegments : 12,
line_height : 1.7
};
function generateTextGeometry(mesh) {
var y_start = (0 - data.text.length * data.size / 2 - data.size / 2 - (data.text.length - 1) * data.line_height)/2;
var loader = new THREE.FontLoader();
loader.load( '../data/suisse_2.json', function ( font ) {
for (var i = data.text.length - 1; i >= 0; i--) {
var geometry = new THREE.TextGeometry( data.text[i], {
font: font,
size: data.size,
height: data.height,
curveSegments: data.curveSegments
});
geometry.center();
mesh.children[i].geometry = geometry;
mesh.children[i].position.y = y_start;
if (i < data.text.length) {
y_start += (data.size + data.line_height);
}else{
y_start += data.size;
}
}
});
}
//global vars for al the desired options all are false because we dont know if it will work.
var current_interaction_mode = null;
var webcam = false;
var gyroscope = false;
var followMouse = false;
var dragMouse = true;
var rotation_vals = {
x: -0.51,
y: 0.51,
range: 0.2
}
check_user_hardware();
//check if all the wanted options are available
function check_user_hardware(){
window.addEventListener("devicemotion", function(event){
if(event.rotationRate.alpha || event.rotationRate.beta || event.rotationRate.gamma){
if (!gyroscope) {
gyroscope = true;
current_interaction_mode = 'gyroscope_option';
set_user_ui_elements();
}
}else{
followMouse = true;
current_interaction_mode = 'followMouse_option';
set_user_ui_elements();
window.addEventListener('mousemove', get_user_mouse_pos);
}
calculate_rotation_mesh_pos(event.rotationRate.beta, event.rotationRate.gamma);
});
}
function get_user_mouse_pos(event){
rotation_vals.x = ( event.clientX / window.innerWidth ) * 2 - 1;
rotation_vals.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
}
function calculate_rotation_mesh_pos(x_angle, y_angle){
// rotation_vals.x = some calculation that needs to be done here
// rotation_vals.y = some calculation that needs to be done here
}
function set_user_ui_elements(){
if (followMouse) {
$('#followMouse_option').show();
}
if (gyroscope) {
$('#gyroscope_option').show();
}
if (dragMouse) {
$('#dragMouse_option').show();
}
if (current_interaction_mode == 'followMouse_option') $('#followMouse_option').css('color', '#ff0000');
if (current_interaction_mode == 'gyroscope_option') $('#gyroscope_option').css('color', '#ff0000');
}
var scene = new THREE.Scene();
var camera = new THREE.OrthographicCamera( window.innerWidth / - 40, window.innerWidth / 40, window.innerHeight / 40, window.innerHeight / - 40, 0, 2000 );
camera.position.z = 1000;
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000, 1 );
document.getElementById('interactive_container').appendChild( renderer.domElement );
//set up interaction parameters
var fakeMouseLoc = new THREE.Vector3();
var orbit = new THREE.OrbitControls( camera, renderer.domElement );
orbit.enableZoom = false;
orbit.enableKeys = false;
orbit.enablePan = false;
orbit.enabled = false;
//generate the text mesh
var mesh = new THREE.Object3D();
for (var i = data.text.length - 1; i >= 0; i--) {
mesh.add( new THREE.Mesh(
new THREE.Geometry(),
new THREE.MeshBasicMaterial({
color: 0xFFFFFF
})
));
}
var options = generateTextGeometry(mesh);
scene.add( mesh );
var render = function(){
if (current_interaction_mode == 'followMouse_option' || current_interaction_mode == 'gyroscope_option') {
fakeMouseLoc.set(rotation_vals.x, rotation_vals.y, rotation_vals.range);
mesh.lookAt(fakeMouseLoc);
}
renderer.render( scene, camera );
requestAnimationFrame( render );
};
render();
window.addEventListener( 'resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
function add_geometry_to_container(container){
container.add( new THREE.Mesh(
new THREE.Geometry(),
new THREE.MeshBasicMaterial({
color: 0xFFFFFF
})
));
}
function clear_geometry_of_container(container, empty){
if (!empty) {
container.children[0].geometry.dispose();
container.children[0].material.dispose();
container.remove(container.children[0]);
}else{
for (var i = container.children.length - 1; i >= 0; i--) {
container.children[i].geometry.dispose();
container.children[i].material.dispose();
container.remove(container.children[i]);
}
}
}
function invert_color(state){
if(state){
console.log("switch to white bg");
renderer.setClearColor( 0xFFFFFF, 1 );
for (var i = data.text.length - 1; i >= 0; i--) {
mesh.children[i].material.color.setHex( 0x000000, 1 );
}
}else{
console.log("switch to black bg");
renderer.setClearColor( 0x000000, 1 );
for (var i = data.text.length - 1; i >= 0; i--) {
mesh.children[i].material.color.setHex( 0xFFFFFF, 1 );
}
}
}
<script src="../supporting_files/general/jquery-3.1.0.min.js"></script>
<script src="../supporting_files/3d_interactive/three.min.js"></script>
<script src="../supporting_files/3d_interactive/OrbitControls.js"></script>
<script src='../supporting_files/3d_interactive/geometry.js'></script>
<script src="../supporting_files/general/check_features.js"></script>
<script src="../supporting_files/main_page_js/desktop_main.js"></script>
<script src="../supporting_files/3d_interactive/main_3d_scene.js"></script>
If you need more info, context or something is unclear pls let me know so i can clarify :)

How to constrain objects in a box/cylinder container in Physijs (with Three.js)

I wrote a program to randomly generate and put ConvexGeometry object into a box container based on Physijs's example shapes.
Everything goes well until too many objects are put into the container, objects just struggle to fly out of the box .
Here is the code to initialize scene:
initScene = function() {
TWEEN.start();
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
document.getElementById( 'viewport' ).appendChild( renderer.domElement );
render_stats = new Stats();
render_stats.domElement.style.position = 'absolute';
render_stats.domElement.style.top = '0px';
render_stats.domElement.style.zIndex = 100;
document.getElementById( 'viewport' ).appendChild( render_stats.domElement );
physics_stats = new Stats();
physics_stats.domElement.style.position = 'absolute';
physics_stats.domElement.style.top = '50px';
physics_stats.domElement.style.zIndex = 100;
document.getElementById( 'viewport' ).appendChild( physics_stats.domElement );
scene = new Physijs.Scene({ fixedTimeStep: 1 / 120 });
scene.setGravity(new THREE.Vector3( 0, -30, 0 ));
scene.addEventListener(
'update',
function() {
scene.simulate( undefined, 2 );
physics_stats.update();
}
);
camera = new THREE.PerspectiveCamera(
35,
window.innerWidth / window.innerHeight,
1,
1000
);
camera.position.set( 150, 120, 150 );
camera.lookAt( scene.position );
scene.add( camera );
// Materials
wall_material = Physijs.createMaterial(
new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 1 } )
);
ground_material = Physijs.createMaterial(
new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture( 'images/rocks.jpg' ) }),
.8, // high friction
.4 // low restitution
);
ground_material.map.wrapS = ground_material.map.wrapT = THREE.RepeatWrapping;
ground_material.map.repeat.set( 2.5, 2.5 );
// Ground
ground = new Physijs.BoxMesh(
new THREE.BoxGeometry(50, 1, 50),
//new THREE.PlaneGeometry(50, 50),
ground_material,
0 // mass
);
ground.receiveShadow = true;
scene.add( ground );
// Bumpers
var bumper,
bumper_geom = new THREE.BoxGeometry(1, 50, 50);
// Back left
bumper = new Physijs.BoxMesh( bumper_geom, ground_material, 0, { restitution: .2 } );
bumper.position.y = 25;
bumper.position.x = -25;
bumper.receiveShadow = true;
bumper.castShadow = true;
scene.add( bumper );
// Front right
bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
bumper.position.y = 25;
bumper.position.x = 25;
bumper.receiveShadow = true;
bumper.castShadow = true;
scene.add( bumper );
// Back right
bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
bumper.position.y = 25;
bumper.position.z = -25;
bumper.rotation.y = Math.PI / 2;
bumper.receiveShadow = true;
bumper.castShadow = true;
scene.add( bumper );
// Front left
bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
bumper.position.y = 25;
bumper.position.z = 25;
bumper.rotation.y = Math.PI / 2;
bumper.receiveShadow = true;
bumper.castShadow = true;
scene.add( bumper );
// Top
bumper = new Physijs.BoxMesh( bumper_geom, wall_material, 0, { restitution: .2 } );
bumper.position.y = 50;
bumper.position.x = 0;
bumper.position.z = 0;
bumper.rotation.z = Math.PI / 2;
bumper.receiveShadow = true;
bumper.castShadow = true;
scene.add( bumper );
requestAnimationFrame( render );
scene.simulate();
createShape();
};
Create shapes:
createShape = (function() {
var addshapes = true,
doCreateShape;
setTimeout(
function addListener() {
var button = document.getElementById( 'stop' );
if ( button ) {
button.addEventListener( 'click', function() { addshapes = false; } );
} else {
setTimeout( addListener );
}
}
);
doCreateShape = function() {
var shape, material = new THREE.MeshLambertMaterial({ opacity: 0, transparent: true });
var minR = 5, maxR = 10;
var minVertices = 4, maxVertices = 6;
var sphere = randomSphereInBox(minR, maxR, {vertex3A: new THREE.Vector3(0, 0, 0), vertex3B: new THREE.Vector3(50, 50, 50)});
var convex_geometry = randomConvexInSphere(minVertices, maxVertices, sphere);
shape = new Physijs.BoxMesh(
convex_geometry,
material
);
shape.material.color.setRGB( Math.random() * 100 / 100, Math.random() * 100 / 100, Math.random() * 100 / 100 );
shape.castShadow = false;
shape.receiveShadow = false;
shape.position.set(
Math.random() * 30 - 15,
40,
Math.random() * 30 - 15
);
if ( addshapes ) {
shape.addEventListener( 'ready', createShape );
}
scene.add( shape );
new TWEEN.Tween(shape.material).to({opacity: 1}, 500).start();
document.getElementById( 'shapecount' ).textContent = ( ++shapes ) + ' shapes created';
};
return function() {
setTimeout( doCreateShape, 10 );
};
})();
Is there any way to constrain all the objects within the container?
Well, the fact that the objects are bouncing out of the box is because you are overloading it to the point where the objects altogether are "too big" for the containement box, leading to leaks. I don't think there is a real fix to this as this is always a problem in physics engines, but it doesn't hurt to try and plug a hole, right?
You could try using the object's own addEventListener method to check for collisions with the containement box and if so, set the position of itself to the center of the containement box, avoiding any extra collisions for a while:
doCreateShape = function(){
// ...
shape.addEventListener('collision', function(collidedWith, lineVel, angleVel){
if(collidedWith.material == wall_material){ // If it actually collided with a wall
this.__dirtyPosition = true; // To actively change the object position
this.position.x = 0;
this.position.y = 40;
this.position.z = 0;
}
});
scene.add(shape);
// ...
}
Just make sure that the wall_material variable is global.
Also, setting the restitution of all objects to 0 will lessen bouncing inside the container.

Change vertice position on mousehover

I have a PlaneGeometry and I want to modify the z position of the vertice hovered but I don't know how to retrieve it.
//THREE.WebGLRenderer 69
// Generating plane
var geometryPlane = new THREE.PlaneGeometry( 100, 100, 20, 10 );
for (var vertIndex = 0; vertIndex < geometryPlane.vertices.length; vertIndex++) {
geometryPlane.vertices[vertIndex].z += Math.random();
}
geometryPlane.dynamic = true;
geometryPlane.computeFaceNormals();
geometryPlane.normalsNeedUpdate = true;
var materialPlane = new THREE.MeshLambertMaterial( {
color: 0xffff00,
side: THREE.DoubleSide,
shading: THREE.FlatShading,
overdraw: 0.5,
vertexColors: THREE.FaceColors
} );
plane = new THREE.Mesh( geometryPlane, materialPlane );
plane.geometry.colorsNeedUpdate = true;
// Mouse event
container[0].addEventListener( 'mousemove', onMouseMove, false );
function onMouseMove( event ) {
var mouseX = ( event.clientX / window.innerWidth ) * 2 - 1;
var mouseY = -( event.clientY / window.innerHeight ) * 2 + 1;
var vector = new THREE.Vector3( mouseX, mouseY, camera.near );
vector.unproject( camera );
raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
if ( intersects.length > 0 ) {
// Change the z position of the selected vertice
var selectedVertice = ???
selectedVertice.position.z +=5;
}
}
If the question concerns one vertex and not the whole object maybe you can :
1- retrieve the intersection face in intersects[0].face
2- this face may contain 3 vertices (it is probably a THREE.Face3) : find the nearest vertex V with the intersection point intersects[0].point.
3- change V.z
I don't know if it works : it is an idea... ;)
You can modify the Z position of the intersected object like this
intersects[0].object.position.z+=10;
You can refer to the code snippet below for demo/code.
var container, stats;
var camera, scene, raycaster, renderer;
var mouse = new THREE.Vector2(),
INTERSECTED;
var radius = 100,
theta = 0;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
var info = document.createElement('div');
info.style.position = 'absolute';
info.style.top = '10px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.innerHTML = 'three.js webgl - interactive cubes';
container.appendChild(info);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
scene = new THREE.Scene();
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(1, 1, 1).normalize();
scene.add(light);
var geometry = new THREE.PlaneGeometry (50, 50, 50);
for (var i = 0; i < 500; i++) {
var object = new THREE.Mesh(geometry, new THREE.MeshLambertMaterial({
color: Math.random() * 0xffffff
}));
object.position.x = Math.random() * 800 - 400;
object.position.y = Math.random() * 800 - 400;
object.position.z = Math.random() * 800 - 400;
object.rotation.x = Math.random() * 2 * Math.PI;
object.rotation.y = Math.random() * 2 * Math.PI;
object.rotation.z = Math.random() * 2 * Math.PI;
object.scale.x = Math.random() + 0.5;
object.scale.y = Math.random() + 0.5;
object.scale.z = Math.random() + 0.5;
scene.add(object);
}
raycaster = new THREE.Raycaster();
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xf0f0f0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.sortObjects = false;
container.appendChild(renderer.domElement);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
container.appendChild(stats.domElement);
document.addEventListener('mousemove', onDocumentMouseMove, false);
//
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function onDocumentMouseMove(event) {
event.preventDefault();
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
//
function animate() {
requestAnimationFrame(animate);
render();
stats.update();
}
function render() {
// find intersections
var vector = new THREE.Vector3(mouse.x, mouse.y, 1).unproject(camera);
raycaster.set(camera.position, vector.sub(camera.position).normalize());
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
if (INTERSECTED != intersects[0].object) {
console.log(intersects[0].point);
console.log(intersects[0].object.position);
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
/*******************************************************************/
/// You can change the Z position like the way done below
intersects[0].object.position.z+=10;
/********************************************************************/
INTERSECTED = intersects[0].object;
INTERSECTED.currentHex = INTERSECTED.material.emissive.getHex();
INTERSECTED.material.emissive.setHex(0xff0000);
}
} else {
if (INTERSECTED) INTERSECTED.material.emissive.setHex(INTERSECTED.currentHex);
INTERSECTED = null;
}
renderer.render(scene, camera);
}
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>

Categories