Webpack in React can't load the 3D model with a GLTF extension, shows 404 not found

六月ゝ 毕业季﹏ 提交于 2021-01-29 12:52:26

问题


I'm trying to load the 3D model with the .gltf extension in React with Typescript. The files in folder with 3D model are .gltf, .png and .bin files. The tools used for this task are webpack and useGLTFLoader from drei library. I've tried different tools. Mainly from three.js library with no effect. Error is showing that the 3D model is not found 404 (shown below) and nothing appears in place where 3D model should be placed.

GET http://localhost:3000/assets/models/Duck/glTF/Duck.gltf 404 (Not Found)

My component for rendering the 3D model is shown below:

import React, { Suspense } from 'react';
import { Canvas } from 'react-three-fiber';
import { useGLTFLoader } from 'drei';

const DuckModel = () => {
 const gltf = useGLTFLoader('../../assets/models/Duck/glTF/Duck.gltf', true);
 return <primitive object={gltf.scene} dispose={null} />;
};

export const ThreeDimensionComponent = () => {
 return (
  <>
   <Canvas camera={{ position: [0, 0, 10], fov: 70 }}>
    <Suspense fallback={null}>
     <mesh position={[0, 250, 0]}>
      <DuckModel />
     </mesh>
    </Suspense>
   </Canvas>
  </>
 );
};

And below I share my webpack config.

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const root = __dirname;

const gsapPath = '/node_modules/gsap/src/uncompressed/';

module.exports = {
 devtool: 'source-map',
 mode: 'development',
 entry: path.join(__dirname, 'src', 'index.tsx'),
 watch: true,
 output: {
  filename: '[name].js',
  path: path.resolve(__dirname, 'dist'),
  sourceMapFilename: '[name].js.map'
 },
 module: {
  rules: [
   {
    test: /\.(tsx|ts)$/,
    use: ['babel-loader', 'ts-loader', 'tslint-loader']
   },
   {
    test: /\.scss$/,
    use: [
     'style-loader',
     {
      loader: 'css-loader',
      options: {
       sourceMap: true
      }
     },
     {
      loader: 'postcss-loader',
      options: {
       plugins: [require('autoprefixer')()],
       sourceMap: true
      }
     },
     {
      loader: 'sass-loader',
      options: {
       sourceMap: true
      }
     }
    ]
   },
   {
    test: /\.(png|jp(e*)g|svg|gif)$/,
    use: [
     {
      loader: 'url-loader',
      options: {
       limit: 8000,
       sourceMap: true
      }
     }
    ]
   },
   {
    test: /\.(ttf|eot|woff|woff2)$/,
    use: {
     loader: 'file-loader',
     options: {
      name: 'fonts/[name].[ext]',
      sourceMap: true
     }
    }
   },
   {
    test: /\.(glb|gltf)$/,
    use: [
     {
      loader: 'file-loader'
      // options: {
      //  outputPath: 'assets/models'
      // }
     }
    ]
   },
   {
    test: /\.(bin)$/,
    use: [
     {
      loader: 'file-loader'
     }
    ]
   }
  ]
 },
 resolve: {
  extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
  modules: ['node_modules', path.resolve(__dirname, 'src')],
  alias: {
   TweenLite: 'gsap',
   CSSPlugin: 'gsap',
   Draggable: path.join(root, gsapPath + 'utils/Draggable.js'),
   ScrollToPlugin: path.join(root, gsapPath + 'plugins/ScrollToPlugin.js')
  }
 },
 devServer: {
  historyApiFallback: true,
  contentBase: './dist',
  inline: true,
  host: 'localhost',
  port: 3000
 },
 plugins: [
  new CleanWebpackPlugin({ verbose: true }),
  new HtmlWebpackPlugin({
   template: path.join(__dirname, 'src', 'index.html')
  }),
  new webpack.ProvidePlugin({
   TweenMax: 'gsap'
  }),
  new CopyWebpackPlugin({
   patterns: [{ from: 'src/assets' }]
  })
 ]
};

My webpack.config.js file is in the root directory for the project. The assets folder is in the src folder. Lastly the file with React code is in src/components/ThreeDimensionComponent/ThreeDimensionComponent.tsx (so path for it is correct).


回答1:


You either need to import the model and use the url you get from that (url-loader), or put it into the public folder. Your path points nowhere in the bundled output.

