【发布时间】:2018-03-14 21:34:53
【问题描述】:
我将 THREE v0.86 与 React 一起使用,我试图获取父母的特定孩子的世界位置,所以当我点击一个按钮时,我可以更改它的材质颜色并使相机面向它。
首先,我在 onLoad 函数中为我感兴趣的每个孩子存储一个引用:
const onLoad = object => {
object.name = "scene 1";
object.position.set(0, 5, 0);
obj3d.add(object);
object.traverse(
function(child) {
if (condition === true) {
let material = new THREE.MeshBasicMaterial({ color: 0xffff00 });
child.material = material;
this[child.name] = child; // <-- Here
}
}.bind(this)
);
};
然后,我尝试了两种方法:第一种启用控件:TrackballControls
moveCamera(selectedChild) {
this[selectedChild].material.color.setHex(0xff0000);
const material = new THREE.MeshBasicMaterial({ color: "#FF0000" });
this[selectedChild].material = material;
const newPosition = new THREE.Vector3();
newPosition.setFromMatrixPosition(this[selectedChild].matrixWorld);
// I've tried this:
this.controls.target = this[selectedChild].getWorldPosition();
// OR this
this.controls.target = newPosition;
this.camera.lookAt(this[selectedChild]);
}
另外,我已经禁用控件并尝试了这个:
moveCamera(selectedChild) {
this[selectedChild].material.color.setHex(0xff0000);
const material = new THREE.MeshBasicMaterial({ color: "#FF0000" });
this[selectedChild].material = material;
this.camera.lookAt(this[selectedChild].getWorldPosition());
}
在 renderScene() 函数中使用这个:
renderScene() {
this.renderer.autoClear = true;
this.renderer.setClearColor(0xfff0f0);
this.renderer.setClearAlpha(0.0);
this.scene.updateMatrixWorld(); // <- THIS
if (this.composer) {
this.composer.render();
} else {
this.renderer.render(this.scene, this.camera);
}
}
moveCamera(childName) 确实改变了特定的子颜色,但问题是它总是看起来在同一个方向,所以我安慰记录了父对象并看了一眼孩子,他们都它们之间有相同的matrix、matrixAutoUpdate: true、matrixWorld、matrixWorldNeedsUpdate: false 属性值,它们也是父级的值,所以当然newPosition.setFromMatrixPosition(this[selectedChild].matrixWorld); 向量总是相同的。我错过了什么?为什么不同的子对象相对于世界的位置不不同?
这是我的场景设置
componentDidMount() {
const { THREE, innerWidth, innerHeight } = window;
OBJLoader(THREE);
MTLLoader(THREE);
this.setScene();
this.setCamera();
this.setRenderer();
this.group = new THREE.Group();
this.selectedObjects = [];
this.mouse = new THREE.Vector2();
this.raycaster = new THREE.Raycaster();
this.enableControls();
this.start();
}
地点:
this.setScene()
setScene() {
const { THREE } = window;
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xcccccc);
scene.fog = new THREE.FogExp2(0xcccccc, 0.002);
// LIGHTS
scene.add(new THREE.AmbientLight(0xaaaaaa, 0.2));
const light = new THREE.DirectionalLight(0xddffdd, 0.6);
light.position.set(1, 1, 1);
light.castShadow = true;
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
const d = 10;
light.shadow.camera.left = -d;
light.shadow.camera.right = d;
light.shadow.camera.top = d;
light.shadow.camera.bottom = -d;
light.shadow.camera.far = 1000;
scene.add(light);
const hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.5);
hemiLight.color.setHSL(0.6, 1, 0.6);
hemiLight.groundColor.setHSL(0.095, 1, 0.75);
hemiLight.position.set(0, 500, 0);
scene.add(hemiLight);
// GROUND
const groundGeo = new THREE.PlaneBufferGeometry(1000, 1000);
const groundMat = new THREE.MeshPhongMaterial({
color: 0xffffff,
specular: 0x050505
});
groundMat.color.setHSL(0.095, 1, 0.75);
const ground = new THREE.Mesh(groundGeo, groundMat);
ground.rotation.x = -Math.PI / 2;
ground.position.y = -0.5;
scene.add(ground);
// SKYDOME
const vertexShader =
"varying vec3 vWorldPosition; void main() { vec4 worldPosition = modelMatrix * vec4( position, 1.0 ); vWorldPosition = worldPosition.xyz; gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }";
const fragmentShader =
"uniform vec3 topColor; uniform vec3 bottomColor; uniform float offset; uniform float exponent; varying vec3 vWorldPosition; void main() { float h = normalize( vWorldPosition + offset ).y; gl_FragColor = vec4( mix( bottomColor, topColor, max( pow( max( h , 0.0), exponent ), 0.0 ) ), 1.0 ); }";
const uniforms = {
topColor: { value: new THREE.Color(0x0077ff) },
bottomColor: { value: new THREE.Color(0xffffff) },
offset: { value: 0 },
exponent: { value: 0.6 }
};
uniforms.topColor.value.copy(hemiLight.color);
scene.fog.color.copy(uniforms.bottomColor.value);
const skyGeo = new THREE.SphereGeometry(300, 32, 15);
const skyMat = new THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
uniforms: uniforms,
side: THREE.BackSide
});
const sky = new THREE.Mesh(skyGeo, skyMat);
scene.add(sky);
this.scene = scene;
}
this.setCamera
setCamera() {
const { THREE, innerWidth, innerHeight } = window;
const camera = new THREE.PerspectiveCamera(
45,
innerWidth / innerHeight,
0.1,
100
);
camera.position.set(-4.1, 7.2, 4.2);
this.camera = camera;
}
this.setRenderer
setRenderer() {
const { THREE, innerWidth, innerHeight } = window;
const renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(innerWidth, innerHeight * this.windowMultiplier);
this.renderer = renderer;
}
this.start this.stop this.animate
start() {
if (!this.frameId) {
this.frameId = requestAnimationFrame(this.animate);
}
}
stop() {
cancelAnimationFrame(this.frameId);
}
animate() {
this.renderScene();
this.frameId = window.requestAnimationFrame(this.animate);
if (!!this.controls) {
this.controls.update();
}
}
【问题讨论】:
标签: javascript reactjs three.js