Remove widthSegments and heightSegments in PlaneGeometry threejs - javascript

I am trying to remove the widthSegments and heightSegments.
If i change this
var tergeo= new THREE.PlaneGeometry(100, 100, 1, 1);
to
var tergeo= new THREE.PlaneGeometry(100, 100, 0, 0);
It does not work
How can i remove widthSegments and heightSegments in this jsFiddle ?

Here is an option with an indexed buffer geometry:
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three#0.136.0";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
let g = QuadGeometry(THREE.MathUtils.randInt(5, 10), THREE.MathUtils.randInt(5, 10));
let m = new THREE.LineBasicMaterial({color: "yellow"});
let quad = new THREE.Line(g, m);
scene.add(quad);
function QuadGeometry(w, h){
let pts = [
[0.5, 0.5],
[-0.5, 0.5],
[-0.5, -0.5],
[0.5, -0.5]
].map(p => {return new THREE.Vector2(p[0], p[1])});
let g = new THREE.BufferGeometry().setFromPoints(pts);
g.setIndex([0, 1, 2, 3, 0]);
g.scale(w, h, 1);
return g;
}
renderer.setAnimationLoop(() => {
renderer.render(scene, camera);
});
</script>

Related

threejs transparent material blending

Blending multiple transparent meshes causes strange behavior: only the first mesh is drawn, the inner meshes are hidden at the intersection. This only happens within a certain camera angle range.
Can is be fixed? Why does this only happen at certain angles?
Tested with r142 and r143. Browser Chrome 104.0.5112.81.
Partially expected behaviour:
Strange blending:
Expected behaviour:
canvas {
position: absolute;
top: 0;
left: 0;
}
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three#0.142.0/build/three.module.js",
"OrbitControls": "https://unpkg.com/three#0.142.0/examples/jsm/controls/OrbitControls.js"
}
}
</script>
<script type="module">
import * as THREE from "three";
import { OrbitControls } from "OrbitControls";
/* -- */
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
const ambientLight = new THREE.AmbientLight(0xffffff);
scene.add(ambientLight);
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);
camera.position.set(0, 0, 5);
const controls = new OrbitControls(camera, renderer.domElement);
/* -- */
const length = 7;
const points = [
new THREE.Vector3(0, -length / 2, 0),
new THREE.Vector3(0, length / 2, 0)
];
const curve = new THREE.CatmullRomCurve3(points);
const createMeshOnScene = (scene, geometry, material, position) => {
const mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(position);
scene.add(mesh);
return mesh;
};
const transparentMaterial = (color) => {
return new THREE.MeshStandardMaterial({
color: color,
side: THREE.DoubleSide,
transparent: true,
opacity: 0.6,
metalness: 0,
roughness: 1
});
};
const opaqueMaterial = new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 0,
roughness: 1
});
createMeshOnScene(
scene,
new THREE.TubeGeometry(curve, 2, 0.2, 16),
opaqueMaterial,
new THREE.Vector3(0, -0.4, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0xaa0000),
new THREE.Vector3(0, 0, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0xaaaa00),
new THREE.Vector3(0, -0.3, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0x00aa00),
new THREE.Vector3(0, -0.6, 0)
);
createMeshOnScene(
scene,
new THREE.ConeGeometry(2, 2, 4, 1, true, 0, Math.PI * 1.6),
transparentMaterial(0x00aaaa),
new THREE.Vector3(0, -0.9, 0)
);
/* -- */
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
/* -- */
window.addEventListener("resize", resize);
function resize() {
let width = window.innerWidth;
let height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize(width, height);
}
resize();
</script>

Three.js - How to pre-position objects to merge?

