Three.js: draw a octahedron - javascript

I want to draw a Octahedron,but the shape of the result is below expectation.I dont know the reason and next step I want to draw a Dodecahedron, any suggestions?The result of the Octahedron
My code:
var mesh, renderer, scene, camera, controls;
init();
animate();
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// scene
scene = new THREE.Scene();
// camera
camera = new THREE.PerspectiveCamera(40, window.innerWidth /
window.innerHeight, 1, 10000);
camera.position.set(20, 20, 20);
// controls
controls = new THREE.OrbitControls(camera);
// ambient
scene.add(new THREE.AmbientLight(0x222222));
// light
var light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(20, 20, 0);
scene.add(light);
// axes
scene.add(new THREE.AxisHelper(20));
// geometry
//var geometry = new THREE.SphereGeometry(5, 12, 8);
var vertices = [
0.5,0,0, 0,0.3,0, -0.5,0,0, 0,-0.3,0, 0,0,0.3, 0,0,-0.3
];
var faces = [
0,1,4, 1,2,4, 2,3,4, 3,0,4, 0,1,5, 1,2,5, 2,3,5, 3,0,5
];
var geometry = new THREE.PolyhedronGeometry(vertices, faces, 5, 1);
// material
var material = new THREE.MeshPhongMaterial({
color: 0x00ffff,
shading: THREE.FlatShading,
wireframe:true,
transparent: true,
opacity: 0.7,
});
// mesh
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function animate() {
requestAnimationFrame(animate);
//controls.update();
renderer.render(scene, camera);
}

Use
var geometry = new THREE.OctahedronGeometry( 5, 0 ); // or DodecahedronGeometry
Read and understand the source code of OctahedronGeometry.js if you want to use PolyhedronGeometry directly.
If wireframe is true, use MeshBasicMaterial, instead.
three.js r.85

Related

Problem rendering first 2 objects in three.js

everything works fine but sphere and box geometry dont show, plane works fine too! does anyone have a clue? i suspect something wrong maybe in the render function or animation frame, im fairly new to three.js and cant seem to know why the scene wont show the other geometry, i tried different materials, rotation, clear color, etc
var renderer,
scene,
camera,
myCanvas = document.getElementById('myCanvas');
//RENDERER
renderer = new THREE.WebGLRenderer({
canvas: myCanvas,
antialias: true,
});
renderer.setClearColor(0x000000);
renderer.setPixelRatio(window.devicePixelRatio); //device pixel ratio
renderer.setSize(window.innerWidth, window.innerHeight); //canvas size
//CAMERA
var camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 300, 10000)
//SCENE
var scene = new THREE.Scene();
//LIGHT
var light = new THREE.AmbientLight(0xffff, 0.5)
scene.add(light);
var light1 = new THREE.PointLight(0xffff, 0.5)
scene.add(light1);
//MATERIAL
var material = new THREE.MeshLambertMaterial({
color: 0xF3FFE2,
lightMap: null,
lightMapIntensity: 1,
emissive: 0x000000,
emissiveMap: null,
emissiveIntensity: 1,
specularMap: null
});
//GEOMETRY
var geometry = new THREE.BoxGeometry(100, 100, 100);
var mesh = new THREE.Points(geometry, material);
mesh.position.z = -1000;
mesh.position.x = -100;
scene.add(mesh);
var geometry2 = new THREE.SphereGeometry(50, 20, 20);
var mesh2 = new THREE.Points(geometry2, material);
mesh2.position.z = -1000;
mesh2.position.x = 100;
scene.add(mesh2);
var geometry3 =  new THREE.PlaneGeometry(10000, 10000, 100, 100);
var mesh3 = new THREE.Mesh(geometry3, material);
mesh3.rotation.x = -90 * Math.PI / 180;
mesh3.position.y = -100;
scene.add(mesh3);
//RENDER LOOP
render();
function render() {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
Tried your code, everything is ok but the 2 objects need to be THREE.Mesh
var geometry = new THREE.BoxGeometry(100, 100, 100);
var mesh = new THREE.Mesh(geometry, material);
mesh.position.z = -1000;
mesh.position.x = -100;
scene.add(mesh);
var geometry2 = new THREE.SphereGeometry(50, 20, 20);
var mesh2 = new THREE.Mesh(geometry2, material);
mesh2.position.z = -1000;
mesh2.position.x = 100;
scene.add(mesh2);

Flat shading with phong material with spot light

I am trying to achieve flat shading with the phong material. As the documentation says we have to set flatShading:true in config when creating the material. I have created a cube with these settings and created a spot light to focus at the center of the cube (not touching the vertices of the cube).
I assume the face of the cube should look same at all pixels but its not looking so. I see a reflection of the light at the center of the face. Indeed, changing the flatShading from true to false, is not affecting the light.
Here is the JS fiddle link to what i tried. https://jsfiddle.net/dj03gktb/.
Below is the code.
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 4;
scene.add(camera);
scene = new THREE.Scene();
var ambientLight = new THREE.AmbientLight(0xcccccc, 0.2);
scene.add(ambientLight);
var pointLight = new THREE.SpotLight({ color: 0xffffff, angle: Math.PI / 10, intensity: 2 });
scene.add(pointLight);
//pointLight.position.x = 5;
pointLight.position.z = 1.5;
pointLight.position.y = 0;
var geometry = new THREE.BoxGeometry(1, 1, 1);
//geometry.computeFlatVertexNormals();
//geometry.rotateY(0.5);
var material = new THREE.MeshPhongMaterial({ color: 0xff0000, flatShading: true, shininess: 100, specular: 0x00ff00 });
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
May be i have under stood flat shading wrongly or could be bug with the THREE.js or problem with the render engine.
Any help would be great.
Unfortunately, using a cube to demonstrate flat shading is a bad example since you won't see any difference. Try it with a sphere instead:
var camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
camera.position.z = 4;
scene = new THREE.Scene();
var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.2 );
scene.add( ambientLight );
var spotLight = new THREE.SpotLight({ color: 0xffffff, angle: Math.PI / 10, intensity: 2});
spotLight.position.z = 1.5;
scene.add(spotLight);
var geometry = new THREE.SphereBufferGeometry( 1, 12, 16);
var material = new THREE.MeshPhongMaterial({color: 0xff0000, flatShading: true, shininess: 100, specular: 0x00ff00});
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.118.3/build/three.js"></script>
I assume the face of the cube should look same at all pixels but its not looking so.
This is not what flat shading does. Normally vertex normals are interpolated in the fragment shader which produces the typical smooth rendering. Flat shading just ensures that the normals of a face are equal across its (flat) surface. So there is no interpolation of vertex normals. Apart from that, lighting calculations are not affected. Hence, you also see specular highlights.

