Three.js Animated curve - javascript

I try to animate a 2D curve in Three.js over time.
I'll need more than 4 control points, so I'm not using Bezier curves.
I created a Three.Line based on a SplineCurve.
If I log the geometry.vertices position of my line they'll change over time, but geometry.attributes.position remains the same. Is it possible to animate the line based on the curve animation ? I managed to do this with Bezier Curves, but can't find a way with SplineCurve.
Thank you for your help, here's my code :
First I create the line :
var curve = new THREE.SplineCurve( [
new THREE.Vector3( -10, 0, 10 ),
new THREE.Vector3( -5, 5, 5 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 5, -5, 5 ),
new THREE.Vector3( 10, 0, 10 )
] );
var points = curve.getPoints( 50 );
var geometry = new THREE.BufferGeometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial( { color : 0xff0000 } );
// Create the final object to add to the scene
curveObject = new THREE.Line( geometry, material );
scene.add( curveObject );
curveObject.curve = curve;
Then I try to update it :
curveObject.curve.points[0].x += 1;
curveObject.geometry.vertices = curveObject.curve.getPoints( 50 );
curveObject.geometry.verticesNeedUpdate = true;
curveObject.geometry.attributes.needsUpdate = true;

You can do it like that:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(8, 13, 25);
var renderer = new THREE.WebGLRenderer({
antialias: true
});
var canvas = renderer.domElement;
document.body.appendChild(canvas);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(20, 40));
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(-10, 0, 10),
new THREE.Vector3(-5, 5, 5),
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(5, -5, 5),
new THREE.Vector3(10, 0, 10)
]);
var points = curve.getPoints(50);
var geometry = new THREE.BufferGeometry().setFromPoints(points);
var material = new THREE.LineBasicMaterial({
color: 0x00ffff
});
var curveObject = new THREE.Line(geometry, material);
scene.add(curveObject);
var clock = new THREE.Clock();
var time = 0;
render();
function resize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
function render() {
if (resize(renderer)) {
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
time += clock.getDelta();
curve.points[1].y = Math.sin(time) * 2.5;
geometry = new THREE.BufferGeometry().setFromPoints(curve.getPoints(50));
curveObject.geometry.dispose();
curveObject.geometry = geometry;
requestAnimationFrame(render);
}
html,
body {
height: 100%;
margin: 0;
overflow: hidden;
}
canvas {
width: 100%;
height: 100%;
display;
block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Related

Calculate line endpoint with rotation of a Cone 3D

I want to rotate a Line to the destination, where a cone is pointing to.
In the snippet below i have a basic ThreeJs Cone and a line, which is at the moment hard coded to stick out vertikal. I want to be able to rotate the cone and the Line is like an laserbeam, which is sticking out at the top. Here is an example image for 2D
.
My goal is to do this in 3D. My overall problem is, that i can only set the points of the Line and not the Rotation.
I know i can get the roation of the cone with cone.rotation. But i didn't managed to calculate the right POsition of the end point of the line
In the Snippet you can rotate the cone by holding down the left mouse button.
let scene = new THREE.Scene();
//Lights
scene.add(new THREE.HemisphereLight(0x808080, 0x606060));
let light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 6, 0);
scene.add(light);
//camera
let camera = new THREE.PerspectiveCamera(
70, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 0, 2);
scene.add(camera);
//Cone
let cone = new THREE.Mesh(
new THREE.ConeBufferGeometry(0.2, 0.5, 20, 20),
new THREE.MeshStandardMaterial({
color: 0xff0000,
roughness: 0.7,
metalness: 0.0,
})
);
scene.add( cone );
//line
var points = [];
points.push( new THREE.Vector3( 0, 0, 0 ) );
points.push( new THREE.Vector3( 0, 0, 0 ) );
var geometry = new THREE.Geometry().setFromPoints( points );
var material = new THREE.LineBasicMaterial({
color: 0x0000ff
});
let line = new THREE.Line( geometry, material );
scene.add( line );
//renderer with loop
let renderer = new THREE.WebGLRenderer({
antialias: true,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
function render() {
updateLine();
renderer.render(scene, camera);
}
renderer.setAnimationLoop(render)
document.addEventListener('contextmenu', event => event.preventDefault());
let middleDown = false;
let mouseStart = {
x:0,
y:0
}
let cur = {
start : {
rot: {
x:0,
y:0,
z:0
}
}
}
document.onmousedown = function (e){
if (e.button == 0)
middleDown = true;
mouseStart.x= e.pageX;
mouseStart.y= e.pageY;
//Save cur
cur.start.rot.x = cone.rotation.x;
cur.start.rot.y = cone.rotation.y;
cur.start.rot.z = cone.rotation.z;
return false;
}
document.onmouseup = function (e){
if (e.button == 0)
middleDown = false;
}
document.onmousemove = function(e){
let pos = {
x: e.pageX,
y: e.pageY
}
if(middleDown){
cone.rotation.x = cur.start.rot.x + (pos.y/350 - mouseStart.y/350);
cone.rotation.z = cur.start.rot.z + (pos.x/350 - mouseStart.x/350);
}
}
function updateLine() {
line.geometry.vertices[0] = cone.position;
//Here i want to update the new Line end
line.geometry.vertices[1] = new THREE.Vector3( 0, 1, 0 )
line.geometry.verticesNeedUpdate = true;
}
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>
</body>

Creating same circles with PointsMaterial and CircleGeometry

I would like to create circles in two different ways:
With a circle sprite, then draw it with Points and PointsMaterial
With basic circle buffer geometries
However, I cannot make them match together because of PointsMaterial size.
const width = window.innerWidth;
const height = window.innerHeight;
const fov = 40;
const near = 10;
const far = 200;
const camera = new THREE.PerspectiveCamera(fov, width / height, near, far);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);
const circle_sprite = new THREE.TextureLoader().load(
'https://fastforwardlabs.github.io/visualization_assets/circle-sprite.png'
);
const factor = 280;
const positions = [
{ x: 100, y: -5 },
{ x: 6, y: 50 }
];
const circleRadius = 20;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xefefef);
/* First method */
const pointsGeometry = new THREE.Geometry();
const colors = [];
for (const position of positions) {
// Set vector coordinates from data
const vertex = new THREE.Vector3(position.x, position.y, 0);
pointsGeometry.vertices.push(vertex);
const color = new THREE.Color(0xff0000);
colors.push(color);
}
pointsGeometry.colors = colors;
const pointsMaterial = new THREE.PointsMaterial({
size: (factor * circleRadius) / fov,
sizeAttenuation: false,
vertexColors: true,
map: circle_sprite,
transparent: true,
opacity: 0.5
});
const firstPoints = new THREE.Points(pointsGeometry, pointsMaterial);
scene.add(firstPoints);
/* Second method */
const circleGeometry = new THREE.CircleBufferGeometry(circleRadius, 32);
const circleMaterial = new THREE.MeshBasicMaterial({
color: 0xffff00,
transparent: true,
opacity: 0.5
});
positions.forEach((position) => {
const circleMesh = new THREE.Mesh(circleGeometry, circleMaterial);
circleMesh.position.set(position.x, position.y, 0);
scene.add(circleMesh);
});
/* Render loop */
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
camera.position.set(0, 0, far);
I try to find the factor variable value but I also discovered that width or height are involved in this factor.
How can I draw same circles with PointsMaterial?
Having this: https://github.com/mrdoob/three.js/issues/12150#issuecomment-327874431, you can compute the size of points.
body {
overflow: hidden;
margin: 0;
}
<script type="module">
import * as THREE from "https://threejs.org/build/three.module.js";
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(50, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);
var grid = new THREE.GridHelper(10, 10);
grid.rotation.x = Math.PI * 0.5;
scene.add(grid);
// geometry
var cGeom = new THREE.CircleBufferGeometry(1, 32);
var cMat = new THREE.MeshBasicMaterial({
color: "magenta"
});
var circle = new THREE.Mesh(cGeom, cMat);
circle.position.set(0, 3, 0);
scene.add(circle);
// points
var g = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3()]);
var c = document.createElement("canvas");
c.width = 128;
c.height = 128;
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, 128, 128);
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(64, 64, 64, 0, 2 * Math.PI);
ctx.fill();
var tex = new THREE.CanvasTexture(c);
var desiredSize = 2;
var pSize = desiredSize / Math.tan( THREE.Math.degToRad( camera.fov / 2 ) );
var m = new THREE.PointsMaterial({
size: pSize,
color: "aqua",
map: tex,
alphaMap: tex,
alphaTest: 0.5
});
var p = new THREE.Points(g, m);
scene.add(p);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera)
});
</script>

ThreeJS rotate around axis

I want to rotate this cube around the light blue axis. I works If I change the rotation around THREE.Vector3(0,0,0) instead of THREE.Vector3(0.4,0,0.9)
I don't know why the cubes shape changes and why it gets smaller with more iterations
An fiddle showing this problem (please ignore the crappy implementation. I just changed a old one)
So this is how I do the rotation:
function rotate(deg) {
_initTranslation = new THREE.Vector3();
_initRotation = new THREE.Quaternion();
_initScale = new THREE.Vector3();
rotateMatrix = new THREE.Matrix4();
cube.matrix.decompose(_initTranslation, _initRotation, _initScale);
cube.matrix = rotateMatrix.compose(_initTranslation, new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0.4,1,0.9), THREE.Math.degToRad(deg)), _initScale);
cube.matrixAutoUpdate = false;
cube.matrixWorldNeedsUpdate = true;
}
Maybe someone knows what I did wrong.
var renderer, scene, camera, controls;
var geometry, material, line, vertices, last, _initTranslation, _initRotation, initScale, rotateMatrix;
var deg = 0;
init();
animate();
function init() {
document.body.style.cssText = 'margin: 0; overflow: hidden;' ;
renderer = new THREE.WebGLRenderer( { alpha: 1, antialias: true, clearColor: 0xffffff } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 5, 5, 5 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
geometry2 = new THREE.BoxGeometry( .5, .5, .5 );
material2 = new THREE.MeshNormalMaterial();
cube = new THREE.Mesh( geometry2, material2 );
scene.add( cube );
material = new THREE.LineBasicMaterial({ color: 0x0077ff });
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3( 0, 0, 0) );
line = new THREE.Line( geometry, material )
scene.add( line );
var sphereAxis = new THREE.AxesHelper(20);
scene.add(sphereAxis);
addStep();
cube.lookAt(new THREE.Vector3(0.4,0,0.9));
}
function addStep() {
vertices = geometry.vertices;
last = vertices[ vertices.length - 1 ];
vertices.push(
new THREE.Vector3(0.4,0,0.9)
);
geometry = new THREE.Geometry();
geometry.vertices = vertices;
scene.remove( line );
line = new THREE.Line( geometry, material )
scene.add( line );
}
function animate() {
rotate(deg)
deg += 5
requestAnimationFrame( animate );
renderer.render(scene, camera);
controls.update();
}
function rotate(deg) {
_initTranslation = new THREE.Vector3();
_initRotation = new THREE.Quaternion();
_initScale = new THREE.Vector3();
rotateMatrix = new THREE.Matrix4();
cube.matrix.decompose(_initTranslation, _initRotation, _initScale);
cube.matrix = rotateMatrix.compose(_initTranslation, new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0.4,0,0.9), THREE.Math.degToRad(deg)), _initScale);
cube.matrixAutoUpdate = false;
cube.matrixWorldNeedsUpdate = true;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
The vector component of the Quaternion has to be (normalize.). The length of a normalized vector (Unit vector) is 1.0.
In your case the length of the vector component (THREE.Vector3(0.4, 0, 0.9)) is less than 1.0:
sqrt(0.9*0.9 + 0.0*0.0 + 0.4*0.4) = sqrt(0.81 + 0.16) = sqrt(0.97) = 0.9409
This causes that the cube scales sown by time. This can be verified by logging the scaling component (console.log(_initScale)).
If you would use a vector component with a length greater than 1.0 (e.g. THREE.Vector3(0.5, 0, 0.9), then the cube will scale up.
Normalize the axis of the Quaternion, to solve the issue:
let axis = new THREE.Vector3(0.4, 0, 0.9);
let q = new THREE.Quaternion().setFromAxisAngle(axis.normalize(), THREE.Math.degToRad(deg));
cube.matrix = rotateMatrix.compose(_initTranslation, q, _initScale);
If you want that one side of the cube is aligned to the axis, in that way, that the axis is normal to the side, then this is something completely different.
You've to do 2 rotations. First rotate the cube (e.g.) continuously around the x-axis, then turn the x-axis to the target axis (0.4, 0, 0.9). Use .setFromAxisAngle` to initialize a quaternion which rotates the x-axis to the target axis:
let x_axis = new THREE.Vector3(1, 0, 0);
let axis = new THREE.Vector3(0.4, 0, 0.9);
let q_align = new THREE.Quaternion().setFromUnitVectors(x_axis, axis.normalize());
let q_rotate = new THREE.Quaternion().setFromAxisAngle(x_axis, THREE.Math.degToRad(deg));
let q_final = q_align.clone().multiply(q_rotate);
cube.matrix = rotateMatrix.compose(_initTranslation, q, _initScale);
See the example, which compares the 2 different behavior:
var renderer, scene, camera, controls;
var geometry, material, line, vertices, last, _initTranslation, _initRotation, initScale, rotateMatrix;
var deg = 0;
init();
animate();
function init() {
document.body.style.cssText = 'margin: 0; overflow: hidden;' ;
renderer = new THREE.WebGLRenderer( { alpha: 1, antialias: true, clearColor: 0xffffff } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 1, 3, 3 );
controls = new THREE.OrbitControls( camera, renderer.domElement );
geometry2 = new THREE.BoxGeometry( .5, .5, .5 );
material2 = new THREE.MeshNormalMaterial();
let shift = 0.5
cube = new THREE.Mesh( geometry2, material2 );
cube.matrix.makeTranslation(shift, 0, 0);
scene.add( cube );
cube2 = new THREE.Mesh( geometry2, material2 );
cube2.matrix.makeTranslation(-shift, 0, 0);
scene.add( cube2 );
material = new THREE.LineBasicMaterial({ color: 0x0077ff });
geometry = new THREE.Geometry();
geometry.vertices.push( new THREE.Vector3(-0.4, 0, -0.9), new THREE.Vector3(0.4, 0, 0.9) );
line = new THREE.Line( geometry, material )
line.position.set(shift, 0, 0);
scene.add( line );
line2 = new THREE.Line( geometry, material )
line2.position.set(-shift, 0, 0);
scene.add( line2 );
var sphereAxis = new THREE.AxesHelper(20);
scene.add(sphereAxis);
window.onresize = function() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
}
function animate() {
rotate(deg)
deg += 5
requestAnimationFrame( animate );
renderer.render(scene, camera);
controls.update();
}
function rotate(deg) {
_initTranslation = new THREE.Vector3();
_initRotation = new THREE.Quaternion();
_initScale = new THREE.Vector3();
let x_axis = new THREE.Vector3(1, 0, 0);
let axis = new THREE.Vector3(0.4, 0, 0.9);
// cube
cube.matrix.decompose(_initTranslation, _initRotation, _initScale);
let q_align = new THREE.Quaternion().setFromUnitVectors(x_axis, axis.normalize());
let q_rotate = new THREE.Quaternion().setFromAxisAngle(x_axis, THREE.Math.degToRad(deg));
let q_final = q_align.clone().multiply(q_rotate);
cube.matrix.compose(_initTranslation, q_final, _initScale);
cube.matrixAutoUpdate = false;
cube.matrixWorldNeedsUpdate = true;
// cube2
cube2.matrix.decompose(_initTranslation, _initRotation, _initScale);
q = new THREE.Quaternion().setFromAxisAngle(axis.normalize(), THREE.Math.degToRad(deg));
cube2.matrix.compose(_initTranslation, q, _initScale);
cube2.matrixAutoUpdate = false;
cube2.matrixWorldNeedsUpdate = true;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/102/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

Animate / update value of tube geometry path points

I made a TubeGeometry by passing in a SplineCurve3 / CatmullRomCurve3 path as a parameter.
I am trying to update the position of each of the path's points with geometry.parameters.path.points[1].y += 0.01; under requestAnimationFrame.
The values itself updates on console.log but the points dont move. How can i do this?
By the way, i'm not looking to move 'vertices' but rather the points of the path that shape how the tube is rendered.
var camera, scene, light, renderer, geometry, material, mesh;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// default bg canvas color //
renderer.setClearColor(0x00ff00);
// use device aspect ratio //
// renderer.setPixelRatio(window.devicePixelRatio);
// set size of canvas within window //
renderer.setSize(window.innerWidth, window.innerHeight);
// create camera //
// params = field of view, aspect ratio, clipping of near objects, clipping of far objs
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
camera.position.z = 100;
// create scene
scene = new THREE.Scene();
// create ambient lighting, params -> color, intensity
light = new THREE.AmbientLight(0xffffff, 0.5)
// add light to scene
scene.add(light)
// create line, with params as x,y,z
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -60, 0, 0 ),
new THREE.Vector3( -50, 10, 0 ),
new THREE.Vector3( -40, 0, 0 ),
new THREE.Vector3( -30, -10, 0 ),
new THREE.Vector3( -20, 0, 0 ),
new THREE.Vector3( -10, 10, 0 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 10, -10, 0 ),
new THREE.Vector3( 20, 0, 0 ),
new THREE.Vector3( 30, 10, 0 ),
new THREE.Vector3( 40, 0, 0 ),
new THREE.Vector3( 50, -10, 0 ),
new THREE.Vector3( 60, 0, 0 )
]);
curve.verticesNeedUpdate = true;
for (i = 0; i < curve.points.length; i++) {
// this will get a number between 1 and 10;
var num = Math.floor(Math.random()*10) + 1;
num *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
curve.points[i].y = num;
// console.log(curve.points[i].y);
}
geometry = new THREE.TubeGeometry(curve, 1000, 0.2, 8, false);
geometry.dynamic = true;
/* standard material */
material = new THREE.MeshBasicMaterial({
color: 0xff0000
});
// create mesh
mesh = new THREE.Mesh(geometry, material);
// set positon of line
mesh.position.set(0,0,-10);
// add to scene
scene.add(mesh);
document.body.appendChild(renderer.domElement);
} /* end init */
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//console.log(geometry.parameters.path.points);
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// mesh.rotation.x += 0.01;
// mesh.rotation.y += 0.01;
geometry.parameters.path.points[1].y += 0.01;
geometry.verticesNeedUpdate = true;
//console.log(geometry.parameters.path.points[1].y)
/* render scene and camera */
renderer.render(scene,camera);
}
body {
margin:0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>
I wasn't able to get it working using TubeGeometry, but I did with TubeBufferGeometry. Luckily, there isn't much to change, because both use the curve path to define the mesh vertices. You're free to try to replicate this with TubeGeometry instead.
The main problem you're seeing though is that Tube(Buffer)Geometry BUILDS geometry, rather than IS geometry, and that's where the convenience ends. Updating the path does not trigger the geometry to rebuild. Instead, if you update your path, you must recreate the Tube(Buffer)Geometry.
In the code below, all I did was swap TubeBufferGeometry in place of TubeGeometry, changed geometry.verticesNeedUpdated to geometry.needsUpdate (this is how BufferGeometry handles updates), and added the line which re-builds the tube:
geometry.copy(new THREE.TubeBufferGeometry(geometry.parameters.path, 1000, 0.2, 8, false));
var camera, scene, light, renderer, geometry, material, mesh;
init();
animate();
function init() {
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// default bg canvas color //
renderer.setClearColor(0x00ff00);
// use device aspect ratio //
// renderer.setPixelRatio(window.devicePixelRatio);
// set size of canvas within window //
renderer.setSize(window.innerWidth, window.innerHeight);
// create camera //
// params = field of view, aspect ratio, clipping of near objects, clipping of far objs
camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 0.1, 3000);
camera.position.z = 100;
// create scene
scene = new THREE.Scene();
// create ambient lighting, params -> color, intensity
light = new THREE.AmbientLight(0xffffff, 0.5)
// add light to scene
scene.add(light)
// create line, with params as x,y,z
var curve = new THREE.CatmullRomCurve3([
new THREE.Vector3( -60, 0, 0 ),
new THREE.Vector3( -50, 10, 0 ),
new THREE.Vector3( -40, 0, 0 ),
new THREE.Vector3( -30, -10, 0 ),
new THREE.Vector3( -20, 0, 0 ),
new THREE.Vector3( -10, 10, 0 ),
new THREE.Vector3( 0, 0, 0 ),
new THREE.Vector3( 10, -10, 0 ),
new THREE.Vector3( 20, 0, 0 ),
new THREE.Vector3( 30, 10, 0 ),
new THREE.Vector3( 40, 0, 0 ),
new THREE.Vector3( 50, -10, 0 ),
new THREE.Vector3( 60, 0, 0 )
]);
curve.verticesNeedUpdate = true;
for (i = 0; i < curve.points.length; i++) {
// this will get a number between 1 and 10;
var num = Math.floor(Math.random()*10) + 1;
num *= Math.floor(Math.random()*2) == 1 ? 1 : -1;
curve.points[i].y = num;
// console.log(curve.points[i].y);
}
geometry = new THREE.TubeBufferGeometry(curve, 1000, 0.2, 8, false);
geometry.dynamic = true;
/* standard material */
material = new THREE.MeshBasicMaterial({
color: 0xff0000
});
// create mesh
mesh = new THREE.Mesh(geometry, material);
// set positon of line
mesh.position.set(0,0,-10);
// add to scene
scene.add(mesh);
document.body.appendChild(renderer.domElement);
} /* end init */
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
//console.log(geometry.parameters.path.points);
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
// mesh.rotation.x += 0.01;
// mesh.rotation.y += 0.01;
geometry.parameters.path.points[3].y += 0.01;
geometry.copy(new THREE.TubeBufferGeometry(geometry.parameters.path, 1000, 0.2, 8, false));
geometry.needsUpdate = true;
//console.log(geometry.parameters.path.points[1].y)
/* render scene and camera */
renderer.render(scene,camera);
}
body {
margin:0;
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/87/three.min.js"></script>

ThreeJS, How to use CSS3Renderer and WebGLRenderer to render 2 objects on the same scene and have them overlap?

JSFiddle :
http://jsfiddle.net/ApoG/50y32971/2/
I am rendering an image as a background using CSS3Renderer, projected as a cube in the app.
I want to have objects, rendered using WebGLRenderer in the middle (later I will make them clickable using ray detection).
It looks like (from my code below), that WebGlrendered wireframe (the wireframe of the randomly generated square in the middle) only shows up when you rotate the view to have white background, when the background is turned to the CSS3Rendered clouds, the wireframe rendered by WebGLRenderer disappears. Is there a way to keep the wireframe in the view?
My ultimate goal is to have several floating objects (3d text for example) with links as an object property, which will be later made clickable (using rays). I want to use CSS3 renderer because it renders well on mobile vs canvasrenderer, ideas and suggestions would greatly appreciated, I am officially stuck. My fiddle:
http://jsfiddle.net/ApoG/50y32971/2/
var camera, scene, renderer;
var scene2, renderer2;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(200, 200, 200);
controls = new THREE.TrackballControls(camera);
scene = new THREE.Scene();
scene2 = new THREE.Scene();
var material = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
wireframeLinewidth: 1,
side: THREE.DoubleSide
});
//
//
for (var i = 0; i < 1; i++) {
var element = document.createElement('div');
element.style.width = '100px';
element.style.height = '100px';
element.style.opacity = 0.5;
element.style.background = new THREE.Color(Math.random() * 0xffffff).getStyle();
var object = new THREE.CSS3DObject(element);
object.position.x = Math.random() * 200 - 100;
object.position.y = Math.random() * 200 - 100;
object.position.z = Math.random() * 200 - 100;
object.rotation.x = Math.random();
object.rotation.y = Math.random();
object.rotation.z = Math.random();
object.scale.x = Math.random() + 0.5;
object.scale.y = Math.random() + 0.5;
scene2.add(object);
var geometry = new THREE.PlaneGeometry(100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.copy(object.position);
mesh.rotation.copy(object.rotation);
mesh.scale.copy(object.scale);
scene.add(mesh);
}
//
var sides = [{
url: 'http://threejs.org/examples/textures/cube/skybox/px.jpg',
position: [-1024, 0, 0],
rotation: [0, Math.PI / 2, 0]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/nx.jpg',
position: [1024, 0, 0],
rotation: [0, -Math.PI / 2, 0]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/py.jpg',
position: [0, 1024, 0],
rotation: [Math.PI / 2, 0, Math.PI]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/ny.jpg',
position: [0, -1024, 0],
rotation: [-Math.PI / 2, 0, Math.PI]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/pz.jpg',
position: [0, 0, 1024],
rotation: [0, Math.PI, 0]
}, {
url: 'http://threejs.org/examples/textures/cube/skybox/nz.jpg',
position: [0, 0, -1024],
rotation: [0, 0, 0]
}];
for (var i = 0; i < sides.length - 1; i++) {
var side = sides[i];
var element = document.createElement('img');
element.width = 2050; // 2 pixels extra to close the gap.
element.src = side.url;
var object = new THREE.CSS3DObject(element);
object.position.fromArray(side.position);
object.rotation.fromArray(side.rotation);
scene2.add(object);
}
//
renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xf0f0f0);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
renderer2 = new THREE.CSS3DRenderer();
renderer2.setSize(window.innerWidth, window.innerHeight);
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.top = 0;
document.body.appendChild(renderer2.domElement);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
renderer2.render(scene2, camera);
}
You are using CSS3DRenderer and WebGLRenderer in overlapping canvas elements.
You you need to make sure the WebGLRenderer's background is transparent. Follow this pattern:
renderer = new THREE.WebGLRenderer( { alpha: true } ); // required
renderer.setClearColor( 0x000000, 0 ); // the default
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
renderer2 = new THREE.CSS3DRenderer();
renderer2.setSize( window.innerWidth, window.innerHeight );
renderer2.domElement.style.position = 'absolute';
renderer2.domElement.style.top = 0;
document.body.appendChild( renderer2.domElement );
three.js r.120

Categories

Resources