I've successfully merged my cubes, although they seem to merge together reverting back to their original position/rotation, ignoring the declared positioning/rotation
var geometries = [];
cube1.position.set( 0, 0, 0 );
geometries.push( cube1 );
cube2.position.set( 1, 0, 0 );
geometries.push( cube2 );
cube3.position.set( 0, 1, 0 );
geometries.push( cube3 );
const cubes = BufferGeometryUtils.mergeBufferGeometries( geometries );
scene.add( cubes );//All the cubes get merged on 0, 0, 0 - overlapping one another
How do I position the cubes so they can be merged in their declared positions?
Here is a working example of using BufferGeometryUtils and .applyMatrix4():
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.js";
import * as BufferGeometryUtils from "https://cdn.skypack.dev/three#0.136.0/examples/jsm/utils/BufferGeometryUtils";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.setScalar(1).setLength(6);
let renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(innerWidth, innerHeight);
renderer.setClearColor(0x404040);
document.body.appendChild(renderer.domElement);
let controls = new OrbitControls(camera, renderer.domElement);
let light = new THREE.DirectionalLight(0xffffff, 1);
light.position.setScalar(1);
scene.add(light, new THREE.AmbientLight(0xffffff, 0.5));
let boxes = [
makeBox(2, 0, 0, 0xff0000),
makeBox(0, 2, 0, 0x00ff00),
makeBox(0, 0, 2, 0x0000ff)
];
let materials = [];
let g = BufferGeometryUtils.mergeBufferGeometries(boxes.map(b => {
materials.push(b.material);
b.updateMatrixWorld(); // needs to be done to be sure that all transformations are applied
return b.geometry.applyMatrix4(b.matrixWorld);
}), true);
let o = new THREE.Mesh(g, materials);
scene.add(o);
window.addEventListener("resize", onWindowResize);
animate();
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
}
function makeBox(x, y, z, color) {
let g = new THREE.BoxGeometry();
let m = new THREE.MeshLambertMaterial({
color: color
});
let box = new THREE.Mesh(g, m);
box.position.set(x, y, z);
return box;
}
</script>

Dashed moving line React Three Fiber

