I'm trying to use Three.js and I have this error showing in my browser:
Here is the code:
import { AxesHelper, PerspectiveCamera, Scene, WebGLRenderer } from 'three'
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
const scene = new Scene();
scene.add(new AxesHelper());
const camera = new PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.01, 1000);
camera.position.z = 2;
camera.position.y = 0.5;
camera.position.x = 0.5;
scene.add(camera);
const renderer = new WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
tick();
function tick() {
renderer.render(scene.camera);
camera.position.x += 0.01;
camera.lookAt(0, 0, 0);
requestAnimationFrame(tick);
}
I have not a clue on how to fix this issue.
It's a typo: this line...
renderer.render(scene.camera);
... should actually be written like this:
renderer.render(scene, camera);
... instead (docs). The error you got is caused by trying to treat scene.camera value as scene instead, blowing on attempt to access its autoUpdate property.
Related
Hello I'm trying to import an fbx model into my scene, but there is not much info on it online I had found one way that looks to use official three.js package but for some reason the model dose not appear in my scene, even through I don't get any errors. If any one can help me please because I have no clue at why it is not loading.
The guide that I used: https://sbcode.net/threejs/loaders-fbx/
The short version of the code.
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
const fbxLoader = new FBXLoader()
fbxLoader.load('models/3dModdleOfTheBox.fbx', (object) => {
scene.add(object)
})
Full code
import React, { useEffect } from 'react'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader'
export default function Threed_model() {
//three js
useEffect(() => {
//basic setup
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
)
camera.position.z = 5
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#canvas'),
})
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
//controls
const controls = new OrbitControls(camera, renderer.domElement)
controls.enableZoom = false
controls.enablePan = false
controls.target.set(0, 0, 0)
//fbx loader
const material = new THREE.MeshNormalMaterial()
const fbxLoader = new FBXLoader()
fbxLoader.load('models/3dModdleOfTheBox.fbx', (object) => {
scene.add(object)
})
//light
const light = new THREE.PointLight()
light.position.set(0.8, 1.4, 1.0)
scene.add(light)
const ambientLight = new THREE.AmbientLight()
scene.add(ambientLight)
//adding stuff
const geometry = new THREE.TorusGeometry(1, 0.5, 16, 100)
const torus = new THREE.Mesh(geometry, material)
scene.add(torus)
function animate() {
requestAnimationFrame(animate)
renderer.render(scene, camera)
}
animate()
renderer.render(scene, camera)
}, [])
return <canvas id="canvas">test</canvas>
}
Turns out you have to set a scale for your model for it to display
object.scale.set(0.01, 0.01, 0.01)
My final code looked like this for who ever might need it.
fbxLoader.load('models/3dModdleOfTheBox.fbx', (object) => {
object.traverse(function (child) {
if (child.isMesh) {
console.log(child.geometry.attributes.uv)
const texture = new THREE.TextureLoader().load(
'models/pakage(12).png'
)
child.material.map = texture
child.material.needsUpdate = true
}
})
object.scale.set(0.01, 0.01, 0.01)
scene.add(object)
console.log(object)
})
I'm using threejs to provide a 3D animation...
this is my main.js file content:
import './style.css'
import {
AxesHelper,
BufferGeometry,
Float32BufferAttribute,
MathUtils,
PerspectiveCamera,
Points,
PointsMaterial,
Scene,
TextureLoader,
VertexColors,
WebGLRenderer,
} from "three";
import {OrbitControls} from 'three/examples/jsm/controls/OrbitControls.js';
const count = 100;
const distance = 2;
const textureLoader = new TextureLoader();
const circleTexture = textureLoader.load("ball.png");
const scene = new Scene();
scene.add(new AxesHelper());
const camera = new PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.01,1000);
camera.position.z = 2;
camera.position.y = 0.5;
camera.position.x = 0.5;
scene.add(camera);
const pts = new Float32Array(count * 3);
const colors = new Float32Array(count * 3);
for (let i = 0; i < pts.length; i++) {
pts[i] = MathUtils.randFloatSpread(distance * 2);
colors[i] = Math.random();
}
const geometry = new BufferGeometry();
geometry.setAttribute('position', new Float32BufferAttribute(pts,3));
geometry.setAttribute('colors', new Float32BufferAttribute(colors,3));
const pointMaterial = new PointsMaterial({
size: 0.1,
map : circleTexture,
alphaTest: 0.01,
transparent: true,
vertexColors : VertexColors,
});
const points = new Points(geometry, pointMaterial);
scene.add(points);
const renderer = new WebGLRenderer({
antialias: true, //removing all ugly pixels from cube's sides
alpha : true,
});
renderer.setClearColor(0x000000, 0);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
function anime() {
renderer.render(scene, camera);
controls.update();
requestAnimationFrame(anime);
}
anime();
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix(); // mettre a jour la camera...
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));
});
in PointsMaterial() constructor , I want to assign a value to vertexColor to make a variety of colors for my objects (3D looking points...), but I got the following error on the console :
Uncaught SyntaxError: The requested module '/node_modules/.vite/deps/three.js?v=19235266' does not provide an export named 'VertexColors' (at main.js?t=1655672405709:13:5)
it seems like threejs doesn't contain this property or what ??!!!
I'm using Three.js in order to render a 3D element.
I work with mousemove in order to rotate the scene with the movement of the mouse.
I'm looking to add an animation that slightly rotates the scene automatically.
It essentially would emulate the rotation done via mouse movement but automatically so the object doesn't appear static when loading.
Does someone know a trivial way to achieve that?
Thanks in advance,
$(function() {
var logoSrc = './assets/vector_gltf/scene.gltf';
var renderer,
scene,
camera,
holder = document.getElementById('holder');
canvas = document.getElementById('canvasLogo');
renderer = new THREE.WebGLRenderer({
canvas: canvas,
antialias: true,
alpha: true,
});
renderer.setSize($(holder).width(), $(holder).height());
holder.appendChild(renderer.domElement);
renderer.setClearColor( 0x000000, 0 );
renderer.setPixelRatio(window.devicePixelRatio);
// renderer.setSize(window.innerWidth, window.innerHeight);
//on resize
window.addEventListener('resize', () => {
// Update camera
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
// Update renderer
// renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setSize($(holder).width(), $(holder).height());
holder.appendChild(renderer.domElement);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
});
camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 0.1, 1000 );
scene = new THREE.Scene();
var light = new THREE.AmbientLight(0x0000ff, 1);
scene.add(light);
var light2 = new THREE.PointLight(0xff0000, 1);
scene.add(light2);
var loader = new THREE.GLTFLoader();
loader.load(logoSrc, handle_load);
var s;var mesh;
function handle_load(gltf) {
s = gltf.scene;
mesh = s.children[0].children[0].children[0];
// s.children[0].material = new THREE.MeshStandardMaterial({
// normalMap : logoSrc + 'textures/StingrayPBS1SG_normal.png',
// emissiveMap : logoSrc + 'textures/StingrayPBS1SG_emissive.png',
// metalnessMap : logoSrc + 'textures/StingrayPBS1SG_metallicRoughness.png',
// map : logoSrc + 'textures/StingrayPBS1SG_baseColor.png'
// });
scene.add(s);
s.position.y = -0.2;
s.position.z = -2;//15
}
$(".intro").on("mousemove", function(e){
mesh.rotation.set(-0.003 * (e.pageY - window.innerHeight / 20),0, -0.02 * (e.pageX - (window.innerWidth / 2) - 3.14));
//.set(0.0018 * (e.pageY - 291.45) - 1.45,0, 0.02 * (e.pageX - (window.innerWidth / 2) - 3.14))
});
//anim
const clock = new THREE.Clock();
const loop = () =>
{
const elapsedTime = clock.getElapsedTime();//delta time
// Render
renderer.render(scene, camera);
// Call tick again on the next frame
window.requestAnimationFrame(loop);
}
loop();
});
This is what you want: http://threejs.org/examples/misc_controls_orbit.html
Include the orbit controls (after you have downloaded them):
<script src="js/controls/OrbitControls.js"></script>
Setup the variable:
var controls;
Attach the controls to the camera and add a listener:
controls = new THREE.OrbitControls( camera );
controls.addEventListener( 'change', render );
and in your animate function update the controls:
controls.update();
controls.autoRotate();
That last line (autoRotate) is really what you want for the rotation, but everything else is setting up your controls.
You can use a function called animate() that is making your 3D element move automatically and combining it to a render() method.
function animate() {
requestAnimationFrame( animate );
group.rotation += 0.005;
render();
}
function render() {
renderer.render( scene, camera );
}
I am using Three.JS and have gotten a .glb file to display beautifully with some mouse movement.
I'm now trying to add DeviceOrientationControls to my GLtf/GLB scene, so I can move around the scene when moving the mobile phone around, however I can't quite work it out.
No matter what I try I always get one error or another.
I have tried adapting the code from this example: https://threejs.org/examples/misc_controls_deviceorientation.html
This is my current code without any DeviceOrientationControls code added:
HTML
<!-- three.min.js r87 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<!-- GLTFLoader.js -->
<script src="https://cdn.jsdelivr.net/gh/mrdoob/three.js#r92/examples/js/loaders/GLTFLoader.js"></script>
<!-- Orientation Controls -->
<script src="https://cdn.rawgit.com/mrdoob/three.js/master/examples/js/controls/DeviceOrientationControls.js"></script>
<div id="overlay">
<div>
<button id="startButton">Start Demo</button>
<p>Using device orientation might require a user interaction.</p>
</div>
</div>
<div class="single-object">
<div id="container"></div>
JS
window.addEventListener("load", loadGltf, false);
window.addEventListener("resize", onWindowResize, false);
const progressBar = document.querySelector("progress");
const gltfStore = {};
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// Attach to container
container = document.getElementById( 'container' );
//Setup camera
const camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight,0.1, 1000 );
camera.position.set(0, 0, 0);
camera.lookAt(0, 0, 5);
windowHalfX = window.innerWidth / 2,
windowHalfY = window.innerHeight / 2,
mouseX = 0,
mouseY = 0;
//Re-establish camera view on window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//Lighting
const lightFill = new THREE.PointLight(0xffffff, 1, 500);
lightFill.position.set(0, 0, 5);
scene.add(lightFill);
const lightKey = new THREE.PointLight(0xffffff, 1, 500);
lightKey.position.set(20, 0, 20);
scene.add(lightKey);
const loader = new THREE.GLTFLoader();
// Device Orientation
// Load the GLB file
function loadGltf() {
loader.load(
"<?php echo get_template_directory_uri();?>/objects/SM_LookDev_TextureTest_FromFBX.glb",
function(gltf) {
scene.add(gltf.scene);
mesh = gltf.scene;
gltf.scene.children[0];
gltfStore.scene = gltf.scene;
// Set listener
document.addEventListener("mousemove", onMouseMove);
}
);
container.appendChild(renderer.domElement);
// Mouse movement
function onMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 10;
mouseY = (event.clientY - windowHalfY) / 30;
}
function animate() {
requestAnimationFrame(animate);
// Adjust mouse and scene position
camera.position.x += (mouseX - camera.position.x) * .0005;
camera.position.y += (-mouseY - camera.position.y) * .0003;
camera.lookAt(0,0,10);
renderer.render(scene, camera);
}
animate();
}
I have gathered from the examples that I need to add these lines (I think):
controls = new DeviceOrientationControls( camera );
controls.update();
and the below for the start button...
var startButton = document.getElementById( 'startButton' );
startButton.addEventListener( 'click', function () {
init();
animate();
}, false );
EDIT
Below is an example of where I have tried to add the lines, but have not worked successfully.
window.addEventListener("load", loadGltf, false);
window.addEventListener("resize", onWindowResize, false);
const progressBar = document.querySelector("progress");
// Add Start Button
var startButton = document.getElementById( 'startButton' );
startButton.addEventListener( 'click', function () {
init();
animate();
}, false );
const gltfStore = {};
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
// Attach to container
container = document.getElementById( 'container' );
//Setup camera
const camera = new THREE.PerspectiveCamera(
75, window.innerWidth / window.innerHeight,0.1, 1000 );
camera.position.set(0, 0, 0);
camera.lookAt(0, 0, 5);
windowHalfX = window.innerWidth / 2,
windowHalfY = window.innerHeight / 2,
mouseX = 0,
mouseY = 0;
//Re-establish camera view on window resize
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
//Lighting
const lightFill = new THREE.PointLight(0xffffff, 1, 500);
lightFill.position.set(0, 0, 5);
scene.add(lightFill);
const lightKey = new THREE.PointLight(0xffffff, 1, 500);
lightKey.position.set(20, 0, 20);
scene.add(lightKey);
const loader = new THREE.GLTFLoader();
// Added Device Orientation Controls
controls = new DeviceOrientationControls( camera );
// Load the GLB file
function loadGltf() {
loader.load(
"<?php echo get_template_directory_uri();?>/objects/SM_LookDev_TextureTest_FromFBX.glb",
function(gltf) {
scene.add(gltf.scene);
mesh = gltf.scene;
gltf.scene.children[0];
gltfStore.scene = gltf.scene;
// Set listener
document.addEventListener("mousemove", onMouseMove);
}
);
container.appendChild(renderer.domElement);
// Mouse movement
function onMouseMove(event) {
mouseX = (event.clientX - windowHalfX) / 10;
mouseY = (event.clientY - windowHalfY) / 30;
}
function animate() {
requestAnimationFrame(animate);
// Adjust mouse and scene position
camera.position.x += (mouseX - camera.position.x) * .0005;
camera.position.y += (-mouseY - camera.position.y) * .0003;
camera.lookAt(0,0,10);
// Add Controls Update
controls.update();
renderer.render(scene, camera);
}
animate();
}
When adding the lines like this, I get these 2 error messages:
Uncaught TypeError: Cannot read property 'addEventListener' of null
and
Uncaught ReferenceError: Cannot access 'loader' before initialization at loadGltf
So, I am unsure how to actually add these lines into my specific code to get it to work?
Any assistance would be appreciated
It's hard to tell exactly the reason why it's not working, especially since your question includes so much extraneous code. You should try to ask your questions with a minimal reproducible example.
First, you're importing your <scripts> from varying sources, and varying versions. The Three.js and GLTFLoader you're loading is r92, but the DeviceOrientationControls script doesn't specify a version, so it's loading the latest at r112, which might no longer be compatible with ThreeJS r92.
Secondly, you're using:
controls = new DeviceOrientationControls( camera );, when it should be:
controls = new THREE.DeviceOrientationControls( camera );
Finally, make sure you organize your code, and call your functions in a sequential manner. Is loadGltf() being called before you initiate const loader = new THREE.GLTFLoader()? Does startButton exist, and is it defined before you call startButton.addEventListener();?
Here is a minimal example implementing the orientation controls: Notice that both scripts are being imported from the same source with r92 to ensure compatibility.
window.addEventListener("resize", resize);
const renderer = new THREE.WebGLRenderer({canvas: document.querySelector("canvas")});
const camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
const controls = new THREE.DeviceOrientationControls( camera );
// Make a scene with geometry
const scene = new THREE.Scene();
const geometry = new THREE.DodecahedronBufferGeometry(100,1);
const material = new THREE.MeshBasicMaterial({
color: 0xff9900,
wireframe: true,
});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
function resize() {
var width = window.innerWidth;
var height = window.innerHeight;
renderer.setSize(width, height, false);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
function animate(time) {
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
resize();
animate(0);
body { margin: 0; }
<canvas></canvas>
<!-- three.min.js r92 -->
<script src="https://cdn.jsdelivr.net/npm/three#0.92/build/three.min.js"></script>
<!-- Orientation Controls r92 -->
<script src="https://cdn.jsdelivr.net/gh/mrdoob/three.js#r92/examples/js/controls/DeviceOrientationControls.js"></script>
Note:
Apple disabled gyroscope access by default since iOS 12.2, so you'll have to enable it in settings when testing. See here for a discussion on the matter.
I just setup a very basic "hello world" for three.js…
But apparently my 3d cube is appearing as a 2d square…
The code to the js file is here
const t = THREE;
const scene = new t.Scene();
const camera = new t.PerspectiveCamera(75, window.innerWidth, window.innerHeight, 0.1, 1000);
const renderer = new t.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// create a shape
const geometry = new t.BoxGeometry(1, 1, 1);
// create a material
const material = new t.MeshBasicMaterial({color: 0xFFFFFF, wireframe: true});
const cube = new t.Mesh(geometry, material);
// cube.position.y = 1;
scene.add(cube);
// camera.position.x = 300;
camera.position.z = 5;
// logic
const update = function () {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
};
// draw scene
const render = function () {
renderer.render(scene, camera);
};
// run render loop (update-render-repeat)
const RenderLoop = function () {
window.requestAnimationFrame(RenderLoop);
update();
render();
};
RenderLoop();
And the result of the code is here
Any help is appreciated!
EDIT:
Sorry for not including the code
You're building your PerspectiveCamera wrong:
Your way:
PerspectiveCamera(75, window.innerWidth, window.innerHeight, 0.1, 1000);
Correct way:
PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
You need to pass the ratio w/h, not two separate w, h arguments.