我想在three.js中创建一个3d房间。我希望在旋转房间时,在摄像机视图前面的墙壁变得透明。
以下是我需要的示例:http://jsfiddle.net/tp2f2oo4/
似乎解决方案是在材料中添加THREE.BackSide。
var material2 = new THREE.MeshPhongMaterial( {
color: 0xffffff,
transparent: false,
side: THREE.BackSide
} );
当房间充当单个THREE.BoxGeometry时,这确实很有效。 但就我而言,每个墙,天花板和地板都是单独的THREE.BoxGeometry对象。有没有办法在摄像机视图前隐藏它们或不渲染?
答案 0 :(得分:4)
您希望根据某些条件隐藏网格。这是使用EventEmitter
和@Component({
selector: 'app-group-selector',
template: `
<div>
<label>Group</label>
<select [(ngModel)]="name" (change)="onGroupChanged(name)">
<option *ngFor="let groupName of groupNames" [value]="groupName">{{groupName}}</option>
</select>
</div>`
})
export class SharedComponent {
@Output() selectedgroup: EventEmitter<string> = new EventEmitter<string>();
groupNames: string[];
// note new property here, to be used as ngModel
name: string;
constructor() {
this.groupNames = ['A', 'B', 'C'];
this.name = 'A';
}
onGroupChanged(newvalue): void {
console.log('from Shared:',newvalue);
this.selectedgroup.emit(newvalue);
}
}
方法的完美用例。
onBeforeRender()
小提琴:http://jsfiddle.net/he6t10r8/
three.js r.87
答案 1 :(得分:0)
您可以使用光线投射来确定要关闭的墙。基本上,从相机拍摄光线,并设置它相交的墙的透明度。
有关简化案例,请参阅下面代码段中的updateWallTransparency_simple
。它从相机中心发射光线,并设置相交墙的透明度。
但是,您可能会遇到一个字面角落案例,您可以从一个墙转换到另一个墙。您可以通过第二次光线投射来补偿这一点,但是您需要将两条光线偏离中心,因此在角落的情况下它们不会与同一墙壁相交。有关示例,请参阅下面代码段中的updateWallTransparency_corners
。
现在这是一个高度简化的案例。如果您的墙壁形状更复杂,您需要进行进一步检查以确定是否应隐藏某些墙壁。此外,如果您将相机倾斜太远,您会发现它会隐藏后墙。作为一个整体,这个问题还有很多需要考虑的问题,但这应该可以让你开始。
var renderer, scene, camera, controls, stats;
var WIDTH = window.innerWidth,
HEIGHT = window.innerHeight,
FOV = 35,
NEAR = 1,
FAR = 1000,
degrad = (Math.PI / 180),
walls = [];
var raycaster = null,
coords = null;
function updateWallTransparency_simple() {
// reset all walls. You can optimize this by storing which ones are transparent/not
walls.forEach(function(wall) {
wall.material.opacity = 1;
});
raycaster.setFromCamera(coords, camera);
var intersects = raycaster.intersectObjects(walls);
if (intersects && intersects.length > 0) {
intersects[0].object.material.opacity = 0.25;
}
}
function updateWallTransparency_corners() {
// reset all walls. You can optimize this by storing which ones are transparent/not
walls.forEach(function(wall) {
wall.material.opacity = 1;
});
coords.set(-0.1, 0);
raycaster.setFromCamera(coords, camera);
var intersects = raycaster.intersectObjects(walls);
if (intersects && intersects.length > 0) {
intersects[0].object.material.opacity = 0.25;
}
coords.set(0.1, 0);
raycaster.setFromCamera(coords, camera);
var intersects = raycaster.intersectObjects(walls);
if (intersects && intersects.length > 0) {
intersects[0].object.material.opacity = 0.25;
}
}
function populateScene() {
var geo = new THREE.BoxBufferGeometry(20, 20, 0.1),
mat = new THREE.MeshPhongMaterial({
color: "darkred",
transparent: true,
opacity: 1
});
var mesh = new THREE.Mesh(geo, mat);
mesh.position.set(0, 0, -10);
mesh.name = "backWall";
scene.add(mesh);
mesh.updateMatrixWorld(true);
walls.push(mesh);
mesh = new THREE.Mesh(geo, mat.clone());
mesh.name = "frontWall";
mesh.position.set(0, 0, 10);
scene.add(mesh);
mesh.updateMatrixWorld(true);
walls.push(mesh);
mesh = new THREE.Mesh(geo, mat.clone());
mesh.name = "leftWall";
mesh.position.set(-10, 0, 0);
mesh.rotation.set(0, (Math.PI / 180) * 90, 0);
scene.add(mesh);
mesh.updateMatrixWorld(true);
walls.push(mesh);
mesh = new THREE.Mesh(geo, mat.clone());
mesh.name = "rightWall";
mesh.position.set(10, 0, 0);
mesh.rotation.set(0, (Math.PI / 180) * 90, 0);
scene.add(mesh);
mesh.updateMatrixWorld(true);
walls.push(mesh);
geo = new THREE.BoxBufferGeometry(50, 0.1, 50),
mat = new THREE.MeshPhongMaterial({
color: "green"
});
mesh = new THREE.Mesh(geo, mat);
mesh.position.set(0, -10, 0);
mesh.name = "ground";
scene.add(mesh);
geo = new THREE.TorusKnotBufferGeometry(2, 0.5, 100, 16),
mat = new THREE.MeshPhongMaterial({
color: "blue"
});
mesh = new THREE.Mesh(geo, mat);
mesh.name = "insideObject";
scene.add(mesh);
}
function init() {
document.body.style.backgroundColor = "lightBlue";
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
document.body.appendChild(renderer.domElement);
document.body.style.overflow = "hidden";
document.body.style.margin = "0";
document.body.style.padding = "0";
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
camera.position.z = 50;
scene.add(camera);
controls = new THREE.OrbitControls(camera);
controls.enableZoom = false;
controls.enablePan = false;
controls.maxPolarAngle = Math.PI / 2;
var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);
light = new THREE.HemisphereLight(0xffffbb, 0x00ff00, 1);
scene.add(light);
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
resize();
window.onresize = resize;
populateScene();
raycaster = new THREE.Raycaster();
coords = new THREE.Vector3();
animate();
}
function resize() {
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
if (renderer && camera && controls) {
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
}
function render() {
renderer.render(scene, camera);
}
function animate() {
requestAnimationFrame(animate);
//updateWallTransparency_simple();
updateWallTransparency_corners();
render();
stats.update();
}
function threeReady() {
init();
}
(function() {
function addScript(url, callback) {
callback = callback || function() {};
var script = document.createElement("script");
script.addEventListener("load", callback);
script.setAttribute("src", url);
document.head.appendChild(script);
}
addScript("https://threejs.org/build/three.js", function() {
addScript("https://threejs.org/examples/js/controls/OrbitControls.js", function() {
addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
threeReady();
})
})
})
})();
&#13;