I´m trying to implement a 3rd person camera on my object.
i´ve tried it with a cube and it worked fine
cube:
var object, camera;
cubeGeometry = new THREE.CubeGeometry( 50, 50, 50 );
cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xFF0000 });
object = new THREE.Mesh( cubeGeometry, cubeMaterial );
scene.add( object );
camera = new THREE.PerspectiveCamera( 45, ASPECT, 0.2, 10000);
camera.position.z = -300;
camera.position.y = 100;
object.add(camera);
camera.lookAt(object.position);
renderer.render( scene, camera );
but with my model is doesnt work:
var object, camera;
var loader = new THREE.OBJMTLLoader();
loader.addEventListener('load', function (event){
object = event.content;
object.updateMatrix();
object.scale.set(20,20,20);
scene.add(object);
}, false);
loader.load( "models/dragster.obj", "models/dragster.mtl" );
camera = new THREE.PerspectiveCamera( 45, ASPECT, 0.2, 10000);
object.add(camera);
camera.position.z = -300;
camera.position.y = 100;
camera.lookAt(object.position);
renderer.render( scene, camera );
when i add the camera to the scene it works, but when i add it to the object it doesnt
thanks in advance
Your problem is simple. The OBJ hasn't loaded by the time you're doing this:
object.add( camera );
Try moving that code to inside the eventlistener.
Related
Hello everyone,I have meet a strange problem which is that I loaded a gltf model in three.js and set color for it.When zooming in it has colors, but when zooming out,it is all black.And when I directly set color for it's material,it can works well.
Thank you.
here is the sample sreenphotos and code.
loadGlbModel() {
const loader = new GLTFLoader();
loader.load(
`/three/eiffel-tower.gltf`,
(gltf) => {
const geometry = gltf.scene.children[0].geometry;
const positions = geometry.attributes.position;
const count = positions.count;
geometry.setAttribute(
"color",
new THREE.BufferAttribute(new Float32Array(count * 3), 3)
);
const color = new THREE.Color();
const colors = geometry.attributes.color;
const radius = 200;
debugger;
for (let i = 0; i < count; i++) {
color.setHSL(positions.getY(i) / radius / 2, 1.0, 0.5);
colors.setXYZ(i, 1, 0, 0);
}
const material = new THREE.MeshPhongMaterial({
color: 0xffffff,
flatShading: true,
vertexColors: true,
shininess: 0,
});
const wireframeMaterial = new THREE.MeshBasicMaterial({
color: 0x000000,
wireframe: true,
transparent: true,
});
let mesh = new THREE.Mesh(geometry, material);
let wireframe = new THREE.Mesh(geometry, wireframeMaterial);
mesh.add(wireframe);
mesh.scale.set(0.1, 0.1, 0.1);
const redColor = new THREE.Color(1, 0, 0);
console.log(mesh);
// mesh.children[0].material.color = redColor;
const light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 0, 1);
this.scene.add(light);
this.scene.add(mesh);
},
(xhr) => {
console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
},
(error) => {
console.error(error);
}
);
},
You are rendering the wireframe version too, which consists of lines in screen-space. As you zoom out, these lines maintain the same width in pixels, thus covering everything else.
Do you wish to render the fireframe too? If not, don't. If you do, then consider hiding it as the user zooms out.
I am trying to implement orbitControls in my react application. I have loaded 3d model GraphicsView
of expo-graphics. Model loaded perfectly, now i need to rotate the 3D model with screen drag. For
this i have added orbitControls, which is not working properly. Model did'nt rotate with screen
drag.Please help what i need to do to do to rotate 3D model in my react app.
Here is my model class.
```
import React from 'react';
import ExpoTHREE, { THREE } from 'expo-three';
import { GraphicsView } from 'expo-graphics';
import OrbitControls from 'three-orbitcontrols';
class Model extends React.Component {
componentDidMount() {
THREE.suppressExpoWarnings();
}
// When our context is built we can start coding 3D things.
onContextCreate = async ({ gl, pixelRatio, width, height }) => {
// Create a 3D renderer
this.renderer = new ExpoTHREE.Renderer({
gl,
pixelRatio,
width,
height,
});
// We will add all of our meshes to this scene.
this.scene = new THREE.Scene();
this.scene.background = new THREE.Color(0x3d392f);
//this.scene.fog = new THREE.Fog( 0xa0a0a0, 10, 50 );
this.camera = new THREE.PerspectiveCamera(12, width/height, 1, 1000);
this.camera.position.set(3, 3, 3);
this.camera.lookAt(0, 0, 0);
this.controls = new OrbitControls(this.camera, this.renderer.domElement);
this.controls.rotateSpeed = 2.0;
this.controls.zoomSpeed = 1.2;
this.controls.panSpeed = 0.8;
this.controls.noPan = false;
this.controls.staticMoving = false;
this.controls.dynamicDampingFactor = 0.3;
this.controls.keys = [ 65, 83, 68 ];
this.controls.addEventListener( 'change', this.onRender );
//clock = new THREE.Clock();
//this.scene.add(new THREE.AmbientLight(0xffffff));
var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
hemiLight.position.set( 0, 20, 0 );
this.scene.add( hemiLight );
var dirLight = new THREE.DirectionalLight( 0xffffff );
dirLight.position.set( - 3, 10, - 10 );
dirLight.castShadow = true;
dirLight.shadow.camera.top = 2;
dirLight.shadow.camera.bottom = - 2;
dirLight.shadow.camera.left = - 2;
dirLight.shadow.camera.right = 2;
dirLight.shadow.camera.near = 0.1;
dirLight.shadow.camera.far = 40;
this.scene.add( dirLight );
await this.loadModel();
};
loadModel = async () => {
const obj = {
"f.obj": require('../assets/models/f.obj')
}
const model = await ExpoTHREE.loadAsync(
obj['f.obj'],
null,
obj
);
// this ensures the model will be small enough to be viewed properly
ExpoTHREE.utils.scaleLongestSideToSize(model, 1);
this.scene.add(model)
};
// When the phone rotates, or the view changes size, this method will be called.
onResize = ({ x, y, scale, width, height }) => {
// Let's stop the function if we haven't setup our scene yet
if (!this.renderer) {
return;
}
this.camera.aspect = width / height;
this.camera.updateProjectionMatrix();
this.renderer.setPixelRatio(scale);
this.renderer.setSize(width, height);
};
// Called every frame.
onRender = delta => {
// Finally render the scene with the Camera
this.renderer.render(this.scene, this.camera);
};
render() {
return (
<GraphicsView
onContextCreate={this.onContextCreate}
onRender={this.onRender}
onResize={this.onResize}
/>
);
}
}
export default Model;
```
To get you into the context, let say i have a camera
camera = new THREE.PerspectiveCamera();
camera.position.set(1,1,1);
camera.lookAt(scene.position);
camera.rotation.set(Math.PI/2, 0 ,0) // <=== this is lost when the orbit control move
then i create an orbit control
controls = new THREE.OrbitControls(camera, renderer.domElement);
The Problem is that when i use the orbit control by dragging the mouse on click or zooming, the camera rotation is lost.
I tried using controls.update() but it's not working
Edit
Here is a link for a jsfiddle
var camera;
var scene;
var conrols;
var renderer;
function init() {
scene = new THREE.Scene();
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);
camera.position.set(0, 0, 5);
scene.add(camera);
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
var light1 = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.7)
scene.add(light1);
var light2 = new THREE.SpotLight(0xffffff, 0.5);
light2.position.set(4, 7, 23);
scene.add(light2);
var light3 = new THREE.SpotLight(0xffffff, 0.5);
light3.position.set(4, 7, -23);
//scene.add(light3);
var geometry = new THREE.BoxGeometry(2, 1, 1);
var material = new THREE.MeshLambertMaterial({
color: 0x00ffff
});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);
controls = new THREE.OrbitControls(camera, renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
document.getElementById('button').onclick = function() {
//console.log("position");
//console.log(camera.position);
//console.log("rotation");
//console.log(camera.rotation);
camera.rotation.set(0, 0, 1.57);
// camera.position.set(-0.041, 1.9, -1.21);
}
init();
animate();
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/build/three.js"></script>
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/OrbitControls.js"></script>
<button id="button">change rotation</button>
in my original application i have a 3D foot mesh. Sometimes i need to have a vertical view of the backfoot with only a click. So i apply a camera rotation. but when i move the camera with orbit control the camera rotation jumps to the old value.
You can switch to a second camera like 2pha says or you can set controls.enableRotate = false;
var stage, output;
function init() {
stage = new createjs.Stage("testCanvas");
// this lets our drag continue to track the mouse even when it leaves the canvas:
// play with commenting this out to see the difference.
stage.mouseMoveOutside = true;
var circle = new createjs.Shape();
circle.graphics.beginFill("red").drawRoundRect(0, 0, 100,20,10);
//console.log(circle.graphics.command.radius);
var label = new createjs.Text("drag me", "bold 14px Arial", "#FFFFFF");
label.textAlign = "center";
label.y = -7;
var dragger = new createjs.Container();
dragger.x = 50;
dragger.y = 10;
dragger.addChild(circle, label);
stage.addChild(dragger);
dragger.on("pressmove",function(evt) {
// currentTarget will be the container that the event listener was added to:
//evt.currentTarget.x = evt.stageX;
//evt.currentTarget.y = evt.stageY;
// make sure to redraw the stage to show the change:
//console.log(evt.currentTarget.children[0].graphics.command);
var newWidth= evt.stageX - evt.currentTarget.x;
console.log(evt.currentTarget.children[0].graphics);
if(newWidth<0)
newWidth = 0;
evt.currentTarget.children[0].graphics.command.w= newWidth;
evt.currentTarget.children[1].x= newWidth/2;
stage.update();
});
stage.update();
}
this code is working fine under http://www.createjs.com/demos
(i can reach this evt.currentTarget.children[0].graphics.command.w, because evt.currentTarget.children[0] returns shape)
but not on your own html. it is there any js i need to add in the heading?
Did you checked if "pressmove" trigger?
Maybe you should use this stage.enableMouseOver(20); to enable mouse events.
guys I know this question has been asked several times, several different ways, but I just can get it to work. Basically I have 2d clouds, but I want the camera to rotate around an object floating above the clouds. The problem is, when im not looking a the face of the clouds u can tell that they are 2d. Soooo i want the the clouds to "look" at the camera where ever it is. I believe my problem stems from how the cloud geometry is called on to the planes, but here take a look. I put the a lookAt function with in my animate function. I hope you can point me in the right direction at least.
Three.js rev. 70...
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.position.set(0, 0, 100);
scene.add(camera);
controls = new THREE.OrbitControls( camera );
controls.target.copy( new THREE.Vector3( 0, 0,475) );
controls.minDistance = 50;
controls.maxDistance = 200;
controls.autoRotate = true;
controls.autoRotateSpeed = .2; // 30 seconds per round when fps is 60
controls.minPolarAngle = Math.PI/4; // radians
controls.maxPolarAngle = Math.PI/2; // radians
controls.enableDamping = true;
controls.dampingFactor = 0.25;
clock = new THREE.Clock();
cloudGeometry = new THREE.Geometry();
var texture = THREE.ImageUtils.loadTexture('img/cloud10.png', null, animate);
texture.magFilter = THREE.LinearMipMapLinearFilter;
texture.minFilter = THREE.LinearMipMapLinearFilter;
var fog = new THREE.Fog(0x4584b4, -100, 3000);
cloudMaterial = new THREE.ShaderMaterial({
uniforms: {
"map": {
type: "t",
value: texture
},
"fogColor": {
type: "c",
value: fog.color
},
"fogNear": {
type: "f",
value: fog.near
},
"fogFar": {
type: "f",
value: fog.far
},
},
vertexShader: document.getElementById('vs').textContent,
fragmentShader: document.getElementById('fs').textContent,
depthWrite: false,
depthTest: false,
transparent: true
});
var plane = new THREE.Mesh(new THREE.PlaneGeometry(64, 64));
for (var i = 0; i < 8000; i++) {
plane.position.x = Math.random() * 1000 - 500;
plane.position.y = -Math.random() * Math.random() * 200 - 15;
plane.position.z = i;
plane.rotation.z = Math.random() * Math.PI;
plane.scale.x = plane.scale.y = Math.random() * Math.random() * 1.5 + 0.5;
plane.updateMatrix();
cloudGeometry.merge(plane.geometry, plane.matrix);
}
cloud = new THREE.Mesh(cloudGeometry, cloudMaterial);
scene.add(cloud);
cloud = new THREE.Mesh(cloudGeometry, cloudMaterial);
cloud.position.z = -8000;
scene.add(cloud);
var radius = 100;
var xSegments = 50;
var ySegments = 50;
var geo = new THREE.SphereGeometry(radius, xSegments, ySegments);
var mat = new THREE.ShaderMaterial({
uniforms: {
lightPosition: {
type: 'v3',
value: light.position
},
textureMap: {
type: 't',
value: THREE.ImageUtils.loadTexture("img/maps/moon.jpg")
},
normalMap: {
type: 't',
value: THREE.ImageUtils.loadTexture("img/maps/normal.jpg")
},
uvScale: {
type: 'v2',
value: new THREE.Vector2(1.0, 1.0)
}
},
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
mesh = new THREE.Mesh(geo, mat);
mesh.geometry.computeTangents();
mesh.position.set(0, 50, 0);
mesh.rotation.set(0, 180, 0);
scene.add(mesh);
}
function onWindowResize() {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
light.orbit(mesh.position, clock.getElapsedTime());
cloud.lookAt( camera );
controls.update(camera);
renderer.render(scene, camera);
}
animate();
window.addEventListener('resize', onWindowResize, false);
just a first guess:
the lookAt function needs Vector3 as parameter. try to use camera.position in the animate function.
cloud.lookAt( camera.position );
first of all, to build 2D objects in a scene that always faces towards the camera, you should use Sprite object, so you don't have to do anything to get this effect. (and have better performance :))
Definition from THREE.org: Sprite - a sprite is a plane in an 3d scene which faces always towards the camera.
var map = THREE.ImageUtils.loadTexture( "sprite.png" );
var material = new THREE.SpriteMaterial( { map: map, color: 0xffffff, fog: true } );
var sprite = new THREE.Sprite( material );
scene.add( sprite );
Please check this example: http://threejs.org/examples/#webgl_points_sprites
I would absolutely agree, I would use Sprite, or even Points, but then, if assign a texture to it, it will render it square-sized. My sprites are animated, and frames cannot be packed in square tiles, cause it would take a lot of space. I might make a mesh and use this lookAt function.