CubeGeometry equivalent using CSS3DRenderer, Three.JS - three.js

Following my previous question at SO, Creating a CubeGeometry equivilent using CSS3DRenderer I am trying to build a flexible 3D cube which would work under CSS3DRenderer.
Here is the current status, also available at http://jsfiddle.net/RJv3b/2/
There is a 3D cube which is create by WebGL in the example below, I would like to create a cube using CSS3D which would perfectly match the wireframe.
var camera, scene, renderer;
var geometry, material, mesh;
var scene2, renderer2;
var controls;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 400, 400, 400 );
controls = new THREE.OrbitControls( camera );
controls.noZoom = false;
controls.noPan = false;
scene = new THREE.Scene();
geometry = new THREE.CubeGeometry( 200, 300, 400 );
material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1 } );
mesh = new THREE.Mesh( geometry, material );
mesh.position.set(50,100,70)
mesh.rotation.x = Math.PI/3;
mesh.rotation.y = Math.PI/4;
mesh.rotation.z = Math.PI/5;
scene.add( mesh );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
scene2 = new THREE.Scene();
// params
var r = Math.PI / 2;
var width = 200;
var height = 300;
var depth = 400;
var x = 50
var y = 100
var z = 70
var pos = [ [ x+width/2, -y+height/2, z ], [ -depth, y/2, x/2 ], [ 0, height/2+y, x/2 ], [ depth, -y/2, x/2 ], [ x, y/2, depth/2+x/2 ], [ 0, y/2, -depth/2 +x/2] ];
var rot = [ [ 0, r, 0 ], [ 0, -r, 0 ], [ -r, 0, 0 ], [ r, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ];
// cube
var cube = new THREE.Object3D();
scene2.add( cube );
// sides
for ( var i = 0; i < 6; i ++ ) {
var txt = document.createTextNode("side:"+i);
var element = document.createElement( 'div' );
element.style.width = width+'px';
element.appendChild(txt);
element.style.height = height+'px';
element.style.background = new THREE.Color( Math.random() * 0xffffff ).getStyle();
element.style.opacity = '0.8';
var object = new THREE.CSS3DObject( element );
object.position.fromArray( pos[ i ] );
object.rotation.fromArray( rot[ i ] );
cube.add( object );
}
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 );
}

I am in the process of attempting to knock out something similar to what you are looking to do. I can't give you a polished answer, but as soon as I finish my development I can come back and update with what really works.
To dynamically integrate data into your scene, which is what I believe you are trying to accomplish, try approaching the problem utilizing the power behind D3.js
D3 will allow you to create editable DOM elements. It also pairs really well with three.js.
Add
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
to your page or download the library and call it in to your page however you would like.
Using the code you have above, you could manipulate the DOM with something like this:
d3.selectAll("div")
.data([4, 8, 15, 16, 23, 42])
.style("font-size", function(d) { return d + "px"; });
and then end up with a result with which you can make further edits via CSS if need be.
As far as opting for a JUST CSS3D render, then simply edit your renderer to be exactly that, CSS3D.
Here is a link to D3.js: http://d3js.org/
Here is a link to D3.js integrated with three.js and rendered via CSS3D: http://www.delimited.io/blog/2014/3/14/d3js-threejs-and-css-3d-transforms
Hope this helps!

Actually here's a much better answer:
Ran into this while building my site. Thought of you! Cheers!
First off make sure you're using the three.js library as your WebGL API. For WebGL development in building for sites versus an app or video game, it's one of the most well documented and built upon libraries that currently exist.
With three.js up, now you can use some wonderful plugins. The one that directly solves your problem was written by the incredible developers over at THREEX.
Here's a link to the site so you can see all the plugins they have written:
http://www.threejsgames.com
Click Extensions. I know Icoulve just linked you to extensions, but I respect the work they put into the homepage. Showing it off for em'.
The Extension you are looking for is the "Dynamic Texture" extension. If viewing the extension from their site, you get a nice description/tutorial and an example to play with.
Otherwise you can just check out the plugin over at Github:
https://github.com/jeromeetienne/threex.dynamictexture
Hope this helps!

Related

Create Rope in Three.js using Physics from Ammo.js or Cannon.js

