Load GLTF file that is not located in Public folder - reactjs

I found a problem that I cannot load GLTF files into a scene if I cannot place them in the Public folder in my React application. For example, I have MyPVPanel.gltf, and I want to load it in react app or in my npm library, or I always to be with my react components.
My questions are:
Is this possible to import assets from a specific folder if you develop an npm package. Do packages have something like /public or /assets?
Can I configure my own package to have such a folder with static assets?
How to load GLTF files without a public folder. For example, we can import .png files without problems in react application.

So there is a thing named data URI. You can convert small files in that format(which is basically a base64 encoded string with some metadata at the beginning of it).
data:[<mediatype>][;base64],<data>
In my case [<mediatype>] is data:application/octet-stream.
So if you want to load small file from specific folder in you application, first of all rename your .gltf file into .json. And after importing and converting it into base64 code you can load it using GLTFLoader from three.js library.
Here is a code example:
import myGLTF from './MyPVPanel.json';
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
import myGLTF from "./MyPVPanel.json";
const loader = new GLTFLoader();
const stringGLTF = JSON.stringify(myGLTF) // convert Object to a String
const base64EncodedGLTF = btoa(stringGLTF) // Base64 encode the String
//First part is: 'data:application/octet-stream;base64,'
const resultingDataURI = `data:application/octet-stream;base64,${base64EncodedGLTF}`;
loader.load(
resultingDataURI,
(gltf: any) => {
console.log('Loaded!!!');
this.scene.add(gltf.scene)
},
() => {},
(e: any) => console.error(e)
);
}}>Load</button>

Related

How to import js module into react public folder?

I have a react public folder that contains a html file and a simple js file.
Then I have an src folder which is outside the public folder.
When I try to import something into that js file which is outside the public folder :
import OpenIdConnect from '#luigi-project/plugin-auth-oidc';
I get the next error :
Cannot use import statement outside a module
How can I use imports into the public folder?
Normally this means your node project is not setup to use ES Modules by default and is instead using common JS modules.
Without modifying config, in files with this restriction, instead of:
import someVar from './filePath';
// ...
export { anotherVar };
use istead:
const someVar = require('./filePath');
// ...
module.exports = anotherVar;
If you wish to pursue a more consistent solution, I would advice reading though the Node.js documentation and any other documentation relevant to any library/framework/tooling that you use to find a suitable solution.

Why can I get an image from public folder but not a json file

I learn Reactjs and came across this
I have an images folder in the public React project created with create-react-app.
I place a json file and a jpg in it and I can use the jpg but not the json.
let photo = "./images/some.jpg";
let file = "./images/somejson.json";
The image works out of the box like
<img alt="image" src={photo} />
But the json cant be read I get Cannot read property 'label' of undefined
<h1 className="title">{file.basics.label}</h1>
And this is the json
{
"basics": {
"name": "Foo Bar",
"label": "Some label"
}
}
Please advice what is wrong?
You should import JSON file before use its properties, your file variable is just a path to a JSON file. If you are using create-react-app it has json-loader, if not you have to install it and configure your Webpack, I can assume you already use it, and then you can import JSON file and use it.
import json from "./images/somejson.json"
...
<img src={json.someSrc} />
you have to replace .json from public to src folder. And also you should export your variable file in the somejson.json file. and also you should import this variable too.
In your JS file, import your json file with correct path.
import file from './somejson.json';
If you need to retain this file in public/ and also use it in React app, add this library.
https://github.com/oklas/react-app-rewire-alias
import file from '../public/images/somejson.json';

Why webpack imports all files in subdirectory instead of the right

I have React app which render 300 pages. They are divided into 4 groups. There are common settings, custom settings for each group and settings for each page in .json files. I don't want to load all the settings for all pages, but only those needed for a particular page. I try use require to import necessary file:
const getThemeConfig = (theme) => {
const filePath = `./themes/${theme}/config.json`;
return require(`${filePath}`)
};
const themeConfig = getThemeConfig(currentTheme);
this file is imported, but at the same time the application tries to upload absolutely all .json files in ./themes directory. IDK how to fix it.