I wanted to know if I can do an effect similar to this: https://reactflow.dev/
With a dashed moving line that signals the direction.
Using r3f but normal three.js is also fine
I also would like that type of background but if I can make the arrow work is also fine.
Just extend LineDashedMaterial with .onBeforeCompile, adding time uniform:
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 5);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
let g = new THREE.BufferGeometry().setFromPoints([
new THREE.Vector2(-2, 2, 0),
new THREE.Vector2(0, -2, 0),
new THREE.Vector2(2, 2, 0)
]);
let uniforms = {
time: {value: 0}
}
let m = new THREE.LineDashedMaterial({
color: "yellow",
dashSize: 0.5,
gapSize: 0.25,
onBeforeCompile: shader => {
shader.uniforms.time = uniforms.time;
shader.fragmentShader = `
uniform float time;
${shader.fragmentShader}
`.replace(
`vLineDistance,`,
`vLineDistance - time,`
);
//console.log(shader.fragmentShader);
}
});
let l = new THREE.Line(g, m);
l.computeLineDistances();
scene.add(l);
let clock = new THREE.Clock();
renderer.setAnimationLoop( _ => {
uniforms.time.value = clock.getElapsedTime();
renderer.render(scene, camera);
});
body{
overflow: hidden;
margin:0;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.126.1/build/three.min.js"></script>

THREE.js setting global position of Mesh causes jittering artifact

I would like to set the global position of an object, so I wrote a function moveToPoint which takes in a world point x y z, converts it into the local coordinate system, and updates the object.position to go to that new local coordinate.
But, when I call this function in the animation loop, I get an unusual jittering artifact. I'm not quite sure why this could happen since the code is deceptively simple.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const sphereGeometry = new THREE.SphereGeometry(0.1, 32, 32);
const sphereMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0, 0);
scene.add(sphere)
camera.position.z = 5;
function moveToPosition(object, x, y, z) {
const pos = new THREE.Vector3(x, y, z);
object.worldToLocal(pos);
object.position.copy(pos);
}
function animate() {
requestAnimationFrame(animate);
moveToPosition(sphere, 0, 1, 0);
renderer.render(scene, camera);
};
animate();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
Thanks for any assistance.
You're basically toggling the Y-position from 0 to 1 to 0 to 1 to 0, etc...
Let's take it frame-by-frame
Frame 1:
starting sphere position: 0, 0, 0
worldToLocal() sets pos to 0, 1, 0
ending sphere position: 0, 1, 0
Frame 2:
starting sphere position: 0, 1, 0
worldToLocal() sets pos to 0, 0, 0
ending sphere position: 0, 0, 0
... and so on
Another way to look at it:
Frame1: [0, 0, 0].worldToLocal([0, 1, 0]) = [0, 1, 0]
Frame2: [0, 1, 0].worldToLocal([0, 1, 0]) = [0, 0, 0]
Solution:
Since the sphere isn't nested within any other objects, you can skip the worldToLocal() call. You typically only need this when you're dealing with nested objects, not when they're directly added to the scene.
I created a simple sin-wave animation from -1 to +1 to demonstrate:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const sphereGeometry = new THREE.SphereGeometry(0.1, 32, 32);
const sphereMaterial = new THREE.MeshBasicMaterial({
color: 0xffffff
});
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0, 0);
scene.add(sphere)
var axesHelper = new THREE.AxesHelper( 2 );
scene.add( axesHelper );
camera.position.z = 5;
function moveToPosition(object, x, y, z) {
const pos = new THREE.Vector3(x, y, z);
//object.worldToLocal(pos);
object.position.copy(pos);
}
function animate(t) {
requestAnimationFrame(animate);
// Sin movement from -1 to +1
const yPos = Math.sin(t / 1000);
moveToPosition(sphere, 0, yPos, 0);
renderer.render(scene, camera);
};
animate(0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>

BoxGeometry sides

I already asked a Question here: Add Thickness to faces
The core question is solved but i ran into another problem.
Before my walls were set on side:THREE.BackSide so that they didnt show when they faced the camera but now when they have a thickness that doesnt work anymore and i dont realy understand why.
Before:
Before
After: After
How can i make the thick walls behave like the Plane walls ?
A very rough concept of controlling the visibility of a wall (I've slightly changed translating and positioning of a geometry):
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 5, 5);
camera.lookAt(scene.position);
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);
scene.add(new THREE.GridHelper(10, 10));
var points = [
new THREE.Vector3(-2, 0, 2),
new THREE.Vector3(2, 0, 2),
new THREE.Vector3(2, 0, -2),
new THREE.Vector3(-2, 0, -2)
]
var walls = [];
points.forEach((p, idx, points) => {
let nextIdx = idx === points.length - 1 ? 0 : idx + 1;
buildWall(p, points[nextIdx], 2, 0.1);
});
function buildWall(pointStart, pointEnd, height, thickness) {
var boxW = pointEnd.clone().sub(pointStart).length();
var boxH = height;
var boxD = thickness;
var boxGeometry = new THREE.BoxGeometry(boxW, boxH, boxD);
boxGeometry.translate(0, boxH * 0.5, 0);
boxGeometry.rotateY(-Math.PI * 0.5);
var wall = new THREE.Mesh(boxGeometry, new THREE.MeshBasicMaterial({
color: "aqua",
wireframe: true
}));
wall.position.copy(pointStart).add(pointEnd).multiplyScalar(0.5);
wall.lookAt(pointEnd);
scene.add(wall);
walls.push(wall);
}
var currentPosition = new THREE.Vector3();
render();
function render() {
requestAnimationFrame(render);
walls.forEach(w => {
w.visible = currentPosition.copy(w.position).sub(camera.position).lengthSq() > camera.position.lengthSq();
})
renderer.render(scene, camera);
}
body {
overflow: hidden;
margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/91/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Categories