I have been trying to create in three.js a rope hanging from a point using any of the 3D physics libraries (ammo.js, cannon.js), but the only one I have successfully done is with (2D)verlet.js.
I really need and want to create it in 3D because I need two ropes attached to a midpoint so that I can show the instability of the midpoint as a load is applied. Something similar as the attached image.
enter image description here
To be honest, I have not idea how to start, I have some experience with Three.js, but non with ammo.js or cannon.js. So far I have been trying to understand the codes for the examples in these links with not success.
http://schteppe.github.io/cannon.js/demos/constraints.html
https://threejs.org/examples/#webgl_physics_rope
I even tried to make a rope using spring function from cannon.js, but you can see that my example is not success.
Can somebody please help me or guide me into the correct way to begin my task?
This is the Code I began to write using Cannon.js:
function initCannon()
{
world = new CANNON.World();
world.gravity.set(.2,-10,.2);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10;
var mass = 1;
var damping = 1;
// STATIC SPHERE
var sphereShape = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
mass = 0;
sphereBody = new CANNON.Body({ mass: 0 });
sphereBody.addShape(sphereShape);
sphereBody.position.set(.5,8,.5);
world.addBody(sphereBody);
// DINAMIC SPHERE 1
var shape = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body = new CANNON.Body({ mass: 1 });
body.addShape(shape);
body.angularDamping = damping;
body.position.set(0,8,0);
world.addBody(body);
// DINAMIC SPHERE 2
var shape2 = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body2 = new CANNON.Body({ mass: 1 });
body2.addShape(shape2);
body2.angularDamping = damping;
body2.position.set(0,8,0);
world.addBody(body2);
// DINAMIC SPHERE 3
var shape3 = new CANNON.Sphere(new CANNON.Vec3(1,1,1));
body3 = new CANNON.Body({ mass: 1 });
body3.addShape(shape3);
body3.angularDamping = damping;
body3.position.set(0,8,0);
world.addBody(body3);
var size = 1;
var rebote = 1;
var spring = new CANNON.Spring(body,sphereBody,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
var spring2 = new CANNON.Spring(body2, body,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
var spring3 = new CANNON.Spring(body3, body2,{
localAnchorA: new CANNON.Vec3(0,size,0),localAnchorB: new CANNON.Vec3(0,0,0),
restLength : 0, stiffness : 50, damping : rebote, });
world.addEventListener("postStep",function(event){ spring.applyForce(); });
world.addEventListener("postStep",function(event){ spring2.applyForce(); });
world.addEventListener("postStep",function(event){ spring3.applyForce(); });
}
function initThree()
{
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100 );
camera.position.y = 3;camera.position.z = 15;
scene.add( camera );
controls = new THREE.TrackballControls( camera );
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
controls.keys = [ 65, 83, 68 ];
var material_wire = new THREE.MeshBasicMaterial( { color: 0xFFFFFF, wireframe: true } );
var sphere_size = .8;
var segmentos = 5;
geometry_sphere = new THREE.SphereGeometry( sphere_size, segmentos, segmentos );
sphere = new THREE.Mesh( geometry_sphere, material_wire );
scene.add( sphere );
geometry = new THREE.SphereGeometry( sphere_size, segmentos,segmentos ); // RRT DEFINE TAMANO DE CUBE
mesh = new THREE.Mesh( geometry, material_wire );
scene.add( mesh );
mesh2 = new THREE.Mesh( geometry, material_wire );
scene.add( mesh2 );
mesh3 = new THREE.Mesh( geometry, material_wire );
scene.add( mesh3 );
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
updatePhysics();
render();
}
function updatePhysics() {
// Step the physics world
world.step(timeStep);
sphere.position.copy(sphereBody.position);
mesh.position.copy(body.position); // HACE QUE SE VEA
mesh2.position.copy(body2.position);
mesh3.position.copy(body3.position);
}
function render() {
renderer.render( scene, camera );
}

Loading External Shaders Using THREE.JS

I am trying to make a THREE.JS scene with GLSL shaders applied, but am having trouble figuring out how to make it load my shaders. The scene appears to work, but the shaders don't do what they're supposed to. I'm using a shader loader function I found that uses pure THREE.JS instead of AJAX or Jquery.
Here is the main javascript for my scene.
var container,
renderer,
scene,
camera,
light,
mesh,
controls,
start = Date.now(),
fov = 30;
window.addEventListener( 'load', function() {
container = document.getElementById( "container" );
if(!Detector.webgl) {
Detector.addGetWebGLMessage(container);
return;
}
//get the width and height
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
//sphere params
var radius = 20,
segments = 4,
rotation = 6;
scene = new THREE.Scene();
// ASPECT RATIO
camera = new THREE.PerspectiveCamera(fov, WIDTH / HEIGHT, 1, 10000);
camera.position.z = 100;
scene.add(new THREE.AmbientLight(0x333333));
light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(100, 3, 5);
scene.add(light);
;
ShaderLoader('./shaders/vertex.vert', './shaders/fragment.frag')
material = new THREE.ShaderMaterial( {
uniforms: {
tExplosion: {
type: "t",
value: THREE.ImageUtils.loadTexture( 'images/explosion.png' )
},
time: { //float initialized to 0
type: "f",
value: 0.0
}
},
vertexShader: ShaderLoader.vertex_text,
fragmentShader: ShaderLoader.fragment_text
} );
mesh = new THREE.Mesh(
new THREE.IcosahedronGeometry( radius, segments ),
material
);
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setSize( WIDTH, HEIGHT );
renderer.setPixelRatio( window.devicePixelRatio );
//update renderer size, aspect ratio, and projectionmatrix, on resize
window.addEventListener('resize', function() {
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
});
controls = new THREE.TrackballControls( camera );
container.appendChild( renderer.domElement );
render();
} );
function render() {
material.uniforms[ 'time' ].value = .00025 * ( Date.now() - start );
controls.update();
requestAnimationFrame( render );
renderer.render(scene, camera);
}
// This is a basic asyncronous shader loader for THREE.js.
function ShaderLoader(vertex_url, fragment_url, onLoad, onProgress, onError) {
var vertex_loader = new THREE.XHRLoader(THREE.DefaultLoadingManager);
vertex_loader.setResponseType('text');
vertex_loader.load(vertex_url, function (vertex_text) {
var fragment_loader = new THREE.XHRLoader(THREE.DefaultLoadingManager);
fragment_loader.setResponseType('text');
fragment_loader.load(fragment_url, function (fragment_text) {
onLoad(vertex_text, fragment_text);
});
}, onProgress, onError);
}
But when my scene loads, it is just a red sphere with no lighting or applied shaders... What am I doing wrong? I'm new to all of this so it is probably something easily noticeable for someone more experienced, but I have searched and searched and been experimenting and can't figure it out.
Thanks!
Try to add material.needsUpdate = true after you load your shader.
The snippet show error of the WebGL detector.
Are you loading that library?
https://github.com/mrdoob/three.js/blob/master/examples/js/Detector.js

Three.js - Camera collision with scene

This is my first question in StackOverflow, but I've been browsing it for some years now, so I kindly ask you to bear with me. :)
I've been experimenting with Three.js to create a 3D world, and everything looked fine until I needed to control the camera. Since I'm using this lib to avoid having to do matricial calculations myself I found and added TrackballControls to my code aswell. It worked fine but then my camera could pass through the 3D shapes, and also below terrain. Unfortunately, although the movement is exactly what I needed, it didn't serve the purpose of allowing camera to respect collision.
My scene is simply the ground (thin BoxGeometry) and a cube (normal-sized BoxGeometry), and a rotating sphere that shares directionalLight position for a "sun light" effect. Some people here suggested adding Physijs to the code and simulate() physics within the scene, and adding a BoxMesh to the camera to make the physics apply to it aswell, but it simply didn't work (scene turned blank).
My working code so far (without Physijs) is:
window.onload = function() {
var renderer, scene, camera, ground, box, sphere, ambient_light, sun_light, controls;
var angle = 0;
var clock = new THREE.Clock();
init();
render();
function init(){
// Create renderer and add it to the page
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xffffff );
renderer.shadowMapEnabled = true;
document.body.appendChild( renderer.domElement );
// Create a scene to hold our awesome 3D world
scene = new THREE.Scene();
/*** 3D WORLD ***/
// Objects
ground = new THREE.Mesh(
new THREE.BoxGeometry(50, 1, 50),
new THREE.MeshLambertMaterial({ color: 0x33CC33 }),
0 // mass
);
ground.receiveShadow = true;
scene.add( ground );
box = new THREE.Mesh(
new THREE.BoxGeometry( 10, 10, 10 ),
new THREE.MeshLambertMaterial({ color: 0xDD3344 })
);
box.position.y = 5;
box.castShadow = true;
scene.add( box );
sphere = new THREE.Mesh(
new THREE.SphereGeometry( 3, 32, 32 ),
new THREE.MeshBasicMaterial({ color: 0xFFBB00 })
);
sphere.position.set( 1, 15.5, 5 );
scene.add( sphere );
// Light
ambient_light = new THREE.AmbientLight( 0x333333 );
ambient_light.mass = 0;
scene.add( ambient_light );
sun_light = new THREE.DirectionalLight( 0xBBBBBB );
sun_light.position.set( 1, 15.5, 5 );
sun_light.castShadow = true;
sun_light.shadowCameraNear = 1;
sun_light.shadowCameraFar = 100;
sun_light.shadowCameraLeft = -50;
sun_light.shadowCameraRight = 50;
sun_light.shadowCameraTop = -50;
sun_light.shadowCameraBottom = 50;
sun_light.shadowBias = -.01;
scene.add( sun_light );
// Create a camera
camera = new THREE.PerspectiveCamera(
45, // FOV
window.innerWidth / window.innerHeight, // Aspect Ratio
1, // Near plane
1000 // Far plane
);
camera.position.set( 30, 30, 30 ); // Position camera
camera.lookAt( box.position ); // Look at the scene origin
scene.add(camera);
// After swapping THREE.Mesh to Physijs.BoxMesh, this is where I'd attach a BoxMesh to the camera
window.addEventListener( 'resize', onWindowResize, false );
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 4.0;
controls.panSpeed = 0.3;
controls.staticMoving = true; // No sliding after-effects
}
function render() {
// use requestAnimationFrame to create a render loop
angle += .007;
var oscillateZ = Math.sin(angle * (Math.PI*4));
var oscillateX = -Math.cos(angle * (Math.PI*4));
//console.log(oscillateZ);
sphere.position.setZ( sphere.position.z + oscillateZ );
sphere.position.setX( sphere.position.x + oscillateX );
sun_light.position.setZ( sun_light.position.z + oscillateZ );
sun_light.position.setX( sun_light.position.x + oscillateX );
requestAnimationFrame( render );
controls.update();
renderer.render( scene, camera );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
};
Can you guys enlighten me? Thank you for your time!
#Edit
Physijs attempt

Physijs object goes through concaveMesh

I've a problem that seems to be known: my "bounding" object doesn't collide with "floor" concaveMesh.
I already read that this issue could be caused by an error in scaling concaveMesh together with the model, so I exported my floor model scaled as I need it and after I applied a concaveMesh (as follow) but it doesn't work.
I red this: https://github.com/chandlerprall/Physijs/issues/102 and a lot of other things about this topic (Physijs Load model three.js collisions don't work and a similar) and I made the following code but nothing to do :(
I really don't understand why "bounding" goes through the floor.
Here my code:
Physijs.scripts.worker = './libs/chandlerprall-Physijs-7e3837b/physijs_worker.js';
Physijs.scripts.ammo = './examples/js/ammo.js';
var gravityVector = new THREE.Vector3( 0, -100, 0 );
//renderer
var renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setClearColor(0xffffff, 0);
renderer.setSize( window.innerWidth, window.innerHeight );
//canvas
var canvas = renderer.domElement;
canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight);
document.body.appendChild( canvas );
var perspectiveCamera = new THREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight, 1, 200000);
//scene
var rttScene = new Physijs.Scene();
var bounding = new Physijs.SphereMesh(new THREE.SphereGeometry(100, 100, 100),
Physijs.createMaterial(
new THREE.MeshBasicMaterial({color: '#ff0000'}),
1.0, // friction
0.0 // restitution
),50 //mass
);
bounding.position.set(200,1200,-5000);
loader.load("http://0.0.0.0:8000/Models/Isola/pavimento.js", function( geometry, materials){
var groundMaterial = Physijs.createMaterial(new THREE.MeshFaceMaterial(materials),
0.8, // friction
0.2 // restitution
);
floor = new Physijs.ConcaveMesh(geometry,groundMaterial,0);
floor.name = "pavimento";
rttScene.add(floor);
initScene();
render();
});
function initScene() {
rttScene.setGravity(gravityVector);
rttScene.add(envModel);
rttScene.add(bounding);
bounding.setAngularFactor(new THREE.Vector3(0, 0, 0));
bounding.setCcdMotionThreshold( 0.1 );
bounding.setCcdSweptSphereRadius( 1 );
var ambientLight = new THREE.AmbientLight(0xD9B775 );
rttScene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight(0xc7af81);
directionalLight.target.position.copy( rttScene.position );
directionalLight.position.set(-550,1950,1950).normalize();
directionalLight.intensity = 0.7;
rttScene.add(directionalLight);
perspectiveCamera.position.set(200,1200,-3000);
perspectiveCamera.lookAt(bounding.position);
}
function render() {
requestAnimationFrame(render);
renderer.clear();
rttScene.simulate();
renderer.render(rttScene, perspectiveCamera);
}
I also tried this into render() function:
var originPoint = bounding.position.clone();
var ray = new THREE.Raycaster(originPoint, new THREE.Vector3(0, -1, 0));
var collisionResults = ray.intersectObjects(rttScene.children)
if (collisionResults.length > 0) {
console.log(collisionResults[0].distance);
}
In console i can read the distance between "bounding" and "floor". This should mean that floor exist as a collider but it doesn't stop bounding from falling. Why?

