├── .gitignore ├── bundler ├── webpack.common.js ├── webpack.dev.js └── webpack.prod.js ├── package-lock.json ├── package.json ├── readme.md ├── src ├── .index.html.swp ├── index.html ├── script.js ├── style.css └── world │ ├── car.js │ └── generateCode.js └── static ├── .gitkeep ├── draco ├── README.md ├── draco_decoder.js ├── draco_decoder.wasm ├── draco_encoder.js ├── draco_wasm_wrapper.js └── gltf │ ├── draco_decoder.js │ ├── draco_decoder.wasm │ ├── draco_encoder.js │ └── draco_wasm_wrapper.js ├── models ├── cybertruck │ ├── chassis.gltf │ ├── tesla-cybertruck.blend │ └── wheel.gltf └── mclaren │ ├── car.gltf │ ├── chassis.gltf │ ├── draco │ ├── chassis.gltf │ └── wheel.gltf │ └── wheel.gltf └── textures └── environmentMaps ├── 0 ├── nx.jpg ├── ny.jpg ├── nz.jpg ├── px.jpg ├── py.jpg └── pz.jpg ├── 1 ├── nx.jpg ├── ny.jpg ├── nz.jpg ├── px.jpg ├── py.jpg └── pz.jpg ├── 2 ├── nx.jpg ├── ny.jpg ├── nz.jpg ├── px.jpg ├── py.jpg └── pz.jpg └── 3 ├── nx.jpg ├── ny.jpg ├── nz.jpg ├── px.jpg ├── py.jpg └── pz.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /bundler/webpack.common.js: -------------------------------------------------------------------------------- 1 | const CopyWebpackPlugin = require('copy-webpack-plugin') 2 | const HtmlWebpackPlugin = require('html-webpack-plugin') 3 | const MiniCSSExtractPlugin = require('mini-css-extract-plugin') 4 | const path = require('path') 5 | 6 | module.exports = { 7 | entry: path.resolve(__dirname, '../src/script.js'), 8 | output: 9 | { 10 | filename: 'bundle.[contenthash].js', 11 | path: path.resolve(__dirname, '../dist') 12 | }, 13 | devtool: 'source-map', 14 | plugins: 15 | [ 16 | new CopyWebpackPlugin({ 17 | patterns: [ 18 | { from: path.resolve(__dirname, '../static') } 19 | ] 20 | }), 21 | new HtmlWebpackPlugin({ 22 | template: path.resolve(__dirname, '../src/index.html'), 23 | minify: true 24 | }), 25 | new MiniCSSExtractPlugin() 26 | ], 27 | module: 28 | { 29 | rules: 30 | [ 31 | // HTML 32 | { 33 | test: /\.(html)$/, 34 | use: ['html-loader'] 35 | }, 36 | 37 | // JS 38 | { 39 | test: /\.js$/, 40 | exclude: /node_modules/, 41 | use: 42 | [ 43 | 'babel-loader' 44 | ] 45 | }, 46 | 47 | // CSS 48 | { 49 | test: /\.css$/, 50 | use: 51 | [ 52 | MiniCSSExtractPlugin.loader, 53 | 'css-loader' 54 | ] 55 | }, 56 | 57 | // Images 58 | { 59 | test: /\.(jpg|png|gif|svg)$/, 60 | use: 61 | [ 62 | { 63 | loader: 'file-loader', 64 | options: 65 | { 66 | outputPath: 'assets/images/' 67 | } 68 | } 69 | ] 70 | }, 71 | 72 | // Fonts 73 | { 74 | test: /\.(ttf|eot|woff|woff2)$/, 75 | use: 76 | [ 77 | { 78 | loader: 'file-loader', 79 | options: 80 | { 81 | outputPath: 'assets/fonts/' 82 | } 83 | } 84 | ] 85 | } 86 | ] 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /bundler/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge') 2 | const commonConfiguration = require('./webpack.common.js') 3 | const ip = require('internal-ip') 4 | const portFinderSync = require('portfinder-sync') 5 | 6 | const infoColor = (_message) => 7 | { 8 | return `\u001b[1m\u001b[34m${_message}\u001b[39m\u001b[22m` 9 | } 10 | 11 | module.exports = merge( 12 | commonConfiguration, 13 | { 14 | mode: 'development', 15 | devServer: 16 | { 17 | host: '0.0.0.0', 18 | port: portFinderSync.getPort(8080), 19 | contentBase: './dist', 20 | watchContentBase: true, 21 | open: true, 22 | https: false, 23 | useLocalIp: true, 24 | disableHostCheck: true, 25 | overlay: true, 26 | noInfo: true, 27 | after: function(app, server, compiler) 28 | { 29 | const port = server.options.port 30 | const https = server.options.https ? 's' : '' 31 | const localIp = ip.v4.sync() 32 | const domain1 = `http${https}://${localIp}:${port}` 33 | const domain2 = `http${https}://localhost:${port}` 34 | 35 | console.log(`Project running at:\n - ${infoColor(domain1)}\n - ${infoColor(domain2)}`) 36 | } 37 | } 38 | } 39 | ) 40 | -------------------------------------------------------------------------------- /bundler/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge') 2 | const commonConfiguration = require('./webpack.common.js') 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin') 4 | 5 | module.exports = merge( 6 | commonConfiguration, 7 | { 8 | mode: 'production', 9 | plugins: 10 | [ 11 | new CleanWebpackPlugin() 12 | ] 13 | } 14 | ) 15 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "build": "webpack --config ./bundler/webpack.prod.js", 4 | "start": "webpack serve --config ./bundler/webpack.dev.js" 5 | }, 6 | "dependencies": { 7 | "@babel/core": "^7.12.10", 8 | "@babel/preset-env": "^7.12.11", 9 | "babel-loader": "^8.2.2", 10 | "cannon": "^0.6.2", 11 | "cannon-es": "^0.18.0", 12 | "cannon-es-debugger": "^0.1.4", 13 | "clean-webpack-plugin": "^3.0.0", 14 | "copy-to-clipboard": "^3.3.1", 15 | "copy-webpack-plugin": "^7.0.0", 16 | "css-loader": "^5.0.1", 17 | "file-loader": "^6.2.0", 18 | "file-saver": "^2.0.5", 19 | "guify": "^0.12.0", 20 | "html-loader": "^1.3.2", 21 | "html-webpack-plugin": "^5.0.0-alpha.7", 22 | "jszip": "^3.7.0", 23 | "mini-css-extract-plugin": "^1.3.4", 24 | "portfinder-sync": "0.0.2", 25 | "raw-loader": "^4.0.2", 26 | "stats.js": "^0.17.0", 27 | "stringify-object": "^3.3.0", 28 | "style-loader": "^2.0.0", 29 | "three": "^0.124.0", 30 | "three-gltf-exporter": "^0.0.1", 31 | "webpack": "^5.14.0", 32 | "webpack-cli": "^4.3.1", 33 | "webpack-dev-server": "^3.11.2", 34 | "webpack-merge": "^5.7.3" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Raycast Vehicle Engine 2 | 3 | [](https://rv-engine.vercel.app/) 4 | 5 | Simply upload your favourite car's chassis model and car's wheel model and the RV Engine would automatically create a car with the same look and feel. It would also be able to control the car's movement and rotation. Add physics and everything else you want to the car and you're good to go. 6 | After that you can simply download it as a zip file. Follow the same setup procedure, and you have a new raycast vehicle generated. 7 | 8 | ## Features 9 | - Vehicle physics 10 | - Change Vehicle Mass, Suspension Strength, Suspension Damping, etc. 11 | - Change the position of each wheel, set the size of each wheel and have all the controls to yourself. 12 | - Change the max speed of the car, movement controls etc directly from the GUI. 13 | - Position the chassis from GUI, see helper to view the chassis in the physics world. Same goes for all of the wheels. 14 | - Generate code, simply either copy Car.JS code or Download the ZIP file that has everything sitting ready for you. All you need to do is install it using npm once unzipped. 15 | 16 | ## Setup 17 | Download [Node.js](https://nodejs.org/en/download/). 18 | Run this followed commands: 19 | 20 | ``` bash 21 | # Install dependencies (only the first time) 22 | npm install 23 | 24 | # Run the local server at localhost:8080 25 | npm run dev 26 | 27 | # Build for production in the dist/ directory 28 | npm run build 29 | ``` 30 | 31 | ## Built With 32 | - [ThreeJS](https://threejs.org/) - JavaScript 3D library 33 | - [Webpack](https://webpack.js.org/) - Module bundler 34 | - [Babel](https://babeljs.io/) - ES6 to ES5 transpiler 35 | - [Cannon-ES](https://pmndrs.github.io/cannon-es/) - 3D physics engine 36 | - [Guify](https://github.com/colejd/guify) - GUI framework 37 | - [JSZip](https://stuk.github.io/jszip/) - JSZip is a javascript library for creating, reading and editing .zip files, with a lovely and simple API. 38 | - [Stats.JS](https://github.com/mrdoob/stats.js/) - JavaScript Performance Monitor 39 | - [File Saver](https://www.npmjs.com/package/file-saver) - Save files to disk 40 | 41 | ## What's next? 42 | - [ ] Add more physics to the car 43 | - [ ] Add more wheels to the car 44 | - [ ] Add more features to the car 45 | - [ ] Add more car models 46 | - [ ] Add more physics models 47 | - [ ] Add more wheel models 48 | 49 | ### Written by [Jaagrav](https://github.com/Jaagrav) 50 | -------------------------------------------------------------------------------- /src/.index.html.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Jaagrav/raycast-vehicle-engine/2283abb336ae1134e5508db639bc6de773401d79/src/.index.html.swp -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |