I have a wireframe sphere, and I'd like to add dots to the vertices. Something similar to this:
.:
Here's all my js:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer( { alpha: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.SphereGeometry( 3.25, 32, 20 );
var material = new THREE.MeshLambertMaterial( { color: 0x43CC4C, wireframe: true } );
var sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
var pointLight = new THREE.PointLight(0xFFFFFF);
pointLight.position.x = 80;
pointLight.position.y = 80;
pointLight.position.z = 130;
scene.add(pointLight);
camera.position.z = 5;
function render() {
renderer.render( scene, camera );
}
render();
[codepen here]
How do I add a dot to each vertex?
Here's an example how you can achieve similar results.
I've added an extra geometry type called IcosahedronGeometry and I'm using it's vertices to create points, for the lines I'm using MeshPhongMaterial with wireframe set to true.
You can change the point's size or replace them with shapes/textures.
// Extra geometry
THREE.IcosahedronGeometry = function(radius, detail) {
var t = (1 + Math.sqrt(5)) / 2;
var vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0,
0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t,
t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1
];
var indices = [
0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
];
THREE.PolyhedronGeometry.call(this, vertices, indices, radius, detail);
this.type = 'IcosahedronGeometry';
this.parameters = {
radius: radius,
detail: detail
};
};
THREE.IcosahedronGeometry.prototype = Object.create(THREE.PolyhedronGeometry.prototype);
THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry;
// Scene
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer({
antialias: 1
});
renderer.setClearColor(0xf7f7f7);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
scene.fog = new THREE.Fog(0xd4d4d4, 8, 20);
// Create vertex points
var mesh = new THREE.IcosahedronGeometry(10, 1); // radius, detail
var vertices = mesh.vertices;
var positions = new Float32Array(vertices.length * 3);
for (var i = 0, l = vertices.length; i < l; i++) {
vertices[i].toArray(positions, i * 3);
}
var geometry = new THREE.BufferGeometry();
geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
var material = new THREE.PointsMaterial({
size: 0.4,
vertexColors: THREE.VertexColors,
color: 0x252525
});
var points = new THREE.Points(geometry, material);
var object = new THREE.Object3D();
object.add(points);
object.add(new THREE.Mesh(
mesh,
new THREE.MeshPhongMaterial({
color: 0x616161,
emissive: 0xa1a1a1,
wireframe: true,
fog: 1
})
));
scene.add(object);
camera.position.z = 20;
var render = function() {
requestAnimationFrame(render);
object.rotation.x += 0.01;
object.rotation.y += 0.01;
renderer.render(scene, camera);
};
render();
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/threejs/r76/three.min.js"></script>
Related
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>
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>
I was able to use the OBB.js in three.js examples to obtain center, halfSize, and rotation values. How do we calculate 8 corners of bounding box and draw the box around the object if we know the center, halfSize, and rotation matrix as follows:
{
center: Vector3
x: 4.453294992446899
y: 7.885950803756714
z: 0.4816467687487602
halfSize: Vector3
x: 0.19511961936950684
y: 0.2595798969268799
z: 0.34599775820970535
rotation: Matrix3
elements: Array(9)
0: 1
1: 0
2: 0
3: 0
4: 1
5: 0
6: 0
7: 0
8: 1
}
Something like this:
body{
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.jsdelivr.net/npm/three#0.126.0/build/three.module.js";
import {OrbitControls} from "https://cdn.jsdelivr.net/npm/three#0.126.0/examples/jsm/controls/OrbitControls.js";
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 5, 20);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
let controls = new OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper());
let halfSize = new THREE.Vector3( 0.19511961936950684, 0.2595798969268799, 0.34599775820970535);
let rotMat = new THREE.Matrix3().identity();
let rot = new THREE.Matrix4().identity().setFromMatrix3(rotMat);
let g = new THREE.SphereGeometry(1, 36, 18);
g.scale(halfSize.x, halfSize.y, halfSize.z);
let obj = new THREE.Mesh(g, new THREE.MeshNormalMaterial());
obj.position.set( 4.453294992446899, 7.885950803756714, 0.4816467687487602);
obj.rotation.setFromRotationMatrix(rot);
obj.updateMatrixWorld();
scene.add(obj);
let gH = new THREE.BufferGeometry().setFromPoints([
new THREE.Vector3(1, 1, 1),
new THREE.Vector3(1, 1, -1),
new THREE.Vector3(1, -1, -1),
new THREE.Vector3(1, -1, 1),
new THREE.Vector3(-1, 1, 1),
new THREE.Vector3(-1, 1, -1),
new THREE.Vector3(-1, -1, -1),
new THREE.Vector3(-1, -1, 1)
]);
gH.setIndex([
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
0, 4, 1, 5, 2, 6, 3, 7
])
let mH = new THREE.LineBasicMaterial({color: "yellow"});
let oH = new THREE.LineSegments(gH, mH);
oH.scale.copy(halfSize);
oH.position.copy(obj.position);
oH.rotation.setFromRotationMatrix(rot);
scene.add(oH);
renderer.setAnimationLoop( _ => {
renderer.render(scene, camera);
});
</script>
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>
I'm dynamically adjusting objects in three.js using dat.gui sliders, and I've got a question about the three.js EdgesHelper class.
As the example below demonstrates, the geometry of the EdgesHelper object, box_edges, does not automatically update when the vertices of the box are repositioned.
I have tried using
box_edges.matrixAutoUpdate = true;
to no avail. I've also tried the matrixUpdate() and applyMatrix() methods.
So how can I ensure that the EdgesHelper object 'tracks' the Geometry object?
<html>
<head>
<title>EdgesHelper test</title>
<style>
body { margin: 0; }
canvas { width: 100%; height: 100% }
</style>
<script src="..\three.js-master\build\three.js"></script>
<script src="..\..\JavaScript Libraries\Detector\Detector.js"></script>
<script src="..\..\JavaScript Libraries\dat.gui.min\dat-gui-min.js"></script>
<script src="..\..\JavaScript Libraries\OrbitControls\OrbitControls.js"></script>
<script src="..\..\JavaScript Libraries\stats.min\stats-min.js"></script>
</head>
<body>
<div id="threejs_scene" style="position: absolute; left:0px; top:0px"></div>
<script>
var container, scene, camera, renderer, controls, stats;
var gui_components_fn, gui_components, gui;
var box_geometry, box_material;
init();
animate();
function init() {
scene = new THREE.Scene();
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45;
var ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT;
var NEAR = 0.1;
var FAR = 20000;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
camera.position.set( -1000, 1000, 1000);
scene.add(camera);
camera.lookAt( 0, 0, 0 );
if ( Detector.webgl )
renderer = new THREE.WebGLRenderer( {antialias: true} );
else
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container = document.getElementById( 'threejs_scene' );
container.appendChild( renderer.domElement );
controls = new THREE.OrbitControls( camera, renderer.domElement );
stats = new Stats();
container.appendChild( stats.dom );
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
var lights = [];
lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 3 ] = new THREE.PointLight( 0xffffff, 1, 0 );
lights[ 0 ].position.set( 1000, 2000, 1000 );
lights[ 1 ].position.set( 1000, 2000, -1000 );
lights[ 2 ].position.set( -1000, 2000, 1000 );
lights[ 3 ].position.set( -1000, 2000, -1000 );
scene.add( lights[ 0 ] );
scene.add( lights[ 1 ] );
scene.add( lights[ 2 ] );
scene.add( lights[ 3 ] );
var box_width = 200;
var box_height = 600;
var box_depth = 150;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
box_geometry = new THREE.Geometry();
var box_vertices = [
new THREE.Vector3(0,0,0),
new THREE.Vector3(box_width,0,0),
new THREE.Vector3(box_width,0, -box_depth),
new THREE.Vector3(0,0,-box_depth),
new THREE.Vector3(0,box_height,0),
new THREE.Vector3(box_width,box_height,0),
new THREE.Vector3(box_width,box_height,-box_depth),
new THREE.Vector3(0,box_height,-box_depth),
];
var box_width_vertices_left = [0, 3, 4, 7];
var box_width_vertices_right = [1, 2, 5, 6];
var box_height_vertices_bottom = [0, 1, 2, 3];
var box_height_vertices_top = [4, 5, 6, 7];
var box_depth_vertices_front = [0, 1, 4, 5];
var box_depth_vertices_rear = [2, 3, 6, 7];
for (var i=0; i<box_vertices.length; i++) {
box_geometry.vertices.push(box_vertices[i]);
}
box_geometry.faces.push( new THREE.Face3( 0, 1, 5 ) );
box_geometry.faces.push( new THREE.Face3( 5, 4, 0 ) );
box_geometry.faces.push( new THREE.Face3( 1, 2, 6 ) );
box_geometry.faces.push( new THREE.Face3( 6, 5, 1) );
box_geometry.faces.push( new THREE.Face3( 2, 3, 7 ) );
box_geometry.faces.push( new THREE.Face3( 7, 6, 2 ) );
box_geometry.faces.push( new THREE.Face3( 3, 0, 4 ) );
box_geometry.faces.push( new THREE.Face3( 4, 7, 3 ) );
box_geometry.faces.push( new THREE.Face3( 0, 3, 2 ) );
box_geometry.faces.push( new THREE.Face3( 2, 1, 0 ) );
box_geometry.faces.push( new THREE.Face3( 5, 6, 7 ) );
box_geometry.faces.push( new THREE.Face3( 7, 4, 5 ) );
box_geometry.computeFaceNormals();
box_material = new THREE.MeshPhongMaterial( { color:0xff0000, transparent:true, opacity:0.75 } );
box = new THREE.Mesh( box_geometry, box_material );
scene.add(box);
box_edges = new THREE.EdgesHelper( box, 0xffffff );
box_edges.visible = true;
scene.add( box_edges );
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var axes = new THREE.AxisHelper(300);
scene.add(axes);
gui_components_fn = function () {
this.box_position_wide_left_gui = 0.0;
this.box_position_wide_right_gui = 0.0;
this.show_edges_gui = true;
};
gui_components = new gui_components_fn();
gui = new dat.GUI();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var folder1 = gui.addFolder('Box dimensions');
var box_position_wide_left_gui = folder1.add(gui_components, 'box_position_wide_left_gui', 0.0, 500.0).name("adjust left");
var box_position_wide_right_gui = folder1.add(gui_components, 'box_position_wide_right_gui', 0.0, 500.0).name("adjust right");
folder1.open();
box_position_wide_left_gui.onChange(function(value) {
for (var i=0; i<box_width_vertices_left.length; i++) {
box.geometry.vertices[box_width_vertices_left[i]].x = -value;
}
box.geometry.verticesNeedUpdate = true;
box.geometry.normalsNeedUpdate = true;
});
box_position_wide_right_gui.onChange(function(value) {
for (var i=0; i<box_width_vertices_right.length; i++) {
box.geometry.vertices[box_width_vertices_right[i]].x = box_width+value;
}
box.geometry.verticesNeedUpdate = true;
box.geometry.normalsNeedUpdate = true;
});
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
var show_edges_gui = gui.add(gui_components, 'show_edges_gui').name("Show edges");
show_edges_gui.onChange(function(value) {
box_edges.visible = value;
});
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
gui.open();
}
function animate()
{
requestAnimationFrame( animate );
render();
update();
}
function update()
{
controls.update();
stats.update();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>