ThreeJs different Text on each face of cube

I'm working on Threejs to animate a cube with different text on each cube faces. I used DynamicTexture to place text on cube faces, but it places same text on each side of cube. I don't know how to place different text on each side. Is there any way to do is and place text on runtime by user inputs? Thanks.
Main.js
var scene = new THREE.Scene();
scene.background = new THREE.Color('white');
var camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 1, 1000);
camera.position.set(4, 4, 4);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('display').appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera);
var dynamictexture = new THREEx.DynamicTexture(512, 512);
dynamictexture.context.font = "bolder 90px verdana";
dynamictexture.texture.needsUpdate = true;
dynamictexture.clear('#d35400').drawText('Text', undefined, 256, 'green');
var geometry = new THREE.BoxGeometry(2, 2, 2);
var material = new THREE.MeshBasicMaterial({color: 0xffffff, map: dynamictexture.texture, opacity:1,
transparent: true});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
function animate() {
requestAnimationFrame(animate);
controls.update();
dynamictexture.texture
renderer.render(scene, camera);
};
animate();
You can use THREE.MeshFaceMaterial(materials) to accomplish this. All you need to do is pass an array containing the materials and specifying the map for each of the faces.
var face_textures = [];
function createFaceTextures() {
var i;
for(i = 0; i < 6; i++) {
var dynamictexture = new THREEx.DynamicTexture(512, 512);
dynamictexture.context.font = "bolder 90px verdana";
dynamictexture.texture.needsUpdate = true;
dynamictexture.clear('#d35400').drawText(i.toString(), undefined, 256, 'green');
face_textures.push(dynamictexture);
}
}
createFaceTextures();
var scene = new THREE.Scene();
scene.background = new THREE.Color('white');
var camera = new THREE.PerspectiveCamera(50, window.innerWidth/window.innerHeight, 1, 1000);
camera.position.set(4, 4, 4);
camera.lookAt(0, 0, 0);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.getElementById('display').appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera);
var dynamictexture = new THREEx.DynamicTexture(512, 512);
dynamictexture.context.font = "bolder 90px verdana";
dynamictexture.texture.needsUpdate = true;
dynamictexture.clear('#d35400').drawText('Text', undefined, 256, 'green');
var geometry = new THREE.BoxGeometry(2, 2, 2,);
var material = new THREE.MeshBasicMaterial({color: 0xffffff, map: dynamictexture.texture, opacity:1, transparent: true});
var materials = [
new THREE.MeshBasicMaterial({map: face_textures[0].texture}),
new THREE.MeshBasicMaterial({map: face_textures[1].texture}),
new THREE.MeshBasicMaterial({map: face_textures[2].texture}),
new THREE.MeshBasicMaterial({map: face_textures[3].texture}),
new THREE.MeshBasicMaterial({map: face_textures[4].texture}),
new THREE.MeshBasicMaterial({map: face_textures[5].texture})
];
var cube = new THREE.Mesh(geometry, materials);
scene.add(cube);
function animate() {
requestAnimationFrame(animate);
controls.update();
dynamictexture.texture
renderer.render(scene, camera);
}
animate();

