├── src ├── assets │ ├── mesh │ │ ├── mesh.obj.manifest │ │ └── mesh.mtl │ └── texture │ │ ├── Thumbs.db │ │ ├── ground.jpg │ │ ├── waterbump.png │ │ └── skybox │ │ ├── Thumbs.db │ │ ├── TropicalSunnyDay_nx.jpg │ │ ├── TropicalSunnyDay_ny.jpg │ │ ├── TropicalSunnyDay_nz.jpg │ │ ├── TropicalSunnyDay_px.jpg │ │ ├── TropicalSunnyDay_py.jpg │ │ └── TropicalSunnyDay_pz.jpg ├── index.ts ├── index.ejs ├── game.ts └── game-utils.ts ├── .gitignore ├── tsconfig.json ├── README.md ├── package.json └── webpack.config.js /src/assets/mesh/mesh.obj.manifest: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .vscode 4 | .idea 5 | *.iml 6 | .gitignore -------------------------------------------------------------------------------- /src/assets/texture/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/Thumbs.db -------------------------------------------------------------------------------- /src/assets/texture/ground.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/ground.jpg -------------------------------------------------------------------------------- /src/assets/texture/waterbump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/waterbump.png -------------------------------------------------------------------------------- /src/assets/texture/skybox/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/Thumbs.db -------------------------------------------------------------------------------- /src/assets/texture/skybox/TropicalSunnyDay_nx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/TropicalSunnyDay_nx.jpg -------------------------------------------------------------------------------- /src/assets/texture/skybox/TropicalSunnyDay_ny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/TropicalSunnyDay_ny.jpg -------------------------------------------------------------------------------- /src/assets/texture/skybox/TropicalSunnyDay_nz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/TropicalSunnyDay_nz.jpg -------------------------------------------------------------------------------- /src/assets/texture/skybox/TropicalSunnyDay_px.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/TropicalSunnyDay_px.jpg -------------------------------------------------------------------------------- /src/assets/texture/skybox/TropicalSunnyDay_py.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/TropicalSunnyDay_py.jpg -------------------------------------------------------------------------------- /src/assets/texture/skybox/TropicalSunnyDay_pz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pandadelphin/babylonjs-typescript-webpack-starter/HEAD/src/assets/texture/skybox/TropicalSunnyDay_pz.jpg -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "target": "es6", 5 | "module": "commonjs", 6 | "noResolve": false, 7 | "noImplicitAny": false, 8 | "sourceMap": true, 9 | "preserveConstEnums": true, 10 | "lib": [ 11 | "dom", 12 | "es6" 13 | ], 14 | "rootDir": "src" 15 | } 16 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import 'babylonjs-loaders'; 2 | import { Game } from './game'; 3 | import CANNON = require('cannon'); 4 | 5 | window.addEventListener('DOMContentLoaded', () => { 6 | // Set global variable for cannonjs physics engine 7 | window.CANNON = CANNON; 8 | let game = new Game('renderCanvas'); 9 | game.createScene(); 10 | game.animate(); 11 | }); 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A starter template for those who want to use the famous javascript 3D game engine babylonjs with typescript and webpack. 2 | 3 | ## How to Start? ## 4 | 5 | 1. Download and Install Node.js 6 | 2. Open Commandline and Enter 7 | ``` 8 | npm install 9 | npm start 10 | ``` 11 | 3. Open Browser and Enter [http://localhost:8080](http://localhost:8080) 12 | 13 | ## Deployable Product Build ## 14 | 1. Build the app 15 | ``` 16 | npm run build 17 | ``` 18 | 2. Deployable app is in dist folder now 19 | -------------------------------------------------------------------------------- /src/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Webpack TypeScript BabylonJS Starter 6 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/assets/mesh/mesh.mtl: -------------------------------------------------------------------------------- 1 | # Blender MTL File: 'Shark.blend' 2 | # Material Count: 3 3 | 4 | newmtl Base 5 | Ns 96.078431 6 | Ka 1.000000 1.000000 1.000000 7 | Kd 0.787908 0.787908 0.787908 8 | Ks 0.500000 0.500000 0.500000 9 | Ke 0.000000 0.000000 0.000000 10 | Ni 1.000000 11 | d 1.000000 12 | illum 2 13 | 14 | newmtl Eye 15 | Ns 96.078431 16 | Ka 1.000000 1.000000 1.000000 17 | Kd 0.015079 0.015079 0.015079 18 | Ks 0.500000 0.500000 0.500000 19 | Ke 0.000000 0.000000 0.000000 20 | Ni 1.000000 21 | d 1.000000 22 | illum 2 23 | 24 | newmtl Top 25 | Ns 96.078431 26 | Ka 1.000000 1.000000 1.000000 27 | Kd 0.321575 0.321575 0.321575 28 | Ks 0.500000 0.500000 0.500000 29 | Ke 0.000000 0.000000 0.000000 30 | Ni 1.000000 31 | d 1.000000 32 | illum 2 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babylonjs-typescript-webpack-starter", 3 | "version": "1.0.0", 4 | "description": "Template for Webpack TypeScript and BabylonJS", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "webpack", 8 | "start": "webpack serve --open" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@types/es6-shim": "^0.31.41", 15 | "clean-webpack-plugin": "^3.0.0", 16 | "copy-webpack-plugin": "^7.0.0", 17 | "css-loader": "^5.1.0", 18 | "html-webpack-plugin": "^5.2.0", 19 | "imports-loader": "^2.0.0", 20 | "style-loader": "^2.0.0", 21 | "ts-loader": "^8.0.17", 22 | "typescript": "^4.2.2", 23 | "webpack": "^5.24.2", 24 | "webpack-cli": "^4.5.0", 25 | "webpack-dev-server": "^3.11.2" 26 | }, 27 | "dependencies": { 28 | "babylonjs": "^4.2.0", 29 | "babylonjs-gui": "^4.2.0", 30 | "babylonjs-loaders": "^4.2.0", 31 | "babylonjs-materials": "^4.2.0", 32 | "cannon": "^0.6.2", 33 | "earcut": "^2.2.2", 34 | "lodash": "^4.17.21", 35 | "oimo": "^1.0.9", 36 | "rxjs": "^6.6.6" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | // Optimizes duplicates in splitted bundles 3 | const webpack = require('webpack'); 4 | // creates index.html file by a template index.ejs 5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 6 | // cleans dist folder 7 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 8 | // copies the assets folder into dist folder 9 | const CopyWebpackPlugin = require('copy-webpack-plugin'); 10 | // output folder location 11 | const distFolder = "./dist"; 12 | 13 | module.exports = { 14 | mode: 'development', 15 | entry: './src/index.ts', 16 | plugins: [ 17 | new CleanWebpackPlugin(), 18 | new HtmlWebpackPlugin({ 19 | template: 'src/index.ejs' 20 | }), 21 | new CopyWebpackPlugin({ 22 | patterns: [ 23 | { from: 'src/assets', to: 'assets' }, 24 | ] 25 | }) 26 | ], 27 | devtool: 'inline-source-map', 28 | devServer: { 29 | contentBase: distFolder 30 | }, 31 | module: { 32 | rules: [ 33 | { 34 | test: /\.tsx?$/, 35 | use: 'ts-loader', 36 | exclude: /node_modules/ 37 | }, 38 | { 39 | test: /\.css$/, 40 | use: [ 41 | 'style-loader', 42 | 'css-loader' 43 | ] 44 | } 45 | ] 46 | }, 47 | optimization: { 48 | splitChunks: { 49 | cacheGroups: { 50 | commons: { 51 | test: /[\\/]node_modules[\\/]/, 52 | name: "vendors", 53 | chunks: "all" 54 | } 55 | } 56 | } 57 | }, 58 | resolve: { 59 | extensions: [".tsx", ".ts", ".js"] 60 | }, 61 | output: { 62 | filename: '[name].bundle.js', 63 | path: path.resolve(__dirname, distFolder) 64 | } 65 | }; -------------------------------------------------------------------------------- /src/game.ts: -------------------------------------------------------------------------------- 1 | import { GameUtils } from './game-utils'; 2 | import * as BABYLON from 'babylonjs'; 3 | import * as GUI from 'babylonjs-gui'; 4 | 5 | export class Game { 6 | 7 | private _canvas: HTMLCanvasElement; 8 | private _engine: BABYLON.Engine; 9 | private _scene: BABYLON.Scene; 10 | private _camera: BABYLON.ArcRotateCamera; 11 | private _light: BABYLON.Light; 12 | private _sharkMesh: BABYLON.AbstractMesh; 13 | private _sharkAnimationTime = 0; 14 | private _swim: boolean = false; 15 | private _txtCoordinates: { txtX: GUI.TextBlock, txtY: GUI.TextBlock, txtZ: GUI.TextBlock } = null; 16 | 17 | constructor(canvasElement: string) { 18 | // Create canvas and engine 19 | this._canvas = document.getElementById(canvasElement); 20 | this._engine = new BABYLON.Engine(this._canvas, true); 21 | } 22 | 23 | /** 24 | * Creates the BABYLONJS Scene 25 | */ 26 | createScene(): void { 27 | // create a basic BJS Scene object 28 | this._scene = new BABYLON.Scene(this._engine); 29 | // create a FreeCamera, and set its position to (x:0, y:5, z:-10) 30 | this._camera = new BABYLON.ArcRotateCamera("Camera", 3 * Math.PI / 2, Math.PI / 4, 30, BABYLON.Vector3.Zero(), this._scene); 31 | this._camera.attachControl(this._canvas, true); 32 | // create a basic light, aiming 0,1,0 - meaning, to the sky 33 | this._light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), this._scene); 34 | // create the skybox 35 | let skybox = GameUtils.createSkybox("skybox", "./assets/texture/skybox/TropicalSunnyDay", this._scene); 36 | // creates the sandy ground 37 | let ground = GameUtils.createGround(this._scene); 38 | // creates the watermaterial and adds the relevant nodes to the renderlist 39 | let waterMaterial = GameUtils.createWater(this._scene); 40 | waterMaterial.addToRenderList(skybox); 41 | waterMaterial.addToRenderList(ground); 42 | // create a shark mesh from a .obj file 43 | GameUtils.createShark(this._scene) 44 | .subscribe(sharkMesh => { 45 | this._sharkMesh = sharkMesh; 46 | this._sharkMesh.getChildren().forEach( 47 | mesh => { 48 | waterMaterial.addToRenderList(mesh); 49 | } 50 | ); 51 | }); 52 | // finally the new ui 53 | let guiTexture = GameUtils.createGUI(); 54 | 55 | // Button to start shark animation 56 | GameUtils.createButtonSwim(guiTexture, "Start Swimming", 57 | (btn) => { 58 | let textControl = btn.children[0] as GUI.TextBlock; 59 | this._swim = !this._swim; 60 | if (this._swim) { 61 | textControl.text = "Stop Swimming"; 62 | } 63 | else { 64 | this._sharkAnimationTime = 0; 65 | textControl.text = "Start Swimming"; 66 | } 67 | }); 68 | 69 | // Debug Text for Shark coordinates 70 | this._txtCoordinates = GameUtils.createCoordinatesText(guiTexture); 71 | 72 | // Physics engine also works 73 | let gravity = new BABYLON.Vector3(0, -0.9, 0); 74 | this._scene.enablePhysics(gravity, new BABYLON.CannonJSPlugin()); 75 | } 76 | 77 | 78 | /** 79 | * Starts the animation loop. 80 | */ 81 | animate(): void { 82 | this._scene.registerBeforeRender(() => { 83 | let deltaTime: number = (1 / this._engine.getFps()); 84 | this.animateShark(deltaTime); 85 | }); 86 | 87 | // run the render loop 88 | this._engine.runRenderLoop(() => { 89 | this._scene.render(); 90 | }); 91 | 92 | // the canvas/window resize event handler 93 | window.addEventListener('resize', () => { 94 | this._engine.resize(); 95 | }); 96 | } 97 | 98 | animateShark(deltaTime: number): void { 99 | this.debugFirstMeshCoordinate(this._sharkMesh as BABYLON.Mesh); 100 | if (this._sharkMesh && this._swim) { 101 | this._sharkAnimationTime += deltaTime; 102 | this._sharkMesh.getChildren().forEach( 103 | mesh => { 104 | let realMesh = mesh; 105 | let vertexData = BABYLON.VertexData.ExtractFromMesh(realMesh); 106 | let positions = vertexData.positions; 107 | let numberOfPoints = positions.length / 3; 108 | for (let i = 0; i < numberOfPoints; i++) { 109 | let vertex = new BABYLON.Vector3(positions[i * 3], positions[i * 3 + 1], positions[i * 3 + 2]); 110 | vertex.x += (Math.sin(0.15 * vertex.z + this._sharkAnimationTime * 4 - 1.6) * 0.05); 111 | positions[i * 3] = vertex.x; 112 | 113 | } 114 | vertexData.applyToMesh(mesh as BABYLON.Mesh); 115 | } 116 | ); 117 | } 118 | } 119 | 120 | /** 121 | * Prints the coordinates of the first vertex of a mesh 122 | */ 123 | public debugFirstMeshCoordinate(mesh: BABYLON.Mesh) { 124 | if(!mesh || !mesh.getChildren()) { 125 | return; 126 | } 127 | let firstMesh = (mesh.getChildren()[0] as BABYLON.Mesh) 128 | let vertexData = BABYLON.VertexData.ExtractFromMesh(firstMesh); 129 | let positions = vertexData.positions; 130 | let firstVertex = new BABYLON.Vector3(positions[0], positions[1], positions[3]); 131 | this.updateCoordinateTexture(firstVertex); 132 | } 133 | 134 | /** 135 | * Prints the given Vector3 136 | * @param coordinates 137 | */ 138 | public updateCoordinateTexture(coordinates: BABYLON.Vector3) { 139 | if(!coordinates) { 140 | return; 141 | } 142 | this._txtCoordinates.txtX.text = "X: " + coordinates.x; 143 | this._txtCoordinates.txtY.text = "Y: " + coordinates.y; 144 | this._txtCoordinates.txtZ.text = "Z: " + coordinates.z; 145 | } 146 | 147 | } -------------------------------------------------------------------------------- /src/game-utils.ts: -------------------------------------------------------------------------------- 1 | import * as BABYLON from 'babylonjs'; 2 | import * as MATERIAL from 'babylonjs-materials'; 3 | import * as GUI from 'babylonjs-gui'; 4 | import { Observable } from 'rxjs'; 5 | import { map } from 'rxjs/operators'; 6 | 7 | export class GameUtils { 8 | 9 | /** 10 | * Creates a basic ground 11 | * @param scene 12 | */ 13 | public static createGround(scene: BABYLON.Scene): BABYLON.Mesh { 14 | // Ground 15 | let groundMaterial = new BABYLON.StandardMaterial("groundMaterial", scene); 16 | groundMaterial.diffuseTexture = new BABYLON.Texture("./assets/texture/ground.jpg", scene); 17 | //groundMaterial.diffuseTexture.uScale = groundMaterial.diffuseTexture.vScale = 4; 18 | let ground = BABYLON.Mesh.CreateGround("ground", 512, 512, 32, scene, false); 19 | ground.position.y = -1; 20 | ground.material = groundMaterial; 21 | 22 | return ground; 23 | } 24 | 25 | /** 26 | * Creates a second ground and adds a watermaterial to it 27 | * @param scene 28 | */ 29 | public static createWater(scene: BABYLON.Scene): MATERIAL.WaterMaterial { 30 | // Water 31 | let waterMesh = BABYLON.Mesh.CreateGround("waterMesh", 512, 512, 32, scene, false); 32 | let waterMaterial = GameUtils.createWaterMaterial("water", "./assets/texture/waterbump.png", scene); 33 | waterMesh.material = waterMaterial; 34 | waterMesh.position.y = 4; 35 | 36 | return waterMaterial; 37 | } 38 | 39 | /** 40 | * Creates a Gui Texture 41 | */ 42 | public static createGUI() { 43 | return GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI"); 44 | } 45 | 46 | /** 47 | * Creates a Button that tells the Shark to swim or not 48 | * @param guiTexture 49 | * @param btnText 50 | * @param btnClicked 51 | */ 52 | public static createButtonSwim(guiTexture: GUI.AdvancedDynamicTexture, btnText: string, btnClicked: (button: GUI.Button) => void) { 53 | 54 | let btnTest = GUI.Button.CreateSimpleButton("but1", btnText); 55 | btnTest.width = "150px"; 56 | btnTest.height = "40px"; 57 | btnTest.color = "white"; 58 | btnTest.background = "grey"; 59 | btnTest.onPointerUpObservable.add(() => { 60 | if (btnClicked) { 61 | btnClicked(btnTest); 62 | } 63 | }); 64 | btnTest.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 65 | btnTest.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 66 | btnTest.left = 12; 67 | btnTest.top = 12; 68 | 69 | guiTexture.addControl(btnTest); 70 | } 71 | 72 | public static createVerticalLine(scene: BABYLON.Scene, position: BABYLON.Vector2) { 73 | //Array of points to construct lines 74 | var myPoints = [ 75 | new BABYLON.Vector3(position.x, 0, position.y), 76 | new BABYLON.Vector3(position.x, 100, position.y), 77 | ]; 78 | //Create lines 79 | var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, scene); 80 | } 81 | 82 | /** 83 | * 84 | * @param guiTexture 85 | */ 86 | public static createCoordinatesText(guiTexture: GUI.AdvancedDynamicTexture): { txtX: GUI.TextBlock, txtY: GUI.TextBlock, txtZ: GUI.TextBlock } { 87 | let txtX = new GUI.TextBlock(); 88 | txtX.height = "20px"; 89 | txtX.width = "500px"; 90 | txtX.fontSize = 20; 91 | txtX.text = "X: "; 92 | txtX.textHorizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 93 | txtX.textVerticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 94 | txtX.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 95 | txtX.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 96 | txtX.left = 20; 97 | txtX.top = 60; 98 | 99 | let txtY = new GUI.TextBlock(); 100 | txtY.height = "20px"; 101 | txtY.width = "500px"; 102 | txtY.fontSize = 20; 103 | txtY.text = "Y: "; 104 | txtY.textHorizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 105 | txtY.textVerticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 106 | txtY.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 107 | txtY.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 108 | txtY.left = 20; 109 | txtY.top = 90; 110 | 111 | let txtZ = new GUI.TextBlock(); 112 | txtZ.height = "20px"; 113 | txtZ.width = "500px"; 114 | txtZ.fontSize = 20; 115 | txtZ.text = "Z: "; 116 | txtZ.textHorizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 117 | txtZ.textVerticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 118 | txtZ.horizontalAlignment = GUI.Control.HORIZONTAL_ALIGNMENT_LEFT; 119 | txtZ.verticalAlignment = GUI.Control.VERTICAL_ALIGNMENT_TOP; 120 | txtZ.left = 20; 121 | txtZ.top = 120; 122 | 123 | guiTexture.addControl(txtX); 124 | guiTexture.addControl(txtY); 125 | guiTexture.addControl(txtZ); 126 | 127 | return { 128 | txtX: txtX, 129 | txtY: txtY, 130 | txtZ: txtZ 131 | } 132 | } 133 | 134 | /** 135 | * Returns Observable of mesh array, which are loaded from a file. 136 | * After mesh importing all meshes become given scaling, position and rotation. 137 | * @param fileName 138 | * @param scene 139 | * @param scaling 140 | * @param position 141 | * @param rotationQuaternion 142 | */ 143 | public static createMeshFromObjFile(folderName: string, fileName: string, scene: BABYLON.Scene, 144 | scaling?: BABYLON.Vector3, position?: BABYLON.Vector3, rotationQuaternion?: BABYLON.Quaternion): Observable { 145 | 146 | if (!fileName) { 147 | return Observable.throw("GameUtils.createMeshFromObjFile: parameter fileName is empty"); 148 | } 149 | if (!scene) { 150 | return Observable.throw("GameUtils.createMeshFromObjFile: parameter scene is empty"); 151 | } 152 | 153 | if (!folderName) folderName = ""; 154 | if (!scaling) scaling = BABYLON.Vector3.One(); 155 | if (!position) position = BABYLON.Vector3.Zero(); 156 | if (!rotationQuaternion) rotationQuaternion = BABYLON.Quaternion.RotationYawPitchRoll(0, 0, 0); 157 | 158 | let assetsFolder = './assets/' + folderName; 159 | 160 | return Observable.create(observer => { 161 | BABYLON.SceneLoader.ImportMesh(null, assetsFolder, fileName, scene, 162 | (meshes: BABYLON.AbstractMesh[], 163 | particleSystems: BABYLON.ParticleSystem[], 164 | skeletons: BABYLON.Skeleton[]) => { 165 | meshes.forEach((mesh) => { 166 | mesh.position = position; 167 | mesh.rotationQuaternion = rotationQuaternion; 168 | mesh.scaling = scaling; 169 | }); 170 | console.log("Imported Mesh: " + fileName); 171 | observer.next(meshes); 172 | observer.complete(); 173 | }); 174 | }); 175 | } 176 | 177 | /** 178 | * Creates a new skybox with the picttures under fileName. 179 | * @param name 180 | * @param fileName 181 | * @param scene 182 | */ 183 | public static createSkybox(name: string, fileName: string, scene: BABYLON.Scene): BABYLON.Mesh { 184 | if (!name) { 185 | console.error("GameUtils.createSkyBox: name is not defined"); 186 | return; 187 | } 188 | if (!fileName) { 189 | console.error("GameUtils.createSkyBox: fileName is not defined"); 190 | return; 191 | } 192 | if (!scene) { 193 | console.error("GameUtils.createSkyBox: scene is not defined"); 194 | return; 195 | } 196 | 197 | // Skybox 198 | let skybox = BABYLON.Mesh.CreateBox(name, 1000.0, scene); 199 | let skyboxMaterial = new BABYLON.StandardMaterial(name, scene); 200 | skyboxMaterial.backFaceCulling = false; 201 | skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture("./assets/texture/skybox/TropicalSunnyDay", scene); 202 | skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE; 203 | skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0); 204 | skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0); 205 | skyboxMaterial.disableLighting = true; 206 | skybox.material = skyboxMaterial; 207 | } 208 | 209 | /** 210 | * Creates a new WaterMaterial Object with a given name. The noiseFile descrips the noise in the water, 211 | * @param name 212 | * @param noiseFile 213 | * @param scene 214 | */ 215 | public static createWaterMaterial(name: string, noiseFile: string, scene: BABYLON.Scene): MATERIAL.WaterMaterial { 216 | if (!name) { 217 | console.error("GameUtils.createWaterMaterial: name is not defined"); 218 | return; 219 | } 220 | if (!noiseFile) { 221 | console.error("GameUtils.createWaterMaterial: noiseFile is not defined"); 222 | return; 223 | } 224 | if (!scene) { 225 | console.error("GameUtils.createWaterMaterial: scene is not defined"); 226 | return; 227 | } 228 | // Water material 229 | let water = new MATERIAL.WaterMaterial(name, scene); 230 | water.bumpTexture = new BABYLON.Texture(noiseFile, scene); 231 | // Water properties 232 | water.windForce = -15; 233 | water.waveHeight = 0; 234 | water.windDirection = new BABYLON.Vector2(1, 1); 235 | water.waterColor = new BABYLON.Color3(0.25, 0.88, 0.82); 236 | water.colorBlendFactor = 0.3; 237 | water.bumpHeight = 0.1; 238 | water.waveLength = 0.1; 239 | 240 | return water 241 | } 242 | 243 | /** 244 | * Loads a shark model from .obj file and adds it scene. 245 | * @param scene 246 | */ 247 | public static createShark(scene: BABYLON.Scene): Observable { 248 | // create a mesh object with loaded from file 249 | let rootMesh = BABYLON.MeshBuilder.CreateBox("rootMesh", {size: 1}, scene); 250 | rootMesh.isVisible = false; 251 | rootMesh.position = new BABYLON.Vector3(0, 0.4, 0); 252 | rootMesh.rotation.y = -3 * Math.PI / 4; 253 | 254 | return GameUtils.createMeshFromObjFile("mesh/", "mesh.obj", scene, new BABYLON.Vector3(1, 1, 1)) 255 | .pipe( 256 | map(meshes => { 257 | meshes.forEach((mesh) => { 258 | mesh.parent = rootMesh; 259 | }); 260 | return rootMesh; 261 | }) 262 | ); 263 | } 264 | 265 | } --------------------------------------------------------------------------------