main.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
  2. import {FBXLoader} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/FBXLoader.js';
  3. import {GLTFLoader} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/loaders/GLTFLoader.js';
  4. import {OrbitControls} from 'https://cdn.jsdelivr.net/npm/[email protected]/examples/jsm/controls/OrbitControls.js';
  5. class BasicCharacterControls {
  6. constructor(params) {
  7. this._Init(params);
  8. }
  9. _Init(params) {
  10. this._params = params;
  11. this._move = {
  12. forward: false,
  13. backward: false,
  14. left: false,
  15. right: false,
  16. };
  17. this._decceleration = new THREE.Vector3(-0.0005, -0.0001, -5.0);
  18. this._acceleration = new THREE.Vector3(1, 0.25, 50.0);
  19. this._velocity = new THREE.Vector3(0, 0, 0);
  20. document.addEventListener('keydown', (e) => this._onKeyDown(e), false);
  21. document.addEventListener('keyup', (e) => this._onKeyUp(e), false);
  22. }
  23. _onKeyDown(event) {
  24. switch (event.keyCode) {
  25. case 87: // w
  26. this._move.forward = true;
  27. break;
  28. case 65: // a
  29. this._move.left = true;
  30. break;
  31. case 83: // s
  32. this._move.backward = true;
  33. break;
  34. case 68: // d
  35. this._move.right = true;
  36. break;
  37. case 38: // up
  38. case 37: // left
  39. case 40: // down
  40. case 39: // right
  41. break;
  42. }
  43. }
  44. _onKeyUp(event) {
  45. switch(event.keyCode) {
  46. case 87: // w
  47. this._move.forward = false;
  48. break;
  49. case 65: // a
  50. this._move.left = false;
  51. break;
  52. case 83: // s
  53. this._move.backward = false;
  54. break;
  55. case 68: // d
  56. this._move.right = false;
  57. break;
  58. case 38: // up
  59. case 37: // left
  60. case 40: // down
  61. case 39: // right
  62. break;
  63. }
  64. }
  65. Update(timeInSeconds) {
  66. const velocity = this._velocity;
  67. const frameDecceleration = new THREE.Vector3(
  68. velocity.x * this._decceleration.x,
  69. velocity.y * this._decceleration.y,
  70. velocity.z * this._decceleration.z
  71. );
  72. frameDecceleration.multiplyScalar(timeInSeconds);
  73. frameDecceleration.z = Math.sign(frameDecceleration.z) * Math.min(
  74. Math.abs(frameDecceleration.z), Math.abs(velocity.z));
  75. velocity.add(frameDecceleration);
  76. const controlObject = this._params.target;
  77. const _Q = new THREE.Quaternion();
  78. const _A = new THREE.Vector3();
  79. const _R = controlObject.quaternion.clone();
  80. if (this._move.forward) {
  81. velocity.z += this._acceleration.z * timeInSeconds;
  82. }
  83. if (this._move.backward) {
  84. velocity.z -= this._acceleration.z * timeInSeconds;
  85. }
  86. if (this._move.left) {
  87. _A.set(0, 1, 0);
  88. _Q.setFromAxisAngle(_A, Math.PI * timeInSeconds * this._acceleration.y);
  89. _R.multiply(_Q);
  90. }
  91. if (this._move.right) {
  92. _A.set(0, 1, 0);
  93. _Q.setFromAxisAngle(_A, -Math.PI * timeInSeconds * this._acceleration.y);
  94. _R.multiply(_Q);
  95. }
  96. controlObject.quaternion.copy(_R);
  97. const oldPosition = new THREE.Vector3();
  98. oldPosition.copy(controlObject.position);
  99. const forward = new THREE.Vector3(0, 0, 1);
  100. forward.applyQuaternion(controlObject.quaternion);
  101. forward.normalize();
  102. const sideways = new THREE.Vector3(1, 0, 0);
  103. sideways.applyQuaternion(controlObject.quaternion);
  104. sideways.normalize();
  105. sideways.multiplyScalar(velocity.x * timeInSeconds);
  106. forward.multiplyScalar(velocity.z * timeInSeconds);
  107. controlObject.position.add(forward);
  108. controlObject.position.add(sideways);
  109. oldPosition.copy(controlObject.position);
  110. }
  111. }
  112. class LoadModelDemo {
  113. constructor() {
  114. this._Initialize();
  115. }
  116. _Initialize() {
  117. this._threejs = new THREE.WebGLRenderer({
  118. antialias: true,
  119. });
  120. this._threejs.shadowMap.enabled = true;
  121. this._threejs.shadowMap.type = THREE.PCFSoftShadowMap;
  122. this._threejs.setPixelRatio(window.devicePixelRatio);
  123. this._threejs.setSize(window.innerWidth, window.innerHeight);
  124. document.body.appendChild(this._threejs.domElement);
  125. window.addEventListener('resize', () => {
  126. this._OnWindowResize();
  127. }, false);
  128. const fov = 60;
  129. const aspect = 1920 / 1080;
  130. const near = 1.0;
  131. const far = 1000.0;
  132. this._camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  133. this._camera.position.set(75, 20, 0);
  134. this._scene = new THREE.Scene();
  135. let light = new THREE.DirectionalLight(0xFFFFFF, 1.0);
  136. light.position.set(20, 100, 10);
  137. light.target.position.set(0, 0, 0);
  138. light.castShadow = true;
  139. light.shadow.bias = -0.001;
  140. light.shadow.mapSize.width = 2048;
  141. light.shadow.mapSize.height = 2048;
  142. light.shadow.camera.near = 0.1;
  143. light.shadow.camera.far = 500.0;
  144. light.shadow.camera.near = 0.5;
  145. light.shadow.camera.far = 500.0;
  146. light.shadow.camera.left = 100;
  147. light.shadow.camera.right = -100;
  148. light.shadow.camera.top = 100;
  149. light.shadow.camera.bottom = -100;
  150. this._scene.add(light);
  151. light = new THREE.AmbientLight(0xFFFFFF, 4.0);
  152. this._scene.add(light);
  153. const controls = new OrbitControls(
  154. this._camera, this._threejs.domElement);
  155. controls.target.set(0, 20, 0);
  156. controls.update();
  157. const loader = new THREE.CubeTextureLoader();
  158. const texture = loader.load([
  159. './resources/posx.jpg',
  160. './resources/negx.jpg',
  161. './resources/posy.jpg',
  162. './resources/negy.jpg',
  163. './resources/posz.jpg',
  164. './resources/negz.jpg',
  165. ]);
  166. this._scene.background = texture;
  167. const plane = new THREE.Mesh(
  168. new THREE.PlaneGeometry(100, 100, 10, 10),
  169. new THREE.MeshStandardMaterial({
  170. color: 0x202020,
  171. }));
  172. plane.castShadow = false;
  173. plane.receiveShadow = true;
  174. plane.rotation.x = -Math.PI / 2;
  175. this._scene.add(plane);
  176. this._mixers = [];
  177. this._previousRAF = null;
  178. this._LoadAnimatedModel();
  179. // this._LoadAnimatedModelAndPlay(
  180. // './resources/dancer/', 'girl.fbx', 'dance.fbx', new THREE.Vector3(0, -1.5, 5));
  181. // this._LoadAnimatedModelAndPlay(
  182. // './resources/dancer/', 'dancer.fbx', 'Silly Dancing.fbx', new THREE.Vector3(12, 0, -10));
  183. // this._LoadAnimatedModelAndPlay(
  184. // './resources/dancer/', 'dancer.fbx', 'Silly Dancing.fbx', new THREE.Vector3(-12, 0, -10));
  185. this._RAF();
  186. }
  187. _LoadAnimatedModel() {
  188. const loader = new FBXLoader();
  189. loader.setPath('./resources/zombie/');
  190. loader.load('mremireh_o_desbiens.fbx', (fbx) => {
  191. fbx.scale.setScalar(0.1);
  192. fbx.traverse(c => {
  193. c.castShadow = true;
  194. });
  195. const params = {
  196. target: fbx,
  197. camera: this._camera,
  198. }
  199. this._controls = new BasicCharacterControls(params);
  200. const anim = new FBXLoader();
  201. anim.setPath('./resources/zombie/');
  202. anim.load('walk.fbx', (anim) => {
  203. const m = new THREE.AnimationMixer(fbx);
  204. this._mixers.push(m);
  205. const idle = m.clipAction(anim.animations[0]);
  206. idle.play();
  207. });
  208. this._scene.add(fbx);
  209. });
  210. }
  211. _LoadAnimatedModelAndPlay(path, modelFile, animFile, offset) {
  212. const loader = new FBXLoader();
  213. loader.setPath(path);
  214. loader.load(modelFile, (fbx) => {
  215. fbx.scale.setScalar(0.1);
  216. fbx.traverse(c => {
  217. c.castShadow = true;
  218. });
  219. fbx.position.copy(offset);
  220. const anim = new FBXLoader();
  221. anim.setPath(path);
  222. anim.load(animFile, (anim) => {
  223. const m = new THREE.AnimationMixer(fbx);
  224. this._mixers.push(m);
  225. const idle = m.clipAction(anim.animations[0]);
  226. idle.play();
  227. });
  228. this._scene.add(fbx);
  229. });
  230. }
  231. _LoadModel() {
  232. const loader = new GLTFLoader();
  233. loader.load('./resources/thing.glb', (gltf) => {
  234. gltf.scene.traverse(c => {
  235. c.castShadow = true;
  236. });
  237. this._scene.add(gltf.scene);
  238. });
  239. }
  240. _OnWindowResize() {
  241. this._camera.aspect = window.innerWidth / window.innerHeight;
  242. this._camera.updateProjectionMatrix();
  243. this._threejs.setSize(window.innerWidth, window.innerHeight);
  244. }
  245. _RAF() {
  246. requestAnimationFrame((t) => {
  247. if (this._previousRAF === null) {
  248. this._previousRAF = t;
  249. }
  250. this._RAF();
  251. this._threejs.render(this._scene, this._camera);
  252. this._Step(t - this._previousRAF);
  253. this._previousRAF = t;
  254. });
  255. }
  256. _Step(timeElapsed) {
  257. const timeElapsedS = timeElapsed * 0.001;
  258. if (this._mixers) {
  259. this._mixers.map(m => m.update(timeElapsedS));
  260. }
  261. if (this._controls) {
  262. this._controls.Update(timeElapsedS);
  263. }
  264. }
  265. }
  266. let _APP = null;
  267. window.addEventListener('DOMContentLoaded', () => {
  268. _APP = new LoadModelDemo();
  269. });