How to rotate object with offset by orbit control in three.js?

I want to control object like this:
Now camera is move around Y coordinate, but need to be move around NEW Y. Code is here:
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
var controls = new THREE.OrbitControls(camera);
cube.position.x = 300;
// controls.target = THREE.Vector3(300, 0, 0);
I found that target option can set the focus point of the controls, but if I add this code: controls.target = THREE.Vector3(300, 0, 0); the object back to the center of the screen, but it should be at the right edge.
More over, when I set new THREE.OrbitControls(camera); to new THREE.OrbitControls(cube); and add controls.target = THREE.Vector3(300, 0, 0); control doesn't work, but when I set controls.target = THREE.Vector3(301, 0, 0); it is managed but not like a camera
OrbitControls.target set the focus point of the controls and the .object orbits around this. But it is a manually manipulation. As mentioned in the documentation OrbitControls.update() must be called after any manual changes to the camera's transform.
e.g.
controls.target = new THREE.Vector3(1, 0, 0)
controls.update();
See the example:
(function onLoad() {
var container, camera, scene, renderer, controls;
init();
animate();
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1.0, -4);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
var ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
directionalLight.position.set(1,2,1.5);
scene.add( directionalLight );
controls = new THREE.OrbitControls(camera, container);
controls.target = new THREE.Vector3(3, 0, 0)
controls.update();
controls.autoRotate = true;
controls.autoRotateSpeed = 5.0
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
})();
<script src="https://cdn.jsdelivr.net/npm/three#0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three#0.115/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>

An ExtrudeGeometry of Three.js can be seen when it's behind another extrude geometry

I created 2 extrude geometries (cubes) side by side, but the cube behind the other can still be seen when rotating the scene camera.
The cube in the front becomes transparent which is supposed to shield the cube behind.
The codes:
var renderer, scene, camera;
function init() {
// renderer
renderer = new THREE.WebGLRenderer({
canvas: document.getElementById('mainCanvas')
});
renderer.setClearColor(0x000000); // black
var gl = renderer.context;
gl.enable(gl.DEPTH_TEST);
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, 4 / 3, -1, 1);
camera.position.set(0, 0, -500);
camera.lookAt(new THREE.Vector3(0, 0, 0));
var light = new THREE.PointLight(0xffffff, 0.8);
camera.add(light);
scene.add(camera);
//-------------------------------------
var extrudeSettings = {
amount : 50
};
// a cube in the scene
var cube = new THREE.Mesh(
new THREE.ExtrudeGeometry(
new THREE.Shape([
new THREE.Vector2(-20, 20),
new THREE.Vector2(20, 20),
new THREE.Vector2(20, -20),
new THREE.Vector2(-20, -20),
new THREE.Vector2(-20, 20),
]),
extrudeSettings),
new THREE.MeshLambertMaterial({
color: 0xff0000
})
);
var cube2 = new THREE.Mesh(
new THREE.ExtrudeGeometry(
new THREE.Shape([
new THREE.Vector2(-60, 20),
new THREE.Vector2(-20, 20),
new THREE.Vector2(-20, -20),
new THREE.Vector2(-60, -20),
new THREE.Vector2(-60, 20),
]),
extrudeSettings
),
new THREE.MeshLambertMaterial({
color: 0x00ff00
})
);
cube2.position.x = -20;
scene.add(cube, cube2);
// render
renderer.render(scene, camera);
oribitControls = new THREE.OrbitControls( camera);
oribitControls.addEventListener( 'change', render );
oribitControls.enableDamping = true;
oribitControls.dampingFactor = 0.25;
oribitControls.enableZoom = false;
oribitControls.autoRotate = true;
oribitControls.autoRotateSpeed = 1.0;
}
function render() {
renderer.render(scene, camera);
}
And jsfiddle:
https://jsfiddle.net/maptalks/y29f32za/
Three.js version : r82
Browser : Chrome (latest)
Many many thanks if any one can point out if there is anything I missed.

Categories

Resources