Three.js Ellipse

How does one go about creating an ellipse in three.js?
I've looked at this:
Drawing an ellipse in THREE.js
But it would be cool if someone could provide a working example.
I've tried this:
ellipse = new THREE.EllipseCurve(0,0,200,400,45,45,10);
but that's not working for me. I have no idea what the parameters mean so I'm just blindly going about it.
edit: I am getting the error "defined is not a function" when I try to create an ellipse curve.
edit2: Figured out I had to include Curves.js for it to work but having a working example somewhere would still be really nice for me and other people since the stackoverflow link I pasted earlier doesn't have an example.
I am unfamiliar with THREE.js, but looking at the code the parameters seem to be
(Center_Xpos, Center_Ypos, Xradius, Yradius, StartAngle, EndAngle, isClockwise)
so a reason your definition isn't working is because you're setting the start and end angles both to the same thing.
There is an example here, and below is my example:
var scene = new THREE.Scene();
var material = new THREE.LineBasicMaterial({color:0x000000, opacity:1});
var ellipse = new THREE.EllipseCurve(0, 0, 1, 5, 0, 2.0 * Math.PI, false);
var ellipsePath = new THREE.CurvePath();
ellipsePath.add(ellipse);
var ellipseGeometry = ellipsePath.createPointsGeometry(100);
ellipseGeometry.computeTangents();
var line = new THREE.Line(ellipseGeometry, material);
scene.add( line );
Notice: this is not a complete example, you should add the rest code like <script src="js/three.min.js"></script> if you want to view the result.
You can directly set a circle geometry and set its scale as: object.scale.setY(2.5);
This could easily form an oval without using any shape or curve.
Here is a complete working example.
<!doctype html>
<html>
<head>
<title>example</title>
<script src="threejs/build/three.min.js"></script>
<script src="threejs/src/core/Curve.js"></script>
<script src="threejs/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script>
var parent, renderer, scene, camera, controls, pivot1, pivot2, pivot3;
init();
animate();
function init() {
// info
info = document.createElement( 'div' );
info.style.position = 'absolute';
info.style.top = '30px';
info.style.width = '100%';
info.style.textAlign = 'center';
info.style.color = '#fff';
info.style.fontWeight = 'bold';
info.style.backgroundColor = 'transparent';
info.style.zIndex = '1';
info.style.fontFamily = 'Monospace';
info.innerHTML = 'Drag your cursor to rotate camera';
document.body.appendChild( info );
// renderer
renderer = new THREE.CanvasRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.physicallyBasedShading = true;
document.body.appendChild( renderer.domElement );
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.1, 100 );
camera.position.set( 20, 20, 20 );
// controls
controls = new THREE.OrbitControls( camera );
// axes
scene.add( new THREE.AxisHelper( 20 ) );
var material = new THREE.LineBasicMaterial({color:0x000000, opacity:1});
var ellipse = new THREE.EllipseCurve(0, 0, 1, 4, 0, 2.0 * Math.PI, false);
var ellipsePath = new THREE.CurvePath();
ellipsePath.add(ellipse);
var ellipseGeometry = ellipsePath.createPointsGeometry(100);
ellipseGeometry.computeTangents();
var line = new THREE.Line(ellipseGeometry, material);
scene.add( line );
}
function animate() {
requestAnimationFrame( animate );
controls.update();
renderer.render( scene, camera );
}
</script>
</body>
</html>

Resources