I want to use threeJS, so i install it with npm i three --save. I followed basic tutorial in threeJS documentation but i got an error.
mounted () {
this.initThree();
},
methods: {
initThree() {
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
this.renderer = new THREE.WebGLRenderer( { canvas: document.getElementById( "background" ), alpha: true, antialias: true } );
this.renderer.setSize( window.innerWidth, window.innerHeight );
let geometry = new THREE.BoxGeometry( 1, 1, 1 );
let material = new THREE.MeshBasicMaterial( { color: 0x0000ff } );
this.cube = new THREE.Mesh( geometry, material );
this.scene.add( this.cube );
this.camera.position.z = 5;
this.animate()
},
animate() {
this.cube.rotation.x += 0.01;
this.renderer.render( this.scene, this.camera );
requestAnimationFrame( this.animate() );
}
}
}
Your problem is not related to VueJS /ThreeJs, you should simply fix this line :
requestAnimationFrame( this.animate() );
It should be :
requestAnimationFrame(this.animate)
Please read more about callback : https://developer.mozilla.org/en-US/docs/Glossary/Callback_function
EDIT: You can try TroisJS, easy ThreeJS integration with VueJS : https://github.com/troisjs/trois
Related
Throwing an error at this.chart.
animation: {
duration: 1,
onComplete: ()=> void {
var chartInstance= this.chart,
ctx = chartInstance.ctx;
// ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach((dataset:any, i:any)=> {
var meta = chartInstance.controller.getDatasetMeta(i);
meta.data.forEach((bar:any, index:any)=> {
var data = dataset.data[index];
ctx.fillText(data, bar._model.x, bar._model.y - 5);
});
});
}
},
tooltips: {"enabled": true}
}
});
}
I am trying to insert a .obj file into a React Native app built using Expo.
From the examples I've found that are successfully working, most of these seem to rely on building spheres or cubes within the rendering. I haven't found a good example with a successful rendering of a local file, specifically .obj.
I'm using the expo-three documentation which describes rendering with obj files, but no working examples.
This is what I have so far, which is not producing any rendered object. But want to know if I am on the right track with this, and what I am missing to get the object to render.
Below is the current file code.
import { Renderer, TextureLoader } from 'expo-three';
import * as React from 'react';
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader';
import {
AmbientLight,
Fog,
GridHelper,
PerspectiveCamera,
PointLight,
Scene,
SpotLight,
} from 'three';
import { Asset } from 'expo-asset';
import { MTLLoader } from 'three/examples/jsm/loaders/MTLLoader';
export default function ThreeDPhytosaur() {
return (
<GLView
style={{ flex: 1 }}
onContextCreate={async (gl) => {
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const sceneColor = 0x6ad6f0;
const renderer = new Renderer({ gl });
renderer.setSize(width, height);
renderer.setClearColor(sceneColor);
const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
camera.position.set(2, 5, 5);
const scene = new Scene();
scene.fog = new Fog(sceneColor, 1, 10000);
scene.add(new GridHelper(10, 10));
const ambientLight = new AmbientLight(0x101010);
scene.add(ambientLight);
const pointLight = new PointLight(0xffffff, 2, 1000, 1);
pointLight.position.set(0, 200, 200);
scene.add(pointLight);
const spotLight = new SpotLight(0xffffff, 0.5);
spotLight.position.set(0, 500, 100);
spotLight.lookAt(scene.position);
scene.add(spotLight);
const asset = Asset.fromModule(model['phytosaur']);
await asset.downloadAsync();
const objectLoader = new OBJLoader();
const object = await objectLoader.loadAsync(asset.uri);
object.scale.set(0.025, 0.025, 0.025);
scene.add(object);
camera.lookAt(object.position);
const render = () => {
timeout = requestAnimationFrame(render);
renderer.render(scene, camera);
gl.endFrameEXP();
};
render();
}}
/>
);
}
const model = {
'phytosaur': require('../assets/phytosaur.obj'),
};
Thanks very much!
This is the code that I got to render the obj file. Changed the structure of the original file based on some other examples found.
But this might help someone else!
import { OBJLoader } from 'three/examples/jsm/loaders/OBJLoader.js';
import { Asset } from 'expo-asset';
import { Renderer} from 'expo-three';
import * as React from 'react';
import {
AmbientLight,
Fog,
PerspectiveCamera,
PointLight,
Scene,
SpotLight,
} from 'three';
export default function ThreeDTwo() {
let timeout;
React.useEffect(() => {
// Clear the animation loop when the component unmounts
return () => clearTimeout(timeout);
}, []);
return (
<GLView
style={{ flex: 1 }}
onContextCreate={async (gl) => {
const { drawingBufferWidth: width, drawingBufferHeight: height } = gl;
const sceneColor = 668096;
// Create a WebGLRenderer without a DOM element
const renderer = new Renderer({ gl });
renderer.setSize(width, height);
renderer.setClearColor(0x668096);
const camera = new PerspectiveCamera(70, width / height, 0.01, 1000);
camera.position.set(2, 5, 5);
const scene = new Scene();
scene.fog = new Fog(sceneColor, 1, 10000);
const ambientLight = new AmbientLight(0x101010);
scene.add(ambientLight);
const pointLight = new PointLight(0xffffff, 2, 1000, 1);
pointLight.position.set(0, 200, 200);
scene.add(pointLight);
const spotLight = new SpotLight(0xffffff, 0.5);
spotLight.position.set(0, 500, 100);
spotLight.lookAt(scene.position);
scene.add(spotLight);
const asset = Asset.fromModule(require("../assets/phytosaur_without_mtl.obj"));
await asset.downloadAsync();
// instantiate a loader
const loader = new OBJLoader();
// load a resource
loader.load(
// resource URL
asset.localUri,
// called when resource is loaded
function ( object ) {
object.scale.set(0.065, 0.065, 0.065)
scene.add( object );
camera.lookAt(object.position)
//rotate my obj file
function rotateObject(object, degreeX=0, degreeY=0, degreeZ=0) {
object.rotateX(THREE.Math.degToRad(degreeX));
object.rotateY(THREE.Math.degToRad(degreeY));
object.rotateZ(THREE.Math.degToRad(degreeZ));
}
// usage:
rotateObject(object, 0, 0, 70);
//animate rotation
function update() {
object.rotation.x += 0.015
}
const render = () => {
timeout = requestAnimationFrame(render);
update();
renderer.render(scene, camera);
gl.endFrameEXP();
};
render();
},
// called when loading is in progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( error );
}
);
}}
/>
);
}
This is the first time that I cannot find an answer and have to write here. I am trying a three.js project with Vue.js. I have this error:
Failed to compile.
./node_modules/three-gltf-loader/index.js
Module not found: Error: Can't resolve 'three' in 'C:\Users\Skunk\Documents\dolfin\dolfin\node_modules\three-gltf-loader'
My code:
import * as THREE from 'three-js';
import GLTFLoader from 'three-gltf-loader';
export default {
name: 'HelloWorld',
props: {
msg: String
},
mounted(){
let scene = new THREE.Scene( );
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerWidth / window.innerHeight, 0.1, 1000);
let renderer = new THREE.WebGLRenderer( );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener( 'resize', function( )
{
let width = window.innerWidth;
let height = window.innerHeight;
renderer.setSize( width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix( );
} );
const loader = new GLTFLoader();
// Load a glTF resource
loader.load(
// resource URL
'models/dol.gltf',
// called when the resource is loaded
function ( gltf ) {
scene.add( gltf.scene );
gltf.animations; // Array<THREE.AnimationClip>
gltf.scene; // THREE.Group
gltf.scenes; // Array<THREE.Group>
gltf.cameras; // Array<THREE.Camera>
gltf.asset; // Object
},
// called while loading is progressing
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
}
);
camera.position.z = 3;
//let ambientLight = new THREE.AmbientLight( 0xFFFFFF, 0.8);
// scene.add( ambientLight );
// game logic
let update = function ( )
{};
// draw scene
let render = function( )
{
renderer.render( scene, camera );
};
// run game loop
let GameLoop = function( )
{
requestAnimationFrame( GameLoop );
update( );
render( );
};
GameLoop( );
}
}
Am I using pieces of code that are not compatible?
For starters, you should not be using the "three-js" node module. This is a really outdated version of Three that got stuck on r79 and hasn't been updated in 4 years. Instead, you should be using the official "three" node module, which is the legitimate library, and is currently on r124.
Second, just import the GLTF loader from the "three/examples" folder as demonstrated in the GLTF examples, instead of installing a whole new module.
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
const loader = new GLTFLoader();
How can I print the values of an array using three.js textGeometry. Trying the following code but no output.
`for(let i=0;i<=4;i++)
{
let arr = [1,2,3,4,5,6,7,8];
let char = arr[i];
let loader = new THREE.FontLoader();
let font = loader.parse(fontJSON);
let geometry = new THREE.TextBufferGeometry(char ,{font : font , size : 1 , height : 0.1 });
let material = new THREE.MeshBasicMaterial({ color : 0xffffff });
let text = new THREE.Mesh(geometry , material);
text.position.set(i,0,0);
scene.add(text);
}`
You have to make sure to provide a string to TextBufferGeometry, no number. You can easily ensure this by calling toString() on your char variable. I've refactored your code a bit to show you a complete example.
let camera, scene, renderer;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 8;
scene = new THREE.Scene();
const material = new THREE.MeshBasicMaterial({
color: 0xffffff
});
const arr = [1, 2, 3, 4, 5, 6, 7, 8];
const loader = new THREE.FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_regular.typeface.json', (font) => {
for (let i = 0; i <= 4; i++) {
const char = arr[i];
const geometry = new THREE.TextBufferGeometry(char.toString(), {
font: font,
size: 1,
height: 0.1
});
const text = new THREE.Mesh(geometry, material);
text.position.set(i, 0, 0);
scene.add(text);
}
});
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
body {
margin: 0;
}
canvas {
display: block;
}
<script src="https://cdn.jsdelivr.net/npm/three#0.117.1/build/three.js"></script>
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;
```