├── .gitignore
├── README.md
├── Web.config
├── WebGLFPS.sln
├── api
└── resources.ashx
├── css
└── bootstrap-darkly.min.css
├── dev
└── notes.txt
├── editor.html
├── fonts
├── glyphicons-halflings-regular.eot
├── glyphicons-halflings-regular.svg
├── glyphicons-halflings-regular.ttf
├── glyphicons-halflings-regular.woff
└── glyphicons-halflings-regular.woff2
├── html
└── editor
│ ├── directives
│ ├── actor-editor.html
│ ├── choose-actor-modal.html
│ ├── choose-controller-modal.html
│ ├── choose-resource-modal.html
│ ├── light-editor.html
│ ├── material-editor.html
│ ├── object-data-editor.html
│ ├── trigger-editor.html
│ └── vec3-editor.html
│ ├── main.html
│ └── tabs
│ ├── actors.html
│ ├── lights.html
│ ├── map.html
│ ├── player.html
│ ├── resources.html
│ └── triggers.html
├── index.html
├── js
├── editor
│ ├── controllers
│ │ ├── actors-controller.js
│ │ ├── editor-controller.js
│ │ ├── lights-controller.js
│ │ ├── map-controller.js
│ │ ├── rendering-controller.js
│ │ ├── resources-controller.js
│ │ └── triggers-controller.js
│ ├── directives
│ │ ├── actor-editor.js
│ │ ├── choose-actor-modal.js
│ │ ├── choose-controller-modal.js
│ │ ├── choose-resource-modal.js
│ │ ├── light-editor.js
│ │ ├── material-editor.js
│ │ ├── object-data-editor.js
│ │ ├── trigger-editor.js
│ │ └── vec3-editor.js
│ ├── editor-app.js
│ └── services
│ │ ├── sector-set-builder.js
│ │ ├── util.js
│ │ └── ws.js
├── engine
│ ├── bit-field.js
│ ├── camera.js
│ ├── canvas-initialiser.js
│ ├── constants.js
│ ├── editor-helper.js
│ ├── effect-manager.js
│ ├── engine.js
│ ├── fixed-length-array.js
│ ├── frame-timer.js
│ ├── free-look-camera-controller.js
│ ├── gl-manager.js
│ ├── gui-draw-spec-builder.js
│ ├── gui-layout-animation-manager.js
│ ├── gui-layout-manager.js
│ ├── keyboard.js
│ ├── line-drawer.js
│ ├── map-data-helper.js
│ ├── map-manager.js
│ ├── material-manager.js
│ ├── math
│ │ ├── math-3d.js
│ │ ├── math-aabb.js
│ │ ├── math-collision-face.js
│ │ ├── math-collision-line.js
│ │ ├── math-frustum.js
│ │ ├── math-plane.js
│ │ ├── math-ray.js
│ │ ├── math-sphere.js
│ │ └── math-types.js
│ ├── mouse.js
│ ├── particle-manager.js
│ ├── physics-manager.js
│ ├── player-controller.js
│ ├── render-state-manager.js
│ ├── renderer.js
│ ├── resource-checker.js
│ ├── resource-loader.js
│ ├── shadow-map-manager.js
│ ├── skinned-mesh-animation-manager.js
│ ├── skinned-mesh-manager.js
│ ├── sprite-sheet-manager.js
│ ├── static-mesh-manager.js
│ ├── static-mesh-math-helper.js
│ ├── texture-manager.js
│ ├── ticker.js
│ ├── trigger-manager.js
│ ├── unit-tests.js
│ ├── util.js
│ └── visibility-manager.js
├── game
│ └── main.js
└── lib
│ ├── angular.min.js
│ ├── bootstrap.min.js
│ ├── gl-matrix-min.js
│ ├── gl-matrix.js
│ └── jquery.min.js
└── resources
├── gui-layouts
└── hud.json
├── maps
├── test-map-1.json
└── test-map-2.json
├── materials
├── brick-wall-1.json
├── pipe-1.json
└── tiled-floor-1.json
├── sector-sets
├── test-map-1.json
└── test-map-2.json
├── shaders
├── gui-fs.txt
├── gui-vs.txt
├── line-fs.txt
├── line-vs.txt
├── particle-fs.txt
├── particle-vs.txt
├── skinned-mesh-main-render-fs.txt
├── skinned-mesh-main-render-vs.txt
├── skinned-mesh-shadow-map-build-back-pass-fs.txt
├── skinned-mesh-shadow-map-build-back-pass-vs.txt
├── skinned-mesh-shadow-map-build-front-pass-fs.txt
├── skinned-mesh-shadow-map-build-front-pass-vs.txt
├── static-mesh-main-render-fs.txt
├── static-mesh-main-render-vs.txt
├── static-mesh-shadow-map-build-back-pass-fs.txt
├── static-mesh-shadow-map-build-back-pass-vs.txt
├── static-mesh-shadow-map-build-front-pass-fs.txt
└── static-mesh-shadow-map-build-front-pass-vs.txt
├── skinned-mesh-animations
├── column-bend.json
└── robot-walk.json
├── skinned-meshes
├── column.json
└── robot.json
├── sprite-sheets
└── sprite-sheet-1.json
├── static-meshes
├── door-1.json
├── fancy-cube.json
├── test-map-1.json
└── test-map-2.json
├── system
└── effects.json
└── textures
├── brick-wall-1-d.png
├── brick-wall-1-n.png
├── light-1.png
├── particle-1.png
├── particle-2.png
├── pipe-1-d.png
├── pipe-1-n.png
├── sprite-sheet-1.png
├── system
├── dummy-cube-nx.png
├── dummy-cube-ny.png
├── dummy-cube-nz.png
├── dummy-cube-px.png
├── dummy-cube-py.png
├── dummy-cube-pz.png
├── missing-diffuse-texture.png
└── missing-normal-texture.png
├── tiled-floor-1-d.png
└── tiled-floor-1-n.png
/.gitignore:
--------------------------------------------------------------------------------
1 | /.vs
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # wegl-fps
2 | This is my attempt to build a rundimentary first person shooter in WebGL. It's very much a work in progress, so don't judge me!
3 |
--------------------------------------------------------------------------------
/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/WebGLFPS.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "wegl-fps", ".", "{6EA9508A-A82C-4AFC-B0D8-7BCEFE12D4E6}"
7 | ProjectSection(WebsiteProperties) = preProject
8 | TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
9 | Debug.AspNetCompiler.VirtualPath = "/localhost_50116"
10 | Debug.AspNetCompiler.PhysicalPath = "..\wegl-fps\"
11 | Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_50116\"
12 | Debug.AspNetCompiler.Updateable = "true"
13 | Debug.AspNetCompiler.ForceOverwrite = "true"
14 | Debug.AspNetCompiler.FixedNames = "false"
15 | Debug.AspNetCompiler.Debug = "True"
16 | Release.AspNetCompiler.VirtualPath = "/localhost_50116"
17 | Release.AspNetCompiler.PhysicalPath = "..\wegl-fps\"
18 | Release.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_50116\"
19 | Release.AspNetCompiler.Updateable = "true"
20 | Release.AspNetCompiler.ForceOverwrite = "true"
21 | Release.AspNetCompiler.FixedNames = "false"
22 | Release.AspNetCompiler.Debug = "False"
23 | VWDPort = "50116"
24 | SlnRelativePath = "..\wegl-fps\"
25 | EndProjectSection
26 | EndProject
27 | Global
28 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
29 | Debug|Any CPU = Debug|Any CPU
30 | EndGlobalSection
31 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
32 | {6EA9508A-A82C-4AFC-B0D8-7BCEFE12D4E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {6EA9508A-A82C-4AFC-B0D8-7BCEFE12D4E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | EndGlobalSection
35 | GlobalSection(SolutionProperties) = preSolution
36 | HideSolutionNode = FALSE
37 | EndGlobalSection
38 | EndGlobal
39 |
--------------------------------------------------------------------------------
/api/resources.ashx:
--------------------------------------------------------------------------------
1 | <%@ WebHandler Language="C#" Class="ResourceApiHandler" %>
2 |
3 | using System;
4 | using System.Web;
5 | using System.IO;
6 | using System.Linq;
7 |
8 | public class ResourceApiHandler : IHttpHandler {
9 |
10 | public void ProcessRequest(HttpContext context)
11 | {
12 | string action = HttpContext.Current.Request["action"];
13 |
14 | if (action == "load-resource-id-list")
15 | {
16 | DoLoadResourceIdList();
17 | }
18 | else if (action == "save-json-resource")
19 | {
20 | DoSaveJsonResource();
21 | }
22 | }
23 |
24 | private void DoLoadResourceIdList()
25 | {
26 | string folder = HttpContext.Current.Request["folder"];
27 |
28 | string folderPath = GetFolderPath(folder);
29 |
30 | string[] resourceIds = Directory.GetFiles(folderPath, "*.*", SearchOption.AllDirectories)
31 | .Select(s => s.Replace(folderPath, "").Replace(Path.GetExtension(s), "").Replace("\\", "/"))
32 | .ToArray();
33 |
34 | string json = "[" + string.Join(", ", resourceIds.Select(id => "\"" + id + "\"").ToArray()) + "]";
35 |
36 | HttpContext.Current.Response.ContentType = "text/json";
37 | HttpContext.Current.Response.Write(json);
38 | }
39 |
40 | private void DoSaveJsonResource()
41 | {
42 | string folder = HttpContext.Current.Request["folder"];
43 | string newResourceId = HttpContext.Current.Request["newResourceId"];
44 | string json = HttpContext.Current.Request["json"];
45 | string oldResourceId = HttpContext.Current.Request["oldResourceId"];
46 |
47 | string newResourceFilePath = BuildResourceFilePath(folder, newResourceId, ".json");
48 |
49 | string newResourceFolderPath = Path.GetDirectoryName(newResourceFilePath);
50 |
51 | if (!Directory.Exists(newResourceFolderPath))
52 | {
53 | Directory.CreateDirectory(newResourceFolderPath);
54 | }
55 |
56 | File.WriteAllText(newResourceFilePath, json);
57 |
58 | if (!string.IsNullOrWhiteSpace(oldResourceId) && oldResourceId != newResourceId)
59 | {
60 | string oldResourceFilePath = BuildResourceFilePath(folder, oldResourceId, ".json");
61 |
62 | if (System.IO.File.Exists(oldResourceFilePath))
63 | {
64 | File.Delete(oldResourceFilePath);
65 | }
66 | }
67 |
68 | HttpContext.Current.Response.ContentType = "text/plain";
69 | HttpContext.Current.Response.Write("OK");
70 | }
71 |
72 | private string GetFolderPath(string folder)
73 | {
74 | if (folder.Contains("."))
75 | {
76 | throw new Exception("Not so fast, sonny Jim.");
77 | }
78 |
79 | string folderPath = HttpContext.Current.Server.MapPath("../resources/" + folder + "/");
80 |
81 | return folderPath;
82 | }
83 |
84 | private string BuildResourceFilePath(string folder, string resourceId, string fileExtension)
85 | {
86 | if (resourceId.Contains("."))
87 | {
88 | throw new Exception("Not so fast, sonny Jim.");
89 | }
90 |
91 | string folderPath = GetFolderPath(folder);
92 |
93 | return folderPath + resourceId.Replace("/", "\\") + fileExtension;
94 | }
95 |
96 | public bool IsReusable { get { return false; } }
97 | }
--------------------------------------------------------------------------------
/dev/notes.txt:
--------------------------------------------------------------------------------
1 | heartbeat
2 | {
3 |
4 | Check resources are loaded (done)
5 |
6 | Coalesce render states exist (done)
7 | * Actors
8 | * Lights
9 | * World static mesh chunks
10 | * GUIs
11 |
12 | Run Physics
13 |
14 | * Offset actors through ether
15 | - Qualifying actors must have:
16 | - physicsMode: ActorPhysicsMode.OffsetThroughEther
17 | - targetOffset: vec3
18 | - speed
19 |
20 | * Push actors through map
21 | - Qualifying actors must have:
22 | - physicsMode: ActorPhysicsMode.PushThroughMap
23 | - applyGravity: true/false
24 | - movementNormal
25 | - speed
26 | - collisionSphere
27 |
28 | * Move particles objects through map
29 | - Qualifying particles must have:
30 | - physicsMode: ParticlePhysicsMode.MoveThroughMap
31 | - direction
32 | - speed
33 |
34 |
35 | Calculate actor final positions (done)
36 |
37 |
38 | Rebuild bounding volumes (done)
39 | * Lights
40 | * Actors
41 |
42 | Update actor resident sectors (done)
43 |
44 | Update render states
45 | * Lights
46 | * World static chunks
47 | * Actors
48 | * GUIs
49 |
50 | Update animations (done)
51 | * Actors
52 | * GUIs
53 |
54 | Check shadow map allocations (done)
55 |
56 | Render (done)
57 |
58 | Game logic
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/html/editor/directives/actor-editor.html:
--------------------------------------------------------------------------------
1 |
2 |
{{actor.id}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
36 |
37 |
47 |
48 |
54 |
55 |
70 |
71 |
81 |
82 |
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/html/editor/directives/choose-actor-modal.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/html/editor/directives/choose-controller-modal.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/html/editor/directives/choose-resource-modal.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/html/editor/directives/light-editor.html:
--------------------------------------------------------------------------------
1 |
2 |
{{light.id}}
3 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/html/editor/directives/material-editor.html:
--------------------------------------------------------------------------------
1 |
2 |
Material Editor
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
29 |
30 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/html/editor/directives/object-data-editor.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/html/editor/directives/trigger-editor.html:
--------------------------------------------------------------------------------
1 |
2 |
{{trigger.id}}
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/html/editor/directives/vec3-editor.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 | Y:
11 |
12 |
13 |
14 |
15 |
16 | Z:
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/html/editor/main.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/html/editor/tabs/actors.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | No map loaded
22 |
23 |
--------------------------------------------------------------------------------
/html/editor/tabs/lights.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | No map loaded
22 |
23 |
--------------------------------------------------------------------------------
/html/editor/tabs/map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | No map loaded
34 |
35 |
--------------------------------------------------------------------------------
/html/editor/tabs/player.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | No map loaded
14 |
--------------------------------------------------------------------------------
/html/editor/tabs/resources.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
21 |
22 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/html/editor/tabs/triggers.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | No map loaded
22 |
23 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | FPS: ()
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/js/editor/controllers/actors-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('ActorsController', ['$scope', 'util', function ($scope, util) {
2 |
3 | $scope.editActor = function (actorId) {
4 |
5 | $scope.$broadcast('edit-actor', {
6 | actorId: actorId
7 | });
8 | }
9 |
10 | $scope.createActor = function () {
11 |
12 | var actor = {
13 | id: 'actor-' + (util.countHashTableKeys(engine.map.actorsById) + 1),
14 | position: [0, 0, 0],
15 | positionOffset: [0, 0, 0],
16 | rotation: [0, 0, 0],
17 | staticMeshId: null,
18 | skinnedMeshId: null,
19 | skinnedMeshAnimationId: null,
20 | frameIndex: 0,
21 | controllerId: null,
22 | data: {}
23 | }
24 |
25 | engine.editorHelper.addActor(actor);
26 | }
27 |
28 | $scope.removeActor = function (actorId) {
29 |
30 | engine.editorHelper.removeActor(actorId);
31 | }
32 | }]);
--------------------------------------------------------------------------------
/js/editor/controllers/editor-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('EditorController', ['$scope', 'ws', function ($scope, ws) {
2 |
3 | $scope.mapMetaData = {
4 | mapId: 'test-map-2'
5 | }
6 |
7 | $scope.map = null;
8 |
9 | $scope.startMap = function () {
10 |
11 | engine.startMap();
12 | }
13 |
14 | $scope.loadMap = function () {
15 |
16 | engine.loadMap($scope.mapMetaData.mapId, function () {
17 |
18 | $scope.map = engine.map;
19 | $scope.$apply();
20 | });
21 | }
22 |
23 | $scope.saveMap = function () {
24 |
25 | ws.saveJsonResource('map', $scope.mapMetaData.mapId, $scope.map, null)
26 | .then(function () { });
27 | }
28 |
29 | /*$scope.chooseWorldMeshSet = function () {
30 |
31 | $scope.map.worldMeshSetId = 'map1';
32 |
33 | engine.reloadWorldMeshSet();
34 | }*/
35 | }]);
--------------------------------------------------------------------------------
/js/editor/controllers/lights-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('LightsController', ['$scope', 'util', function ($scope, util) {
2 |
3 | $scope.editLight = function (lightId) {
4 |
5 | $scope.$broadcast('edit-light', {
6 | lightId: lightId
7 | });
8 | }
9 |
10 | $scope.createLight = function () {
11 |
12 | var light = {
13 | id: 'light-' + (util.countHashTableKeys(engine.map.lightsById) + 1),
14 | type: 'point',
15 | position: [0, 0, 0],
16 | radius: 1,
17 | colour: [1, 1, 1]
18 | }
19 |
20 | engine.editorHelper.addLight(light);
21 | }
22 |
23 | $scope.removeLight = function (lightId) {
24 |
25 | engine.editorHelper.removeLight(lightId);
26 | }
27 | }]);
--------------------------------------------------------------------------------
/js/editor/controllers/map-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('MapController', ['$scope', '$rootScope', 'sectorSetBuilder', 'ws', function ($scope, $rootScope, sectorSetBuilder, ws) {
2 |
3 | $scope.chooseWorldStaticMesh = function () {
4 |
5 | $rootScope.$broadcast('choose-resource', {
6 | resourceType: 'static-mesh',
7 | callback: function (staticMeshId) {
8 |
9 | $scope.map.worldStaticMeshId = staticMeshId;
10 | engine.reloadWorldMeshSet();
11 | }
12 | });
13 | }
14 |
15 | $scope.rebuildSectorSet = function () {
16 |
17 | engine.resourceLoader.loadJsonResource('static-mesh', $scope.map.worldStaticMeshId, function (staticMesh) {
18 |
19 | var sectorSet = sectorSetBuilder.buildSectorSetForStaticMesh(staticMesh);
20 |
21 | ws.saveJsonResource('sector-set', $scope.map.sectorSetId, sectorSet, $scope.map.sectorSetId);
22 | });
23 | }
24 | }]);
--------------------------------------------------------------------------------
/js/editor/controllers/rendering-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('RenderingController', ['$scope', function ($scope) {
2 |
3 | $scope.renderingOptions = {
4 | renderLightVolumes: false,
5 | renderWorldMeshChunkAABBs: false,
6 | renderActorIdentifiers: false,
7 | renderActorBoundingSpheres: false,
8 | renderTriggers: false
9 | }
10 |
11 | $scope.init = function () {
12 |
13 | $scope.$watch('renderingOptions', function () {
14 |
15 | util.copyObjectPropertiesToOtherObject($scope.renderingOptions, engine.renderer.renderingOptions)
16 |
17 | }, true);
18 | }
19 |
20 | $scope.init();
21 | }]);
--------------------------------------------------------------------------------
/js/editor/controllers/resources-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('ResourcesController', ['$rootScope', '$scope', 'ws', function ($rootScope, $scope, ws) {
2 |
3 | $scope.resourceType = 'map';
4 | $scope.resourceIds = [];
5 | $scope.newMaterial = {
6 | materialId: ''
7 | }
8 |
9 | $scope.init = function () {
10 |
11 | $scope.$watch('resourceType', function () {
12 | $scope.loadResourceList();
13 | });
14 | }
15 |
16 | $scope.loadResourceList = function () {
17 |
18 | ws.loadResourceIdList($scope.resourceType)
19 | .then(function (resourceIds) {
20 | $scope.resourceIds = resourceIds;
21 | });
22 | }
23 |
24 | $scope.editResource = function (resourceId) {
25 |
26 | if ($scope.resourceType == 'material') {
27 |
28 | $scope.$broadcast('load-and-edit-material', {
29 | materialId: resourceId,
30 | callback: function () {
31 | $scope.loadResourceList();
32 | }
33 | });
34 | }
35 | }
36 |
37 | $scope.importStaticMesh = function () {
38 |
39 | $rootScope.$broadcast('import-static-mesh');
40 | }
41 |
42 | $scope.importSkinnedMesh = function () {
43 |
44 | $rootScope.$broadcast('import-skinned-mesh');
45 | }
46 |
47 | $scope.importSkinnedMeshAnimation = function () {
48 |
49 | $rootScope.$broadcast('import-skinned-mesh-animation');
50 | }
51 |
52 | $scope.createMaterial = function () {
53 |
54 | var materialId = $scope.newMaterial.materialId;
55 |
56 | if (materialId == '') {
57 | alert('Please enter a name for the new material.');
58 | return;
59 | }
60 |
61 | var material = {
62 |
63 | }
64 |
65 | ws.saveJsonResource('material', materialId, material, null)
66 | .then(function () { $scope.loadResourceList(); });
67 | }
68 |
69 | $scope.init();
70 | }]);
--------------------------------------------------------------------------------
/js/editor/controllers/triggers-controller.js:
--------------------------------------------------------------------------------
1 | editorApp.controller('TriggersController', ['$scope', 'util', function ($scope, util) {
2 |
3 | $scope.editTrigger = function (triggerId) {
4 |
5 | $scope.$broadcast('edit-trigger', {
6 | triggerId: triggerId
7 | });
8 | }
9 |
10 | $scope.createTrigger = function () {
11 |
12 | var trigger = {
13 | id: 'trigger-' + (util.countHashTableKeys(engine.map.triggersById) + 1),
14 | position: [0, 0, 0],
15 | size: [0, 0, 0],
16 | controllerId: null,
17 | data: {}
18 | }
19 |
20 | engine.editorHelper.addTrigger(trigger);
21 | }
22 |
23 | $scope.removeTrigger = function (triggerId) {
24 |
25 | engine.editorHelper.removeTrigger(triggerId);
26 | }
27 | }]);
--------------------------------------------------------------------------------
/js/editor/directives/actor-editor.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('actorEditor', ['$rootScope', function ($rootScope) {
2 | return {
3 | templateUrl: 'html/editor/directives/actor-editor.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.chooseStaticMesh = function () {
10 |
11 | $rootScope.$broadcast('choose-resource', {
12 | resourceType: 'static-mesh',
13 | callback: function (resourceId) {
14 | $scope.actor.staticMeshId = resourceId;
15 | }
16 | });
17 | }
18 |
19 | $scope.clearStaticMesh = function () {
20 |
21 | $scope.actor.staticMeshId = null;
22 | }
23 |
24 | $scope.chooseSkinnedMesh = function () {
25 |
26 | $rootScope.$broadcast('choose-resource', {
27 | resourceType: 'skinned-mesh',
28 | callback: function (resourceId) {
29 | $scope.actor.skinnedMeshId = resourceId;
30 | }
31 | });
32 | }
33 |
34 | $scope.clearSkinnedMesh = function () {
35 |
36 | $scope.actor.skinnedMeshId = null;
37 | }
38 |
39 | $scope.chooseSkinnedMeshAnimation = function () {
40 |
41 | $rootScope.$broadcast('choose-resource', {
42 | resourceType: 'skinned-mesh-animation',
43 | callback: function (resourceId) {
44 | $scope.actor.skinnedMeshAnimationId = resourceId;
45 | }
46 | });
47 | }
48 |
49 | $scope.clearSkinnedMeshAnimation = function () {
50 |
51 | $scope.actor.skinnedMeshAnimationId = null;
52 | }
53 |
54 | $scope.createHitBox = function () {
55 |
56 | $scope.actor.hitBox = new AABB([-0.5, 1, 0.5], [0.5, 0, -0.5]);
57 | }
58 |
59 | $scope.removeHitBox = function () {
60 |
61 | $scope.actor.hitBox = null;
62 | }
63 |
64 | $scope.chooseController = function () {
65 |
66 | $rootScope.$broadcast('choose-controller', {
67 | controllerType: 'actor',
68 | callback: function (controllerId) {
69 | $scope.actor.controllerId = controllerId;
70 |
71 | engine.mapDataHelper.checkActorData($scope.actor);
72 | $scope.loadDataSchema();
73 | }
74 | });
75 | }
76 |
77 | $scope.clearController = function () {
78 |
79 | $scope.actor.controllerId = null;
80 | $scope.loadDataSchema();
81 | }
82 |
83 | $scope.loadDataSchema = function () {
84 |
85 | $scope.dataSchema = null;
86 | var controller = engine.actorControllersById[$scope.actor.controllerId];
87 | if (controller != null) {
88 | $scope.dataSchema = controller.dataSchema;
89 | }
90 | }
91 | },
92 | link: function ($scope, element, attrs) {
93 |
94 | $scope.$on('edit-actor', function (event, args) {
95 |
96 | $scope.actor = engine.map.actorsById[args.actorId];
97 |
98 | $scope.loadDataSchema();
99 |
100 | engine.renderer.renderingParameters.renderActorIdentifierForActorId = $scope.actor.id;
101 | });
102 | }
103 | }
104 | }]);
--------------------------------------------------------------------------------
/js/editor/directives/choose-actor-modal.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('chooseActorModal', [function () {
2 | return {
3 | templateUrl: 'html/editor/directives/choose-actor-modal.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.chooseActor = function (actor) {
10 |
11 | $scope.callback(actor);
12 |
13 | $scope.closeModal();
14 | }
15 | },
16 | link: function ($scope, element, attrs) {
17 |
18 | $scope.$on('choose-actor', function (event, args) {
19 |
20 | $scope.callback = args.callback;
21 | $scope.actorsById = engine.map.actorsById;
22 |
23 | $scope.showModal();
24 | });
25 |
26 | $scope.showModal = function () {
27 |
28 | $(element).find('.modal').modal('show');
29 | }
30 |
31 | $scope.closeModal = function () {
32 |
33 | $(element).find('.modal').modal('hide');
34 | }
35 | }
36 | }
37 | }]);;
--------------------------------------------------------------------------------
/js/editor/directives/choose-controller-modal.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('chooseControllerModal', [function () {
2 | return {
3 | templateUrl: 'html/editor/directives/choose-controller-modal.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.chooseController = function (controllerId) {
10 |
11 | $scope.callback(controllerId);
12 |
13 | $scope.closeModal();
14 | }
15 | },
16 | link: function ($scope, element, attrs) {
17 |
18 | $scope.$on('choose-controller', function (event, args) {
19 |
20 | $scope.callback = args.callback;
21 |
22 | var controllerLookupName =
23 | args.controllerType == 'game' ? 'gameControllersById' :
24 | args.controllerType == 'actor' ? 'actorControllersById' :
25 | args.controllerType == 'emitter' ? 'emitterControllersById' :
26 | args.controllerType == 'particle' ? 'particleControllersById' :
27 | args.controllerType == 'trigger' ? 'triggerControllersById' : null;
28 |
29 | $scope.controllerLookup = engine[controllerLookupName];
30 |
31 | $scope.showModal();
32 | });
33 |
34 | $scope.showModal = function () {
35 |
36 | $(element).find('.modal').modal('show');
37 | }
38 |
39 | $scope.closeModal = function () {
40 |
41 | $(element).find('.modal').modal('hide');
42 | }
43 | }
44 | }
45 | }]);;
--------------------------------------------------------------------------------
/js/editor/directives/choose-resource-modal.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('chooseResourceModal', ['ws', function (ws) {
2 | return {
3 | templateUrl: 'html/editor/directives/choose-resource-modal.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.chooseResource = function (resourceId) {
10 |
11 | $scope.callback(resourceId);
12 |
13 | $scope.closeModal();
14 | }
15 | },
16 | link: function ($scope, element, attrs) {
17 |
18 | $scope.$on('choose-resource', function (event, args) {
19 |
20 | $scope.callback = args.callback;
21 | $scope.resourceType = args.resourceType;
22 |
23 | ws.loadResourceIdList($scope.resourceType).then(function (resourceIds) {
24 | $scope.resourceIds = resourceIds;
25 | });
26 |
27 | $scope.showModal();
28 | });
29 |
30 | $scope.showModal = function () {
31 |
32 | $(element).find('.modal').modal('show');
33 | }
34 |
35 | $scope.closeModal = function () {
36 |
37 | $(element).find('.modal').modal('hide');
38 | }
39 | }
40 | }
41 | }]);;
--------------------------------------------------------------------------------
/js/editor/directives/light-editor.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('lightEditor', [function () {
2 | return {
3 | templateUrl: 'html/editor/directives/light-editor.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.$watch('light', function () {
10 |
11 | if ($scope.light != null) {
12 | engine.editorHelper.invalidateLight($scope.light.id);
13 | }
14 |
15 | }, true);
16 | },
17 | link: function ($scope, element, attrs) {
18 |
19 | $scope.$on('edit-light', function (event, args) {
20 |
21 | $scope.light = engine.map.lightsById[args.lightId];
22 |
23 | engine.renderer.renderingOptions.renderLightVolumeForLightId = $scope.light.id;
24 | });
25 | }
26 | }
27 | }]);
--------------------------------------------------------------------------------
/js/editor/directives/material-editor.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('materialEditor', ['$rootScope', '$timeout', 'ws', function ($rootScope, $timeout, ws) {
2 | return {
3 | templateUrl: 'html/editor/directives/material-editor.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.save = function () {
10 |
11 | /*ws.get(
12 | '/ResourceApi/SaveJsonResource',
13 | {
14 | folder: engine.resourceLoader.getFolderNameForResourceType('material'),
15 | oldResourceId: $scope.materialMetaData.oldMaterialId,
16 | newResourceId: $scope.materialMetaData.newMaterialId,
17 | json: angular.toJson($scope.material)
18 | })
19 | .then(function () {
20 |
21 | $scope.materialMetaData.oldMaterialId = $scope.materialMetaData.newMaterialId;
22 |
23 | if ($scope.callback != null) {
24 | $scope.callback();
25 | }
26 | });*/
27 |
28 | ws.saveJsonResource('material', $scope.materialMetaData.newMaterialId, $scope.material, $scope.materialMetaData.oldMaterialId)
29 | .then(function () {
30 | $scope.materialMetaData.oldMaterialId = $scope.materialMetaData.newMaterialId;
31 |
32 | if ($scope.callback != null) {
33 | $scope.callback();
34 | }
35 | });
36 | }
37 |
38 | $scope.chooseDiffuseTexture = function () {
39 |
40 | $rootScope.$broadcast('choose-resource', {
41 | resourceType: 'texture',
42 | callback: function (resourceId) {
43 | $scope.material.diffuseTextureId = resourceId;
44 | }
45 | });
46 | }
47 |
48 | $scope.chooseNormalTexture = function () {
49 |
50 | $rootScope.$broadcast('choose-resource', {
51 | resourceType: 'texture',
52 | callback: function (resourceId) {
53 | $scope.material.normalTextureId = resourceId;
54 | }
55 | });
56 | }
57 |
58 | $scope.chooseSelfIlluminationTexture = function () {
59 |
60 | $rootScope.$broadcast('choose-resource', {
61 | resourceType: 'texture',
62 | callback: function (resourceId) {
63 | $scope.material.selfIlluminationTextureId = resourceId;
64 | }
65 | });
66 | }
67 |
68 | $scope.clearSelfIlluminationTexture = function () {
69 |
70 | $scope.material.selfIlluminationTextureId = null;
71 | }
72 | },
73 | link: function ($scope, element, attrs) {
74 |
75 | $scope.$on('load-and-edit-material', function (event, args) {
76 |
77 | $scope.callback = args.callback;
78 |
79 | $scope.materialMetaData = {
80 | oldMaterialId: args.materialId,
81 | newMaterialId: args.materialId
82 | }
83 |
84 | engine.materialManager.loadMaterial($scope.materialMetaData.oldMaterialId, function (material) {
85 |
86 | $timeout(function () {
87 | $scope.material = material;
88 | })
89 | });
90 | });
91 | }
92 | }
93 | }]);
--------------------------------------------------------------------------------
/js/editor/directives/object-data-editor.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('objectDataEditor', ['$rootScope', function ($rootScope) {
2 | return {
3 | templateUrl: 'html/editor/directives/object-data-editor.html',
4 | scope: {
5 | obj: '=obj',
6 | schema: '=schema'
7 | },
8 | controller: function ($scope) {
9 |
10 | $scope.chooseActor = function (propertyName) {
11 |
12 | $rootScope.$broadcast('choose-actor', {
13 | callback: function (actor) {
14 | $scope.obj.data[propertyName] = actor.id;
15 | }
16 | });
17 | }
18 |
19 | $scope.clearValue = function (propertyName) {
20 |
21 | $scope.obj.data[propertyName] = '';
22 | }
23 | },
24 | link: function ($scope, element, attrs) {
25 |
26 | }
27 | }
28 | }]);
--------------------------------------------------------------------------------
/js/editor/directives/trigger-editor.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('triggerEditor', ['$rootScope', function ($rootScope) {
2 | return {
3 | templateUrl: 'html/editor/directives/trigger-editor.html',
4 | scope: {
5 |
6 | },
7 | controller: function ($scope) {
8 |
9 | $scope.loadDataSchema = function () {
10 |
11 | $scope.dataSchema = null;
12 | var controller = engine.triggerControllersById[$scope.trigger.controllerId];
13 | if (controller != null) {
14 | $scope.dataSchema = controller.dataSchema;
15 | }
16 | }
17 | },
18 | link: function ($scope, element, attrs) {
19 |
20 | $scope.$on('edit-trigger', function (event, args) {
21 |
22 | $scope.trigger = engine.map.triggersById[args.triggerId];
23 |
24 | $scope.loadDataSchema();
25 | });
26 | }
27 | }
28 | }]);
--------------------------------------------------------------------------------
/js/editor/directives/vec3-editor.js:
--------------------------------------------------------------------------------
1 | editorApp.directive('vec3Editor', function () {
2 | return {
3 | templateUrl: 'html/editor/directives/vec3-editor.html',
4 | scope: {
5 | vec: '=vec'
6 | },
7 | controller: function ($scope) {
8 | },
9 | link: function ($scope, element, attrs) {
10 | }
11 | }
12 | });
--------------------------------------------------------------------------------
/js/editor/editor-app.js:
--------------------------------------------------------------------------------
1 | var editorApp = angular.module('editorApp', []);
--------------------------------------------------------------------------------
/js/editor/services/sector-set-builder.js:
--------------------------------------------------------------------------------
1 | editorApp.factory('sectorSetBuilder', [function () {
2 |
3 | var sectorSetBuilder = {
4 |
5 | buildSectorSetForStaticMesh: function (staticMesh) {
6 |
7 | var self = this;
8 |
9 | engine.staticMeshMathHelper.buildStaticMeshChunkCollisionFaces(staticMesh);
10 | engine.staticMeshMathHelper.findStaticMeshPointCompletelyOutsideOfExtremities(staticMesh);
11 |
12 | var sectorSet = {
13 | metrics: {
14 | sectorCount: [4, 2, 3],
15 | sectorSize: [12, 12, 12],
16 | rootOrigin: [-24, 0, 12]
17 | },
18 | sectors: []
19 | }
20 |
21 | var sectorPointsByIndex = [];
22 |
23 | console.log('Creating sector points.');
24 |
25 | self.forEachSector(sectorSet, function (sectorIndex, sectorOrigin) {
26 |
27 | sectorPointsByIndex[sectorIndex] = [];
28 |
29 | for (var i = 0; i < 150; i++) {
30 |
31 | var point = vec3.create();
32 |
33 | self.createRandomPointWithinSector(point, sectorSet.metrics, sectorOrigin);
34 |
35 | if (engine.staticMeshMathHelper.determineIfPointIsWithinStaticMesh(point, staticMesh)) {
36 | sectorPointsByIndex[sectorIndex].push(point);
37 | }
38 | }
39 | });
40 |
41 | var line = new CollisionLine();
42 |
43 | self.forEachSector(sectorSet, function (sectorAIndex, sectorAOrigin) {
44 |
45 | console.log('Checking sector ' + sectorAIndex + '.');
46 |
47 | var sector = {
48 | visibleSectorIndexes: []
49 | }
50 |
51 | sector.visibleSectorIndexes.push(sectorAIndex);
52 |
53 | sectorSet.sectors[sectorAIndex] = sector;
54 |
55 | self.forEachSector(sectorSet, function (sectorBIndex, sectorBOrigin) {
56 |
57 | if (sectorAIndex == sectorBIndex) {
58 | return;
59 | }
60 |
61 | for (var i = 0; i < sectorPointsByIndex[sectorAIndex].length; i++) {
62 | for (var j = 0; j < sectorPointsByIndex[sectorBIndex].length; j++) {
63 |
64 | line.from = sectorPointsByIndex[sectorAIndex][i];
65 | line.to = sectorPointsByIndex[sectorBIndex][j];
66 | math3D.buildCollisionLineFromFromAndToPoints(line);
67 |
68 | if (!self.determineIfLineIntersectsAnyFace(line, staticMesh)) {
69 | sector.visibleSectorIndexes.push(sectorBIndex);
70 | return;
71 | }
72 | }
73 | }
74 | });
75 | });
76 |
77 | console.log('Done!');
78 |
79 | return sectorSet;
80 | },
81 |
82 | forEachSector: function (sectorSet, callback) {
83 |
84 | var index = 0;
85 | var origin = vec3.create();
86 |
87 | for (var x = 0; x < sectorSet.metrics.sectorCount[0]; x++) {
88 |
89 | for (var y = 0; y < sectorSet.metrics.sectorCount[1]; y++) {
90 |
91 | for (var z = 0; z < sectorSet.metrics.sectorCount[2]; z++) {
92 |
93 | vec3.set(
94 | origin,
95 | x * sectorSet.metrics.sectorSize[0],
96 | y * sectorSet.metrics.sectorSize[1],
97 | z * -sectorSet.metrics.sectorSize[2]);
98 |
99 | vec3.add(origin, sectorSet.metrics.rootOrigin, origin);
100 |
101 | callback(index, origin);
102 |
103 | index++
104 | }
105 | }
106 | }
107 | },
108 |
109 | /*createRandomLineBetweenSectors: function (out, sectorMetrics, sectorAOrigin, sectorBOrigin) {
110 |
111 | this.createRandomPointWithinSector(out.from, sectorMetrics, sectorAOrigin);
112 | this.createRandomPointWithinSector(out.to, sectorMetrics, sectorBOrigin);
113 |
114 | math3D.buildCollisionLineFromFromAndToPoints(out);
115 | },*/
116 |
117 | createRandomPointWithinSector: function (out, sectorMetrics, sectorOrigin) {
118 |
119 | vec3.copy(out, sectorOrigin);
120 |
121 | out[0] += Math.random() * sectorMetrics.sectorSize[0];
122 | out[1] += Math.random() * sectorMetrics.sectorSize[1];
123 | out[2] -= Math.random() * sectorMetrics.sectorSize[2];
124 | },
125 |
126 | determineIfLineIntersectsAnyFace: function (line, staticMesh) {
127 |
128 | for (var chunkIndex = 0; chunkIndex < staticMesh.chunks.length; chunkIndex++) {
129 |
130 | var chunk = staticMesh.chunks[chunkIndex];
131 |
132 | // TODO - AABB check
133 |
134 | for (var faceIndex = 0; faceIndex < chunk.collisionFaces.length; faceIndex++) {
135 |
136 | var collisionFace = chunk.collisionFaces[faceIndex];
137 |
138 | var faceIntersectionType = math3D.calculateCollisionLineIntersectionWithCollisionFace(null, line, collisionFace)
139 |
140 | if (faceIntersectionType != FaceIntersectionType.None) {
141 |
142 | return true;
143 | }
144 | }
145 | }
146 |
147 | return false;
148 | }
149 | }
150 |
151 | return sectorSetBuilder;
152 | }]);
--------------------------------------------------------------------------------
/js/editor/services/util.js:
--------------------------------------------------------------------------------
1 | editorApp.factory('util', [function () {
2 |
3 | var util = {
4 |
5 | countHashTableKeys: function (hashtable) {
6 |
7 | var count = 0;
8 |
9 | for (var propName in hashtable) {
10 |
11 | count++;
12 | }
13 |
14 | return count;
15 | }
16 | }
17 |
18 | return util;
19 | }]);
--------------------------------------------------------------------------------
/js/editor/services/ws.js:
--------------------------------------------------------------------------------
1 | editorApp.factory('ws', ['$http', '$q', function ($http, $q) {
2 |
3 | $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8;';
4 |
5 | var ws = {
6 |
7 | loadResourceIdList: function (resourceType) {
8 |
9 | return this.get(
10 | 'api/resources.ashx',
11 | {
12 | action: 'load-resource-id-list',
13 | folder: engine.resourceLoader.getFolderNameForResourceType(resourceType)
14 | });
15 | },
16 |
17 | saveJsonResource: function (resourceType, newResourceId, resource, oldResourceId) {
18 |
19 | return this.post(
20 | 'api/resources.ashx',
21 | {
22 | action: 'save-json-resource',
23 | folder: engine.resourceLoader.getFolderNameForResourceType(resourceType),
24 | newResourceId: newResourceId,
25 | oldResourceId: oldResourceId,
26 | json: angular.toJson(resource)
27 | });
28 | },
29 |
30 | get: function (url, parameters) {
31 |
32 | var deferred = $q.defer();
33 |
34 | $http.get(
35 | url + '?noCache=' + Math.round(Math.random() * 10000),
36 | {
37 | params: parameters
38 | })
39 | .success(function (response) {
40 | deferred.resolve(response);
41 | });
42 |
43 | return deferred.promise;
44 | },
45 |
46 | post: function (url, parameters) {
47 |
48 | var deferred = $q.defer();
49 |
50 | var postDataChunks = [];
51 | for (var propertyName in parameters) {
52 | postDataChunks.push(encodeURIComponent(propertyName) + '=' + encodeURIComponent(parameters[propertyName]));
53 | }
54 | var postData = postDataChunks.join("&");
55 |
56 | $http.post(
57 | url + '?noCache=' + Math.round(Math.random() * 10000),
58 | postData)
59 | .success(function (response) {
60 | deferred.resolve(response);
61 | });
62 |
63 | return deferred.promise;
64 | }
65 | }
66 |
67 | return ws;
68 | }]);
--------------------------------------------------------------------------------
/js/engine/bit-field.js:
--------------------------------------------------------------------------------
1 | function BitField() {
2 |
3 | this.length = 0;//length;
4 | this.sizeInBytes = 0;//Math.ceil(this.length / 8);
5 | this.data = null;//new Uint8Array(this.sizeInBytes);
6 |
7 | this.getBit = function (index) {
8 |
9 | var byteIndex = Math.floor(index / 8);
10 | var bitOffset = index % 8;
11 | var bitMask = 0x80 >> bitOffset;
12 |
13 | var maskedByte = this.data[byteIndex] & bitMask;
14 | var bitSet = maskedByte != 0;
15 |
16 | return bitSet;
17 | }
18 |
19 | this.setBit = function (index) {
20 |
21 | var byteIndex = Math.floor(index / 8);
22 | var bitOffset = index % 8;
23 | var bitMask = 0x80 >> bitOffset;
24 | var invBitMask = ~bitMask;
25 |
26 | var byte = this.data[byteIndex];
27 | this.data[byteIndex] = (byte & invBitMask) | bitMask;
28 | }
29 |
30 | this.unsetBit = function (index) {
31 |
32 | var byteIndex = Math.floor(index / 8);
33 | var bitOffset = index % 8;
34 | var bitMask = 0x80 >> bitOffset;
35 | var invBitMask = ~bitMask;
36 |
37 | var byte = this.data[byteIndex];
38 | this.data[byteIndex] = (byte & invBitMask);
39 | }
40 |
41 | this.reset = function (length) {
42 |
43 | if (this.length != length) {
44 | this.length = length;
45 | this.sizeInBytes = Math.ceil(this.length / 8);
46 | this.data = new Uint8Array(this.sizeInBytes);
47 | }
48 |
49 | for (var i = 0; i < this.data.length; i++) {
50 | this.data[i] = 0;
51 | }
52 | }
53 |
54 | this.countSetBits = function () {
55 |
56 | var count = 0;
57 | for (var i = 0; i < this.length; i++) {
58 | if (this.getBit(i)) {
59 | count++;
60 | }
61 | }
62 | return count;
63 | }
64 | }
--------------------------------------------------------------------------------
/js/engine/camera.js:
--------------------------------------------------------------------------------
1 | function Camera(engine) {
2 |
3 | // Members.
4 | this.position = vec3.create();
5 |
6 | /*this.axes = {
7 | xAxis: [1, 0, 0],
8 | yAxis: [0, 1, 0],
9 | zAxis: [0, 0, 1]
10 | };*/
11 | this.axes = new Axes();
12 |
13 | this.lookAt = vec3.create();
14 | this.viewMatrix = mat4.create();
15 | this.projMatrix = mat4.create();
16 | this.viewProjMatrix = mat4.create();
17 |
18 | this.init = function (callback) {
19 |
20 | callback();
21 | }
22 |
23 | this.updateMatrixes = function (fov, aspectRatio, nearClippingDistance, farClippingDistance) {
24 |
25 | this.updateViewMatrix();
26 | this.updateProjMatrix(fov, aspectRatio, nearClippingDistance, farClippingDistance);
27 | this.updateViewProjMatrix();
28 | }
29 |
30 | this.updateViewMatrix = function () {
31 |
32 | //var viewMatrix = mat4.create();
33 |
34 | //var lookAt = vec3.create();
35 | vec3.add(this.lookAt, this.position, this.axes.zAxis);
36 |
37 | mat4.lookAt(this.viewMatrix, this.position, this.lookAt, this.axes.yAxis);
38 |
39 | //return viewMatrix;
40 | }
41 |
42 | this.updateProjMatrix = function (fov, aspectRatio, nearClippingDistance, farClippingDistance) {
43 |
44 | mat4.perspective(this.projMatrix, fov, aspectRatio, nearClippingDistance, farClippingDistance);
45 | }
46 |
47 | this.updateViewProjMatrix = function () {
48 |
49 | //var viewMatrix = this.makeViewMatrix();
50 |
51 | //var projMatrix = mat4.create();
52 | //mat4.perspective(projMatrix, fov, aspectRatio, nearClippingDistance, farClippingDistance);
53 |
54 | //var viewProjMatrix = mat4.create();
55 | mat4.multiply(this.viewProjMatrix, this.projMatrix, this.viewMatrix);
56 |
57 | //return viewProjMatrix;
58 | }
59 | }
--------------------------------------------------------------------------------
/js/engine/canvas-initialiser.js:
--------------------------------------------------------------------------------
1 | function CanvasInitialiser(engine) {
2 |
3 | this.init = function (callback) {
4 |
5 | if (document.getElementById('canvas') != null) {
6 | callback();
7 | return;
8 | }
9 |
10 | var fullscreenMode = document.getElementById('cb-fullscreen').checked;
11 | var resolutionMultiplier = document.getElementById('lb-resolution-scale').value;
12 |
13 | var canvasSize = {
14 | width: 0,
15 | height: 0
16 | }
17 |
18 | if (fullscreenMode) {
19 |
20 | canvasSize.width = window.screen.width;
21 | canvasSize.height = window.screen.height;
22 |
23 | } else {
24 |
25 | canvasSize.width = 960;//240
26 | canvasSize.height = canvasSize.width * 0.5625;
27 | }
28 |
29 | var canvasResolution = {
30 | width: canvasSize.width * resolutionMultiplier,
31 | height: canvasSize.height * resolutionMultiplier
32 | }
33 |
34 | var canvasContainer = document.getElementById('canvas-container');
35 | canvasContainer.innerHTML = '';
36 |
37 | if (!fullscreenMode) {
38 | canvasContainer.style.width = canvasSize.width + 'px';
39 | canvasContainer.style.height = canvasSize.height + 'px';
40 | canvasContainer.style.borderWidth = '4px';
41 | canvasContainer.style.borderColor = 'grey';
42 | canvasContainer.style.borderStyle = 'solid'
43 | canvasContainer.style.marginTop = '100px';
44 | canvasContainer.style.marginLeft = 'auto';
45 | canvasContainer.style.marginRight = 'auto';
46 | }
47 |
48 | var settingsContainer = document.getElementById('settings-container');
49 | settingsContainer.style.display = 'none';
50 |
51 | var statsContainer = document.getElementById('stats-container');
52 | statsContainer.style.display = 'block';
53 |
54 | if (fullscreenMode) {
55 |
56 | var mainContainer = document.getElementById('main-container');
57 |
58 | if (mainContainer.webkitRequestFullscreen) {
59 |
60 | document.addEventListener('webkitfullscreenchange', function () {
61 | callback();
62 | });
63 |
64 | } else if (mainContainer.mozRequestFullscreen) {
65 |
66 | document.addEventListener('mozfullscreenchange', function () {
67 | callback();
68 | });
69 |
70 | } else if (mainContainer.requestFullscreen) {
71 |
72 | document.addEventListener('fullscreenchange', function () {
73 | callback();
74 | });
75 | }
76 |
77 | mainContainer.requestFullscreen =
78 | mainContainer.requestFullscreen ||
79 | mainContainer.mozRequestFullscreen ||
80 | mainContainer.webkitRequestFullscreen;
81 |
82 | mainContainer.requestFullscreen();
83 |
84 | } else {
85 | callback();
86 | }
87 | }
88 | }
--------------------------------------------------------------------------------
/js/engine/constants.js:
--------------------------------------------------------------------------------
1 | var ShadowMapBuildResult = {
2 | NotBuilt: 0,
3 | Built: 1,
4 | BuiltWithDynamicObjects: 2,
5 | BuiltWithoutDynamicObjects: 3
6 | }
7 |
8 | var FrustumPlane = {
9 | Near: 0,
10 | Far: 1,
11 | Top: 2,
12 | Bottom: 3,
13 | Left: 4,
14 | Right: 5
15 | }
16 |
17 | var EngineLimits = {
18 | //MaxVisibleWorldStaticMeshChunkIndexesForCamera: 1000,
19 | //MaxVisibleWorldStaticMeshChunkIndexesPerLight: 400,
20 | MaxVisibleActorsIdsPerLight: 100,
21 | MaxVisibleActorsIdsForCamera: 100,
22 | //MaxActorResidentSectorIndexes: 16,
23 | MaxVisibleLightIdsForCamera: 1000,
24 | MaxEffectiveLightsPerObject: 5
25 | }
26 |
27 | var RgbColours = {
28 | Red: [1, 0, 0],
29 | Green: [0, 1, 0],
30 | Blue: [0, 0, 1],
31 | White: [1, 1, 1]
32 | }
33 |
34 | var FaceIntersectionType = {
35 | None: 0,
36 | FrontSide: 1,
37 | BackSide: 2
38 | }
39 |
40 | var SpritePropertyId = {
41 | PositionXOffset: 1,
42 | PositionYOffset: 2,
43 | SizeXOffset: 3,
44 | SizeYOffset: 4,
45 | RotationOffset: 5,
46 | Visible: 6
47 | }
48 |
49 | var ActorPhysicsMode = {
50 | None: 0,
51 | OffsetThroughEther: 1,
52 | PushThroughMapTowardsDirection: 2,
53 | PushThroughMapTowardsDestination: 3
54 | }
55 |
56 | var ParticlePhysicsMode = {
57 | None: 0,
58 | MoveThroughMap: 1
59 | }
60 |
61 | var ParticleCreator = {
62 | None: 0,
63 | Player: 1,
64 | Actor: 2
65 | }
66 |
67 | var ParticleCollisionType = {
68 | Actor: 0,
69 | Map: 1,
70 | Player: 2
71 | }
--------------------------------------------------------------------------------
/js/engine/editor-helper.js:
--------------------------------------------------------------------------------
1 | function EditorHelper(engine) {
2 |
3 | this.init = function (callback) {
4 |
5 | callback();
6 | }
7 |
8 | this.addLight = function (light) {
9 |
10 | engine.map.lightsById[light.id] = light;
11 | }
12 |
13 | this.removeLight = function (lightId) {
14 |
15 | delete engine.map.lightsById[lightId];
16 |
17 | // TODO - should really clean up the light render state and shadow map allocation.
18 | }
19 |
20 | this.invalidateLight = function (lightId) {
21 |
22 | var lightRenderState = engine.renderStateManager.coalesceLightRenderState(lightId);
23 |
24 | lightRenderState.isDirty = true;
25 | }
26 |
27 | this.addActor = function (actor) {
28 |
29 | engine.map.actorsById[actor.id] = actor;
30 |
31 | engine.mapDataHelper.checkActorData(actor);
32 | }
33 |
34 | this.removeActor = function (actorId) {
35 |
36 | delete engine.map.actorsById[actorId];
37 | }
38 |
39 | this.addTrigger = function (trigger) {
40 |
41 | engine.map.triggersById[trigger.id] = trigger;
42 |
43 | engine.mapDataHelper.checkTriggerData(trigger);
44 | }
45 |
46 | this.removeTrigger = function (triggerId) {
47 |
48 | delete engine.map.triggersById[triggerId];
49 | }
50 | }
--------------------------------------------------------------------------------
/js/engine/effect-manager.js:
--------------------------------------------------------------------------------
1 | function EffectManager(engine) {
2 |
3 | var self = this;
4 | var gl = null;
5 |
6 | this.effectsById = {};
7 | this.currentEffect = null;
8 |
9 | this.init = function (callback) {
10 |
11 | self.log('Loading effects...');
12 |
13 | gl = engine.glManager.gl;
14 |
15 | engine.resourceLoader.loadJsonResource('system', 'effects', function (effectsById) {
16 |
17 | self.effectsById = effectsById;
18 |
19 | var effectIds = util.getObjectPropertyNames(effectsById);
20 |
21 | util.recurse(function (recursor, recursionCount) {
22 | if (recursionCount < effectIds.length) {
23 | var effect = effectsById[effectIds[recursionCount]];
24 | self.initEffect(effect, recursor);
25 | } else {
26 | self.log('... done.');
27 | callback();
28 | }
29 | });
30 |
31 | });
32 | }
33 |
34 | this.useEffect = function (effectId) {
35 |
36 | this.currentEffect = this.effectsById[effectId];
37 |
38 | gl.useProgram(this.currentEffect.shaderProgram);
39 |
40 | return this.currentEffect;
41 | }
42 |
43 | this.initEffect = function (effect, callback) {
44 |
45 | this.loadShader(effect.id + '-vs', 'vertex', function (shader) {
46 |
47 | effect.vertexShader = shader;
48 |
49 | self.loadShader(effect.id + '-fs', 'fragment', function (shader) {
50 |
51 | effect.fragmentShader = shader;
52 |
53 | effect.shaderProgram = gl.createProgram();
54 | gl.attachShader(effect.shaderProgram, effect.vertexShader);
55 | gl.attachShader(effect.shaderProgram, effect.fragmentShader);
56 | gl.linkProgram(effect.shaderProgram);
57 |
58 | if (!gl.getProgramParameter(effect.shaderProgram, gl.LINK_STATUS)) {
59 |
60 | var lastError = gl.getProgramInfoLog(effect.shaderProgram);
61 |
62 | //var compilationLog = gl.getShaderInfoLog(effect.shaderProgram);
63 | //console.log('Shader compiler log: ' + compilationLog);
64 |
65 | throw 'Failed to initialise shader: ' + name + '. Last error: ' + lastError + '.';
66 | }
67 |
68 | // Setup the effect's attributes.
69 | for (var attributeName in effect.attributes) {
70 |
71 | var location = gl.getAttribLocation(effect.shaderProgram, attributeName);
72 | if (location < 0) {
73 | console.log('Unable to find attribute: ' + attributeName);
74 | continue;
75 | }
76 |
77 | effect.attributes[attributeName] = location;
78 | }
79 |
80 | // Setup the effects uniforms.
81 | for (var uniformName in effect.uniforms) {
82 |
83 | var location = gl.getUniformLocation(effect.shaderProgram, uniformName);
84 | if (location == null) {
85 | console.log('Unable to find uniform: ' + uniformName);
86 | continue;
87 | }
88 |
89 | effect.uniforms[uniformName] = location;
90 | }
91 |
92 | self.log('Loaded effect: ' + effect.id);
93 |
94 | callback();
95 | });
96 | });
97 | }
98 |
99 | this.loadShader = function (shaderId, type, callback) {
100 |
101 | self.log('Loading shader: ' + shaderId);
102 |
103 | engine.resourceLoader.loadTextResource('shader', shaderId, function (data) {
104 |
105 | var shader = null;
106 |
107 | if (type == 'vertex') {
108 |
109 | shader = gl.createShader(gl.VERTEX_SHADER);
110 |
111 | } else if (type == 'fragment') {
112 |
113 | shader = gl.createShader(gl.FRAGMENT_SHADER);
114 |
115 | } else {
116 |
117 | throw 'Unknown shader type: ' + type;
118 | }
119 |
120 | gl.shaderSource(shader, data);
121 | gl.compileShader(shader);
122 |
123 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
124 |
125 | throw 'Failed to compile shader: ' + gl.getShaderInfoLog(shader);
126 | }
127 |
128 | callback(shader);
129 | });
130 | }
131 |
132 | this.log = function (message) {
133 |
134 | console.log('Effect Manager: ' + message);
135 | }
136 | }
--------------------------------------------------------------------------------
/js/engine/fixed-length-array.js:
--------------------------------------------------------------------------------
1 | function FixedLengthArray(maxLength, initialItemValue) {
2 |
3 | this.items = [];
4 | this.length = 0;
5 | this.maxLength = maxLength;
6 |
7 | for (var i = 0; i < this.maxLength; i++) {
8 | this.items.push(initialItemValue);
9 | }
10 | }
--------------------------------------------------------------------------------
/js/engine/frame-timer.js:
--------------------------------------------------------------------------------
1 | function FrameTimer(engine) {
2 |
3 | // Members.
4 | this.frameDelta = 0;
5 | this.lastFrameDurationMillis = 0;
6 | this.lastFrameStartTime = null;
7 | this.lastTenFramesTotalDuration = 0;
8 | this.fpsCounterTickUp = 0;
9 |
10 | this.init = function (callback) {
11 |
12 | callback();
13 | }
14 |
15 | this.startFrame = function () {
16 |
17 | if (this.lastFrameStartTime == null) {
18 |
19 | this.lastFrameDurationMillis = 0;
20 | this.frameDelta = 0;
21 |
22 | } else {
23 |
24 | this.lastFrameDurationMillis = performance.now() - this.lastFrameStartTime;
25 |
26 | var desiredFrameDurationMillis = 1 / 60 * 1000;
27 |
28 | this.frameDelta = this.lastFrameDurationMillis / desiredFrameDurationMillis;
29 | }
30 |
31 | this.lastTenFramesTotalDuration += this.lastFrameDurationMillis;
32 | this.fpsCounterTickUp++;
33 |
34 | this.lastFrameStartTime = performance.now();
35 | }
36 |
37 | this.updateStats = function () {
38 |
39 | if (this.fpsCounterTickUp < 10) {
40 | return;
41 | }
42 |
43 | var averageFrameDuration = this.lastTenFramesTotalDuration / 10;
44 | var averagefps = 1000 / averageFrameDuration;
45 |
46 | var averageRenderingTimeElement = document.getElementById('average-rendering-time');
47 | if (averageRenderingTimeElement != null) {
48 | averageRenderingTimeElement.innerHTML = Math.round(averageFrameDuration) + 'ms';
49 | }
50 |
51 | var averageFpsElement = document.getElementById('average-fps');
52 | if (averageFpsElement != null) {
53 | averageFpsElement.innerHTML = Math.round(averagefps) + ' fps';
54 | }
55 |
56 | var numberOfVisibleWorldStaticMeshChunksElement = document.getElementById('number-of-visible-world-static-mesh-chunks');
57 | if (numberOfVisibleWorldStaticMeshChunksElement != null) {
58 | numberOfVisibleWorldStaticMeshChunksElement.innerHTML = engine.stats.numberOfVisibleWorldStaticMeshChunks;
59 | }
60 |
61 | var numberOfVisibleActorsElement = document.getElementById('number-of-visible-actors');
62 | if (numberOfVisibleActorsElement != null) {
63 | numberOfVisibleActorsElement.innerHTML = engine.stats.numberOfVisibleActors;
64 | }
65 |
66 | var numberOfVisibleLightsElement = document.getElementById('number-of-visible-lights');
67 | if (numberOfVisibleLightsElement != null) {
68 | numberOfVisibleLightsElement.innerHTML = engine.stats.numberOfVisibleLights;
69 | }
70 |
71 | var numberOfShadowMapsBuiltThisFrameElement = document.getElementById('number-of-shadow-maps-built-this-frame');
72 | if (numberOfShadowMapsBuiltThisFrameElement != null) {
73 | numberOfShadowMapsBuiltThisFrameElement.innerHTML = engine.stats.numberOfShadowMapsBuiltThisFrame;
74 | }
75 |
76 | var cameraIsWithinMapElement = document.getElementById('camera-is-within-map');
77 | if (cameraIsWithinMapElement != null) {
78 | cameraIsWithinMapElement.innerHTML = engine.stats.cameraIsWithinMap;
79 | }
80 |
81 |
82 |
83 | this.lastTenFramesTotalDuration = 0;
84 | this.fpsCounterTickUp = 0;
85 | }
86 | }
--------------------------------------------------------------------------------
/js/engine/free-look-camera-controller.js:
--------------------------------------------------------------------------------
1 | function FreeLookCameraController(engine) {
2 |
3 | var self = this;
4 |
5 | this.rotation = vec3.create();
6 | this.rotateRate = 0.001;
7 | this.moveRate = 0.3;
8 |
9 | this.init = function (callback) {
10 |
11 | vec3.set(engine.camera.position, 0, 1, 0);
12 |
13 | engine.mouse.addMouseMoveListener(function (event) {
14 |
15 | if (engine.mode != 'editor') {
16 | return;
17 | }
18 |
19 | self.handleMouseMove(event);
20 | });
21 |
22 | callback();
23 | }
24 |
25 | this.heartbeat = function () {
26 |
27 | var $ = this.$heartbeat;
28 |
29 | var camera = engine.camera;
30 |
31 | math3D.buildAxesFromRotations(camera.axes, this.rotation);
32 |
33 | math3D.buildMovementNormalFromAxes(
34 | $.movementNormal, camera.axes, engine.keyboard.movementAxisMultipliers);
35 |
36 | var movementAmount = this.moveRate * engine.frameTimer.frameDelta;
37 |
38 | vec3.scaleAndAdd(camera.position, engine.camera.position, $.movementNormal, movementAmount);
39 | }
40 |
41 | this.handleMouseMove = function (event) {
42 |
43 | this.rotation[0] += this.rotateRate * event.movementY * -1;
44 | this.rotation[1] += this.rotateRate * event.movementX * -1;
45 | }
46 |
47 | // Function locals.
48 | this.$heartbeat = {
49 | movementNormal: vec3.create()
50 | }
51 | }
--------------------------------------------------------------------------------
/js/engine/gl-manager.js:
--------------------------------------------------------------------------------
1 | function GlManager(engine) {
2 |
3 | var self = this;
4 |
5 | this.gl = null;
6 | this.viewportInfo = null
7 |
8 | this.init = function (callback) {
9 |
10 | self.log('Initialising WebGL...');
11 |
12 | var canvas = document.getElementById('canvas');
13 |
14 | self.gl = canvas.getContext('experimental-webgl');
15 |
16 | var requiredExtensionNames = [
17 | 'OES_texture_float',
18 | 'OES_texture_float_linear',
19 | //'WEBGL_draw_buffers',
20 | 'WEBGL_depth_texture'];
21 |
22 | for (var i = 0; i < requiredExtensionNames.length; i++) {
23 | var extensionName = requiredExtensionNames[i];
24 | if (self.gl.getExtension(extensionName) == null) {
25 | throw 'Extention not available: ' + extensionName;
26 | }
27 | }
28 |
29 | //canvas.width = canvas.clientWidth;
30 | //canvas.height = canvas.clientHeight;
31 |
32 | self.viewportInfo = {
33 | width: canvas.width,
34 | height: canvas.height
35 | }
36 |
37 | self.gl.viewport(0, 0, self.viewportInfo.width, self.viewportInfo.height);
38 |
39 | self.log('... done.');
40 |
41 | callback();
42 | }
43 |
44 | this.log = function (message) {
45 |
46 | console.log('GL Manger: ' + message);
47 | }
48 | }
--------------------------------------------------------------------------------
/js/engine/gui-draw-spec-builder.js:
--------------------------------------------------------------------------------
1 | function GuiDrawSpecBuilder(engine) {
2 |
3 | this.buildGuiDrawSpecs = function (out, gui) {
4 |
5 | out.length = 0;
6 |
7 | var guiLayout = engine.guiLayoutManager.getGuiLayout(gui.layoutId);
8 | if (guiLayout == null) {
9 | return;
10 | }
11 |
12 | var spriteSheet = engine.spriteSheetManager.getSpriteSheet(guiLayout.spriteSheetId);
13 | if (spriteSheet == null) {
14 | return;
15 | }
16 |
17 | var texture = engine.textureManager.getTexture(spriteSheet.textureId);
18 | if (texture == null) {
19 | return;
20 | }
21 |
22 | for (var spriteId in guiLayout.spritesById) {
23 |
24 | var sprite = guiLayout.spritesById[spriteId];
25 |
26 | var spriteSpec = spriteSheet.spriteSpecsById[sprite.spriteSpecId];
27 | if (spriteSpec == null) {
28 | continue;
29 | }
30 |
31 | var drawSpec = out.items[out.length];
32 | if (drawSpec == null) {
33 | drawSpec = {
34 | position: vec2.create(),
35 | size: vec2.create(),
36 | rotation: 0,
37 | uvPosition: vec2.create(),
38 | uvSize: vec2.create(),
39 | visible: false
40 | }
41 |
42 | out.items[out.length] = drawSpec;
43 | }
44 |
45 | vec2.copy(drawSpec.position, sprite.position);
46 | vec2.copy(drawSpec.size, sprite.size);
47 | drawSpec.rotation = sprite.rotation;
48 |
49 | drawSpec.uvPosition[0] = spriteSpec.position[0] / texture.width;
50 | drawSpec.uvPosition[1] = spriteSpec.position[1] / texture.height;
51 |
52 | drawSpec.uvSize[0] = spriteSpec.size[0] / texture.width;
53 | drawSpec.uvSize[1] = spriteSpec.size[1] / texture.height;
54 |
55 | drawSpec.visible = sprite.visible;
56 |
57 | for (var animationId in guiLayout.animationsById) {
58 |
59 | var animationState = gui.animationStatesById[animationId];
60 | if (animationState == null || !animationState.active) {
61 | continue;
62 | }
63 |
64 | var animation = guiLayout.animationsById[animationId];
65 | var animationExpansion = engine.guiLayoutAnimationManager.getGuiLayoutAnimationExpansion(guiLayout.id, animation.id);
66 | if (animationExpansion == null) {
67 | continue;
68 | }
69 |
70 | var frameIndex = Math.floor(animationState.frameIndex);
71 | var tweenIndexes = animationExpansion.tweenIndexesByFrameIndex[frameIndex];
72 |
73 | for (var i = 0; i < tweenIndexes.length; i++) {
74 |
75 | var tweenIndex = tweenIndexes[i];
76 | var tween = animation.tweens[tweenIndex];
77 |
78 | if (tween.targetId != sprite.id) {
79 | continue;
80 | }
81 |
82 | var value = 0;
83 |
84 | if (tween.absoluteValue != null) {
85 |
86 | value = tween.absoluteValue;
87 |
88 | } else {
89 |
90 | var lerpFactor = math3D.calculateLerpFactor(tween.startFrameIndex, tween.startFrameIndex + tween.numberOfFrames, frameIndex);
91 | value = math3D.lerp(tween.fromValue, tween.toValue, lerpFactor);
92 | }
93 |
94 | if (tween.propertyId == SpritePropertyId.PositionXOffset) {
95 | drawSpec.position[0] += value;
96 | } else if (tween.propertyId == SpritePropertyId.PositionYOffset) {
97 | drawSpec.position[1] += value;
98 | } else if (tween.propertyId == SpritePropertyId.SizeXOffset) {
99 | drawSpec.size[0] += value;
100 | } else if (tween.propertyId == SpritePropertyId.SizeYOffset) {
101 | drawSpec.size[1] += value;
102 | } else if (tween.propertyId == SpritePropertyId.RotationOffset) {
103 | drawSpec.rotation += value;
104 | } else if (tween.propertyId == SpritePropertyId.Visible) {
105 | drawSpec.visible = value == 1;
106 | }
107 | }
108 |
109 | }
110 |
111 | vec2.divide(drawSpec.position, drawSpec.position, guiLayout.size);
112 | vec2.divide(drawSpec.size, drawSpec.size, guiLayout.size);
113 |
114 | out.length++;
115 | }
116 | }
117 | }
--------------------------------------------------------------------------------
/js/engine/gui-layout-animation-manager.js:
--------------------------------------------------------------------------------
1 | function GuiLayoutAnimationManager(engine) {
2 |
3 | this.guiLayoutAnimationExpansionSetsByLayoutId = {
4 | }
5 |
6 | this.getGuiLayoutAnimationExpansion = function (layoutId, animationId) {
7 |
8 | var set = this.guiLayoutAnimationExpansionSetsByLayoutId[layoutId];
9 | if (set == null) {
10 | return null;
11 | }
12 |
13 | var animationExpansion = set[animationId];
14 |
15 | return animationExpansion;
16 | }
17 |
18 | this.buildGuiLayoutAnimationExpansion = function (layoutId, animationId) {
19 |
20 | var set = this.guiLayoutAnimationExpansionSetsByLayoutId[layoutId];
21 | if (set == null) {
22 | set = {}
23 | this.guiLayoutAnimationExpansionSetsByLayoutId[layoutId] = set;
24 | }
25 |
26 | var animationExpansion = {
27 | tweenIndexesByFrameIndex: []
28 | }
29 |
30 | set[animationId] = animationExpansion;
31 |
32 | var layout = engine.guiLayoutManager.getGuiLayout(layoutId);
33 | var animation = layout.animationsById[animationId];
34 |
35 | for (var i = 0; i < animation.numberOfFrames; i++) {
36 | animationExpansion.tweenIndexesByFrameIndex[i] = [];
37 | }
38 |
39 | for (var tweenIndex = 0; tweenIndex < animation.tweens.length; tweenIndex++) {
40 |
41 | var tween = animation.tweens[tweenIndex];
42 |
43 | for (var frameIndex = tween.startFrameIndex; frameIndex < tween.startFrameIndex + tween.numberOfFrames; frameIndex++) {
44 | animationExpansion.tweenIndexesByFrameIndex[frameIndex].push(tweenIndex);
45 | }
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/js/engine/gui-layout-manager.js:
--------------------------------------------------------------------------------
1 | function GuiLayoutManager(engine) {
2 |
3 | var self = this;
4 |
5 | this.guiLayoutsById = {};
6 | this.loadingGuiLayoutIds = {};
7 | this.failedGuiLayoutIds = {};
8 |
9 | this.loadGuiLayout = function (guiLayoutId, callback) {
10 |
11 | callback = callback || function () { }
12 |
13 | if (guiLayoutId == null) {
14 | callback(null);
15 | return;
16 | }
17 |
18 | var guiLayout = this.guiLayoutsById[guiLayoutId];
19 |
20 | if (guiLayout != null) {
21 | callback(guiLayout);
22 | return;
23 | }
24 |
25 | if (this.loadingGuiLayoutIds[guiLayoutId] || this.failedGuiLayoutIds[guiLayoutId]) {
26 | callback(null);
27 | return;
28 | }
29 |
30 | this.log('Loading GUI layout: ' + guiLayoutId);
31 |
32 | this.loadingGuiLayoutIds[guiLayoutId] = guiLayoutId;
33 |
34 | engine.resourceLoader.loadJsonResource('gui-layout', guiLayoutId, function (guiLayout) {
35 |
36 | if (guiLayout == null) {
37 |
38 | self.failedGuiLayoutIds[guiLayoutId] = true;
39 |
40 | } else {
41 |
42 | self.guiLayoutsById[guiLayoutId] = guiLayout;
43 | }
44 |
45 | delete self.loadingGuiLayoutIds[guiLayoutId];
46 |
47 | callback(guiLayout);
48 | });
49 | }
50 |
51 | this.getGuiLayout = function (guiLayoutId) {
52 |
53 | if (guiLayoutId == null) {
54 | return null;
55 | }
56 |
57 | return this.guiLayoutsById[guiLayoutId];
58 | }
59 |
60 | this.log = function (message) {
61 |
62 | console.log('GUI Layout Manager: ' + message);
63 | }
64 | }
--------------------------------------------------------------------------------
/js/engine/keyboard.js:
--------------------------------------------------------------------------------
1 | function Keyboard(engine) {
2 |
3 | this.state = {};
4 |
5 | this.A = 65;
6 | this.D = 68;
7 | this.W = 83;
8 | this.S = 87;
9 |
10 | this.movementAxisMultipliers = vec3.create();
11 |
12 | this.init = function (callback) {
13 |
14 | var self = this;
15 |
16 | window.addEventListener('keydown', function (event) {
17 |
18 | self.state[event.which] = true;
19 |
20 | if (event.which == self.A) {
21 | self.movementAxisMultipliers[0] = -1;
22 | } else if (event.which == self.D) {
23 | self.movementAxisMultipliers[0] = 1;
24 | } else if (event.which == self.W) {
25 | self.movementAxisMultipliers[2] = -1;
26 | } else if (event.which == self.S) {
27 | self.movementAxisMultipliers[2] = 1;
28 | }
29 | });
30 |
31 | window.addEventListener('keyup', function (event) {
32 |
33 | self.state[event.which] = false;
34 |
35 | if (event.which == self.A && self.movementAxisMultipliers[0] == -1) {
36 | self.movementAxisMultipliers[0] = 0;
37 | } else if (event.which == self.D && self.movementAxisMultipliers[0] == 1) {
38 | self.movementAxisMultipliers[0] = 0;
39 | } else if (event.which == self.W && self.movementAxisMultipliers[2] == -1) {
40 | self.movementAxisMultipliers[2] = 0;
41 | } else if (event.which == self.S && self.movementAxisMultipliers[2] == 1) {
42 | self.movementAxisMultipliers[2] = 0;
43 | }
44 | });
45 |
46 | callback();
47 | }
48 | }
--------------------------------------------------------------------------------
/js/engine/line-drawer.js:
--------------------------------------------------------------------------------
1 | function LineDrawer(engine) {
2 |
3 | var gl = null;
4 |
5 | this.cubeVertexBuffer = null;
6 | this.sphereVertexBuffer = null;
7 | this.numSpherePoints = 0;
8 |
9 | this.init = function (callback) {
10 |
11 | gl = engine.glManager.gl;
12 |
13 | this.initCube();
14 | this.initSphere();
15 |
16 | callback();
17 | }
18 |
19 | this.initCube = function () {
20 |
21 | this.cubeVertexBuffer = gl.createBuffer();
22 |
23 | var points = [
24 | 0, 0, 0, 1, 0, 0, // Front bottom
25 | 0, 1, 0, 1, 1, 0, // Front top
26 | 0, 0, 0, 0, 1, 0, // Front left
27 | 1, 0, 0, 1, 1, 0, // Front right
28 | 0, 0, -1, 1, 0, -1, // Back bottom
29 | 0, 1, -1, 1, 1, -1, // Back top
30 | 0, 0, -1, 0, 1, -1, // Back left
31 | 1, 0, -1, 1, 1, -1, // Back right
32 | 0, 0, 0, 0, 0, -1, // Left bottom
33 | 0, 1, 0, 0, 1, -1, // Left top
34 | 1, 0, 0, 1, 0, -1, // Right bottom
35 | 1, 1, 0, 1, 1, -1 // Right top
36 | ];
37 |
38 | gl.bindBuffer(gl.ARRAY_BUFFER, this.cubeVertexBuffer);
39 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW);
40 | }
41 |
42 | this.initSphere = function () {
43 |
44 | this.sphereVertexBuffer = gl.createBuffer();
45 |
46 | var points = [];
47 |
48 | var numSegments = 20;
49 | var numSegmentPoints = 40;
50 | var segmentRadiansStep = (Math.PI * 2) / numSegments;
51 | var segmentPointsRadiansStep = (Math.PI * 2) / numSegmentPoints;
52 | var segmentRadians = 0;
53 |
54 | for (var i = 0; i < numSegments; i++) {
55 |
56 | var segmentDirection = {
57 | x: Math.cos(segmentRadians),
58 | z: Math.sin(segmentRadians)
59 | }
60 |
61 | segmentRadians += segmentRadiansStep;
62 |
63 | var segmentPointsRadians = 0;
64 |
65 | for (var j = 0; j <= numSegmentPoints; j++) {
66 |
67 | var d = Math.sin(segmentPointsRadians);
68 |
69 | points.push(segmentDirection.x * d);
70 | points.push(Math.cos(segmentPointsRadians));
71 | points.push(segmentDirection.z * d);
72 |
73 | segmentPointsRadians += segmentPointsRadiansStep;
74 | }
75 | }
76 |
77 | this.numSpherePoints = points.length / 3;
78 |
79 | gl.bindBuffer(gl.ARRAY_BUFFER, this.sphereVertexBuffer);
80 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(points), gl.STATIC_DRAW);
81 | }
82 |
83 | this.drawCube = function (renderingParameters, position, size, colour, enableDepthTest) {
84 |
85 | if (colour == null) {
86 | colour = RgbColours.White;
87 | }
88 |
89 | if (enableDepthTest == null) {
90 | enableDepthTest = true;
91 | }
92 |
93 | var effect = engine.effectManager.useEffect('line');
94 |
95 | gl.uniformMatrix4fv(effect.uniforms.viewProjMatrix, false, renderingParameters.viewProjMatrix);
96 | gl.uniform3fv(effect.uniforms.position, position);
97 | gl.uniform3fv(effect.uniforms.size, size);
98 | gl.uniform3fv(effect.uniforms.colour, colour);
99 |
100 | gl.disable(gl.BLEND);
101 |
102 | gl.bindBuffer(gl.ARRAY_BUFFER, this.cubeVertexBuffer);
103 | gl.vertexAttribPointer(
104 | effect.attributes.vertexPosition,
105 | 3, gl.FLOAT, false, 0, 0);
106 | gl.enableVertexAttribArray(effect.attributes.vertexPosition);
107 |
108 | if (enableDepthTest) {
109 | gl.enable(gl.DEPTH_TEST);
110 | } else {
111 | gl.disable(gl.DEPTH_TEST);
112 | }
113 |
114 | //gl.disable(gl.DEPTH_TEST);
115 | gl.drawArrays(gl.LINES, 0, 24);
116 | //gl.enable(gl.DEPTH_TEST);
117 | }
118 |
119 | this.drawSphere = function (renderingParameters, position, radius, colour, enableDepthTest) {
120 |
121 | if (colour == null) {
122 | colour = RgbColours.White;
123 | }
124 |
125 | var effect = engine.effectManager.useEffect('line');
126 |
127 | gl.uniformMatrix4fv(effect.uniforms.viewProjMatrix, false, renderingParameters.viewProjMatrix);
128 | gl.uniform3fv(effect.uniforms.position, position);
129 | gl.uniform3f(effect.uniforms.size, radius, radius, radius);
130 | gl.uniform3fv(effect.uniforms.colour, colour);
131 |
132 | gl.disable(gl.BLEND);
133 |
134 | gl.bindBuffer(gl.ARRAY_BUFFER, this.sphereVertexBuffer);
135 | gl.vertexAttribPointer(
136 | effect.attributes.vertexPosition,
137 | 3, gl.FLOAT, false, 0, 0);
138 | gl.enableVertexAttribArray(effect.attributes.vertexPosition);
139 |
140 | if (enableDepthTest) {
141 | gl.enable(gl.DEPTH_TEST);
142 | } else {
143 | gl.disable(gl.DEPTH_TEST);
144 | }
145 |
146 | //gl.disable(gl.DEPTH_TEST);
147 | gl.drawArrays(gl.LINE_STRIP, 0, this.numSpherePoints);
148 | //gl.enable(gl.DEPTH_TEST);
149 | }
150 | }
--------------------------------------------------------------------------------
/js/engine/map-data-helper.js:
--------------------------------------------------------------------------------
1 | function MapDataHelper(engine) {
2 |
3 | this.checkMapData = function () {
4 |
5 | this.checkGameData();
6 | this.checkActorsData();
7 | this.checkEmittersData();
8 | this.checkTriggersData();
9 | }
10 |
11 | this.checkGameData = function () {
12 |
13 | if (engine.map.gameData == null) {
14 | engine.map.gameData = {}
15 | }
16 |
17 | var controller = engine.gameControllersById[engine.map.gameControllerId];
18 |
19 | if (controller != null && controller.dataSchema != null) {
20 |
21 | this.checkData(engine.map.gameData, controller.dataSchema);
22 | }
23 | }
24 |
25 | this.checkActorsData = function () {
26 |
27 | for (var actorId in engine.map.actorsById) {
28 |
29 | var actor = engine.map.actorsById[actorId];
30 |
31 | this.checkActorData(actor);
32 | }
33 | }
34 |
35 | this.checkActorData = function (actor) {
36 |
37 | if (actor.data == null) {
38 | actor.data = {}
39 | }
40 |
41 | var controller = engine.actorControllersById[actor.controllerId];
42 |
43 | if (controller != null && controller.dataSchema != null) {
44 |
45 | this.checkData(actor.data, controller.dataSchema);
46 | }
47 | }
48 |
49 | this.checkEmittersData = function () {
50 |
51 | for (var emitterId in engine.map.emittersById) {
52 |
53 | var emitter = engine.map.emittersById[emitterId];
54 |
55 | this.checkEmitterData(emitter);
56 |
57 | for (var i = 0; i < emitter.particles.length; i++) {
58 |
59 | var particle = emitter.particles[i];
60 |
61 | this.checkParticleData(emitter, particle);
62 | }
63 | }
64 | }
65 |
66 | this.checkEmitterData = function (emitter) {
67 |
68 | if (emitter.data == null) {
69 | emitter.data = {}
70 | }
71 |
72 | var controller = engine.actorControllersById[emitter.emitterControllerId];
73 |
74 | if (controller != null && controller.dataSchema != null) {
75 |
76 | this.checkData(emitter.data, controller.dataSchema);
77 | }
78 | }
79 |
80 | this.checkParticleData = function (emitter, particle) {
81 |
82 | if (particle.data == null) {
83 | particle.data = {}
84 | }
85 |
86 | var controller = engine.actorControllersById[emitter.particleControllerId];
87 |
88 | if (controller != null && controller.dataSchema != null) {
89 |
90 | this.checkData(particle.data, controller.dataSchema);
91 | }
92 | }
93 |
94 | this.checkTriggersData = function () {
95 |
96 | for (var triggerId in engine.map.triggersById) {
97 |
98 | var trigger = engine.map.triggersById[triggerId];
99 |
100 | this.checkTriggerData(trigger);
101 | }
102 | }
103 |
104 | this.checkTriggerData = function (trigger) {
105 |
106 | if (trigger.data == null) {
107 | trigger.data = {}
108 | }
109 |
110 | var controller = engine.triggerControllersById[trigger.controllerId];
111 |
112 | if (controller != null && controller.dataSchema != null) {
113 |
114 | this.checkData(trigger.data, controller.dataSchema);
115 | }
116 | }
117 |
118 | this.checkData = function (data, dataSchema) {
119 |
120 | for (var propertyName in dataSchema) {
121 |
122 | var property = dataSchema[propertyName];
123 |
124 | if (data[propertyName] == null) {
125 | data[propertyName] = property.defaultValue;
126 | }
127 | }
128 | }
129 | }
--------------------------------------------------------------------------------
/js/engine/material-manager.js:
--------------------------------------------------------------------------------
1 | function MaterialManager(engine) {
2 |
3 | var self = this;
4 |
5 | this.materialsById = {};
6 | this.loadingMaterialIds = {};
7 | this.failedMaterialIds = {};
8 |
9 | this.loadMaterial = function (materialId, callback) {
10 |
11 | callback = callback || function () { }
12 |
13 | if (materialId == null) {
14 | callback(null);
15 | return;
16 | }
17 |
18 | var material = this.materialsById[materialId];
19 |
20 | if (material != null) {
21 | callback(material);
22 | return;
23 | }
24 |
25 | if (this.loadingMaterialIds[materialId] || this.failedMaterialIds[materialId]) {
26 | callback(null);
27 | return;
28 | }
29 |
30 | this.log('Loading material: ' + materialId);
31 |
32 | this.loadingMaterialIds[materialId] = materialId;
33 |
34 | engine.resourceLoader.loadJsonResource('material', materialId, function (material) {
35 |
36 | if (material == null) {
37 |
38 | self.failedMaterialIds[materialId] = true;
39 |
40 | } else {
41 |
42 | self.materialsById[materialId] = material;
43 | }
44 |
45 | delete self.loadingMaterialIds[materialId];
46 |
47 | callback(material);
48 | });
49 | }
50 |
51 | this.getMaterial = function (materialId) {
52 |
53 | if (materialId == null) {
54 | return null;
55 | }
56 |
57 | return this.materialsById[materialId];
58 | }
59 |
60 | this.log = function (message) {
61 |
62 | console.log('Material Manager: ' + message);
63 | }
64 | }
--------------------------------------------------------------------------------
/js/engine/math/math-aabb.js:
--------------------------------------------------------------------------------
1 | function MathAABB() {
2 |
3 | this.buildAABBFromPoints = function (out, points) {
4 |
5 | var from = out.from;
6 | var to = out.to;
7 |
8 | var fromIsSet = false;
9 | var toIsSet = false;
10 |
11 | for (var i = 0; i < points.length; i++) {
12 | var point = points[i];
13 |
14 | if (!fromIsSet) {
15 | vec3.copy(from, point);
16 | fromIsSet = true;
17 | } else if (point[0] < from[0]) {
18 | from[0] = point[0];
19 | } else if (point[1] < from[1]) {
20 | from[1] = point[1];
21 | } else if (point[2] > from[2]) {
22 | from[2] = point[2];
23 | }
24 |
25 | if (!toIsSet) {
26 | vec3.copy(to, point);
27 | toIsSet = true;
28 | } else if (point[0] > to[0]) {
29 | to[0] = point[0];
30 | } else if (point[1] > to[1]) {
31 | to[1] = point[1];
32 | } else if (point[2] < to[2]) {
33 | to[2] = point[2];
34 | }
35 | }
36 | }
37 |
38 | this.buildAABBPoints = function (out, aabb) {
39 |
40 | /*var points = [
41 | [aabb.from[0], aabb.from[1], aabb.from[2]],
42 | [aabb.to[0], aabb.from[1], aabb.from[2]],
43 | [aabb.from[0], aabb.to[1], aabb.from[2]],
44 | [aabb.to[0], aabb.to[1], aabb.from[2]],
45 | [aabb.from[0], aabb.from[1], aabb.to[2]],
46 | [aabb.to[0], aabb.from[1], aabb.to[2]],
47 | [aabb.from[0], aabb.to[1], aabb.to[2]],
48 | [aabb.to[0], aabb.to[1], aabb.to[2]]
49 | ];
50 |
51 | return points;
52 | */
53 |
54 | out[0][0] = aabb.from[0]; out[0][1] = aabb.from[1]; out[0][2] = aabb.from[2];
55 | out[1][0] = aabb.to[0]; out[1][1] = aabb.from[1]; out[1][2] = aabb.from[2];
56 | out[2][0] = aabb.from[0]; out[2][1] = aabb.to[1]; out[2][2] = aabb.from[2];
57 | out[3][0] = aabb.to[0]; out[3][1] = aabb.to[1]; out[3][2] = aabb.from[2];
58 | out[4][0] = aabb.from[0]; out[4][1] = aabb.from[1]; out[4][2] = aabb.to[2];
59 | out[5][0] = aabb.to[0]; out[5][1] = aabb.from[1]; out[5][2] = aabb.to[2];
60 | out[6][0] = aabb.from[0]; out[6][1] = aabb.to[1]; out[6][2] = aabb.to[2];
61 | out[7][0] = aabb.to[0]; out[7][1] = aabb.to[1]; out[7][2] = aabb.to[2];
62 | }
63 |
64 |
65 | this.calculateAABBSize = function (out, aabb) {
66 |
67 | //return [aabb.to[0] - aabb.from[0], aabb.to[1] - aabb.from[1], aabb.from[2] - aabb.to[2]];
68 |
69 | out[0] = aabb.to[0] - aabb.from[0];
70 | out[1] = aabb.to[1] - aabb.from[1];
71 | out[2] = aabb.from[2] - aabb.to[2];
72 | }
73 |
74 | /*this.cloneAABB = function (aabb) {
75 |
76 | return new AABB(vec3.clone(aabb.from), vec3.clone(aabb.to));
77 | }*/
78 |
79 | this.translateAABB = function (aabb, amount) {
80 |
81 | vec3.add(aabb.from, aabb.from, amount);
82 | vec3.add(aabb.to, aabb.to, amount);
83 | }
84 |
85 | this.clampPointToAABB = function (out, point, aabb) {
86 |
87 | vec3.copy(out, point);
88 |
89 | if (point[0] < aabb.from[0]) {
90 | out[0] = aabb.from[0];
91 | }
92 |
93 | if (point[1] < aabb.from[1]) {
94 | out[1] = aabb.from[1];
95 | }
96 |
97 | if (point[2] > aabb.from[2]) {
98 | out[2] = aabb.from[2];
99 | }
100 |
101 | if (point[0] > aabb.to[0]) {
102 | out[0] = aabb.to[0];
103 | }
104 |
105 | if (point[1] > aabb.to[1]) {
106 | out[1] = aabb.to[1];
107 | }
108 |
109 | if (point[2] < aabb.to[2]) {
110 | out[2] = aabb.to[2];
111 | }
112 | }
113 |
114 | this.checkAAABIntersectsAABB = function (aabb1, aabb2) {
115 |
116 | if (aabb1.from[0] > aabb2.to[0] ||
117 | aabb1.from[1] > aabb2.to[1] ||
118 | aabb1.from[2] < aabb2.to[2] ||
119 | aabb1.to[0] < aabb2.from[0] ||
120 | aabb1.to[1] < aabb2.from[1] ||
121 | aabb1.to[2] > aabb2.from[2]) {
122 |
123 | return false;
124 | }
125 |
126 | return true;
127 | }
128 |
129 | this.checkPointIsWithinAABB = function (aabb, point) {
130 |
131 | if (aabb.from[0] > point[0] ||
132 | aabb.from[1] > point[1] ||
133 | aabb.from[2] < point[2] ||
134 | aabb.to[0] < point[0] ||
135 | aabb.to[1] < point[1] ||
136 | aabb.to[2] > point[2]) {
137 |
138 | return false;
139 | }
140 |
141 | return true;
142 | }
143 | }
--------------------------------------------------------------------------------
/js/engine/math/math-collision-face.js:
--------------------------------------------------------------------------------
1 | function MathCollisionFace() {
2 |
3 | this.buildCollisionFaceFromPoints = function (points) {
4 |
5 | var $ = this.$buildCollisionFaceFromPoints;
6 |
7 | // Calculate face normal.
8 | vec3.sub($.freeEdgeAB, points[1], points[0]);
9 | vec3.sub($.freeEdgeAC, points[2], points[0]);
10 |
11 | vec3.cross($.faceNormal, $.freeEdgeAB, $.freeEdgeAC);
12 | vec3.normalize($.faceNormal, $.faceNormal);
13 |
14 | var facePlane = new Plane(); // FIXME
15 | math3D.buildPlaneFromNormalAndPoint(facePlane, $.faceNormal, points[0]);
16 |
17 | // Calculate the edge planes and edge lengths.
18 | var freeNormalisedEdges = [vec3.create(), vec3.create(), vec3.create()];
19 | var edgeLengths = [];
20 |
21 | vec3.sub(freeNormalisedEdges[0], points[1], points[0]);
22 | edgeLengths[0] = vec3.length(freeNormalisedEdges[0]);
23 | vec3.normalize(freeNormalisedEdges[0], freeNormalisedEdges[0]);
24 |
25 | vec3.sub(freeNormalisedEdges[1], points[2], points[1]);
26 | edgeLengths[1] = vec3.length(freeNormalisedEdges[1]);
27 | vec3.normalize(freeNormalisedEdges[1], freeNormalisedEdges[1]);
28 |
29 | vec3.sub(freeNormalisedEdges[2], points[0], points[2]);
30 | edgeLengths[2] = vec3.length(freeNormalisedEdges[2]);
31 | vec3.normalize(freeNormalisedEdges[2], freeNormalisedEdges[2]);
32 |
33 | var edgePlaneNormals = [vec3.create(), vec3.create(), vec3.create()]; // FIXME
34 |
35 | vec3.cross(edgePlaneNormals[0], freeNormalisedEdges[0], $.faceNormal);
36 | vec3.cross(edgePlaneNormals[1], freeNormalisedEdges[1], $.faceNormal);
37 | vec3.cross(edgePlaneNormals[2], freeNormalisedEdges[2], $.faceNormal);
38 |
39 | var edgePlanes = [new Plane(), new Plane(), new Plane()];
40 |
41 | math3D.buildPlaneFromNormalAndPoint(edgePlanes[0], edgePlaneNormals[0], points[0]);
42 | math3D.buildPlaneFromNormalAndPoint(edgePlanes[1], edgePlaneNormals[1], points[1]);
43 | math3D.buildPlaneFromNormalAndPoint(edgePlanes[2], edgePlaneNormals[2], points[2]);
44 |
45 | return new CollisionFace(points, facePlane, edgePlanes, freeNormalisedEdges, edgeLengths);
46 | }
47 |
48 | this.findNearestPointOnCollisionFacePerimeterToPoint = function (out, collisionFace, point) {
49 |
50 | var $ = this.$findNearestPointOnCollisionFacePerimeterToPoint;
51 |
52 | var nearestPointDistanceSqr = -1
53 |
54 | for (var i = 0; i < 3; i++) {
55 |
56 | vec3.copy($.ray.origin, collisionFace.points[i]);
57 | vec3.copy($.ray.normal, collisionFace.freeNormalisedEdges[i]);
58 |
59 | math3D.calculateNearestPointOnRayToOtherPoint($.potentialNearestPoint, $.ray, point, collisionFace.edgeLengths[i]);
60 |
61 | var potentialNearestPointDistanceSqr = vec3.sqrDist(point, $.potentialNearestPoint);
62 |
63 | if (nearestPointDistanceSqr == -1 || potentialNearestPointDistanceSqr < nearestPointDistanceSqr) {
64 | nearestPointDistanceSqr = potentialNearestPointDistanceSqr;
65 | vec3.copy(out, $.potentialNearestPoint);
66 | }
67 | }
68 | }
69 |
70 | this.determineIfPointOnFacePlaneIsWithinCollisionFace = function (collisionFace, point) {
71 |
72 | for (var i = 0; i < collisionFace.edgePlanes.length; i++) {
73 |
74 | var edgePlane = collisionFace.edgePlanes[i];
75 |
76 | var distanceToEdgePlane = math3D.calculatePointDistanceFromPlane(edgePlane, point);
77 |
78 | if (distanceToEdgePlane > 0) {
79 | return false;
80 | }
81 | }
82 |
83 | return true;
84 | }
85 |
86 | // Function locals.
87 | this.$buildCollisionFaceFromPoints = {
88 | freeEdgeAB: vec3.create(),
89 | freeEdgeAC: vec3.create(),
90 | faceNormal: vec3.create()
91 | }
92 |
93 | this.$findNearestPointOnCollisionFacePerimeterToPoint = {
94 | ray: new Ray(),
95 | potentialNearestPoint: vec3.create()
96 | }
97 | }
--------------------------------------------------------------------------------
/js/engine/math/math-collision-line.js:
--------------------------------------------------------------------------------
1 | function MathCollisionLine() {
2 |
3 | this.buildCollisionLineFromFromAndToPoints = function (out) {
4 |
5 | vec3.copy(out.ray.origin, out.from);
6 |
7 | vec3.sub(out.ray.normal, out.to, out.from);
8 | out.length = vec3.length(out.ray.normal);
9 |
10 | vec3.normalize(out.ray.normal, out.ray.normal);
11 | }
12 |
13 | this.calculateCollisionLineIntersectionWithCollisionFace = function (out, line, face) {
14 |
15 | var $ = this.$calculateCollisionLineIntersectionWithCollisionFace;
16 |
17 | var isFrontSideCollision = math3D.calculatePointDistanceFromPlane(face.facePlane, line.from) > 0;
18 |
19 | var lineIntersects = math3D.calculateRayIntersectionWithPlane($.facePlaneIntersection, line.ray, face.facePlane);
20 |
21 | if (!lineIntersects) {
22 | return FaceIntersectionType.None;
23 | }
24 |
25 | if (!math3D.determineIfPointOnFacePlaneIsWithinCollisionFace(face, $.facePlaneIntersection)) {
26 | return FaceIntersectionType.None;
27 | }
28 |
29 | var distanceToFacePlaneIntersectionSqr = vec3.squaredDistance(line.from, $.facePlaneIntersection);
30 |
31 | var lineLengthSqr = line.length * line.length;
32 |
33 | if (distanceToFacePlaneIntersectionSqr > lineLengthSqr) {
34 | return FaceIntersectionType.None;
35 | }
36 |
37 | if (out != null) {
38 | vec3.copy(out, $.facePlaneIntersection);
39 | }
40 |
41 | return isFrontSideCollision ? FaceIntersectionType.FrontSide : FaceIntersectionType.BackSide;
42 | }
43 |
44 | this.determineIfCollisionLineIntersectsSphere = function (line, sphere) {
45 |
46 | var $ = this.$determineIfCollisionLineIntersectsSphere;
47 |
48 | var sphereSadiusSqr = sphere.radius * sphere.radius;
49 | var fromPointDistanceSqr = vec3.sqrDist(line.from, sphere.position);
50 | if (fromPointDistanceSqr <= sphereSadiusSqr) {
51 | return true;
52 | }
53 |
54 | var toPointDistanceSqr = vec3.sqrDist(line.from, sphere.position);
55 | if (toPointDistanceSqr <= sphereSadiusSqr) {
56 | return true;
57 | }
58 |
59 | var rayIntersectsSphere = math3D.calculateRayIntersectionWithSphere($.intersectionPoint, line.ray, sphere);
60 |
61 | if (!rayIntersectsSphere) {
62 | return false;
63 | }
64 |
65 | var distanceToIntersectionPointSqr = vec3.squaredDistance(line.from, $.intersectionPoint);
66 |
67 | var lineLengthSqr = line.length * line.length;
68 |
69 | if (distanceToIntersectionPointSqr > lineLengthSqr) {
70 | return false;
71 | }
72 |
73 | return true;
74 | }
75 |
76 | this.checkIfCollisionLineIntersectsAABB = function (line, aabb) {
77 |
78 | var $ = this.$checkIfCollisionLineIntersectsAABB;
79 |
80 | if (this.checkPointIsWithinAABB(aabb, line.from)) {
81 | return true;
82 | }
83 |
84 | if (this.checkPointIsWithinAABB(aabb, line.to)) {
85 | return true;
86 | }
87 |
88 | // Test if the ray intersection with any of the AABB's planes is within the AABB.
89 | this.buildPlaneFromNormalAndPoint($.planes[0], this.axes3D.positiveZ, aabb.from); // Front
90 | this.buildPlaneFromNormalAndPoint($.planes[1], this.axes3D.negativeZ, aabb.to); // Back
91 | this.buildPlaneFromNormalAndPoint($.planes[2], this.axes3D.negativeX, aabb.from); // Left
92 | this.buildPlaneFromNormalAndPoint($.planes[3], this.axes3D.positiveX, aabb.to); // Right
93 | this.buildPlaneFromNormalAndPoint($.planes[4], this.axes3D.positiveY, aabb.from); // Top
94 | this.buildPlaneFromNormalAndPoint($.planes[5], this.axes3D.negativeY, aabb.to); // Bottom
95 |
96 | for (var i = 0; i < $.planes.length; i++) {
97 | var lineIntersects = this.calculateRayIntersectionWithPlane($.planeIntersection, line.ray, $.planes[i]);
98 | if (lineIntersects && this.checkPointIsWithinAABB(aabb, $.planeIntersection)) {
99 | return true;
100 | }
101 | }
102 |
103 | return false;
104 | }
105 |
106 | // Function locals.
107 | this.$calculateCollisionLineIntersectionWithCollisionFace = {
108 | facePlaneIntersection: vec3.create()
109 | }
110 |
111 | this.$determineIfCollisionLineIntersectsSphere = {
112 | intersectionPoint: vec3.create()
113 | }
114 |
115 | this.$checkIfCollisionLineIntersectsAABB = {
116 | planes: [new Plane(), new Plane(), new Plane(), new Plane(), new Plane(), new Plane()],
117 | planeIntersection: vec3.create()
118 | }
119 | }
--------------------------------------------------------------------------------
/js/engine/math/math-frustum.js:
--------------------------------------------------------------------------------
1 | function MathFrustum() {
2 |
3 | this.buildFrustumFromViewProjMatrix = function (out, viewProjMatrix) {
4 |
5 | var $ = this.$buildFrustumFromViewProjMatrix;
6 |
7 | mat4.invert($.invViewProjMatrix, viewProjMatrix);
8 |
9 | if (!$.trianglesAreInitialised) {
10 |
11 | vec4.set($.triangles[FrustumPlane.Near][0], -1, 1, -1, 1);
12 | vec4.set($.triangles[FrustumPlane.Near][1], -1, -1, -1, 1);
13 | vec4.set($.triangles[FrustumPlane.Near][2], 1, 1, -1, 1);
14 |
15 | vec4.set($.triangles[FrustumPlane.Far][0], -1, 1, 1, 1);
16 | vec4.set($.triangles[FrustumPlane.Far][1], 1, 1, 1, 1);
17 | vec4.set($.triangles[FrustumPlane.Far][2], -1, -1, 1, 1);
18 |
19 | vec4.set($.triangles[FrustumPlane.Left][0], -1, 1, 1, 1);
20 | vec4.set($.triangles[FrustumPlane.Left][1], -1, -1, 1, 1);
21 | vec4.set($.triangles[FrustumPlane.Left][2], -1, 1, -1, 1);
22 |
23 | vec4.set($.triangles[FrustumPlane.Right][0], 1, 1, -1, 1);
24 | vec4.set($.triangles[FrustumPlane.Right][1], 1, -1, -1, 1);
25 | vec4.set($.triangles[FrustumPlane.Right][2], 1, 1, 1, 1);
26 |
27 | vec4.set($.triangles[FrustumPlane.Top][0], -1, 1, 1, 1);
28 | vec4.set($.triangles[FrustumPlane.Top][1], -1, 1, -1, 1);
29 | vec4.set($.triangles[FrustumPlane.Top][2], 1, 1, 1, 1);
30 |
31 | vec4.set($.triangles[FrustumPlane.Bottom][0], -1, -1, -1, 1);
32 | vec4.set($.triangles[FrustumPlane.Bottom][1], -1, -1, 1, 1);
33 | vec4.set($.triangles[FrustumPlane.Bottom][2], 1, -1, 1, 1);
34 |
35 | $.trianglesAreInitialised = true;
36 | }
37 |
38 | for (var triangleIndex = 0; triangleIndex < $.triangles.length; triangleIndex++) {
39 |
40 | var triangle = $.triangles[triangleIndex];
41 |
42 | for (var i = 0; i < triangle.length; i++) {
43 | var point = triangle[i];
44 | vec4.transformMat4($.tempPoint, point, $.invViewProjMatrix);
45 | vec4.set($.transformedPoints[i], $.tempPoint[0] / $.tempPoint[3], $.tempPoint[1] / $.tempPoint[3], $.tempPoint[2] / $.tempPoint[3]);
46 | }
47 |
48 | this.buildPlaneFromPoints(out.planes[triangleIndex], $.transformedPoints);
49 | }
50 | }
51 |
52 | this.checkFrustumIntersectsAABB = function (frustum, aabb) {
53 |
54 | var $ = this.$checkFrustumIntersectsAABB;
55 |
56 | var intersects = true;
57 |
58 | this.buildAABBPoints($.aabbPoints, aabb);
59 |
60 | for (var planeIndex = 0; planeIndex < frustum.planes.length; planeIndex++) {
61 |
62 | var plane = frustum.planes[planeIndex];
63 |
64 | var allPointsAreInfrontOfPlane = true;
65 |
66 | for (var pointIndex = 0; pointIndex < $.aabbPoints.length; pointIndex++) {
67 |
68 | var point = $.aabbPoints[pointIndex];
69 |
70 | var pointDistanceFromPlane = this.calculatePointDistanceFromPlane(plane, point);
71 |
72 | if (pointDistanceFromPlane <= 0) {
73 | allPointsAreInfrontOfPlane = false;
74 | break;
75 | }
76 | }
77 |
78 | if (allPointsAreInfrontOfPlane) {
79 | intersects = false;
80 | break;
81 | }
82 | }
83 |
84 | return intersects;
85 | }
86 |
87 | this.checkFrustumIntersectsSphere = function (frustum, sphere) {
88 |
89 | var intersects = true;
90 |
91 | for (var planeIndex = 0; planeIndex < frustum.planes.length; planeIndex++) {
92 |
93 | var plane = frustum.planes[planeIndex];
94 |
95 | var spherePositionDistanceFromPlane = this.calculatePointDistanceFromPlane(plane, sphere.position);
96 |
97 | if (spherePositionDistanceFromPlane > sphere.radius) {
98 | intersects = false;
99 | break;
100 | }
101 | }
102 |
103 | return intersects;
104 | }
105 |
106 | // Function locals.
107 | this.$checkFrustumIntersectsAABB = {
108 | aabbPoints: [
109 | vec3.create(), vec3.create(), vec3.create(), vec3.create(),
110 | vec3.create(), vec3.create(), vec3.create(), vec3.create()]
111 | }
112 |
113 | this.$buildFrustumFromViewProjMatrix = {
114 | invViewProjMatrix: mat4.create(),
115 | triangles: [
116 | [vec4.create(), vec4.create(), vec4.create()],
117 | [vec4.create(), vec4.create(), vec4.create()],
118 | [vec4.create(), vec4.create(), vec4.create()],
119 | [vec4.create(), vec4.create(), vec4.create()],
120 | [vec4.create(), vec4.create(), vec4.create()],
121 | [vec4.create(), vec4.create(), vec4.create()]
122 | ],
123 | trianglesAreInitialised: false,
124 | transformedPoints: [vec4.create(), vec4.create(), vec4.create()],
125 | tempPoint: vec4.create()
126 | }
127 | }
--------------------------------------------------------------------------------
/js/engine/math/math-plane.js:
--------------------------------------------------------------------------------
1 | function MathPlane() {
2 |
3 | this.buildPlaneFromPoints = function (out, points) {
4 |
5 | var vecA = vec3.create();
6 | var vecB = vec3.create();
7 | vec3.subtract(vecA, points[1], points[0]);
8 | vec3.subtract(vecB, points[2], points[0]);
9 |
10 | //var normal = vec3.create();
11 | vec3.cross(out.normal, vecA, vecB);
12 | vec3.normalize(out.normal, out.normal);
13 |
14 | out.d = -vec3.dot(out.normal, points[0]);
15 |
16 | //var plane = new Plane(normal, d);
17 |
18 | //return plane;
19 | }
20 |
21 | this.buildPlaneFromNormalAndPoint = function (out, normal, point) {
22 |
23 | vec3.copy(out.normal, normal);
24 | out.d = -vec3.dot(normal, point);
25 | }
26 |
27 | this.calculatePointDistanceFromPlane = function (plane, point) {
28 |
29 | var distance = vec3.dot(plane.normal, point) + plane.d;
30 |
31 | return distance;
32 | }
33 |
34 | this.calculatePlaneIntersectionSlideReaction = function (out, plane, intersection, desiredDirection, desiredDistance) {
35 |
36 | var $ = this.$calculatePlaneIntersectionSlideReaction;
37 |
38 | vec3.scaleAndAdd($.targetPoint, intersection, desiredDirection, desiredDistance);
39 |
40 | vec3.copy($.targetPointToProjectionPointRay.origin, $.targetPoint);
41 | vec3.copy($.targetPointToProjectionPointRay.normal, plane.normal);
42 |
43 | var targetPointToProjectionPointRayIntersectsPlane = math3D.calculateRayIntersectionWithPlane(
44 | $.projectionPoint, $.targetPointToProjectionPointRay, plane);
45 |
46 | if (!targetPointToProjectionPointRayIntersectsPlane) {
47 | return false;
48 | }
49 |
50 | vec3.subtract($.slideVector, $.projectionPoint, intersection);
51 |
52 | var slideDistance = vec3.length($.slideVector);
53 |
54 | vec3.normalize($.slideVector, $.slideVector);
55 |
56 | // Copy out the results.
57 | vec3.copy(out.direction, $.slideVector);
58 | out.distance = slideDistance;
59 |
60 | return true;
61 | }
62 |
63 | this.copyPlane = function (out, plane) {
64 |
65 | vec3.copy(out.normal, plane.normal);
66 | out.d = plane.d;
67 | }
68 |
69 | // Function locals.
70 | this.$calculatePlaneIntersectionSlideReaction = {
71 | targetPoint: vec3.create(),
72 | targetPointToProjectionPointRay: new Ray(),
73 | projectionPoint: vec3.create(),
74 | slideVector: vec3.create()
75 | }
76 | }
--------------------------------------------------------------------------------
/js/engine/math/math-types.js:
--------------------------------------------------------------------------------
1 | function Scalar(value) {
2 |
3 | this.value = value;
4 | }
5 |
6 | function Sphere(position, radius) {
7 |
8 | this.position = position || vec3.create();
9 | this.radius = radius || 0;
10 | }
11 |
12 | function AABB(from, to) {
13 |
14 | this.from = from || vec3.create();
15 | this.to = to || vec3.create();
16 | }
17 |
18 | function Plane(normal, d) {
19 |
20 | this.normal = normal || vec3.create();
21 | this.d = d || 0;
22 | }
23 |
24 | function Frustum(planes) {
25 |
26 | this.planes = planes || [new Plane(), new Plane(), new Plane(), new Plane(), new Plane(), new Plane()];
27 | }
28 |
29 | function Ray(origin, normal) {
30 |
31 | this.origin = origin || vec3.create();
32 | this.normal = normal || vec3.create();
33 | }
34 |
35 | function Axes() {
36 | this.xAxis = vec3.create();
37 | this.yAxis = vec3.create();
38 | this.zAxis = vec3.create();
39 | }
40 |
41 | function CollisionLine(from, to, ray, length) {
42 |
43 | this.from = from || vec3.create();
44 | this.to = to || vec3.create()
45 | this.ray = ray || new Ray();
46 | this.length = length || 0;
47 | }
48 |
49 | function CollisionFace(points, facePlane, edgePlanes, freeNormalisedEdges, edgeLengths) {
50 |
51 | this.points = points;
52 | this.facePlane = facePlane;
53 | this.edgePlanes = edgePlanes;
54 | this.freeNormalisedEdges = freeNormalisedEdges;
55 | this.edgeLengths = edgeLengths;
56 | }
57 |
58 | function CalculateSphereCollisionWithCollisionFaceResult() {
59 |
60 | this.intersection = vec3.create();
61 | this.distance = 0;
62 | this.collisionPlane = new Plane();
63 | }
64 |
65 | function PlaneIntersectionSlideReaction() {
66 | this.direction = vec3.create();
67 | this.distance = 0;
68 | }
--------------------------------------------------------------------------------
/js/engine/mouse.js:
--------------------------------------------------------------------------------
1 | function Mouse(engine) {
2 |
3 | this.mouseMoveListeners = [];
4 | this.mouseIsDown = false;
5 | this.canvas = null;
6 |
7 | this.init = function (callback) {
8 |
9 | var self = this;
10 |
11 | this.canvas = document.getElementById('canvas');
12 |
13 | this.canvas.onclick = function () {
14 |
15 | self.canvas.requestPointerLock =
16 | self.canvas.requestPointerLock ||
17 | self.canvas.mozRequestPointerLock ||
18 | self.canvas.webkitRequestPointerLock;
19 |
20 | self.canvas.requestPointerLock();
21 | }
22 |
23 | document.addEventListener('mousemove', function (event) {
24 |
25 | if (self.hasPointerLock()) {
26 | for (var i = 0; i < self.mouseMoveListeners.length; i++) {
27 | self.mouseMoveListeners[i](event);
28 | }
29 | }
30 |
31 | }, false);
32 |
33 | document.addEventListener('mousedown', function (event) {
34 |
35 | if (self.hasPointerLock()) {
36 | self.mouseIsDown = true;
37 | }
38 |
39 | }, false);
40 |
41 | document.addEventListener('mouseup', function (event) {
42 |
43 | self.mouseIsDown = false;
44 |
45 | }, false);
46 |
47 | callback();
48 | }
49 |
50 | this.addMouseMoveListener = function (callback) {
51 |
52 | this.mouseMoveListeners.push(callback);
53 | }
54 |
55 | this.hasPointerLock = function () {
56 |
57 | document.pointerLockElement =
58 | document.pointerLockElement ||
59 | document.mozPointerLockElement ||
60 | document.webkitPointerLockElement;
61 |
62 | if (document.pointerLockElement !== this.canvas) {
63 | return false;
64 | }
65 |
66 | return true;
67 | }
68 | }
--------------------------------------------------------------------------------
/js/engine/particle-manager.js:
--------------------------------------------------------------------------------
1 | function ParticleManager(engine) {
2 |
3 | this.spawnParticle = function (emitter) {
4 |
5 | var particle = null;
6 |
7 | for (var i = 0; i < emitter.particles.length; i++) {
8 |
9 | var possibleParticle = emitter.particles[i];
10 |
11 | if (!possibleParticle.active) {
12 | particle = possibleParticle;
13 | break;
14 | }
15 | }
16 |
17 | if (particle == null) {
18 |
19 | particle = {
20 | active: false,
21 | position: [0, 0, 0],
22 | direction: [0, 0, 0],
23 | textureIds: [null, null, null, null],
24 | data: null,
25 | physics: {}
26 | }
27 |
28 | emitter.particles.push(particle);
29 | }
30 |
31 | particle.physics.mode = ParticlePhysicsMode.None;
32 | particle.physics.lastCollisionType = ParticleCollisionType.None;
33 |
34 | engine.mapDataHelper.checkParticleData(emitter, particle);
35 |
36 | particle.active = true;
37 |
38 | return particle;
39 | }
40 |
41 | this.heartbeat = function () {
42 |
43 | for (var emitterId in engine.map.emittersById) {
44 |
45 | var emitter = engine.map.emittersById[emitterId];
46 |
47 | for (var i = 0; i < emitter.particles.length; i++) {
48 |
49 | var particle = emitter.particles[i];
50 |
51 | if (!particle.active) {
52 | continue;
53 | }
54 |
55 | if (emitter.particleControllerId != null) {
56 |
57 | var particleController = engine.particleControllersById[emitter.particleControllerId];
58 |
59 | particleController.heartbeat(emitter, i);
60 | }
61 | }
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/js/engine/player-controller.js:
--------------------------------------------------------------------------------
1 | function PlayerController(engine) {
2 |
3 | var self = this;
4 |
5 | this.rotateRate = 0.003;
6 | this.moveRate = 0.2;
7 |
8 | this.init = function (callback) {
9 |
10 | engine.mouse.addMouseMoveListener(function (event) {
11 |
12 | if (engine.mode != 'game') {
13 | return;
14 | }
15 |
16 | self.handleMouseMove(event);
17 | });
18 |
19 | callback();
20 | }
21 |
22 | this.heartbeat = function () {
23 |
24 | var $ = this.$heartbeat;
25 |
26 | var player = engine.map.player;
27 |
28 | vec3.set($.playerYAxisOnlyRotation, 0, player.rotation[1], 0);
29 | math3D.buildAxesFromRotations($.movementAxes, $.playerYAxisOnlyRotation);
30 |
31 | math3D.buildMovementNormalFromAxes(
32 | $.movementNormal, $.movementAxes, engine.keyboard.movementAxisMultipliers);
33 |
34 | var movementAmount = this.moveRate * engine.frameTimer.frameDelta;
35 |
36 | this.movePlayerThoughMap($.movementNormal, movementAmount);
37 |
38 | engine.camera.position = player.position;
39 |
40 | math3D.buildAxesFromRotations(engine.camera.axes, player.rotation);
41 | }
42 |
43 | this.handleMouseMove = function (event) {
44 |
45 | var player = engine.map.player;
46 |
47 | player.rotation[0] += this.rotateRate * event.movementY * -1;
48 | player.rotation[1] += this.rotateRate * event.movementX * -1;
49 | }
50 |
51 | this.movePlayerThoughMap = function (movementNormal, movementAmount) {
52 |
53 | var $ = this.$movePlayerThoughMap;
54 |
55 | var player = engine.map.player;
56 | var heightOffGround = 1.0;
57 |
58 | vec3.copy($.collisionTestSphere.position, player.position);
59 | $.collisionTestSphere.radius = 0.45;
60 |
61 | vec3.sub($.collisionTestSphere.position, $.collisionTestSphere.position, [0, heightOffGround, 0]);
62 |
63 | engine.mapManager.moveSphereThroughMap($.collisionTestSphere, movementNormal, movementAmount, true);
64 |
65 | vec3.copy(engine.camera.position, $.collisionTestSphere.position);
66 | vec3.add(engine.camera.position, engine.camera.position, [0, heightOffGround, 0]);
67 | }
68 |
69 | // Function locals.
70 | this.$heartbeat = {
71 | movementAxes: new Axes(),
72 | //lookAxes: new Axes(),
73 | playerYAxisOnlyRotation: vec3.create(),
74 | movementNormal: vec3.create()
75 | }
76 |
77 | this.$movePlayerThoughMap = {
78 | collisionTestSphere: new Sphere()
79 | }
80 | }
--------------------------------------------------------------------------------
/js/engine/resource-checker.js:
--------------------------------------------------------------------------------
1 | function ResourceChecker(engine) {
2 |
3 | this.ensureResourcesAreLoaded = function () {
4 |
5 | var allResourcesAreLoaded = true;
6 |
7 | // Check static meshes.
8 | for (var staticMeshId in engine.staticMeshManager.staticMeshesById) {
9 |
10 | var staticMesh = engine.staticMeshManager.staticMeshesById[staticMeshId];
11 |
12 | for (var chunkIndex = 0; chunkIndex < staticMesh.chunks.length; chunkIndex++) {
13 | var chunk = staticMesh.chunks[chunkIndex];
14 | if (engine.materialManager.materialsById[chunk.materialId] == null) {
15 | engine.materialManager.loadMaterial(chunk.materialId);
16 | allResourcesAreLoaded = false;
17 | }
18 | }
19 | }
20 |
21 | // Check materials.
22 | for (var materialId in engine.materialManager.materialsById) {
23 | var material = engine.materialManager.materialsById[materialId];
24 |
25 | if (!util.stringIsNullOrEmpty(material.diffuseTextureId) && engine.textureManager.texturesById[material.diffuseTextureId] == null) {
26 | engine.textureManager.loadTexture(material.diffuseTextureId);
27 | allResourcesAreLoaded = false;
28 | }
29 |
30 | if (!util.stringIsNullOrEmpty(material.normalTextureId) && engine.textureManager.texturesById[material.normalTextureId] == null) {
31 | engine.textureManager.loadTexture(material.normalTextureId);
32 | allResourcesAreLoaded = false;
33 | }
34 |
35 | if (!util.stringIsNullOrEmpty(material.selfIlluminationTextureId) && engine.textureManager.texturesById[material.selfIlluminationTextureId] == null) {
36 | engine.textureManager.loadTexture(material.selfIlluminationTextureId);
37 | allResourcesAreLoaded = false;
38 | }
39 | }
40 |
41 | // Check actors.
42 | for (var actorId in engine.map.actorsById) {
43 |
44 | var actor = engine.map.actorsById[actorId];
45 |
46 | if (!util.stringIsNullOrEmpty(actor.staticMeshId) && engine.staticMeshManager.staticMeshesById[actor.staticMeshId] == null) {
47 |
48 | engine.staticMeshManager.loadStaticMesh(actor.staticMeshId, {
49 | buildChunkAABBs: true,
50 | buildChunkCollisionFaces: true,
51 | buildRotationSafeBoundingSphere: true
52 | });
53 |
54 | allResourcesAreLoaded = false;
55 | }
56 |
57 | if (!util.stringIsNullOrEmpty(actor.skinnedMeshId) && engine.skinnedMeshManager.getSkinnedMesh(actor.skinnedMeshId) == null) {
58 | engine.skinnedMeshManager.loadSkinnedMesh(actor.skinnedMeshId, { buildRotationSafeBoundingSphere: true });
59 | allResourcesAreLoaded = false;
60 | }
61 |
62 | if (!util.stringIsNullOrEmpty(actor.skinnedMeshAnimationId) && engine.skinnedMeshAnimationManager.skinnedMeshAnimationsById[actor.skinnedMeshAnimationId] == null) {
63 | engine.skinnedMeshAnimationManager.loadSkinnedMeshAnimation(actor.skinnedMeshAnimationId, {});
64 | allResourcesAreLoaded = false;
65 | }
66 | }
67 |
68 | // Check GUIs.
69 | for (var guiId in engine.map.guisById) {
70 |
71 | var gui = engine.map.guisById[guiId];
72 |
73 | if (engine.guiLayoutManager.guiLayoutsById[gui.layoutId] == null) {
74 | engine.guiLayoutManager.loadGuiLayout(gui.layoutId);
75 | allResourcesAreLoaded = false;
76 | }
77 | }
78 |
79 | // Check GUI layouts.
80 | for (var guiLayoutId in engine.guiLayoutManager.guiLayoutsById) {
81 |
82 | var guiLayout = engine.guiLayoutManager.guiLayoutsById[guiLayoutId];
83 |
84 | for (var animationId in guiLayout.animationsById) {
85 | if (engine.guiLayoutAnimationManager.getGuiLayoutAnimationExpansion(guiLayout.id, animationId) == null) {
86 | engine.guiLayoutAnimationManager.buildGuiLayoutAnimationExpansion(guiLayout.id, animationId);
87 | allResourcesAreLoaded = false;
88 | }
89 | }
90 |
91 | if (engine.spriteSheetManager.getSpriteSheet(guiLayout.spriteSheetId) == null) {
92 | engine.spriteSheetManager.loadSpriteSheet(guiLayout.spriteSheetId);
93 | allResourcesAreLoaded = false;
94 | }
95 | }
96 |
97 | // Check sprite sheets.
98 | for (var spriteSheetId in engine.spriteSheetManager.spriteSheetsById) {
99 |
100 | var spriteSheet = engine.spriteSheetManager.spriteSheetsById[spriteSheetId];
101 |
102 | if (engine.textureManager.getTexture(spriteSheet.textureId) == null) {
103 | engine.textureManager.loadTexture(spriteSheet.textureId);
104 | allResourcesAreLoaded = false;
105 | }
106 | }
107 |
108 | return allResourcesAreLoaded;
109 | }
110 | }
--------------------------------------------------------------------------------
/js/engine/resource-loader.js:
--------------------------------------------------------------------------------
1 | function ResourceLoader(engine) {
2 |
3 | this.loadTextResource = function (resourceType, resourceId, callback) {
4 |
5 | this.loadTextResourceInternal(resourceType, resourceId, 'txt', function (text) {
6 | callback(text);
7 | });
8 | }
9 |
10 | this.loadJsonResource = function (resourceType, resourceId, callback) {
11 |
12 | this.loadTextResourceInternal(resourceType, resourceId, 'json', function (json) {
13 |
14 | if (json == null) {
15 | callback(null);
16 | } else {
17 | var obj = JSON.parse(json);
18 | callback(obj);
19 | }
20 | });
21 | }
22 |
23 | this.loadImageResource = function (resourceType, resourceId, callback) {
24 |
25 | var url = this.getResourceUrl(resourceType, resourceId, 'png');
26 |
27 | var image = new Image();
28 |
29 | image.onload = function () {
30 | callback(image);
31 | }
32 |
33 | image.onerror = function () {
34 | console.log('Failed to load resource: ' + resourceId);
35 | callback(null);
36 | }
37 |
38 | image.src = url;
39 | }
40 |
41 | this.loadTextResourceInternal = function (resourceType, resourceId, dataType, callback) {
42 |
43 | var request = new XMLHttpRequest();
44 |
45 | request.onload = function () {
46 |
47 | if (request.status == 404) {
48 | console.log('Failed to load resource: ' + resourceId);
49 | callback(null);
50 | } else {
51 | callback(this.responseText);
52 | }
53 | }
54 |
55 | var url = this.getResourceUrl(resourceType, resourceId, dataType);
56 |
57 | request.open('get', url, true);
58 | request.send();
59 | }
60 |
61 | this.getResourceUrl = function (resourceType, resourceId, dataType) {
62 |
63 | return 'resources/' + this.getFolderNameForResourceType(resourceType) + '/' + resourceId + '.' + dataType + '?noCache=' + Math.random();
64 | }
65 |
66 | this.getFolderNameForResourceType = function (resourceType) {
67 |
68 | var resourceFoldersByResourceType = {
69 | 'map': 'maps',
70 | 'static-mesh': 'static-meshes',
71 | 'skinned-mesh': 'skinned-meshes',
72 | 'skinned-mesh-animation': 'skinned-mesh-animations',
73 | 'sector-set': 'sector-sets',
74 | 'shader': 'shaders',
75 | 'material': 'materials',
76 | 'texture': 'textures',
77 | 'gui-layout': 'gui-layouts',
78 | 'sprite-sheet': 'sprite-sheets',
79 | 'system': 'system'
80 | }
81 |
82 | return resourceFoldersByResourceType[resourceType];
83 | }
84 | }
--------------------------------------------------------------------------------
/js/engine/shadow-map-manager.js:
--------------------------------------------------------------------------------
1 | function ShadowMapManager(engine) {
2 |
3 | var self = this;
4 | var gl = null;
5 |
6 | this.bufferSize = 512;
7 |
8 | this.nextAvailableShadowMapChannel = null;
9 |
10 | this.shadowMaps = [];
11 |
12 | this.init = function (callback) {
13 |
14 | self.log('Initialising point light shadow map manager...');
15 |
16 | gl = engine.glManager.gl;
17 |
18 | self.log('... done.');
19 |
20 | callback();
21 | }
22 |
23 | this.allocateShadowMap = function (lightType) {
24 |
25 | if (this.nextAvailableShadowMapChannel == null) {
26 |
27 | this.createNewShadowMap(lightType);
28 |
29 | this.nextAvailableShadowMapChannel = 0;
30 | }
31 |
32 | var allocation = {
33 | index: this.shadowMaps.length - 1,
34 | channel: this.nextAvailableShadowMapChannel
35 | }
36 |
37 | this.log("Allocated shadow map " + allocation.index + ", channel: " + allocation.channel + ".");
38 |
39 | this.nextAvailableShadowMapChannel++;
40 | if (this.nextAvailableShadowMapChannel == 2) {
41 | this.nextAvailableShadowMapChannel = null;
42 | }
43 |
44 | return allocation;
45 | }
46 |
47 | this.createNewShadowMap = function (lightType) {
48 |
49 | if (lightType == 'point') {
50 |
51 | this.createPointLightShadowMap();
52 |
53 | } else {
54 |
55 | throw 'Unknown light type: ' + lightType;
56 | }
57 | }
58 |
59 | this.createPointLightShadowMap = function () {
60 |
61 | var shadowMap = {
62 | lightType: 'point',
63 | frameBuffer: null,
64 | cubeTexture: null
65 | };
66 |
67 | shadowMap.frameBuffer = gl.createFramebuffer();
68 | gl.bindFramebuffer(gl.FRAMEBUFFER, shadowMap.frameBuffer);
69 |
70 | shadowMap.cubeTexture = gl.createTexture();
71 | gl.bindTexture(gl.TEXTURE_CUBE_MAP, shadowMap.cubeTexture);
72 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
73 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
74 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
75 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
76 |
77 | gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA, this.bufferSize, this.bufferSize, 0, gl.RGBA, gl.FLOAT, null);
78 | gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA, this.bufferSize, this.bufferSize, 0, gl.RGBA, gl.FLOAT, null);
79 | gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA, this.bufferSize, this.bufferSize, 0, gl.RGBA, gl.FLOAT, null);
80 | gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA, this.bufferSize, this.bufferSize, 0, gl.RGBA, gl.FLOAT, null);
81 | gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA, this.bufferSize, this.bufferSize, 0, gl.RGBA, gl.FLOAT, null);
82 | gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA, this.bufferSize, this.bufferSize, 0, gl.RGBA, gl.FLOAT, null);
83 |
84 | gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
85 |
86 | gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, engine.renderer.shadowMapBuildBuffers.depthRenderBuffer);
87 |
88 | this.shadowMaps.push(shadowMap);
89 |
90 | this.log('Created new point light shadow map.');
91 | }
92 |
93 | this.buildViewProjMatrixForPointLightCubeMapFaceBuild = function (out, position, face) {
94 |
95 | var lookAt = vec3.create();
96 | vec3.add(lookAt, position, face.lookAt);
97 |
98 | var viewMatrix = mat4.create();
99 | mat4.lookAt(viewMatrix, position, lookAt, face.up);
100 |
101 | var projMatrix = mat4.create();
102 | mat4.perspective(projMatrix, Math.PI / 2.0, 1.0, 0.1, 10000.0);
103 |
104 | //var viewProjMatrix = mat4.create();
105 | mat4.multiply(out, projMatrix, viewMatrix);
106 |
107 | //return viewProjMatrix;
108 | }
109 |
110 | this.cleanUp = function () {
111 |
112 | this.log('Cleaning up...');
113 |
114 | for (var i = 0; i < this.shadowMaps.length; i++) {
115 |
116 | var shadowMap = this.shadowMaps[i];
117 |
118 | if (shadowMap.lightType == 'point') {
119 | gl.deleteFramebuffer(shadowMap.frameBuffer);
120 | gl.deleteTexture(shadowMap.cubeTexture);
121 | }
122 | }
123 |
124 | this.shadowMaps = [];
125 |
126 | this.log('... done.');
127 | }
128 |
129 | this.log = function (message) {
130 |
131 | console.log('Shadow Map Manager: ' + message);
132 | }
133 | }
--------------------------------------------------------------------------------
/js/engine/skinned-mesh-animation-manager.js:
--------------------------------------------------------------------------------
1 | function SkinnedMeshAnimationManager(engine) {
2 |
3 | var self = this;
4 | var gl = null;
5 |
6 | this.skinnedMeshAnimationsById = {};
7 | this.loadingSkinnedMeshAnimationIds = {};
8 | this.failedSkinnedMeshAnimationIds = {};
9 |
10 | this.init = function (callback) {
11 |
12 | gl = engine.glManager.gl;
13 |
14 | callback();
15 | }
16 |
17 | this.loadSkinnedMeshAnimation = function (skinnedMeshAnimationId, options, callback) {
18 |
19 | options = options || {};
20 |
21 | callback = callback || function () { }
22 |
23 | if (skinnedMeshAnimationId == null) {
24 | callback(null);
25 | return;
26 | }
27 |
28 | var skinnedMeshAnimation = this.skinnedMeshAnimationsById[skinnedMeshAnimationId];
29 |
30 | if (skinnedMeshAnimation != null) {
31 | callback(skinnedMeshAnimation);
32 | return;
33 | }
34 |
35 | if (this.loadingSkinnedMeshAnimationIds[skinnedMeshAnimationId] || this.failedSkinnedMeshAnimationIds[skinnedMeshAnimationId]) {
36 | callback(null);
37 | return;
38 | }
39 |
40 | this.log('Loading skinned mesh animation: ' + skinnedMeshAnimationId);
41 |
42 | this.loadingSkinnedMeshAnimationIds[skinnedMeshAnimationId] = skinnedMeshAnimationId;
43 |
44 | engine.resourceLoader.loadJsonResource('skinned-mesh-animation', skinnedMeshAnimationId, function (skinnedMeshAnimation) {
45 |
46 | if (skinnedMeshAnimation == null) {
47 |
48 | self.failedSkinnedMeshAnimationIds[skinnedMeshAnimationId] = true;
49 |
50 | } else {
51 |
52 | self.skinnedMeshAnimationsById[skinnedMeshAnimationId] = skinnedMeshAnimation;
53 | }
54 |
55 | delete self.loadingSkinnedMeshAnimationIds[skinnedMeshAnimationId];
56 |
57 | callback(skinnedMeshAnimation);
58 | });
59 | }
60 |
61 | this.getSkinnedMeshAnimation = function (skinnedMeshAnimationId) {
62 |
63 | if (skinnedMeshAnimationId == null) {
64 | return null;
65 | }
66 |
67 | return this.skinnedMeshAnimationsById[skinnedMeshAnimationId];
68 | }
69 |
70 | this.cleanUp = function () {
71 |
72 | this.log('Cleaning up...');
73 |
74 | this.skinnedMeshAnimationsById = {};
75 |
76 | this.log('... done.')
77 | }
78 |
79 | this.log = function (message) {
80 |
81 | console.log('Skinned Mesh Animation Manager: ' + message);
82 | }
83 | }
--------------------------------------------------------------------------------
/js/engine/sprite-sheet-manager.js:
--------------------------------------------------------------------------------
1 | function SpriteSheetManager(engine) {
2 |
3 | var self = this;
4 |
5 | this.spriteSheetsById = {};
6 | this.loadingSpriteSheetIds = {};
7 | this.failedSpriteSheetIds = {};
8 |
9 | this.loadSpriteSheet = function (spriteSheetId, callback) {
10 |
11 | callback = callback || function () { }
12 |
13 | if (spriteSheetId == null) {
14 | callback(null);
15 | return;
16 | }
17 |
18 | var spriteSheet = this.spriteSheetsById[spriteSheetId];
19 |
20 | if (spriteSheet != null) {
21 | callback(spriteSheet);
22 | return;
23 | }
24 |
25 | if (this.loadingSpriteSheetIds[spriteSheetId] || this.failedSpriteSheetIds[spriteSheetId]) {
26 | callback(null);
27 | return;
28 | }
29 |
30 | this.log('Loading sprite sheet: ' + spriteSheetId);
31 |
32 | this.loadingSpriteSheetIds[spriteSheetId] = spriteSheetId;
33 |
34 | engine.resourceLoader.loadJsonResource('sprite-sheet', spriteSheetId, function (spriteSheet) {
35 |
36 | if (spriteSheet == null) {
37 |
38 | self.failedSpriteSheetIds[spriteSheetId] = true;
39 |
40 | } else {
41 |
42 | self.spriteSheetsById[spriteSheetId] = spriteSheet;
43 | }
44 |
45 | delete self.loadingSpriteSheetIds[spriteSheetId];
46 |
47 | callback(spriteSheet);
48 | });
49 | }
50 |
51 | this.getSpriteSheet = function (spriteSheetId) {
52 |
53 | if (spriteSheetId == null) {
54 | return null;
55 | }
56 |
57 | return this.spriteSheetsById[spriteSheetId];
58 | }
59 |
60 | this.log = function (message) {
61 |
62 | console.log('Sprite Sheet Manager: ' + message);
63 | }
64 | }
--------------------------------------------------------------------------------
/js/engine/static-mesh-manager.js:
--------------------------------------------------------------------------------
1 | function StaticMeshManager(engine) {
2 |
3 | var self = this;
4 | var gl = null;
5 |
6 | this.staticMeshesById = {};
7 | this.loadingStaticMeshIds = {};
8 | this.failedStaticMeshIds = {};
9 |
10 | this.init = function (callback) {
11 |
12 | gl = engine.glManager.gl;
13 |
14 | callback();
15 | }
16 |
17 | this.loadStaticMesh = function (staticMeshId, options, callback) {
18 |
19 | options = options || {};
20 |
21 | callback = callback || function () { }
22 |
23 | if (staticMeshId == null) {
24 | callback(null);
25 | return;
26 | }
27 |
28 | var staticMesh = this.staticMeshesById[staticMeshId];
29 |
30 | if (staticMesh != null) {
31 | callback(staticMesh);
32 | return;
33 | }
34 |
35 | if (this.loadingStaticMeshIds[staticMeshId] || this.failedStaticMeshIds[staticMeshId]) {
36 | callback(null);
37 | return;
38 | }
39 |
40 | this.log('Loading static mesh: ' + staticMeshId);
41 |
42 | this.loadingStaticMeshIds[staticMeshId] = staticMeshId;
43 |
44 | engine.resourceLoader.loadJsonResource('static-mesh', staticMeshId, function (staticMesh) {
45 |
46 | if (staticMesh == null) {
47 |
48 | self.failedStaticMeshIds[staticMeshId] = true;
49 |
50 | } else {
51 |
52 | self.initStaticMesh(staticMesh, options);
53 |
54 | self.staticMeshesById[staticMeshId] = staticMesh;
55 | }
56 |
57 | delete self.loadingStaticMeshIds[staticMeshId];
58 |
59 | callback(staticMesh);
60 | });
61 | }
62 |
63 | this.getStaticMesh = function (staticMeshId) {
64 |
65 | if (staticMeshId == null) {
66 | return null;
67 | }
68 |
69 | return this.staticMeshesById[staticMeshId];
70 | }
71 |
72 | this.initStaticMesh = function (staticMesh, options) {
73 |
74 | if (options.buildRotationSafeBoundingSphere) {
75 | engine.staticMeshMathHelper.buildStaticMeshRotationSafeBoundingSphereRadius(staticMesh);
76 | }
77 |
78 | if (options.buildChunkAABBs) {
79 | engine.staticMeshMathHelper.buildStaticMeshChunkAABBs(staticMesh);
80 | }
81 |
82 | if (options.buildChunkCollisionFaces) {
83 | engine.staticMeshMathHelper.buildStaticMeshChunkCollisionFaces(staticMesh);
84 | }
85 |
86 | if (options.findPointCompletelyOutsideOfExtremities) {
87 | engine.staticMeshMathHelper.findStaticMeshPointCompletelyOutsideOfExtremities(staticMesh);
88 | }
89 |
90 | staticMesh.buffers = {
91 | vertexBuffer: gl.createBuffer(),
92 | normalsBuffer: gl.createBuffer(),
93 | tangentsBuffer: gl.createBuffer(),
94 | bitangentsBuffer: gl.createBuffer(),
95 | texCoordBuffer: gl.createBuffer(),
96 | indexBuffer: gl.createBuffer()
97 | };
98 |
99 | gl.bindBuffer(gl.ARRAY_BUFFER, staticMesh.buffers.vertexBuffer);
100 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(staticMesh.verts), gl.STATIC_DRAW);
101 |
102 | gl.bindBuffer(gl.ARRAY_BUFFER, staticMesh.buffers.normalsBuffer);
103 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(staticMesh.normals), gl.STATIC_DRAW);
104 |
105 | gl.bindBuffer(gl.ARRAY_BUFFER, staticMesh.buffers.tangentsBuffer);
106 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(staticMesh.tangents), gl.STATIC_DRAW);
107 |
108 | gl.bindBuffer(gl.ARRAY_BUFFER, staticMesh.buffers.bitangentsBuffer);
109 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(staticMesh.bitangents), gl.STATIC_DRAW);
110 |
111 | gl.bindBuffer(gl.ARRAY_BUFFER, staticMesh.buffers.texCoordBuffer);
112 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(staticMesh.uvs), gl.STATIC_DRAW);
113 |
114 | gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, staticMesh.buffers.indexBuffer);
115 | gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(staticMesh.indecies), gl.STATIC_DRAW);
116 |
117 | delete staticMesh.verts;
118 | delete staticMesh.normals;
119 | delete staticMesh.tangents;
120 | delete staticMesh.bitangents;
121 | delete staticMesh.uvs;
122 | delete staticMesh.indecies;
123 | }
124 |
125 | this.cleanUp = function () {
126 |
127 | this.log('Cleaning up...');
128 |
129 | for (var staticMeshId in this.staticMeshesById) {
130 |
131 | var staticMesh = this.staticMeshesById[staticMeshId];
132 |
133 | this.cleanUpStaticMeshBuffers(staticMesh)
134 | }
135 |
136 | this.staticMeshesById = {};
137 |
138 | this.log('... done.')
139 | }
140 |
141 | this.cleanUpStaticMeshBuffers = function (staticMesh) {
142 |
143 | for (var bufferName in staticMesh.buffers) {
144 |
145 | var buffer = staticMesh.buffers[bufferName];
146 |
147 | if (buffer != null) {
148 | gl.deleteBuffer(buffer);
149 | }
150 | }
151 | }
152 |
153 | this.log = function (message) {
154 |
155 | console.log('Static Mesh Manager: ' + message);
156 | }
157 | }
--------------------------------------------------------------------------------
/js/engine/texture-manager.js:
--------------------------------------------------------------------------------
1 | function TextureManager(engine) {
2 |
3 | var self = this;
4 | var gl = null;
5 |
6 | this.texturesById = {};
7 | this.loadingTextureIds = {};
8 | this.failedTextureIds = {};
9 |
10 | this.init = function (callback) {
11 |
12 | gl = engine.glManager.gl;
13 |
14 | callback();
15 | }
16 |
17 | this.loadTextures = function (textureIds, callback) {
18 |
19 | util.recurse(function (recursor, recursionCount) {
20 | if (recursionCount < textureIds.length) {
21 | self.loadTexture(textureIds[recursionCount], recursor);
22 | } else {
23 | callback();
24 | }
25 | });
26 | }
27 |
28 | this.loadTexture = function (textureId, callback) {
29 |
30 | callback = callback || function () { }
31 |
32 | if (textureId == null) {
33 | callback(null);
34 | return;
35 | }
36 |
37 | var texture = this.getTexture(textureId);
38 |
39 | if (texture != null) {
40 | callback(texture);
41 | return;
42 | }
43 |
44 | if (this.loadingTextureIds[textureId] || this.failedTextureIds[textureId]) {
45 | callback(null);
46 | return;
47 | }
48 |
49 | this.log('Loading texture: ' + textureId);
50 |
51 | if (textureId.indexOf('-cube') == -1) {
52 |
53 | this.load2dTextureInternal(textureId, callback);
54 |
55 | } else {
56 |
57 | this.loadCubeTextureInternal(textureId, callback);
58 | }
59 | }
60 |
61 | this.load2dTextureInternal = function (textureId, callback) {
62 |
63 | this.loadingTextureIds[textureId] = true;
64 |
65 | engine.resourceLoader.loadImageResource('texture', textureId, function (image) {
66 |
67 | var texture = null;
68 |
69 | if (image == null) {
70 |
71 | self.failedTextureIds[textureId] = true;
72 |
73 | } else {
74 |
75 | texture = gl.createTexture();
76 | gl.bindTexture(gl.TEXTURE_2D, texture);
77 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
78 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
79 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
80 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
81 | gl.bindTexture(gl.TEXTURE_2D, null);
82 |
83 | texture.width = image.width;
84 | texture.height = image.height;
85 |
86 | self.texturesById[textureId] = texture;
87 | }
88 |
89 | delete self.loadingTextureIds[textureId];
90 |
91 | callback(texture);
92 | });
93 | }
94 |
95 | this.loadCubeTextureInternal = function (textureId, callback) {
96 |
97 | var faces = [
98 | { faceTextureId: textureId + "-px", cubeFace: gl.TEXTURE_CUBE_MAP_POSITIVE_X, image: null },
99 | { faceTextureId: textureId + "-nx", cubeFace: gl.TEXTURE_CUBE_MAP_NEGATIVE_X, image: null },
100 | { faceTextureId: textureId + "-py", cubeFace: gl.TEXTURE_CUBE_MAP_POSITIVE_Y, image: null },
101 | { faceTextureId: textureId + "-ny", cubeFace: gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, image: null },
102 | { faceTextureId: textureId + "-pz", cubeFace: gl.TEXTURE_CUBE_MAP_POSITIVE_Z, image: null },
103 | { faceTextureId: textureId + "-nz", cubeFace: gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, image: null }];
104 |
105 | var allFaceTexturesWereLoaded = true;
106 |
107 | util.recurse(function (recursor, recursionCount) {
108 |
109 | if (recursionCount < faces.length) {
110 |
111 | var face = faces[recursionCount];
112 |
113 | engine.resourceLoader.loadImageResource('texture', face.faceTextureId, function (image) {
114 | face.image = image;
115 | allFaceTexturesWereLoaded = allFaceTexturesWereLoaded && (image != null);
116 | recursor();
117 | });
118 |
119 | } else {
120 |
121 | delete self.loadingTextureIds[textureId];
122 |
123 | var texture = null;
124 |
125 | if (allFaceTexturesWereLoaded) {
126 |
127 | texture = gl.createTexture();
128 |
129 | gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
130 | gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
131 |
132 | for (var i = 0; i < faces.length; i++) {
133 | var face = faces[i];
134 | gl.texImage2D(face.cubeFace, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, face.image);
135 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
136 | gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
137 | }
138 |
139 | gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
140 |
141 | self.texturesById[textureId] = texture;
142 |
143 | } else {
144 |
145 | self.failedTextureIds[textureId] = true;
146 | }
147 |
148 | callback(texture);
149 | }
150 | });
151 | }
152 |
153 | this.getTexture = function (textureId) {
154 |
155 | if (textureId == null) {
156 | return null;
157 | }
158 |
159 | return this.texturesById[textureId];
160 | }
161 |
162 | this.cleanUp = function () {
163 |
164 | this.log('Cleaning up...');
165 |
166 | for (var textureId in this.texturesById) {
167 |
168 | if (textureId.indexOf('system/') == 0) {
169 | continue;
170 | }
171 |
172 | var texture = this.texturesById[textureId];
173 |
174 | gl.deleteTexture(texture);
175 | delete this.texturesById[textureId];
176 | }
177 |
178 | this.loadingTextureIds = {};
179 | this.failedTextureIds = {};
180 |
181 | this.log('... done.');
182 | }
183 |
184 | this.log = function (message) {
185 |
186 | console.log('Texture Manager: ' + message);
187 | }
188 | }
--------------------------------------------------------------------------------
/js/engine/ticker.js:
--------------------------------------------------------------------------------
1 | function Ticker(ticksPerSecond) {
2 |
3 | this.ticksPerSecond = ticksPerSecond;
4 | this.t = -1;
5 | }
6 |
7 | Ticker.prototype.tick = function () {
8 |
9 | var isTick = false;
10 |
11 | if (this.t == -1) {
12 |
13 | this.t = (1000 / this.ticksPerSecond) * Math.random();
14 |
15 | } else {
16 |
17 | this.t -= engine.frameTimer.lastFrameDurationMillis;
18 | if (this.t <= 0) {
19 | this.t = 1000 / this.ticksPerSecond;
20 | isTick = true;
21 | }
22 | }
23 |
24 | return isTick;
25 | }
--------------------------------------------------------------------------------
/js/engine/trigger-manager.js:
--------------------------------------------------------------------------------
1 | function TriggerManager(engine) {
2 |
3 | this.triggerStatesByTriggerId = {};
4 |
5 | this.heartbeat = function () {
6 |
7 | for (var triggerId in engine.map.triggersById) {
8 |
9 | var trigger = engine.map.triggersById[triggerId];
10 | var triggerState = this.coalesceTriggerState(triggerId);
11 | var triggerController = engine.triggerControllersById[trigger.controllerId];
12 |
13 | // Update the trigger's AABB.
14 | vec3.copy(triggerState.aabb.from, trigger.position);
15 | vec3.copy(triggerState.aabb.to, trigger.position);
16 | triggerState.aabb.to[0] += trigger.size[0];
17 | triggerState.aabb.to[1] += trigger.size[1];
18 | triggerState.aabb.to[2] -= trigger.size[2];
19 |
20 | // Determine if the player is within trigger.
21 | var playerWasPreviouslyWithinTrigger = triggerState.playerIsWithinTrigger;
22 | triggerState.playerIsWithinTrigger = math3D.checkPointIsWithinAABB(triggerState.aabb, engine.map.player.position);
23 |
24 | var playerHasJustEnteredTrigger = !playerWasPreviouslyWithinTrigger && triggerState.playerIsWithinTrigger;
25 | var playerHasJustLeftTrigger = playerWasPreviouslyWithinTrigger && !triggerState.playerIsWithinTrigger;
26 |
27 | // Handle events (if there are any).
28 | if (triggerController != null) {
29 |
30 | if (playerHasJustEnteredTrigger && triggerController.handlePlayerEnter != null) {
31 | triggerController.handlePlayerEnter(trigger);
32 | }
33 |
34 | if (playerHasJustLeftTrigger && triggerController.handlePlayerLeave != null) {
35 | triggerController.handlePlayerLeave(trigger);
36 | }
37 | }
38 | }
39 | }
40 |
41 | this.coalesceTriggerState = function (triggerId) {
42 |
43 | var triggerState = this.triggerStatesByTriggerId[triggerId];
44 |
45 | if (triggerState == null) {
46 |
47 | triggerState = {
48 | aabb: new AABB(),
49 | playerIsWithinTrigger: false
50 | }
51 |
52 | this.triggerStatesByTriggerId[triggerId] = triggerState;
53 | }
54 |
55 | return triggerState;
56 | }
57 | }
--------------------------------------------------------------------------------
/js/engine/util.js:
--------------------------------------------------------------------------------
1 | function Util() {
2 |
3 | this.recurse = function (recursionFunction) {
4 |
5 | var recursor = null;
6 | var recursionCount = -1;
7 |
8 | recursor = function () {
9 | recursionCount++;
10 | recursionFunction(recursor, recursionCount);
11 | }
12 |
13 | recursor();
14 | }
15 |
16 | this.getObjectPropertyNames = function (obj) {
17 |
18 | var names = [];
19 | for (var propertyName in obj) {
20 | names.push(propertyName);
21 | }
22 |
23 | return names;
24 | }
25 |
26 | this.copyObjectPropertiesToOtherObject = function (src, dest) {
27 | for (var propertyName in src) {
28 | dest[propertyName] = src[propertyName];
29 | }
30 | }
31 |
32 | this.arrayPushMany = function (destArray, srcArray) {
33 | for (var i = 0; i < srcArray.length; i++) {
34 | destArray.push(srcArray[i]);
35 | }
36 | }
37 |
38 | this.arraySetMany = function (destArray, destStartIndex, srcArray) {
39 | for (var i = 0; i < srcArray.length; i++) {
40 | destArray[destStartIndex + i] = srcArray[i];
41 | }
42 | }
43 |
44 | this.arrayIndexOf = function (array, value) {
45 | var i = 0;
46 | for (var i = 0; i < array.length; i++) {
47 | if (array[i] == value) {
48 | return i;
49 | }
50 | }
51 |
52 | return -1;
53 | }
54 |
55 | this.clearFixedLengthArray = function (array, clearValue) {
56 |
57 | array.length = 0;
58 |
59 | for (var i = 0; i < array.maxLength; i++) {
60 | array.items[i] = clearValue;
61 | }
62 | }
63 |
64 | this.fixedLengthArrayIndexOf = function (array, value) {
65 | var i = 0;
66 | for (var i = 0; i < array.length; i++) {
67 | if (array.items[i] == value) {
68 | return i;
69 | }
70 | }
71 |
72 | return -1;
73 | }
74 |
75 | this.fixedLengthArrayPush = function (array, value) {
76 |
77 | array.items[array.length++] = value;
78 | }
79 |
80 | this.stringIsNullOrEmpty = function (s) {
81 |
82 | return s == null || s == '';
83 | }
84 | }
85 |
86 |
--------------------------------------------------------------------------------
/resources/gui-layouts/hud.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "hud",
3 | "spriteSheetId": "sprite-sheet-1",
4 | "size": [512, 512],
5 | "spritesById": {
6 | "health-bar": {
7 | "id": "health-bar-inner",
8 | "spriteSpecId": "health-bar-inner",
9 | "position": [ 30, 16 ],
10 | "size": [ 50, 12 ],
11 | "rotation": 0,
12 | "visible": true
13 | },
14 | "health-overlay": {
15 | "id": "health-bar-overlay",
16 | "spriteSpecId": "health-bar-overlay",
17 | "position": [ 10, 10 ],
18 | "size": [ 75, 25 ],
19 | "rotation": 0,
20 | "visible": true
21 | },
22 | "health-bar-icon": {
23 | "id": "health-bar-icon",
24 | "spriteSpecId": "health-bar-icon",
25 | "position": [ 17, 18 ],
26 | "size": [ 10, 10 ],
27 | "rotation": 0,
28 | "visible": true
29 | },
30 | "crosshair": {
31 | "id": "crosshair",
32 | "spriteSpecId": "crosshair",
33 | "position": [ 250, 135 ],
34 | "size": [ 10, 10 ],
35 | "rotation": 0,
36 | "visible": true
37 | },
38 | "player-death-message": {
39 | "id": "player-death-message",
40 | "spriteSpecId": "player-death-message",
41 | "position": [ 100, 120 ],
42 | "size": [ 324, 69 ],
43 | "rotation": 0,
44 | "visible": false
45 | }
46 | },
47 | "animationsById": {
48 | "health-bar-grow": {
49 | "id": "health-bar-grow",
50 | "numberOfFrames": 100,
51 | "tweens": [
52 | {
53 | "startFrameIndex": 0,
54 | "numberOfFrames": 100,
55 | "targetId": "health-bar-inner",
56 | "propertyId": 3,
57 | "fromValue": 0.0,
58 | "toValue": -50.0
59 | }
60 | ]
61 | },
62 | "health-bar-icon": {
63 | "id": "health-bar-icon",
64 | "numberOfFrames": 100,
65 | "tweens": [
66 | {
67 | "startFrameIndex": 0,
68 | "numberOfFrames": 100,
69 | "targetId": "health-bar-icon",
70 | "propertyId": 5,
71 | "fromValue": 0.0,
72 | "toValue": 6.28318
73 | }
74 | ]
75 | },
76 | "player-death-message-toggle": {
77 | "id": "player-death-message-toggle",
78 | "numberOfFrames": 2,
79 | "tweens": [
80 | {
81 | "startFrameIndex": 0,
82 | "numberOfFrames": 1,
83 | "targetId": "player-death-message",
84 | "propertyId": 6,
85 | "absoluteValue": 0
86 | },
87 | {
88 | "startFrameIndex": 1,
89 | "numberOfFrames": 1,
90 | "targetId": "player-death-message",
91 | "propertyId": 6,
92 | "absoluteValue": 1
93 | }
94 | ]
95 | }
96 | }
97 | }
--------------------------------------------------------------------------------
/resources/maps/test-map-1.json:
--------------------------------------------------------------------------------
1 | {"worldStaticMeshId":"test-map-1","sectorSetId":"test-map-1","player":{"position":[1.468284249305725,-1.0399999618530273,4.5205793380737305],"rotation":[0.10200000000000142,0.06799999999980647,0]},"globalIlluminationColours":[[0.13,0.13,0.18],[0.02,0.02,0.06],[0.11,0.11,0.14],[0.04,0.04,0.1],[0.15,0.15,0.15],[0.06,0.06,0.06],[0.01,0.01,0.01],[0.02,0.02,0.02]],"lightsById":{"light-1":{"id":"light-1","type":"point","position":[1,-0.5,1],"radius":3,"colour":[1,0,0],"enabled":true,"castsShadows":true},"light-2":{"id":"light-2","type":"point","position":[0,5,-4],"radius":10,"colour":[1,1,1],"enabled":true,"castsShadows":true},"light-3":{"id":"light-3","type":"point","position":[8,-0.8,5],"radius":6,"colour":[0.5,0.5,1],"enabled":true,"castsShadows":false},"light-4":{"id":"light-4","type":"point","position":[-4,3,1],"radius":2.5,"colour":[1,1,0],"enabled":true,"castsShadows":false},"light-5":{"id":"light-5","type":"point","position":[2,5.5,4],"radius":3.8,"colour":[1,0,1],"enabled":true,"castsShadows":false}},"actorsById":{"actor-1":{"id":"actor-1","position":[0,0,0],"rotation":[0,35.13000000000158,35.13000000000158],"controllerId":"TestActorController","staticMeshId":"fancy-cube","data":{"direction":1,"speed":0.01},"frameIndex":0},"actor-2":{"id":"actor-2","position":[-3,3,-5],"rotation":[0,0,0],"staticMeshId":"","controllerId":null,"data":{},"skinnedMeshId":"robot","skinnedMeshAnimationId":"robot-walk","frameIndex":0.8386099999826406}}}
--------------------------------------------------------------------------------
/resources/materials/brick-wall-1.json:
--------------------------------------------------------------------------------
1 | {"diffuseTextureId":"brick-wall-1-d","normalTextureId":"brick-wall-1-n","selfIlluminationTextureId":"light-1"}
--------------------------------------------------------------------------------
/resources/materials/pipe-1.json:
--------------------------------------------------------------------------------
1 | {"diffuseTextureId":"pipe-1-d","normalTextureId":"pipe-1-n"}
--------------------------------------------------------------------------------
/resources/materials/tiled-floor-1.json:
--------------------------------------------------------------------------------
1 | {"diffuseTextureId":"tiled-floor-1-d","normalTextureId":"tiled-floor-1-n"}
--------------------------------------------------------------------------------
/resources/sector-sets/test-map-1.json:
--------------------------------------------------------------------------------
1 | {
2 | "metrics": {
3 | "sectorCount": [ 5, 2, 5 ],
4 | "sectorSize": [ 4, 4, 4 ],
5 | "rootOrigin": [ -10, -5, 10 ]
6 | },
7 | "sectors": [
8 | { "visibleSectorIndexes": [ ] }
9 | ]
10 | }
--------------------------------------------------------------------------------
/resources/sector-sets/test-map-2.json:
--------------------------------------------------------------------------------
1 | {"metrics":{"sectorCount":[4,2,3],"sectorSize":[12,12,12],"rootOrigin":[-24,0,12]},"sectors":[{"visibleSectorIndexes":[0,1,2,6]},{"visibleSectorIndexes":[1,0,2,6]},{"visibleSectorIndexes":[2,0,1,7,8,10,11,13,14,16,17,19,22]},{"visibleSectorIndexes":[3,4,5,9]},{"visibleSectorIndexes":[4,3,5,9]},{"visibleSectorIndexes":[5,3,4,7,8,10,11,13,14,16,17,19,22]},{"visibleSectorIndexes":[6,0,1,12,18]},{"visibleSectorIndexes":[7,2,5,8,10,11,13,14,16,17,19,22]},{"visibleSectorIndexes":[8,2,5,7,10,11,13,14,16,17,19,22]},{"visibleSectorIndexes":[9,3,4,15,21]},{"visibleSectorIndexes":[10,2,5,7,8,11,13,14,16,17,19,22]},{"visibleSectorIndexes":[11,2,5,7,8,10,13,14,16,17,19,22]},{"visibleSectorIndexes":[12,6,18,19]},{"visibleSectorIndexes":[13,2,5,7,8,10,11,14,16,17,19,22]},{"visibleSectorIndexes":[14,2,5,7,8,10,11,13,16,17,19,22]},{"visibleSectorIndexes":[15,9,21,22]},{"visibleSectorIndexes":[16,2,5,7,8,10,11,13,14,17,19,22]},{"visibleSectorIndexes":[17,2,5,7,8,10,11,13,14,16,19,22]},{"visibleSectorIndexes":[18,6,12,19,20]},{"visibleSectorIndexes":[19,2,5,7,8,10,11,12,13,14,16,17,18,20]},{"visibleSectorIndexes":[20,18,19]},{"visibleSectorIndexes":[21,9,15,22,23]},{"visibleSectorIndexes":[22,2,5,7,8,10,11,13,14,15,16,17,21,23]},{"visibleSectorIndexes":[23,21,22]}]}
--------------------------------------------------------------------------------
/resources/shaders/gui-fs.txt:
--------------------------------------------------------------------------------
1 | precision highp float;
2 |
3 | uniform sampler2D textureSampler;
4 |
5 | varying vec2 texCoord;
6 |
7 | void main(void)
8 | {
9 | vec4 textureColour = texture2D(textureSampler, texCoord);
10 |
11 | gl_FragColor = textureColour;
12 | }
--------------------------------------------------------------------------------
/resources/shaders/gui-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec2 sizeMultiplier;
2 |
3 | uniform vec2 position;
4 | uniform vec2 size;
5 | uniform vec2 scale;
6 | uniform vec2 xAxis;
7 | uniform vec2 yAxis;
8 | uniform vec2 uvPosition;
9 | uniform vec2 uvSize;
10 |
11 | varying vec2 texCoord;
12 |
13 | void main(void)
14 | {
15 | /*vec2 guiSpacePosition =
16 | position + (size * sizeMultiplier);
17 |
18 | guiSpacePosition =
19 | guiSpacePosition - (size / 2.0);
20 |
21 | guiSpacePosition =
22 | ((xAxis * guiSpacePosition.x) + (yAxis * guiSpacePosition.y));
23 |
24 | guiSpacePosition =
25 | guiSpacePosition + (size / 2.0);*/
26 |
27 | vec2 guiSpacePosition =
28 | position + (size * sizeMultiplier);
29 |
30 | guiSpacePosition =
31 | guiSpacePosition - position - (size / 2.0);
32 |
33 | guiSpacePosition =
34 | ((xAxis * guiSpacePosition.x) + (yAxis * guiSpacePosition.y));
35 |
36 | guiSpacePosition =
37 | guiSpacePosition + position + (size / 2.0);
38 |
39 |
40 | vec2 clipSpacePosition =
41 | vec2(-1, 1) +
42 | ((guiSpacePosition * scale * vec2(1.0, -1.0) * 2.0));
43 |
44 | texCoord = (uvPosition + (uvSize * sizeMultiplier)) * vec2(1.0, -1.0);
45 |
46 | gl_Position = vec4(clipSpacePosition, 0.0, 1.0);
47 | }
--------------------------------------------------------------------------------
/resources/shaders/line-fs.txt:
--------------------------------------------------------------------------------
1 | precision highp float;
2 | uniform vec3 colour;
3 |
4 | void main(void)
5 | {
6 | gl_FragColor = vec4(colour, 1.0);
7 | }
--------------------------------------------------------------------------------
/resources/shaders/line-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 |
3 | uniform mat4 viewProjMatrix;
4 | uniform vec3 position;
5 | uniform vec3 size;
6 |
7 | void main(void)
8 | {
9 | vec3 temp = vertexPosition * size + position;
10 |
11 | gl_Position = viewProjMatrix * vec4(temp, 1.0);
12 | }
--------------------------------------------------------------------------------
/resources/shaders/particle-fs.txt:
--------------------------------------------------------------------------------
1 | precision highp float;
2 |
3 | uniform sampler2D texture1Sampler;
4 | uniform sampler2D texture2Sampler;
5 |
6 | varying vec2 texCoord;
7 |
8 | void main(void)
9 | {
10 | vec4 texture1Colour = texture2D(texture1Sampler, texCoord);
11 | vec4 texture2Colour = texture2D(texture2Sampler, texCoord);
12 |
13 | vec4 finalColour = vec4(0.0, 0.0, 0.0, 0.0);
14 |
15 | finalColour.rgb = texture1Colour.rgb + (texture2Colour.rgb * texture2Colour.a);
16 | finalColour.a = texture1Colour.a + texture2Colour.a;
17 |
18 | gl_FragColor = finalColour;
19 | }
--------------------------------------------------------------------------------
/resources/shaders/particle-vs.txt:
--------------------------------------------------------------------------------
1 | //attribute vec3 vertexPosition;
2 | attribute vec2 vertexOffset;
3 | attribute vec2 vertexTexCoord;
4 |
5 | uniform mat4 viewProjMatrix;
6 | uniform vec3 position;
7 | uniform vec2 size;
8 | uniform vec3 cameraXAxis;
9 | uniform vec3 cameraYAxis;
10 |
11 | varying vec2 texCoord;
12 |
13 | void main(void)
14 | {
15 | vec3 temp = position;
16 |
17 | temp += (vertexOffset.x * size.x) * cameraXAxis;
18 | temp += (vertexOffset.y * size.y) * cameraYAxis;
19 |
20 | texCoord = vertexTexCoord;
21 |
22 | gl_Position = viewProjMatrix * vec4(temp, 1.0);
23 | }
--------------------------------------------------------------------------------
/resources/shaders/skinned-mesh-main-render-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 | attribute vec3 vertexNormal;
3 | attribute vec2 vertexTexCoord;
4 | attribute float firstBoneIndex;
5 | attribute float secondBoneIndex;
6 | attribute float thirdBoneIndex;
7 | attribute float fourthBoneIndex;
8 | attribute float fifthBoneIndex;
9 | attribute float firstWeight;
10 | attribute float secondWeight;
11 | attribute float thirdWeight;
12 | attribute float fourthWeight;
13 | attribute float fifthWeight;
14 |
15 | uniform mat4 worldMatrix;
16 | uniform mat4 viewProjMatrix;
17 | uniform mat4 boneMatrices[30];
18 |
19 | varying vec3 fragmentWorldSpacePosition;
20 | varying vec3 fragmentNormal;
21 | /*varying vec3 fragmentTangent;
22 | varying vec3 fragmentBitangent;*/
23 | varying vec2 texCoord;
24 |
25 | vec3 transformVectorByBone(int boneIndex, vec3 v);
26 | vec3 transformVectorByBoneRotationOnly(int boneIndex, vec3 v);
27 | mat4 getBoneMatrix(int boneIndex);
28 |
29 | void main(void)
30 | {
31 | // Calculate the skinned position.
32 | vec3 positionTransformedByFirstBone = transformVectorByBone(int(firstBoneIndex), vertexPosition);
33 | vec3 positionTransformedBySecondBone = transformVectorByBone(int(secondBoneIndex), vertexPosition);
34 | vec3 positionTransformedByThirdBone = transformVectorByBone(int(thirdBoneIndex), vertexPosition);
35 | vec3 positionTransformedByFourthBone = transformVectorByBone(int(fourthBoneIndex), vertexPosition);
36 | vec3 positionTransformedByFifthBone = transformVectorByBone(int(fifthBoneIndex), vertexPosition);
37 |
38 | vec3 positionTransformedByBones =
39 | (positionTransformedByFirstBone * firstWeight) +
40 | (positionTransformedBySecondBone * secondWeight) +
41 | (positionTransformedByThirdBone * thirdWeight) +
42 | (positionTransformedByFourthBone * fourthWeight) +
43 | (positionTransformedByFifthBone * fifthWeight);
44 |
45 | vec4 tempWorldSpacePosition = worldMatrix * vec4(positionTransformedByBones, 1.0);
46 |
47 | // Calculate the skinned normal.
48 | vec3 normalTransformedByFirstBone = transformVectorByBoneRotationOnly(int(firstBoneIndex), vertexNormal);
49 | vec3 normalTransformedBySecondBone = transformVectorByBoneRotationOnly(int(secondBoneIndex), vertexNormal);
50 | vec3 normalTransformedByThirdBone = transformVectorByBoneRotationOnly(int(thirdBoneIndex), vertexNormal);
51 | vec3 normalTransformedByFourthBone = transformVectorByBoneRotationOnly(int(fourthBoneIndex), vertexNormal);
52 | vec3 normalTransformedByFifthBone = transformVectorByBoneRotationOnly(int(fifthBoneIndex), vertexNormal);
53 |
54 | vec3 normalTransformedByBones =
55 | (normalTransformedByFirstBone * firstWeight) +
56 | (normalTransformedBySecondBone * secondWeight) +
57 | (normalTransformedByThirdBone * thirdWeight) +
58 | (normalTransformedByFourthBone * fourthWeight) +
59 | (normalTransformedByFifthBone * fifthWeight);
60 |
61 | vec3 tempWorldSpaceNormal = normalize(mat3(worldMatrix) * normalTransformedByBones);
62 | //vec3 tempWorldSpaceNormal = vertexNormal;
63 |
64 | // Output values.
65 | fragmentWorldSpacePosition = tempWorldSpacePosition.xyz;
66 |
67 | texCoord = vertexTexCoord;
68 |
69 | fragmentNormal = tempWorldSpaceNormal;
70 |
71 | gl_Position = viewProjMatrix * tempWorldSpacePosition;
72 | }
73 |
74 | vec3 transformVectorByBone(int boneIndex, vec3 v)
75 | {
76 | if (boneIndex != -1)
77 | {
78 | mat4 boneMatrix = getBoneMatrix(boneIndex);
79 |
80 | vec4 vectorTransformedByBone = boneMatrix * vec4(v, 1.0);
81 |
82 | return vectorTransformedByBone.xyz;
83 | }
84 | else
85 | {
86 | return v;//vec3(0, 0, 0);
87 | }
88 | }
89 |
90 | vec3 transformVectorByBoneRotationOnly(int boneIndex, vec3 v)
91 | {
92 | if (boneIndex != -1)
93 | {
94 | mat4 boneMatrix = getBoneMatrix(boneIndex);
95 |
96 | vec3 vectorTransformedByBone = mat3(boneMatrix) * v;
97 |
98 | return vectorTransformedByBone;
99 | }
100 | else
101 | {
102 | return vec3(0, 0, 0);
103 | }
104 | }
105 |
106 | mat4 getBoneMatrix(int boneIndex)
107 | {
108 | for (int i = 0; i < 30; i++)
109 | {
110 | if (i == boneIndex)
111 | {
112 | return boneMatrices[i];
113 | }
114 | }
115 |
116 | return boneMatrices[0]; // This just shuts the compiler up. This should never happen.
117 | }
--------------------------------------------------------------------------------
/resources/shaders/skinned-mesh-shadow-map-build-back-pass-fs.txt:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform vec3 lightWorldPosition;
4 | uniform vec4 shadowMapMask;
5 |
6 | varying vec3 worldVertexPosition;
7 |
8 | void main(void)
9 | {
10 | vec3 lightToVertex = worldVertexPosition - lightWorldPosition;
11 |
12 | float distanceSquared = dot(lightToVertex, lightToVertex);
13 |
14 | gl_FragColor = shadowMapMask * distanceSquared;
15 | //gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
16 | }
--------------------------------------------------------------------------------
/resources/shaders/skinned-mesh-shadow-map-build-back-pass-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 | attribute float firstBoneIndex;
3 | attribute float secondBoneIndex;
4 | attribute float thirdBoneIndex;
5 | attribute float fourthBoneIndex;
6 | attribute float fifthBoneIndex;
7 | attribute float firstWeight;
8 | attribute float secondWeight;
9 | attribute float thirdWeight;
10 | attribute float fourthWeight;
11 | attribute float fifthWeight;
12 |
13 | uniform mat4 worldMatrix;
14 | uniform mat4 viewProjMatrix;
15 | uniform mat4 boneMatrices[30];
16 |
17 | varying vec3 worldVertexPosition;
18 |
19 | vec3 transformVectorByBone(int boneIndex, vec3 v);
20 | vec3 transformVectorByBoneRotationOnly(int boneIndex, vec3 v);
21 | mat4 getBoneMatrix(int boneIndex);
22 |
23 | void main(void)
24 | {
25 | // Calculate the skinned position.
26 | vec3 positionTransformedByFirstBone = transformVectorByBone(int(firstBoneIndex), vertexPosition);
27 | vec3 positionTransformedBySecondBone = transformVectorByBone(int(secondBoneIndex), vertexPosition);
28 | vec3 positionTransformedByThirdBone = transformVectorByBone(int(thirdBoneIndex), vertexPosition);
29 | vec3 positionTransformedByFourthBone = transformVectorByBone(int(fourthBoneIndex), vertexPosition);
30 | vec3 positionTransformedByFifthBone = transformVectorByBone(int(fifthBoneIndex), vertexPosition);
31 |
32 | vec3 positionTransformedByBones =
33 | (positionTransformedByFirstBone * firstWeight) +
34 | (positionTransformedBySecondBone * secondWeight) +
35 | (positionTransformedByThirdBone * thirdWeight) +
36 | (positionTransformedByFourthBone * fourthWeight) +
37 | (positionTransformedByFifthBone * fifthWeight);
38 |
39 | vec4 tempWorldSpacePosition = worldMatrix * vec4(positionTransformedByBones, 1.0);
40 |
41 | // Output values.
42 | worldVertexPosition = tempWorldSpacePosition.xyz;
43 |
44 | gl_Position = viewProjMatrix * tempWorldSpacePosition;
45 | }
46 |
47 | vec3 transformVectorByBone(int boneIndex, vec3 v)
48 | {
49 | if (boneIndex != -1)
50 | {
51 | mat4 boneMatrix = getBoneMatrix(boneIndex);
52 |
53 | vec4 vectorTransformedByBone = boneMatrix * vec4(v, 1.0);
54 |
55 | return vectorTransformedByBone.xyz;
56 | }
57 | else
58 | {
59 | return vec3(0, 0, 0);
60 | }
61 | }
62 |
63 | vec3 transformVectorByBoneRotationOnly(int boneIndex, vec3 v)
64 | {
65 | if (boneIndex != -1)
66 | {
67 | mat4 boneMatrix = getBoneMatrix(boneIndex);
68 |
69 | vec3 vectorTransformedByBone = mat3(boneMatrix) * v;
70 |
71 | return vectorTransformedByBone;
72 | }
73 | else
74 | {
75 | return vec3(0, 0, 0);
76 | }
77 | }
78 |
79 | mat4 getBoneMatrix(int boneIndex)
80 | {
81 | for (int i = 0; i < 30; i++)
82 | {
83 | if (i == boneIndex)
84 | {
85 | return boneMatrices[i];
86 | }
87 | }
88 |
89 | return boneMatrices[0]; // This just shuts the compiler up. This should never happen.
90 | }
--------------------------------------------------------------------------------
/resources/shaders/skinned-mesh-shadow-map-build-front-pass-fs.txt:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform vec3 lightWorldPosition;
4 | uniform vec4 shadowMapMask;
5 | uniform float shadowMapSize;
6 |
7 | uniform sampler2D backPassSampler;
8 |
9 | varying vec3 worldVertexPosition;
10 |
11 | void main(void)
12 | {
13 | vec3 lightToVertex = worldVertexPosition - lightWorldPosition;
14 |
15 | float frontPassDistanceSquared = dot(lightToVertex, lightToVertex);
16 |
17 | vec2 texCoord = gl_FragCoord.xy / vec2(shadowMapSize, shadowMapSize);
18 |
19 | vec4 backPassSample = texture2D(backPassSampler, texCoord);
20 |
21 | float backPassDistanceSquared = dot(backPassSample, shadowMapMask);
22 |
23 | if (backPassDistanceSquared >= 1000.0) {
24 |
25 | gl_FragColor = shadowMapMask * (frontPassDistanceSquared + 10.0);
26 |
27 | } else {
28 |
29 | float middleDistanceSquared = frontPassDistanceSquared + (backPassDistanceSquared - frontPassDistanceSquared) * 0.6;
30 |
31 | gl_FragColor = shadowMapMask * middleDistanceSquared;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/resources/shaders/skinned-mesh-shadow-map-build-front-pass-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 | attribute float firstBoneIndex;
3 | attribute float secondBoneIndex;
4 | attribute float thirdBoneIndex;
5 | attribute float fourthBoneIndex;
6 | attribute float fifthBoneIndex;
7 | attribute float firstWeight;
8 | attribute float secondWeight;
9 | attribute float thirdWeight;
10 | attribute float fourthWeight;
11 | attribute float fifthWeight;
12 |
13 | uniform mat4 worldMatrix;
14 | uniform mat4 viewProjMatrix;
15 | uniform mat4 boneMatrices[30];
16 |
17 | varying vec3 worldVertexPosition;
18 |
19 | vec3 transformVectorByBone(int boneIndex, vec3 v);
20 | vec3 transformVectorByBoneRotationOnly(int boneIndex, vec3 v);
21 | mat4 getBoneMatrix(int boneIndex);
22 |
23 | void main(void)
24 | {
25 | // Calculate the skinned position.
26 | vec3 positionTransformedByFirstBone = transformVectorByBone(int(firstBoneIndex), vertexPosition);
27 | vec3 positionTransformedBySecondBone = transformVectorByBone(int(secondBoneIndex), vertexPosition);
28 | vec3 positionTransformedByThirdBone = transformVectorByBone(int(thirdBoneIndex), vertexPosition);
29 | vec3 positionTransformedByFourthBone = transformVectorByBone(int(fourthBoneIndex), vertexPosition);
30 | vec3 positionTransformedByFifthBone = transformVectorByBone(int(fifthBoneIndex), vertexPosition);
31 |
32 | vec3 positionTransformedByBones =
33 | (positionTransformedByFirstBone * firstWeight) +
34 | (positionTransformedBySecondBone * secondWeight) +
35 | (positionTransformedByThirdBone * thirdWeight) +
36 | (positionTransformedByFourthBone * fourthWeight) +
37 | (positionTransformedByFifthBone * fifthWeight);
38 |
39 | vec4 tempWorldSpacePosition = worldMatrix * vec4(positionTransformedByBones, 1.0);
40 |
41 | // Output values.
42 | worldVertexPosition = tempWorldSpacePosition.xyz;
43 |
44 | gl_Position = viewProjMatrix * tempWorldSpacePosition;
45 | }
46 |
47 | vec3 transformVectorByBone(int boneIndex, vec3 v)
48 | {
49 | if (boneIndex != -1)
50 | {
51 | mat4 boneMatrix = getBoneMatrix(boneIndex);
52 |
53 | vec4 vectorTransformedByBone = boneMatrix * vec4(v, 1.0);
54 |
55 | return vectorTransformedByBone.xyz;
56 | }
57 | else
58 | {
59 | return vec3(0, 0, 0);
60 | }
61 | }
62 |
63 | vec3 transformVectorByBoneRotationOnly(int boneIndex, vec3 v)
64 | {
65 | if (boneIndex != -1)
66 | {
67 | mat4 boneMatrix = getBoneMatrix(boneIndex);
68 |
69 | vec3 vectorTransformedByBone = mat3(boneMatrix) * v;
70 |
71 | return vectorTransformedByBone;
72 | }
73 | else
74 | {
75 | return vec3(0, 0, 0);
76 | }
77 | }
78 |
79 | mat4 getBoneMatrix(int boneIndex)
80 | {
81 | for (int i = 0; i < 30; i++)
82 | {
83 | if (i == boneIndex)
84 | {
85 | return boneMatrices[i];
86 | }
87 | }
88 |
89 | return boneMatrices[0]; // This just shuts the compiler up. This should never happen.
90 | }
--------------------------------------------------------------------------------
/resources/shaders/static-mesh-main-render-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 | attribute vec3 vertexNormal;
3 | attribute vec3 vertexTangent;
4 | attribute vec3 vertexBitangent;
5 | attribute vec2 vertexTexCoord;
6 |
7 | uniform mat4 worldMatrix;
8 | uniform mat4 viewProjMatrix;
9 |
10 | varying vec3 fragmentWorldSpacePosition;
11 | varying vec3 fragmentNormal;
12 | varying vec3 fragmentTangent;
13 | varying vec3 fragmentBitangent;
14 | varying vec2 texCoord;
15 |
16 | void main(void)
17 | {
18 | vec4 tempWorldSpacePosition = worldMatrix * vec4(vertexPosition, 1.0);
19 |
20 | fragmentWorldSpacePosition = tempWorldSpacePosition.xyz;
21 |
22 | mat3 rotationMatrix = mat3(worldMatrix);
23 | fragmentNormal = rotationMatrix * vertexNormal;
24 | fragmentTangent = rotationMatrix * vertexTangent;
25 | fragmentBitangent = rotationMatrix * vertexBitangent;
26 |
27 | texCoord = vertexTexCoord;
28 |
29 | gl_Position = viewProjMatrix * tempWorldSpacePosition;
30 | }
--------------------------------------------------------------------------------
/resources/shaders/static-mesh-shadow-map-build-back-pass-fs.txt:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform vec3 lightWorldPosition;
4 | uniform vec4 shadowMapMask;
5 |
6 | varying vec3 worldVertexPosition;
7 |
8 | void main(void)
9 | {
10 | vec3 lightToVertex = worldVertexPosition - lightWorldPosition;
11 |
12 | float distanceSquared = dot(lightToVertex, lightToVertex);
13 |
14 | gl_FragColor = shadowMapMask * distanceSquared;
15 | //gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
16 | }
--------------------------------------------------------------------------------
/resources/shaders/static-mesh-shadow-map-build-back-pass-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 |
3 | uniform mat4 viewProjMatrix;
4 |
5 | uniform mat4 worldMatrix;
6 |
7 | varying vec3 worldVertexPosition;
8 |
9 | void main(void)
10 | {
11 | vec4 tempWorldSpacePosition = worldMatrix * vec4(vertexPosition, 1.0);
12 |
13 | worldVertexPosition = tempWorldSpacePosition.xyz;
14 |
15 | gl_Position = viewProjMatrix * tempWorldSpacePosition;
16 | }
--------------------------------------------------------------------------------
/resources/shaders/static-mesh-shadow-map-build-front-pass-fs.txt:
--------------------------------------------------------------------------------
1 | precision mediump float;
2 |
3 | uniform vec3 lightWorldPosition;
4 | uniform vec4 shadowMapMask;
5 | uniform float shadowMapSize;
6 |
7 | uniform sampler2D backPassSampler;
8 |
9 | varying vec3 worldVertexPosition;
10 |
11 | void main(void)
12 | {
13 | vec3 lightToVertex = worldVertexPosition - lightWorldPosition;
14 |
15 | float frontPassDistanceSquared = dot(lightToVertex, lightToVertex);
16 |
17 | vec2 texCoord = gl_FragCoord.xy / vec2(shadowMapSize, shadowMapSize);
18 |
19 | vec4 backPassSample = texture2D(backPassSampler, texCoord);
20 |
21 | float backPassDistanceSquared = dot(backPassSample, shadowMapMask);
22 |
23 | if (backPassDistanceSquared >= 1000.0) {
24 |
25 | gl_FragColor = shadowMapMask * (frontPassDistanceSquared + 10.0);
26 |
27 | } else {
28 |
29 | float middleDistanceSquared = frontPassDistanceSquared + (backPassDistanceSquared - frontPassDistanceSquared) * 0.6;
30 |
31 | gl_FragColor = shadowMapMask * middleDistanceSquared;
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/resources/shaders/static-mesh-shadow-map-build-front-pass-vs.txt:
--------------------------------------------------------------------------------
1 | attribute vec3 vertexPosition;
2 |
3 | uniform mat4 viewProjMatrix;
4 |
5 | uniform mat4 worldMatrix;
6 |
7 | varying vec3 worldVertexPosition;
8 |
9 | void main(void)
10 | {
11 | vec4 tempWorldSpacePosition = worldMatrix * vec4(vertexPosition, 1.0);
12 |
13 | worldVertexPosition = tempWorldSpacePosition.xyz;
14 |
15 | gl_Position = viewProjMatrix * tempWorldSpacePosition;
16 | }
--------------------------------------------------------------------------------
/resources/skinned-mesh-animations/column-bend.json:
--------------------------------------------------------------------------------
1 | {"frames": [{"trans":[{ "quat": [0.0000,0.0000,-0.0000,1.0000] },{ "quat": [0.0000,0.0000,-0.0000,1.0000] },{ "quat": [0.0000,0.0000,0.0000,1.0000] },{ "quat": [0.0000,0.0000,-0.0000,1.0000] }]},{"trans":[{ "quat": [0.0000,0.7071,-0.0000,0.7071] },{ "quat": [0.0000,0.0000,-0.0000,1.0000] },{ "quat": [0.0000,0.0000,0.0000,1.0000] },{ "quat": [0.0000,0.0000,-0.0000,1.0000] }]}]}
--------------------------------------------------------------------------------
/resources/skinned-mesh-animations/robot-walk.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | "frames": [
4 | {
5 | "trans": [
6 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
7 | { "quat": [ 0.1300, -0.0114, 0.0864, 0.9877 ] },
8 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
9 | { "quat": [ -0.2667, -0.1389, -0.4404, 0.8460 ] },
10 | { "quat": [ -0.0714, -0.4001, 0.0225, 0.9134 ] },
11 | { "quat": [ 0.0000, -0.0000, -0.0000, 1.0000 ] },
12 | { "quat": [ 0.3034, -0.1579, 0.4339, 0.8335 ] },
13 | { "quat": [ 0.0714, 0.1962, 0.0225, 0.9777 ] },
14 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
15 | { "quat": [ -0.1361, -0.0267, -0.1206, 0.9830 ] },
16 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
17 | { "quat": [ -0.0000, 0.0000, -0.0872, 0.9962 ] },
18 | { "quat": [ 0.3007, -0.0000, -0.0000, 0.9537 ] },
19 | { "quat": [ 0.3007, -0.0000, 0.0000, 0.9537 ] },
20 | { "quat": [ -0.0000, 0.0000, -0.0436, 0.9990 ] },
21 | { "quat": [ -0.3420, 0.0000, -0.0000, 0.9397 ] },
22 | { "quat": [ 0.4617, 0.0000, -0.0000, 0.8870 ] }
23 | ]
24 | },
25 | {
26 | "trans": [
27 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
28 | { "quat": [ 0.0436, -0.0019, 0.0436, 0.9981 ] },
29 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
30 | { "quat": [ -0.1540, -0.0802, -0.4547, 0.8735 ] },
31 | { "quat": [ 0.0470, -0.2736, -0.0171, 0.9605 ] },
32 | { "quat": [ 0.0000, -0.0000, -0.0000, 1.0000 ] },
33 | { "quat": [ 0.1540, -0.0802, 0.4547, 0.8735 ] },
34 | { "quat": [ 0.0936, 0.2032, 0.0341, 0.9741 ] },
35 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
36 | { "quat": [ -0.0439, -0.0019, -0.0432, 0.9981 ] },
37 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
38 | { "quat": [ -0.0000, 0.0000, -0.0436, 0.9990 ] },
39 | { "quat": [ 0.1305, 0.0000, -0.0000, 0.9914 ] },
40 | { "quat": [ 0.1736, -0.0000, 0.0000, 0.9848 ] },
41 | { "quat": [ 0.0000, 0.0000, 0.0000, 1.0000 ] },
42 | { "quat": [ -0.1736, 0.0000, -0.0000, 0.9848 ] },
43 | { "quat": [ 0.3007, -0.0000, -0.0000, 0.9537 ] }
44 | ]
45 | },
46 | {
47 | "trans": [
48 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
49 | { "quat": [ 0.0000, 0.0000, -0.0436, 0.9990 ] },
50 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
51 | { "quat": [ 0.0000, 0.0000, -0.4617, 0.8870 ] },
52 | { "quat": [ 0.1563, -0.1798, -0.0729, 0.9685 ] },
53 | { "quat": [ 0.0000, -0.0000, -0.0000, 1.0000 ] },
54 | { "quat": [ 0.0000, -0.0000, 0.4617, 0.8870 ] },
55 | { "quat": [ 0.1593, 0.1374, 0.0660, 0.9754 ] },
56 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
57 | { "quat": [ -0.0436, -0.0019, 0.0436, 0.9981 ] },
58 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
59 | { "quat": [ -0.0000, -0.0000, 0.0000, 1.0000 ] },
60 | { "quat": [ -0.1736, 0.0000, 0.0000, 0.9848 ] },
61 | { "quat": [ 0.1736, -0.0000, 0.0000, 0.9848 ] },
62 | { "quat": [ -0.0000, -0.0000, 0.0436, 0.9990 ] },
63 | { "quat": [ 0.1305, -0.0000, 0.0000, 0.9914 ] },
64 | { "quat": [ 0.3827, 0.0000, -0.0000, 0.9239 ] }
65 | ]
66 | },
67 | {
68 | "trans": [
69 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
70 | { "quat": [ 0.0435, 0.0038, -0.0871, 0.9952 ] },
71 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
72 | { "quat": [ 0.3749, 0.1951, -0.4185, 0.8039 ] },
73 | { "quat": [ 0.0714, -0.1962, -0.0225, 0.9777 ] },
74 | { "quat": [ 0.0000, -0.0000, -0.0000, 1.0000 ] },
75 | { "quat": [ -0.3749, 0.1951, 0.4185, 0.8039 ] },
76 | { "quat": [ -0.0936, 0.4705, -0.0341, 0.8768 ] },
77 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
78 | { "quat": [ -0.0455, 0.0093, 0.1294, 0.9905 ] },
79 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
80 | { "quat": [ 0.0000, -0.0000, 0.0436, 0.9990 ] },
81 | { "quat": [ -0.3827, -0.0000, 0.0000, 0.9239 ] },
82 | { "quat": [ 0.4226, -0.0000, 0.0000, 0.9063 ] },
83 | { "quat": [ -0.0000, -0.0000, 0.0872, 0.9962 ] },
84 | { "quat": [ 0.3007, -0.0000, -0.0000, 0.9537 ] },
85 | { "quat": [ 0.5373, 0.0000, -0.0000, 0.8434 ] }
86 | ]
87 | },
88 | {
89 | "trans": [
90 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
91 | { "quat": [ 0.0436, 0.0000, 0.0000, 0.9990 ] },
92 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
93 | { "quat": [ 0.2296, 0.1195, -0.4460, 0.8568 ] },
94 | { "quat": [ 0.0679, -0.3221, -0.0316, 0.9437 ] },
95 | { "quat": [ 0.0000, -0.0000, -0.0000, 1.0000 ] },
96 | { "quat": [ -0.0387, 0.0201, 0.4613, 0.8862 ] },
97 | { "quat": [ 0.1347, 0.2140, 0.0624, 0.9655 ] },
98 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
99 | { "quat": [ 0.0000, 0.0038, 0.0435, 0.9990 ] },
100 | { "quat": [ 0.0000, 0.0000, -0.0000, 1.0000 ] },
101 | { "quat": [ 0.0000, -0.0000, 0.0436, 0.9990 ] },
102 | { "quat": [ -0.1736, 0.0000, 0.0000, 0.9848 ] },
103 | { "quat": [ 0.3420, -0.0000, 0.0000, 0.9397 ] },
104 | { "quat": [ 0.0000, 0.0000, 0.0000, 1.0000 ] },
105 | { "quat": [ -0.0000, -0.0000, 0.0000, 1.0000 ] },
106 | { "quat": [ 0.3007, -0.0000, 0.0000, 0.9537 ] }
107 | ]
108 | }
109 | ]
110 | }
--------------------------------------------------------------------------------
/resources/skinned-meshes/column.json:
--------------------------------------------------------------------------------
1 | {"verts":[-0.2500000476837158,-2.9802322387695314e-09,0.25000002384185793,0.2499999761581421,0.5,0.25000002384185793,-0.25000002384185793,0.5,0.25000002384185793,-0.2501410722732544,0.5000000476837159,-0.25,-0.25,-2.9802322387695314e-09,0.25000002384185793,-0.24985892772674562,0.5000000476837159,0.25000002384185793,0.25000002384185793,0.5000000476837159,0.25000002384185793,0.25,-2.9802322387695314e-09,-0.25,0.25,0.5,-0.25,-0.2500000476837158,0.5,0.25000002384185793,0.25,0.5,-0.25,-0.25000002384185793,0.5,-0.25,-0.2500000476837158,-2.9802322387695314e-09,0.25000002384185793,0.25000002384185793,-6.617444900424222e-24,0.25000002384185793,0.2499999761581421,0.5,0.25000002384185793,-0.2501410722732544,0.5000000476837159,-0.25,-0.24971785545349123,-2.9802322387695314e-09,-0.25,-0.25,-2.9802322387695314e-09,0.25000002384185793,0.25000002384185793,0.5000000476837159,0.25000002384185793,0.2499999523162842,-2.9802322387695314e-09,0.25000002384185793,0.25,-2.9802322387695314e-09,-0.25,-0.2500000476837158,0.5,0.25000002384185793,0.25,0.5,0.25000002384185793,0.25,0.5,-0.25],"normals":[0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,-0.9999999403953552,-0.00028214440681040287,1.2969653129246694e-10,-0.9999998807907104,-0.0002821445814333856,-5.558421431461902e-11,-0.9999998211860657,0.0002821444650180638,0.0005642889882437885,1.0,-7.152555525635762e-08,2.3841858265427618e-08,1.0,-7.152557657263969e-08,2.3841868923568654e-08,1.0,0.0,-4.768370942542788e-08,0.0,1.0,-0.0,0.0,1.0,-0.0,0.0,1.0,-0.0,0.0,0.0,1.0,0.0,0.0,1.0,0.0,0.0,1.0,-0.9999999403953552,-0.00028214440681040287,1.2969653129246694e-10,-0.9999995231628418,-0.0008464331040158868,-0.0005642887554131448,-0.9999998807907104,-0.0002821445814333856,-5.558421431461902e-11,1.0,-7.152555525635762e-08,2.3841858265427618e-08,1.0,-1.4305113893442467e-07,9.536744016713783e-08,1.0,-7.152557657263969e-08,2.3841868923568654e-08,0.0,1.0,-0.0,0.0,1.0,-0.0,0.0,1.0,-0.0],"uvs":[0.0002,0.0001,0.7692,0.7696,0.0001,0.7696,0.0001,0.9999,0.9999,0.0001,0.9999,0.9999,0.0001,0.9999,0.9999,0.0001,0.9999,0.9999,0.0001,0.0001,0.9999,0.9999,0.0001,0.9999,0.0002,0.0001,0.7692,0.0024,0.7692,0.7696,0.0001,0.9999,0.0001,0.0001,0.9999,0.0001,0.0001,0.9999,0.0001,0.0001,0.9999,0.0001,0.0001,0.0001,0.9999,0.0001,0.9999,0.9999],"firstBoneIndexes":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"secondBoneIndexes":[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],"thirdBoneIndexes":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],"fourthBoneIndexes":[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],"firstWeights":[0.8893013000488281,0.625490128993988,0.7573957443237305,0.5845423936843872,0.8309930562973022,0.5844825506210327,0.5844932794570923,0.8310133814811707,0.5844932794570923,0.4999999701976776,0.5,0.5,0.8893013000488281,0.8597182035446167,0.625490128993988,0.5845423936843872,0.8310688734054565,0.8309930562973022,0.5844932794570923,0.8310133814811707,0.8310133814811707,0.4999999701976776,0.4999999701976776,0.5],"secondWeights":[0.1106986328959465,0.3745098412036896,0.24260424077510834,0.4154576361179352,0.16900698840618134,0.4155174791812897,0.4155066907405853,0.16898660361766815,0.4155066907405853,0.4999999701976776,0.5,0.5,0.1106986328959465,0.14028175175189972,0.3745098412036896,0.4154576361179352,0.16893114149570465,0.16900698840618134,0.4155066907405853,0.16898658871650696,0.16898660361766815,0.4999999701976776,0.4999999701976776,0.5],"thirdWeights":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"fourthWeights":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"bones": [{ "name": "Bone" , "position": [0.0,0.0,-0.0], "parentBoneIndex": -1},{ "name": "Bone.001" , "position": [0.0,0.2,-0.0], "parentBoneIndex": 0},{ "name": "Bone.002" , "position": [0.0,0.4,4.4862107984045e-08], "parentBoneIndex": 1},{ "name": "Bone.003" , "position": [0.0,0.6000000000000001,1.422419018126675e-07], "parentBoneIndex": 2}]}
--------------------------------------------------------------------------------
/resources/sprite-sheets/sprite-sheet-1.json:
--------------------------------------------------------------------------------
1 | {
2 | "textureId": "sprite-sheet-1",
3 | "spriteSpecsById": {
4 | "health-bar-overlay": {
5 | "id": "health-bar-overlay",
6 | "position": [0, 0],
7 | "size": [290, 95]
8 | },
9 | "health-bar-inner": {
10 | "id": "health-bar-inner",
11 | "position": [ 0, 98 ],
12 | "size": [ 184, 40 ]
13 | },
14 | "health-bar-icon": {
15 | "id": "health-bar-icon",
16 | "position": [ 190, 96 ],
17 | "size": [ 42, 42 ]
18 | },
19 | "crosshair": {
20 | "id": "crosshair",
21 | "position": [ 298, 11 ],
22 | "size": [ 68, 72 ]
23 | },
24 | "player-death-message": {
25 | "id": "player-death-message",
26 | "position": [ 3, 140 ],
27 | "size": [ 324, 69 ]
28 | }
29 | }
30 | }
--------------------------------------------------------------------------------
/resources/system/effects.json:
--------------------------------------------------------------------------------
1 | {
2 | "static-mesh-main-render": {
3 | "id": "static-mesh-main-render",
4 |
5 | "attributes": {
6 | "vertexPosition": null,
7 | "vertexNormal": null,
8 | "vertexTangent": null,
9 | "vertexBitangent": null,
10 | "vertexTexCoord": null
11 | },
12 |
13 | "uniforms": {
14 | "worldMatrix": null,
15 | "viewProjMatrix": null,
16 |
17 | "diffuseSampler": null,
18 | "normalSampler": null,
19 | "selfIlluminationSampler": null,
20 | "pointLightShadowMapSamplers": null,
21 |
22 | "lightEnableds": null,
23 | "lightWorldSpacePositions": null,
24 | "lightRadiusSqrs": null,
25 | "lightColours": null,
26 | "lightCastsShadows": null,
27 | "lightStaticObjectShadowMapMasks": null,
28 | "lightDynamicObjectShadowMapMasks": null,
29 | "cameraWorldSpacePosition": null,
30 |
31 | "globalIlluminationNormals": null,
32 | "globalIlluminationColours": null,
33 |
34 | "hasSelfIllumination": null
35 | }
36 | },
37 |
38 | "skinned-mesh-main-render": {
39 | "id": "skinned-mesh-main-render",
40 |
41 | "attributes": {
42 | "vertexPosition": null,
43 | "vertexNormal": null,
44 | "vertexTexCoord": null,
45 | "firstBoneIndex": null,
46 | "secondBoneIndex": null,
47 | "thirdBoneIndex": null,
48 | "fourthBoneIndex": null,
49 | "fifthBoneIndex": null,
50 | "firstWeight": null,
51 | "secondWeight": null,
52 | "thirdWeight": null,
53 | "fourthWeight": null,
54 | "fifthWeight": null
55 | },
56 |
57 | "uniforms": {
58 | "worldMatrix": null,
59 | "viewProjMatrix": null,
60 | "boneMatrices": null,
61 |
62 | "diffuseSampler": null,
63 | "normalSampler": null,
64 | "selfIlluminationSampler": null,
65 | "pointLightShadowMapSamplers": null,
66 |
67 | "lightEnableds": null,
68 | "lightWorldSpacePositions": null,
69 | "lightRadiusSqrs": null,
70 | "lightColours": null,
71 | "lightCastsShadows": null,
72 | "lightStaticObjectShadowMapMasks": null,
73 | "lightDynamicObjectShadowMapMasks": null,
74 | "cameraWorldSpacePosition": null,
75 |
76 | "globalIlluminationNormals": null,
77 | "globalIlluminationColours": null,
78 |
79 | "hasSelfIllumination": null
80 | }
81 | },
82 |
83 | "static-mesh-shadow-map-build-back-pass": {
84 | "id": "static-mesh-shadow-map-build-back-pass",
85 |
86 | "attributes": {
87 | "vertexPosition": null
88 | },
89 |
90 | "uniforms": {
91 | "worldMatrix": null,
92 | "viewProjMatrix": null,
93 | "lightWorldPosition": null,
94 | "shadowMapMask": null
95 | }
96 | },
97 |
98 | "static-mesh-shadow-map-build-front-pass": {
99 | "id": "static-mesh-shadow-map-build-front-pass",
100 |
101 | "attributes": {
102 | "vertexPosition": null
103 | },
104 |
105 | "uniforms": {
106 | "worldMatrix": null,
107 | "viewProjMatrix": null,
108 | "lightWorldPosition": null,
109 | "shadowMapMask": null,
110 | "shadowMapSize": null
111 | }
112 | },
113 |
114 | "skinned-mesh-shadow-map-build-back-pass": {
115 | "id": "skinned-mesh-shadow-map-build-back-pass",
116 |
117 | "attributes": {
118 | "vertexPosition": null,
119 | "firstBoneIndex": null,
120 | "secondBoneIndex": null,
121 | "thirdBoneIndex": null,
122 | "fourthBoneIndex": null,
123 | "fifthBoneIndex": null,
124 | "firstWeight": null,
125 | "secondWeight": null,
126 | "thirdWeight": null,
127 | "fourthWeight": null,
128 | "fifthWeight": null
129 | },
130 |
131 | "uniforms": {
132 | "worldMatrix": null,
133 | "viewProjMatrix": null,
134 | "boneMatrices": null,
135 | "lightWorldPosition": null,
136 | "shadowMapMask": null
137 | }
138 | },
139 |
140 | "skinned-mesh-shadow-map-build-front-pass": {
141 | "id": "skinned-mesh-shadow-map-build-front-pass",
142 |
143 | "attributes": {
144 | "vertexPosition": null,
145 | "firstBoneIndex": null,
146 | "secondBoneIndex": null,
147 | "thirdBoneIndex": null,
148 | "fourthBoneIndex": null,
149 | "fifthBoneIndex": null,
150 | "firstWeight": null,
151 | "secondWeight": null,
152 | "thirdWeight": null,
153 | "fourthWeight": null,
154 | "fifthWeight": null
155 | },
156 |
157 | "uniforms": {
158 | "worldMatrix": null,
159 | "viewProjMatrix": null,
160 | "boneMatrices": null,
161 | "lightWorldPosition": null,
162 | "shadowMapMask": null,
163 | "shadowMapSize": null
164 | }
165 | },
166 |
167 | "particle": {
168 | "id": "particle",
169 |
170 | "attributes": {
171 | "vertexOffset": null,
172 | "vertexTexCoord": null
173 | },
174 |
175 | "uniforms": {
176 | "viewProjMatrix": null,
177 | "position": null,
178 | "size": null,
179 | "cameraXAxis": null,
180 | "cameraYAxis": null,
181 | "texture1Sampler": null,
182 | "texture2Sampler": null
183 | }
184 | },
185 |
186 | "gui": {
187 | "id": "gui",
188 |
189 | "attributes": {
190 | "sizeMultiplier": null
191 | },
192 |
193 | "uniforms": {
194 | "position": null,
195 | "size": null,
196 | "scale": null,
197 | "xAxis": null,
198 | "yAxis": null,
199 | "uvPosition": null,
200 | "uvSize": null,
201 | "textureSampler": null
202 | }
203 | },
204 |
205 | "line": {
206 | "id": "line",
207 |
208 | "attributes": {
209 | "vertexPosition": null
210 | },
211 |
212 | "uniforms": {
213 | "viewProjMatrix": null,
214 | "position": null,
215 | "size": null,
216 | "colour": null
217 | }
218 | }
219 | }
--------------------------------------------------------------------------------
/resources/textures/brick-wall-1-d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/brick-wall-1-d.png
--------------------------------------------------------------------------------
/resources/textures/brick-wall-1-n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/brick-wall-1-n.png
--------------------------------------------------------------------------------
/resources/textures/light-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/light-1.png
--------------------------------------------------------------------------------
/resources/textures/particle-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/particle-1.png
--------------------------------------------------------------------------------
/resources/textures/particle-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/particle-2.png
--------------------------------------------------------------------------------
/resources/textures/pipe-1-d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/pipe-1-d.png
--------------------------------------------------------------------------------
/resources/textures/pipe-1-n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/pipe-1-n.png
--------------------------------------------------------------------------------
/resources/textures/sprite-sheet-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/sprite-sheet-1.png
--------------------------------------------------------------------------------
/resources/textures/system/dummy-cube-nx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/dummy-cube-nx.png
--------------------------------------------------------------------------------
/resources/textures/system/dummy-cube-ny.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/dummy-cube-ny.png
--------------------------------------------------------------------------------
/resources/textures/system/dummy-cube-nz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/dummy-cube-nz.png
--------------------------------------------------------------------------------
/resources/textures/system/dummy-cube-px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/dummy-cube-px.png
--------------------------------------------------------------------------------
/resources/textures/system/dummy-cube-py.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/dummy-cube-py.png
--------------------------------------------------------------------------------
/resources/textures/system/dummy-cube-pz.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/dummy-cube-pz.png
--------------------------------------------------------------------------------
/resources/textures/system/missing-diffuse-texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/missing-diffuse-texture.png
--------------------------------------------------------------------------------
/resources/textures/system/missing-normal-texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/system/missing-normal-texture.png
--------------------------------------------------------------------------------
/resources/textures/tiled-floor-1-d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/tiled-floor-1-d.png
--------------------------------------------------------------------------------
/resources/textures/tiled-floor-1-n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/thunderholt/webgl-fps/0e1a40c4e3c424044cf254767ad215ef98f82fec/resources/textures/tiled-floor-1-n.png
--------------------------------------------------------------------------------