0

Hi, my name is Giuliano and this is the first question of my life on this website :)

I have generated in a canvas a CircleBufferGeometry rendered as a #fff wireframe on a #000 black background; the rendering is stable and the scene is without errors.

Now i'm trying to select just one of the rendered wireframe lines and change its color. My final goal is to create a circle with 60 vertex lines (lines that goes from the center to the edge of the object) and every second alternate the color of just 1 line as a simulation of a clock hand.

This is the code i now have visible on my work in progress website:

        var material = new THREE.MeshBasicMaterial( 
{ color: 0xfefefe, wireframe: true, opacity: 0.5 } );

		  	init();
			  function addMesh() {
				if ( mesh !== undefined ) {

					scene.remove( mesh );
					geometry.dispose();
          
				}
        
		geometry = geometries[ options.Geometry ];
		geometry.computeBoundingSphere();
        
	var scaleFactor = 1160 / geometry.boundingSphere.radius;
        
	geometry.scale( scaleFactor, scaleFactor, scaleFactor );
	mesh = new THREE.Mesh( geometry, material );
	scene.add( mesh );
        
			}

The ideal solution would be a jQuery selector (or whatever selector) that allows me to target the line i want among an array of lines and use an increasing value to cycle through them.

I thought I could use an inwards vertex normal helper (colored in red) to simulate the effect but i lack in knowledge and really don't know how to apply some ideas yet... I just started experimenting in Three.js :)

Every help is appreciated, sorry for my yet shallow understanding of basic mechanics. Giuliano

1
  • Hi! Welcome to Stackoverflow :) Have a look at this SO answer and its jsfiddle example. Commented Jun 17, 2018 at 14:17

1 Answer 1

1

A very rough concept of how you can do it:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var segs = 60;
var baseVector = new THREE.Vector3(0, 5, 0);
var axisVector = new THREE.Vector3(0, 0, 1);
var step = THREE.Math.degToRad(6);
var vertices = [];
for (var i = 0; i < segs; i++) {
  vertices.push(new THREE.Vector3());
  vertices.push(baseVector.clone().applyAxisAngle(axisVector, -step * i));
}
var geom = new THREE.BufferGeometry().setFromPoints(vertices);
var colors = [];
var baseColor = new THREE.Color("gray");
var color = new THREE.Color("aqua");
for (let i = 1; i <= segs; i++) {
  let idx = (i - 1) * 6;
  baseColor.toArray(colors, idx);
  baseColor.toArray(colors, idx + 3);
}
geom.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));

var lines = new THREE.LineSegments(geom, new THREE.LineBasicMaterial({
  vertexColors: THREE.VertexColors
}));
scene.add(lines);

function setLineColor(idx, color) {
  geom.attributes.color.setXYZ(idx * 2, color.r, color.g, color.b);
  geom.attributes.color.setXYZ(idx * 2 + 1, color.r, color.g, color.b);
}

function getSec() {
  return new Date().getSeconds();
}

var prevSecond = getSec();
var currSecond = 0;

render();

function render() {
  requestAnimationFrame(render);
  currSecond = getSec();
  if (prevSecond != currSecond) {
    setLineColor(currSecond, color);
    setLineColor(prevSecond, baseColor);
    geom.attributes.color.needsUpdate = true;
    prevSecond = currSecond;
  }
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/93/three.min.js"></script>

Another option is to rotate a mesh (or its geometry, it's up to you):

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var segs = 60;
var baseVector = new THREE.Vector3(0, 5, 0);
var axisVector = new THREE.Vector3(0, 0, 1);
var step = THREE.Math.degToRad(6);
var vertices = [];
for (var i = 0; i < segs; i++) {
  vertices.push(new THREE.Vector3());
  vertices.push(baseVector.clone().applyAxisAngle(axisVector, -step * i));
}
var geom = new THREE.BufferGeometry().setFromPoints(vertices);
var colors = [];
var baseColor = new THREE.Color("gray");
var color = new THREE.Color("aqua");
for (let i = 1; i <= segs; i++) {
  let idx = (i - 1) * 6;
  baseColor.toArray(colors, idx);
  baseColor.toArray(colors, idx + 3);
}
geom.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));

var lines = new THREE.LineSegments(geom, new THREE.LineBasicMaterial({
  vertexColors: THREE.VertexColors
}));
scene.add(lines);

function setLineColor(idx, color) {
  geom.attributes.color.setXYZ(idx * 2, color.r, color.g, color.b);
  geom.attributes.color.setXYZ(idx * 2 + 1, color.r, color.g, color.b);
}

setLineColor(0, color);
geom.attributes.color.needsUpdate = true;
lines.rotation.z = -step * getSec();

function getSec() {
  return new Date().getSeconds();
}

var prevSecond = getSec();
var currSecond = 0;

render();

function render() {
  requestAnimationFrame(render);
  currSecond = getSec();
  if (prevSecond != currSecond) {
    lines.rotation.z = -step * currSecond;
    prevSecond = currSecond;
  }
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/93/three.min.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.