How to encode/compress gltf to draco

I want to compress/encode gltf file using draco programatically in threejs with reactjs. I dont want to use any commandline tool, I want it to be done programatically. Please suggest me a solution.
I tried using gltf-pipeline but its not working in client side. Cesium library was showing error when I used it in reactjs.
Yes, this is can be implemented with glTF-Transform. There's also an open feature request on three.js, not yet implemented.
First you'll need to download the Draco encoder/decoder libraries (the versions currently published to NPM do not work client side), host them in a folder, and then load them as global script tags. There should be six files, and two script tags (which will load the remaining files).
Files:
draco_decoder.js
draco_decoder.wasm
draco_wasm_wrapper.js
draco_encoder.js
draco_encoder.wasm
draco_encoder_wrapper.js
<script src="assets/draco_encoder.js"></script>
<script src="assets/draco_decoder.js"></script>
Then you'll need to write code to load a GLB file, apply compression, and do something with the compressed result. This will require first installing the two packages shown below, and then bundling the web application with your tool of choice (I used https://www.snowpack.dev/ here).
import { WebIO } from '#gltf-transform/core';
import { DracoMeshCompression } from '#gltf-transform/extensions';
const io = new WebIO()
.registerExtensions([DracoMeshCompression])
.registerDependencies({
'draco3d.encoder': await new DracoEncoderModule(),
'draco3d.decoder': await new DracoDecoderModule(),
});
// Load an uncompressed GLB file.
const document = await io.read('./assets/Duck.glb');
// Configure compression settings.
document.createExtension(DracoMeshCompression)
.setRequired(true)
.setEncoderOptions({
method: DracoMeshCompression.EncoderMethod.EDGEBREAKER,
encodeSpeed: 5,
decodeSpeed: 5,
});
// Create compressed GLB, in an ArrayBuffer.
const arrayBuffer = io.writeBinary(document); // ArrayBuffer
In the latest version of 1.5.0, what are these two files? draco_decoder_gltf.js and draco_encoder_gltf.js. Does this means we no longer need the draco_encoder and draco_decoder files? and how do we invoke the transcoder interface without using MeshBuilder. A simpler API would be musth better.

Import multiple files in folder in React / Nextjs

I'm trying to import multiple files with a certain extension in a folder:
const allEntries = require.context('../static/blog', true, '/\.md/')
but I'm getting:
Unhandled Rejection (TypeError): __webpack_require__(...).context is not a function
I'm using Nextjs and require the files in one of the pages. Something seems off here?
Edit: I don't necessarily need to do it via require I just want to be able to import/require multiple files at once without knowing the filename or how many of the files are in a folder.
You can give the following a try in webpack:
const glob = require('glob');
const allEntries = glob.sync("../static/blog/*.md");
The glob will return an array of files. The array will contain all files with .md extension in the ../static/blog/ folder. Eventough there is a package it shouldn't be required to install the package.
Try using require context npm library.
$ npm i --save require-context
In your file:
// Load globally into all modules.
require('require-context/register')
// Load locally as a function.
var requireContext = require('require-context');
function requireAll(r) { r.keys().forEach(r); }
requireAll(requireContext('../static/blog', true, /\.md$/));
From what I understand you are very close, from the error you are using webpack's require.context
const allEntries = require.context('../static/blog', true, '/\.md/')
console.log(allEntries.keys()) // all the files found in the context
allEntries.keys().forEach(allEntries) // require them all
const imageDirectory = path.join(process.cwd(), '/public/dirname');
const imageFilenames = await fs.readdir(imageDirectory)
// Store the file names in an array and use it.
webpack.require is basically using webpack, make sure what you're using is webpack in fact

Resources