我正在使用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();
}
}
答案 0 :(得分:0)
Object3D .lookAt
方法需要一个位于世界空间中的位置:
var position = new THREE.Vector3().copy( child.position );
child.localToWorld( position );
camera.lookAt( position );
使用TrackballControls或OrbitControl会使这一点复杂化,我不确定lookAt
是否可以与所涉及的任何一个正常工作。
three.js r89
答案 1 :(得分:0)