One more thing, it's @react-three/drei and useGLTF(url).




回答2:


Here is a working example with a loaded 3D model in case anyone needed it. I marked an answer from hpalu as correct because it helped me to solve this problem.

I needed to use Suspense with a fallback that isn't an HTML element but instead is a component from react-three-fiber.

The post that also has helped me to solve the bug:

  • https://spectrum.chat/react-three-fiber/general/hello-im-trying-to-use-the-texture-loader-with-suspense~a9671405-3b8a-4486-a319-cad820347ddc?m=MTU4NDExMzIyMTMwOA==

Here is React component:

import { useGLTF } from '@react-three/drei';
import React, { Suspense } from 'react';
import { Canvas } from 'react-three-fiber';

const DuckModel = () => {
 const gltf = useGLTF('./models/Duck/glTF/Duck.gltf', true);
 return <primitive object={gltf.scene} dispose={null} />;
};

export const ThreeDimensionComponent = () => {
 return (
  <>
   <Canvas camera={{ position: [0, 0, 3], fov: 80 }}>
    <ambientLight intensity={0.3} />
    <Suspense
     fallback={
      <mesh>
       <boxBufferGeometry args={[1, 1, 1]} />
       <meshStandardMaterial />
      </mesh>
     }
    >
     <DuckModel />
    </Suspense>
   </Canvas>
  </>
 );
};

And here is the webpack config for this example:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const gsapPath = '/node_modules/gsap/src/uncompressed/';

module.exports = {
 devtool: 'source-map',
 mode: 'development',
 entry: path.join(__dirname, 'src', 'index.tsx'),
 watch: true,
 output: {
  filename: '[name].js',
  path: path.resolve(__dirname, 'dist'),
  sourceMapFilename: '[name].js.map',
  publicPath: '/'
 },
 module: {
  rules: [
   {
    test: /\.(tsx|ts)$/,
    use: ['babel-loader', 'ts-loader', 'tslint-loader']
   },
   {
    test: /\.scss$/,
    use: [
     'style-loader',
     {
      loader: 'css-loader',
      options: {
       sourceMap: true
      }
     },
     {
      loader: 'postcss-loader',
      options: {
       plugins: [require('autoprefixer')()],
       sourceMap: true
      }
     },
     {
      loader: 'sass-loader',
      options: {
       sourceMap: true
      }
     }
    ]
   },
   {
    test: /\.(png|jp(e*)g|svg|gif)$/,
    use: [
     {
      loader: 'url-loader',
      options: {
       limit: 8000,
       sourceMap: true
      }
     }
    ]
   },
   {
    test: /\.(ttf|eot|woff|woff2)$/,
    use: {
     loader: 'file-loader',
     options: {
      name: 'fonts/[name].[ext]'
      // sourceMap: true
     }
    }
   },
   {
    test: /\.(glb|gltf)$/,
    use: [
     {
      loader: 'file-loader',
      options: {
       outputPath: 'assets/models',
       sourceMap: true
      }
     }
    ]
   },
   {
    test: /\.(bin)$/,
    use: [
     {
      loader: 'file-loader',
      options: {
       outputPath: 'assets/models',
       sourceMap: true
      }
     }
    ]
   }
  ]
 },
 resolve: {
  extensions: ['.ts', '.tsx', '.js', '.jsx', '.json'],
  modules: ['node_modules', path.resolve(__dirname, 'src')],
  alias: {
   TweenLite: 'gsap',
   CSSPlugin: 'gsap',
   Draggable: path.join(__dirname, gsapPath + 'utils/Draggable.js'),
   ScrollToPlugin: path.join(__dirname, gsapPath + 'plugins/ScrollToPlugin.js')
  }
 },
 devServer: {
  historyApiFallback: true,
  contentBase: './dist',
  inline: true,
  host: 'localhost',
  port: 3000
 },
 plugins: [
  new CleanWebpackPlugin({ verbose: true }),
  new HtmlWebpackPlugin({
   template: path.join(__dirname, 'src', 'index.html')
  }),
  new webpack.ProvidePlugin({
   TweenMax: 'gsap'
  }),
  new CopyWebpackPlugin({
   patterns: [{ from: 'src/assets' }]
  })
 ]
};


来源:https://stackoverflow.com/questions/64526248/webpack-in-react-cant-load-the-3d-model-with-a-gltf-extension-shows-404-not-fo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!