Display loaded OBJ model in wireframe mode in three.js - three.js

I wanted to display my loaded .obj file in wireframe mode..
I got to know about the WireFrameGeometry But for somereason the .mtl texture only gets display .
Below is the code ..
/* Model */
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setBaseUrl('assets/');
mtlLoader.setPath('assets/');
mtlLoader.load('materialfile.mtl', function(materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('Objectfile.obj', function(object) {
object.traverse(function(child) {
if (child.isMesh) {
var wireframeGeomtry = new THREE.WireframeGeometry(child.geometry);
var wireframeMaterial = new THREE.LineBasicMaterial({
color: 0xffffff
});
var wireframe = new THREE.LineSegments(wireframeGeomtry, wireframeMaterial);
child.add(wireframe);
}
});
scene.add(object);
});
});
I only want the wireframe of the model without any fill..
Thanks in advance.
The entire code is below...
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="three.js"></script>
<script src="TrackballControls.js"></script>
<script src="cannon.js"></script>
<script src="Detector.js"></script>
<script src="OrbitControls.js"></script>
<script src="OBJLoader.js"></script>
<script src="MTLLoader.js"></script>
</head>
<body>
<script>
if (!Detector.webgl) {
Detector.addGetWebGLMessage();
}
var container;
var camera, controls, scene, renderer;
var lighting, ambient, keyLight, fillLight, backLight;
init();
animate();
function init() {
container = document.createElement('div');
document.body.appendChild(container);
/* Camera */
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 50;
/* Scene */
scene = new THREE.Scene();
lighting = false;
ambient = new THREE.AmbientLight(0xffffff, 1.0);
scene.add(ambient);
// keyLight = new THREE.DirectionalLight(new THREE.Color('hsl(30, 100%, 75%)'), 1.0);
// keyLight.position.set(-100, 0, 100);
// fillLight = new THREE.DirectionalLight(new THREE.Color('hsl(240, 100%, 75%)'), 0.75);
// fillLight.position.set(100, 0, 100);
// backLight = new THREE.DirectionalLight(0xffffff, 1.0);
// backLight.position.set(100, 0, -100).normalize();
/* Model */
// var mtlLoader = new THREE.MTLLoader();
// mtlLoader.setBaseUrl('assets/');
// mtlLoader.setPath('assets/');
// mtlLoader.load('mtlfile.mtl', function(materials) {
// materials.preload();
// materials.materials.default.map.magFilter = THREE.NearestFilter;
// materials.materials.default.map.minFilter = THREE.LinearFilter;
var objLoader = new THREE.OBJLoader();
// objLoader.setMaterials(materials);
objLoader.setPath('assets/');
objLoader.load('objectfile.obj', function(object) {
object.traverse(function(child) {
if (child.isMesh) {
var wireframeGeomtry = new THREE.WireframeGeometry(child.geometry);
var wireframeMaterial = new THREE.LineBasicMaterial({
color: 0xeeeeee
});
var wireframe = new THREE.LineSegments(wireframeGeomtry, wireframeMaterial);
// add to child so we get same orientation
child.add(wireframe);
// to parent of child. Using attach keeps our orietation
child.parent.attach(wireframe);
// remove child (we don't want child)
child.parent.remove(child);
}
});
scene.add(object);
});
// });
/* Renderer */
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(new THREE.Color("hsl(0, 0%, 10%)"));
container.appendChild(renderer.domElement);
/* Controls */
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
controls.autoRotate = true;
/* Events */
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function animate() {
requestAnimationFrame(animate);
controls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
</html>
So this is the entire code..
Its just the basic obj loader ..
I don't know whether the problem is in the code or model .
It shows as a fully filled white model

object.traverse(function(child) {
if (child.isMesh) {
child.material.wireframe = true;
}
}

This worked for me
objLoader.load('Objectfile.obj', function(object) {
object.traverse(function(child) {
if (child.isMesh) {
var wireframeGeomtry = new THREE.WireframeGeometry(child.geometry);
var wireframeMaterial = new THREE.LineBasicMaterial({
color: 0xffffff
});
var wireframe = new THREE.LineSegments(wireframeGeomtry, wireframeMaterial);
// add to child so we get same orientation
child.add(wireframe);
// to parent of child. Using attach keeps our orietation
child.parent.attach(wireframe);
// remove child (we don't want child)
child.parent.remove(child);
}
});
scene.add(object);
});
Example:
html, body {
margin: 0;
height: 100%;
}
#c {
width: 100%;
height: 100%;
display: block;
}
<canvas id="c"></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/controls/OrbitControls.js';
import {OBJLoader2} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/loaders/OBJLoader2.js';
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 45;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 20);
const controls = new OrbitControls(camera, canvas);
controls.target.set(0, 5, 0);
controls.update();
const scene = new THREE.Scene();
scene.background = new THREE.Color('black');
{
const objLoader = new OBJLoader2();
objLoader.load('https://threejsfundamentals.org/threejs/resources/models/windmill/windmill.obj', (root) => {
root.traverse(child => {
if (child.isMesh) {
var wireframeGeomtry = new THREE.WireframeGeometry(child.geometry);
var wireframeMaterial = new THREE.LineBasicMaterial({
color: 0xffffff
});
var wireframe = new THREE.LineSegments(wireframeGeomtry, wireframeMaterial);
child.add(wireframe);
child.parent.attach(wireframe);
child.parent.remove(child);
}
});
scene.add(root);
});
}
function resizeRendererToDisplaySize(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 (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>
You can also do it the way manthrax suggested except you need to check if child.material is an array or not, then for each material remove the map (so the texture is not used) and set emissive to some color (you might also want to set color to black)`.
html, body {
margin: 0;
height: 100%;
}
#c {
width: 100%;
height: 100%;
display: block;
}
<canvas id="c"></canvas>
<script type="module">
import * as THREE from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/build/three.module.js';
import {OrbitControls} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/controls/OrbitControls.js';
import {OBJLoader2} from 'https://threejsfundamentals.org/threejs/resources/threejs/r115/examples/jsm/loaders/OBJLoader2.js';
function main() {
const canvas = document.querySelector('#c');
const renderer = new THREE.WebGLRenderer({canvas});
const fov = 45;
const aspect = 2; // the canvas default
const near = 0.1;
const far = 100;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 10, 20);
const controls = new OrbitControls(camera, canvas);
controls.target.set(0, 5, 0);
controls.update();
const scene = new THREE.Scene();
scene.background = new THREE.Color('black');
function makeWireframe(material) {
material.wireframe = true;
material.emissive.set('#0FF');
material.map = undefined;
}
{
const objLoader = new OBJLoader2();
objLoader.load('https://threejsfundamentals.org/threejs/resources/models/windmill/windmill.obj', (root) => {
root.traverse(child => {
if (child.isMesh) {
if (Array.isArray(child.material)) {
child.material.forEach(makeWireframe);
} else {
makeWireframe(child.material)
}
}
});
scene.add(root);
});
}
function resizeRendererToDisplaySize(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 (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
}
main();
</script>

Related

How to change variable after checking controller.userData

I'm working with Three.js on a project. I just started working with it and mostly tried my luck with picking different things from the examples.
In short: I'm loading a volume and want to show another layer of it after the event listener for one of the controllers fired.
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js vr - dragging</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<link type="text/css" rel="stylesheet" href="main.css">
</head>
<body>
<div id="info">
three.js nrrd
</div>
<!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims#1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "../build/three.module.js",
"three/addons/": "./jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { VRButton } from 'three/addons/webxr/VRButton.js';
import { XRControllerModelFactory } from 'three/addons/webxr/XRControllerModelFactory.js';
import { NRRDLoader } from 'three/addons/loaders/NRRDLoader.js';
let camera, scene, renderer;
let controller1, controller2;
let raycaster;
let xlayer ;
const intersected = [];
const tempMatrix = new THREE.Matrix4();
let controls, group, array;
init();
animate();
function init() {
const container = document.createElement('div');
document.body.appendChild(container);
scene = new THREE.Scene();
scene.background = new THREE.Color(0x808080);
camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 40);
camera.position.set(0, 1.6, 3);
controls = new OrbitControls(camera, container);
controls.target.set(0, 1.6, 0);
controls.update();
scene.add(new THREE.HemisphereLight(0x808080, 0x606060));
group = new THREE.Group();
array = [];
scene.add(group);
var holder = new THREE.Group();
const loader = new NRRDLoader();
loader.load('models/nrrd/retina.nrrd', function (volume) {
const a = volume.xLength;
const b = volume.yLength;
const c = volume.zLength;
//box helper to see the extend of the volume
const geometry = new THREE.BoxGeometry(volume.xLength, volume.yLength, volume.zLength);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
cube.visible = false;
const box = new THREE.BoxHelper(cube);
holder.add(box);
box.applyMatrix4(volume.matrix);
holder.add(cube);
//z plane
const sliceZ = volume.extractSlice('z', xlayer);
holder.add(sliceZ.mesh);
holder.scale.set((1 / a) * 10, (1 / b) * 6, (1 / c) * 5);
holder.position.set(0, 0, -15);
scene.add(holder);
});
//l-left, r-right, t-top, b-bottom
const planegeometrylr = new THREE.PlaneGeometry(5, 6);
const planegeometrytb = new THREE.PlaneGeometry(10, 5);
const planematerial = new THREE.MeshBasicMaterial({ color: 'blue', side: THREE.DoubleSide });
const planel = new THREE.Mesh(planegeometrylr, planematerial);
const planer = new THREE.Mesh(planegeometrylr, planematerial);
const planet = new THREE.Mesh(planegeometrytb, planematerial);
const planeb = new THREE.Mesh(planegeometrytb, planematerial);
planel.rotateY(Math.PI / 2);
planel.position.set(-(10 / 2), 0, -15);
array.push(planel);
group.add(planel);
planer.rotateY(Math.PI / 2);
planer.position.set((10 / 2), 0, -15);
array.push(planer);
group.add(planer);
planet.rotateX(Math.PI / 2);
planet.position.set(0, (6 / 2), -15);
array.push(planet);
group.add(planet);
planeb.rotateX(Math.PI / 2);
planeb.position.set(0, -(6 / 2), -15);
array.push(planeb);
group.add(planeb);
//
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.shadowMap.enabled = true;
renderer.xr.enabled = true;
container.appendChild(renderer.domElement);
document.body.appendChild(VRButton.createButton(renderer));
// controllers
controller1 = renderer.xr.getController(0);
controller1.addEventListener('selectstart', onSelectStart);
controller1.addEventListener('selectend', onSelectEnd);
controller1.userData.selected = false;
scene.add(controller1);
controller2 = renderer.xr.getController(1);
controller2.addEventListener('selectstart', onSelectStart);
controller2.addEventListener('selectend', onSelectEnd);
controller2.userData.selected = false;
scene.add(controller2);
const controllerModelFactory = new XRControllerModelFactory();
//
const geometry = new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(0, 0, 0), new THREE.Vector3(0, 0, - 1)]);
const line = new THREE.Line(geometry);
line.name = 'line';
line.scale.z = 5;
controller1.add(line.clone());
controller2.add(line.clone());
raycaster = new THREE.Raycaster();
//
window.addEventListener('resize', onWindowResize);
function onSelectStart() {
this.userData.selected = true;
}
function onSelectEnd(event) {
const controller = event.target;
controller.userData.selected = false;
}
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
function handle(controller) {
if (controller.userData.selected){
scene.background = new THREE.Color( 'green' );
xlayer=60;
}
}
function animate() {
renderer.setAnimationLoop(render);
}
function render() {
handle(controller1);
handle(controller2);
renderer.render(scene, camera);
}
</script>
</body>
</html>
xlayer=60 works in handle()(shows layer 60 other than defined in init()):
when its before the if clause of the controller.UserData
when its in it and I set it true right above the if clause
it doesn't work
whenever its in the if clause, even if something else in the if clause worked (like setting the background green)
I wonder if I did something wrong or if it just doesn't work like that.

The DOM element created by CSS3DObject cannot be obscured by the GL plane

I found that it seems to be solved by setting the blending attribute of material, but it still cannot be solved after trying.
Incorrect occlusion
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader.js"
import {
CSS3DRenderer,
CSS3DObject
} from "three/examples/jsm/renderers/CSS3DRenderer.js"
import dat from "dat.gui"
function initThree() {
const scene = new THREE.Scene();
const scene2 = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
10000
);
camera.position.set(0, 0, 2500);
scene.add(camera);
const renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true,
});
renderer.shadowMap.enabled = true;
renderer.setSize(window.innerWidth, window.innerHeight);
document.querySelector('#webgl').appendChild(renderer.domElement);
const labelRenderer = new CSS3DRenderer()
labelRenderer.setSize(window.innerWidth, window.innerHeight);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
document.body.appendChild(labelRenderer.domElement);
scene.add(new THREE.AxesHelper(1000))
const controls = new OrbitControls(camera, labelRenderer.domElement);
controls.enableDamping = true;
const clock = new THREE.Clock()
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
labelRenderer.setSize(window.innerWidth, window.innerHeight);
});
return {
scene,
scene2,
camera,
renderer,
labelRenderer,
controls,
clock,
}
}
const gltfLoader = new GLTFLoader()
const textureLoader = new THREE.TextureLoader()
const gui = new dat.GUI()
const {
scene,
scene2,
camera,
renderer,
labelRenderer,
controls,
clock
} = initThree();
const ambientLight = new THREE.AmbientLight("#ffffff", 1)
scene.add(ambientLight)
const position = new THREE.Vector3(0, 900, 300);
const rotation = new THREE.Euler(0, 0, 0);
const container = document.createElement('div');
container.style.width = '1000px';
container.style.height = '1000px';
container.style.opacity = '1';
container.style.background = '#1d2e2f';
const iframe = document.createElement('iframe');
iframe.src = "http://csyedu.top"
iframe.style.width = "1000px"
iframe.style.height = "1000px"
iframe.style.padding = 10 + 'px';
iframe.style.boxSizing = 'border-box';
iframe.style.opacity = '1';
container.appendChild(iframe);
const object = new CSS3DObject(container);
// copy monitor position and rotation
object.position.copy(position);
object.rotation.copy(rotation);
// Add to CSS scene
scene2.add(object);
// Create GL plane
const material = new THREE.MeshLambertMaterial();
material.side = THREE.DoubleSide;
material.opacity = 0;
material.transparent = true;
// NoBlending allows the GL plane to occlude the CSS plane
material.blending = THREE.NoBlending;
// Create plane geometry
const geometry = new THREE.PlaneGeometry(1000, 1000);
// Create the GL plane mesh
const mesh = new THREE.Mesh(geometry, material);
// Copy the position, rotation and scale of the CSS plane to the GL plane
mesh.position.copy(object.position);
mesh.rotation.copy(object.rotation);
mesh.scale.copy(object.scale);
// Add to gl scene
scene.add(mesh);
gltfLoader.load("./models/computer_setup.glb", model => {
const texture = textureLoader.load("./models/baked_computer.jpg");
texture.flipY = false;
texture.encoding = THREE.sRGBEncoding;
const material = new THREE.MeshBasicMaterial({
map: texture,
});
model.scene.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.scale.set(900, 900, 900);
child.material.map = texture;
child.material = material;
}
});
scene.add(model.scene)
})
function render() {
const elapsedTime = clock.getElapsedTime();
controls.update();
renderer.render(scene, camera);
labelRenderer.render(scene2, camera)
requestAnimationFrame(render);
}
render();
The effect I want is that the 3D mesh can correctly occlude the CSS3DObject.
I runned over the same problem, I'm trying your code and works good on my project, I think you have a styling problem.
I have separated the WebGL and CSS3DRenderer on the html.
<body>
<div id="css"></div>
<div id="webgl"></div>
</body>
#css,
#webgl
{
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
If I only put the #css on absolute this is the result
If I put both in absolute it works fine.
I wish that'll help

Guidance required for this handle shape in ThreeJS

I have to create this handle shape in ThreeJS:
I've imagined it as being a combination of a plane geometry and a twisted/squashed cone at each end with a smaller z position than the rest of the object.
I think it'd be simpler to create just one Shape for this rather than attempting to merge meshes together. Here's what I have so far:
(function onLoad() {
var container, camera, scene, renderer;
init();
animate();
function init() {
container = document.getElementById('container');
initScene();
addGridHelper();
addCamera();
addRenderer();
addOrbitControls();
var knottedRibbonHandleTwo = createKnottedRibbonHandleTwo();
knottedRibbonHandleTwo.position.x -= 250;
scene.add(knottedRibbonHandleTwo);
var sceneLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
scene.add(sceneLight);
}
function createKnottedRibbonHandleTwo() {
var belt = new THREE.Shape();
belt.moveTo(0, 0);
belt.lineTo(25, 0);
belt.lineTo(25, 2.5);
belt.lineTo(0, 2.5);
var extrudeSettings = {
steps: 1,
amount: 1,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
var geometry = new THREE.ExtrudeGeometry(belt, extrudeSettings);
var material = new THREE.MeshPhongMaterial({
color: 0xffd700,
wireframe: false
});
var mesh = new THREE.Mesh(geometry, material);
mesh.scale.multiplyScalar(20);
return mesh;
}
/**** Basic Scene Setup ****/
function initScene() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
}
function addCamera() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(349.11334070460066, 405.44010726325604, 359.3111192889029);
scene.add(camera);
}
function addGridHelper() {
var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
planeGeometry.rotateX(-Math.PI / 2);
var planeMaterial = new THREE.ShadowMaterial({
opacity: 0.2
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = -200;
plane.receiveShadow = true;
scene.add(plane);
var helper = new THREE.GridHelper(2000, 100);
// helper.position.y = -199;
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper();
scene.add(axis);
}
function addRenderer() {
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
}
function addOrbitControls() {
var controls = new THREE.OrbitControls(camera, renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
})();
body {
background: transparent;
padding: 0;
margin: 0;
font-family: sans-serif;
}
#canvas {
margin: 10px auto;
width: 800px;
height: 350px;
margin-top: -44px;
}
<body>
<div id="container"></div>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
</body>
But I'm confused as to how I'd achieve the end parts.
Thanks.
Creativity is up to you. You can create any shape you want. I just modified your snippet a bit:
(function onLoad() {
var container, camera, scene, renderer;
init();
animate();
function init() {
container = document.getElementById('container');
initScene();
addGridHelper();
addCamera();
addRenderer();
addOrbitControls();
var knottedRibbonHandleTwo = createKnottedRibbonHandleTwo();
knottedRibbonHandleTwo.position.x -= 250;
scene.add(knottedRibbonHandleTwo);
var sceneLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
scene.add(sceneLight);
}
function createKnottedRibbonHandleTwo() {
var belt = new THREE.Shape();
belt.moveTo(0, 1.25);
belt.lineTo(1.25, 0.5);
belt.lineTo(2.5, 0);
belt.lineTo(22.5, 0);
belt.lineTo(23.75, 0.5);
belt.lineTo(25, 1.25);
belt.lineTo(23.75, 2);
belt.lineTo(22.5, 2.5);
belt.lineTo(2.5, 2.5);
belt.lineTo(1.25, 2);
var extrudeSettings = {
steps: 1,
amount: .25,
bevelEnabled: false,
bevelThickness: 1,
bevelSize: 1,
bevelSegments: 1
};
var geometry = new THREE.ExtrudeGeometry(belt, extrudeSettings);
var material = new THREE.MeshPhongMaterial({
color: 0xffd700,
wireframe: false
});
var mesh = new THREE.Mesh(geometry, material);
mesh.scale.setScalar(20);
return mesh;
}
/**** Basic Scene Setup ****/
function initScene() {
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
}
function addCamera() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.set(349.11334070460066, 405.44010726325604, 359.3111192889029);
scene.add(camera);
}
function addGridHelper() {
var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
planeGeometry.rotateX(-Math.PI / 2);
var planeMaterial = new THREE.ShadowMaterial({
opacity: 0.2
});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.y = -200;
plane.receiveShadow = true;
scene.add(plane);
var helper = new THREE.GridHelper(2000, 100);
// helper.position.y = -199;
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper();
scene.add(axis);
}
function addRenderer() {
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
}
function addOrbitControls() {
var controls = new THREE.OrbitControls(camera, renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
renderer.render(scene, camera);
}
})();
body {
background: transparent;
padding: 0;
margin: 0;
font-family: sans-serif;
}
#canvas {
margin: 10px auto;
width: 800px;
height: 350px;
margin-top: -44px;
}
<body>
<div id="container"></div>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
</body>

three.js r88 meshdepthmaterial there is no effect

I'm a new three.js men, and below is my code snippet...
In three.js docs said that the MeshDepthMaterial is drawing geometry by depth. Depth is based off of the camera near and far plane. White is nearest, black is farthest. But in my case, there is no effect for three.js r88, but three.js r 67. Can anybody please tell me why? Thanks very much...
<!DOCTYPE html>
<html>
<head>
<title>示例 04.02 - MeshDepthMaterial</title>
<script src="../build/three.js"></script>
<script src="../build/js/controls/OrbitControls.js"></script>
<script src="../build/js/libs/stats.min.js"></script>
<script src="../build/js/libs/dat.gui.min.js"></script>
<script src="../build/js/renderers/CanvasRenderer.js"></script>
<script src="../build/js/renderers/Projector.js"></script>
<script src="../jquery/jquery-3.2.1.min.js"></script>
<style>
body {
/* 设置 margin 为 0,并且 overflow 为 hidden,来完成页面样式 */
margin: 0;
overflow: hidden;
}
/* 统计对象的样式 */
#Stats-output {
position: absolute;
left: 0px;
top: 0px;
}
</style>
</head>
<body>
<!-- 用于 WebGL 输出的 Div -->
<div id="webgl-output"></div>
<!-- 用于统计 FPS 输出的 Div -->
<div id="stats-output"></div>
<!-- 运行 Three.js 示例的 Javascript 代码 -->
<script type="text/javascript">
var scene;
var camera;
var render;
var webglRender;
var canvasRender;
var controls;
var stats;
var guiParams;
var ground;
var cube;
var plane;
var sphere;
var meshMaterial;
var ambientLight;
var spotLight;
$(function() {
stats = initStats();
scene = new THREE.Scene();
scene.overrideMaterial = new THREE.MeshDepthMaterial({
morphTargets: true
});
webglRender = new THREE.WebGLRenderer( {antialias: true, alpha: true, logarithmicDepthBuffer: true} ); // antialias 抗锯齿
webglRender.setSize(window.innerWidth, window.innerHeight);
webglRender.setClearColor(0x000000, 1.0);
webglRender.shadowMap.enabled = true; // 允许阴影投射
render = webglRender;
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // 2147483647
camera.position.set(-50, 40, 50);
var target = new THREE.Vector3(0, 0 , 0);
controls = new THREE.OrbitControls(camera, render.domElement);
controls.target = target;
camera.lookAt(target);
$('#webgl-output')[0].appendChild(render.domElement);
window.addEventListener('resize', onWindowResize, false);
ambientLight = new THREE.AmbientLight(0x000000);
scene.add(ambientLight);
/** 用来保存那些需要修改的变量 */
guiParams = new function() {
this.rotationSpeed = 0.02;
this.near = 2;
this.far = 50;
this.addCube = function() {
for (var i=0; i<100; i++) {
// 定义 cube 几何
var cubeGeometry = new THREE.BoxGeometry(5, 5, 5);
// 定义网格材质
meshMaterial = new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff});
// 定义 cube 网格
cube = new THREE.Mesh(cubeGeometry, meshMaterial);
cube.castShadow = true;
cube.position.x = -60 + Math.round((Math.random() * 100));
cube.position.y = Math.round((Math.random() * 10));
cube.position.z = -100 + Math.round((Math.random() * 150));
// 默认加入 cube
scene.add(cube);
}
};
}
/** 定义 dat.GUI 对象,并绑定 guiParams 的几个属性 */
var gui = new dat.GUI();
gui.add(guiParams, 'addCube');
gui.add(guiParams, 'near', 0, 50).onChange(function(e) {
camera.near = e;
});
gui.add(guiParams, 'far', 5, 200).onChange(function(e) {
camera.far = e;
});
guiParams.addCube();
renderScene();
});
/** 渲染场景 */
function renderScene() {
stats.update();
rotateMesh(); // 旋转物体
requestAnimationFrame(renderScene);
render.render(scene, camera);
}
/** 初始化 stats 统计对象 */
function initStats() {
stats = new Stats();
stats.setMode(0); // 0 为监测 FPS;1 为监测渲染时间
$('#stats-output').append(stats.domElement);
return stats;
}
/** 当浏览器窗口大小变化时触发 */
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render.setSize(window.innerWidth, window.innerHeight);
}
/** 旋转物体 */
function rotateMesh() {
scene.traverse(function(mesh) {
if (mesh instanceof THREE.Mesh) {
mesh.rotation.x += guiParams.rotationSpeed;
mesh.rotation.y += guiParams.rotationSpeed;
mesh.rotation.z += guiParams.rotationSpeed;
}
});
}
</script>
</body>
</html>
When you change camera.near or camera.far you need to call:
camera.updateProjectionMatrix();
three.js r.88

webGL readPixels and FireFox 35

I have updated to FireFox35 and the following code is not working anymore:
var ctx = renderer2.getContext("experimental-webgl",{preserveDrawingBuffer: true}) || renderer2.getContext("webgl",{preserveDrawingBuffer: true});
renderer2.render(scene2, camera2, renderTarget);
var arr = new Uint8Array( 4 * 1024 * 1024);
ctx.readPixels(0, 0, 1024, 1024, ctx.RGBA, ctx.UNSIGNED_BYTE, arr);
Thre returned array is completely black. It work until FireFox 34 to return the webGL canvas snapshot and it is still working in IE and Chrome.
Is there a workaround, or another way to get the pixel data from a webGL canvas?
A bug has been opened #Bugzilla. It seems to be a regression.
Example:
http://codepen.io/anon/pen/XJMQwV
<!DOCTYPE html>
<html lang="en">
<head>
<title> </title>
<style>
body {
background-color: #000;
color: #000;
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/threejs/r69/three.min.js"></script>
<script>
var renderer, camera, renderTarget;
var scene, element;
var ambient;
function createPIP(){
}
function init(){
pip = document.createElement('div');
pip.id = "divPIP";
pip.style.width = 512;
pip.style.height = 512;
pip.style.position = 'absolute';
pip.style.backgroundColor = 'black';
pip.style.borderRadius = "5px";
pip.style.border = '2px solid white';
pip.style.padding = "0px 20px";
pip.style.left = "50px";
pip.style.top = "25px";
document.body.appendChild(pip);
pip2 = document.createElement('div');
pip2.id = "divpip2";
pip2.style.width = 512;
pip2.style.height = 512;
pip2.style.position = 'absolute';
pip2.style.backgroundColor = 'black';
pip2.style.borderRadius = "5px";
pip2.style.border = '2px solid white';
pip2.style.padding = "0px 20px";
pip2.style.left = "650px";
pip2.style.top = "25px";
document.body.appendChild(pip2);
canvaspip2 = document.createElement('canvas');
canvaspip2.width = 512;
canvaspip2.height = 512;
canvaspip2.id = "canvaspip2";
pip2.appendChild(canvaspip2);
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer();
renderer.setSize(512, 512);
pip.appendChild(renderer.domElement);
renderTarget = new THREE.WebGLRenderTarget( 512, 512 );
var ambient = new THREE.AmbientLight( 0xffffff );
scene.add( ambient );
camera = new THREE.OrthographicCamera( -256, 256, 256, -256, 1, 1e6 );
scene.add(camera);
camera.position.set(0, 0, 500);
cube = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200 ), new THREE.MeshNormalMaterial() );
scene.add(cube);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
var ctx = renderer.getContext("experimental-webgl",{preserveDrawingBuffer: true}) || renderer.getContext("webgl",{preserveDrawingBuffer: true});
renderer.render(scene, camera, renderTarget);
var arr = new Uint8Array( 4 * 512 * 512);
ctx.readPixels(0, 0, 512, 512, ctx.RGBA, ctx.UNSIGNED_BYTE, arr);
var c=document.getElementById("canvaspip2");
var ctx=c.getContext("2d");
var ImgData = ctx.createImageData(512, 512);
ImgData.data.set( arr, 0, arr.length );
var c=document.getElementById("canvaspip2");
var ctx=c.getContext("2d");
ctx.putImageData(ImgData,0,0);
renderer.autoClear = false;
renderer.clear();
renderer.render(scene, camera);
}
window.onload = function() {
init();
animate();
}
</script>
</body>
</html>

Resources