Day 1 on babylon.js. I have cloned this repository for angular 9.1 and babylon 4.1 starter kit. I am able to run the project.
Next step is that I wanted to load the gltf model for which I have installed the package babylonjs-loaders and used the library but getting error that path to model 404.
Code:
import { WindowRefService } from './../services/window-ref.service';
import {ElementRef, Injectable, NgZone} from '#angular/core';
import {
Engine,
FreeCamera,
Scene,
Light,
Mesh,
Color3,
Color4,
Vector3,
HemisphericLight,
StandardMaterial,
Texture,
DynamicTexture
} from 'babylonjs';
import 'babylonjs-materials';
import 'babylonjs-loaders';
#Injectable({ providedIn: 'root' })
export class EngineService {
private canvas: HTMLCanvasElement;
private engine: BABYLON.Engine;
private camera: BABYLON.FreeCamera;
private scene: BABYLON.Scene;
private light: BABYLON.Light;
private sphere: Mesh;
public constructor(
private ngZone: NgZone,
private windowRef: WindowRefService
) {}
public animate(): void {
// We have to run this outside angular zones,
// because it could trigger heavy changeDetection cycles.
this.ngZone.runOutsideAngular(() => {
const rendererLoopCallback = () => {
this.scene.render();
};
if (this.windowRef.document.readyState !== 'loading') {
this.engine.runRenderLoop(rendererLoopCallback);
} else {
this.windowRef.window.addEventListener('DOMContentLoaded', () => {
this.engine.runRenderLoop(rendererLoopCallback);
});
}
this.windowRef.window.addEventListener('resize', () => {
this.engine.resize();
});
});
}
public loadScene(canvas: ElementRef<HTMLCanvasElement>): void {
// The first step is to get the reference of the canvas element from our HTML document
this.canvas = canvas.nativeElement;
// Then, load the Babylon 3D engine:
this.engine = new BABYLON.Engine(this.canvas, true);
// create a basic BJS Scene object
this.scene = new BABYLON.Scene(this.engine);
this.scene.clearColor = new Color4(0, 0, 0, 0);
// create a FreeCamera, and set its position to (x:5, y:10, z:-20 )
this.camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(5, 10, -20), this.scene);
// target the camera to scene origin
this.camera.setTarget(BABYLON.Vector3.Zero());
// attach the camera to the canvas
this.camera.attachControl(this.canvas, false);
// create a basic light, aiming 0,1,0 - meaning, to the sky
this.light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0, 1, 0), this.scene);
BABYLON.SceneLoader.Append("./", "bmw.gltf", this.scene, function (scene) {
// do something with the scene
});
}
}
I have googled on similar question but did not reach to any conclusion. I might be missing something basic. I have kept the gltf on the same directory as ts file and path is proper. I have tested with putting png image on same path and able to see it in network tab of chrome dev tool with 200 status.
Please help guys. I am guessing the way i am importing babylonjs-loaders is the culprit here.
error screenshot:
Your bmw.gltf file should be located in your assets folder.
this means that you will have to load the files from there.
BABYLON.SceneLoader.Append("/assets", "bmw.gltf"
Related
I'm using pdfjs-dist "^2.16.105" to import pdf files into fabric as fabric.Images in my React Application. According to the http://fabricjs.com/import-pdf example, this all works in Chrome, Firefox, but does not work in Safari. I'm testing in Safari version 14.1.2. Here's the error in the console when loading react app.
SyntaxError: Unexpected private name #ensureObj. Cannot parse class method with private
name.
I have read that safari versions before 14.5 does not support private classes. How can this problem be solved?
In Safari React application doesn't start, I only see a blank screen.
This is my code
import * as PDFJS from "pdfjs-dist";
import * as pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
PDFJS.GlobalWorkerOptions.workerSrc = pdfjsWorker;
...
PDFJS.getDocument({
data: pdfData,
}).promise.then((a) => {
a.getPage(1).then((page) => {
let viewport = page.getViewport({ scale: window.devicePixelRatio });
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
canvas.height = viewport.height;
canvas.width = viewport.width;
const render_context = {
canvasContext: context,
viewport: viewport,
};
const renderTask = page.render(render_context);
renderTask.promise.then(() => {
const canvasImage = new fabric.Image(canvas, {});
renderCanvasImg(canvasImage);
});
});
});
One possibility is to downgrade pdf-dist library to v2.4.456 since the version v2.13.216 introduced #ensureObj - private fields ES2022 feature (see build/pdf.js).
package.json:
{
dependencies: {
"pdfjs-dist": "v2.4.456",
...
}
...
}
Second possibility would be to use some transpiler (etc. Babel) to downgrade the ES version.
so whenever I want to import a model via GLTFLoader locally I get this error:
JSON.parse: unexpected character at line 1 column 1 of the JSON data
but when I try it via a link it works.
The link I tried with is:
https://s3-us-west-2.amazonaws.com/s.cdpn.io/39255/ladybug.gltf
I tested the models I used in the official three.js-Editor and even exported them from there to get a "clean" gltf model. I also saved the content of the link in a gltf file and it didnt work neither.
This is my code:
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
async function run() {
try {
var loader = new GLTFLoader();
loader.crossOrigin = true;
loader.load(
"./scene.gltf",
//"https://s3-us-west-2.amazonaws.com/s.cdpn.io/39255/ladybug.gltf",
function (data) {
var object = data.scene;
object.position.set(0, 0, 0);
scene.add(object);
}
);
} catch (e) {
console.log(e);
}
}
run();
As Marquizzo said: You have to run a local server for the models. You cannot import them via a path normally, because of security restrictions.
I have been using babylonjs within a reactjs environment and so far it's very good. However i've been having trouble loading 3d models into the canvas. I've managed to load models into a non-react environment but not the react environment.
You can see a simple example of my current code below.
import React from 'react'
import {useEffect, useState, useRef} from 'react'
import path from 'path'
import * as BABYLON from '#babylonjs/core'
import 'babylonjs-loaders'
import SceneComponent from 'babylonjs-hook'; // ^^ point to file we created above or 'babylonjs-hook' NPM.
import SceneComp from '../components/babylonComponent'
const MyPage = () =>{
var box = undefined
var page = "landing"
//this configures the scene
const onSceneReady = (scene) =>{
scene.clearColor = BABYLON.Color3.Black()
//create and position free camera
var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5, -10), scene)
//this targets the camera to scene of origin
const canvas = scene.getEngine().getRenderingCanvas()
//attatch camera to canvas
camera.attachControl(canvas, true)
//this creates a light aiming 0,1,0 - to the sky (non - mesh)
var light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0,1,0), scene)
//default intensity is 1, let's dim the light a small amount
light.intensity = 0.7
var myModel = BABYLON.SceneLoader.Append("./3dAssetts/untitled-scene-babylon/", "untitled-scene.babylon", scene, function(meshes){
})
return scene
}
//this funciton will run on every frame render
const onRender = (scene) =>{
}
return(
<div>
<div style={canvasStyler}>
<SceneComp antialias onSceneReady={onSceneReady} onRender={onRender} id='my-canvas' />
</div>
</div>
)
}
const menuButton= {
color:'black',
textDecoration:'none',
}
const canvasStyler ={
position:'absolute',
width:'100%',
top:'0px',
zIndex:'-1'
}
export default MyPage
The canvas and the page loads fine but the 3d model does not and I am getting the following error.
Unable to load from ./3dAssetts/untitled-scene-babylon/untitled-scene.babylon: importScene of undefined from undefined version: undefined, exporter version: undefinedimportScene has failed JSON parse
Unable to work out what i'm doing wrong, anybody got any ideas?
I have managed to get .babylon 3d model files imported using the following
I created an assets folder within the create-react-app /public folder.
I then put my .babylon file within this folder and called it in the import mesh code using the following.
var car = BABYLON.SceneLoader.Append("./assets/", "carModel.babylon", scene, function(meshes){
})
However i'm still having problems loading other object file types such as .gltf and .OBJ
for further info see the following useful link
https://www.html5gamedevs.com/topic/40304-trouble-loading-assets-in-react/
If you are using version 4, try replacing
import 'babylonjs-loaders'
with
import '#babylonjs/loaders'
I'm trying to load a .fbx file, the loader.load function throws the following error:
THREE.FBXLoader: Cannot find the version number for the file given.
I don't know how to solve this problem. How can I check in the fbx file if it has a version number?
Below you can find the react component that I've written. When I test the app, I see only a black canvas.
I tried two different files, but have the same error for both files.
export default class myComponent extends Component {
componentDidMount() {
const camera = new THREE.PerspectiveCamera(
45,
window.innerWidth / window.innerHeight,
1,
2000
);
camera.position.set(2, 18, 28);
const scene = new THREE.Scene();
const light = new THREE.HemisphereLight(0xffffff, 0x444444);
light.position.set(0, 1, 0);
scene.add(light);
const gridHelper = new THREE.GridHelper(28, 28, 0x303030, 0x303030);
scene.add(gridHelper);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
this.model.appendChild(renderer.domElement);
const loader = new FBXLoader();
let model = new THREE.Object3D();
loader.load(
'./3DModels/MHT.fbx',
function(object) {
model = object.scene;
scene.add(model);
},
undefined,
function(e) {
console.log(e);
}
);
renderer.render(scene, camera);
}
render() {
return <div ref={ref => (this.model = ref)} />;
}
}
FBXLoader throws this error: THREE.FBXLoader: Cannot find the version number for the file given.
loader.load('./3DModels/MHT.fbx', function(object) {
...
})
instead:
const path = require(./3DModels/MHT.fbx);//写在类的外面
loader.load(path, function(object) {
...
})
I have meeted the same problem just now, you can try to debug like this:
I find the reason that my project use Mockjs which make XMLHttpRequest become MockXMLHttpRequest:
// relative code in three.js:
request.addEventListener( 'load', function ( event ) {
// if you use Mockjs, this become MockXMLHttpRequest but not XMLHttpRequest
// this.response not is ArrayBuffer ,there is the bug.
var response = this.response;
var callbacks = loading[ url ];
Here just my case which maybe help you.
Are you hosting your files in your src folder or public folder?
You should be keeping the fbx files in public folder.
The loader scans the document and parses the text to find what it needs to load. Case with working in react is this will trigger before the DOM is rendered, so it basicaly can't the version because it sees no file.
I worked it out while trying to "debug" the loader code. It turned out it was me :)
Another fbx thing is you should always use the latest loader plugin. Under this link you will find both the link to the original plugin and the example how to convert it to React module.
Hope this helps.
I had exactly the same error coming up on a ThreeJS RPG game hosted on Heroku. I eventually found a simple solution which worked for me and am posting here for any other poor soul who runs into to this issue.
The issue for me was that when I was downloading the FBX file from mixamo I was downloading just the FBX.binary file. **You need to download the fbx file with the version number **. So I just downloaded the FBX animation as FBX 7.4 and it worked. See image.
Hope this helps someone save the stupid number of hours I wasted on this...
download fbx 7.4 or 6.1
I have a React app bundled with Webpack. I would like to use a web worker for one of my components, which exports data to Pdf. The generation of the pdf can take a while and lock the browser, so I want to do this work in a web worker to do it in a separate thread. The problem I am having is importing the JsPDF library into my web worker script so i can use it.
This is my worker script:
import * as JsPDF from "jspdf";
export default () => {
self.addEventListener("message", event => {
const canvases = event.data;
const pdf = new JsPDF({
orientation: "l",
unit: "in",
});
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < canvases.length; i++) {
if (i > 0) pdf.addPage();
pdf.addImage(canvases[i].toDataURL("image/png"), "PNG", 0.25, 0, 11, 8);
}
pdf.save("report.pdf");
self.postMessage("done", "");
});
};
This gives me this error at runtime:
Uncaught ReferenceError: jspdf__WEBPACK_IMPORTED_MODULE_0__ is not defined
at blob:http://localhost:11449/ea75c456-15ee-45e9-b82b-902c518dc635:4
I did also try using the importScript() function, like so:
export default () => {
importScripts("jspdf");
self.addEventListener("message", event => {
const canvases = event.data;
const pdf = new JsPDF({
orientation: "l",
unit: "in",
});
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < canvases.length; i++) {
if (i > 0) pdf.addPage();
pdf.addImage(canvases[i].toDataURL("image/png"), "PNG", 0.25, 0, 11, 8);
}
pdf.save("report.pdf");
self.postMessage("done", "");
});
};
and I get this error:
Uncaught DOMException: Failed to execute 'importScripts' on 'WorkerGlobalScope': The URL 'jspdf' is invalid.
or I try:
importScripts("../../../../node_modules/jspdf/dist/jspdf.min.js");
and I get the same invalid URL error.
I also tried using require outside of the export:
const JsPDF = require("jspdf");
but i still get an error that JsPDF is not defined. What else can I try?
I should mention that the web worker is instantiated using a custom class, as in https://medium.com/prolanceer/optimizing-react-app-performance-using-web-workers-79266afd4a7, for getting the correct URL with webpack:
export default class WebWorker {
constructor(worker: any) {
const code = worker.toString();
const blob = new Blob([`(${code})()`]);
return new Worker(URL.createObjectURL(blob));
}
}
I ended up using worker-loader for webpack. This allows me to import modules in worker scripts like in any other script.