matrix-engine-wgpu 1.0.6 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.codesandbox/tasks.json +46 -0
- package/.devcontainer/devcontainer.json +22 -0
- package/.github/dependabot.yml +12 -0
- package/REFERENCE.md +3 -5
- package/dev.md +460 -0
- package/empty.js +7 -6
- package/examples/games/jamb/jamb.js +1133 -0
- package/examples/load-obj-file.js +65 -28
- package/examples/unlit-textures.js +26 -23
- package/examples.js +35 -3
- package/index.js +8 -2
- package/main.js +454 -48
- package/non-project-files/dev.txt +21 -0
- package/non-project-files/image1.png +0 -0
- package/non-project-files/image6.png +0 -0
- package/package.json +31 -13
- package/public/app.js +2234 -114
- package/public/css/style.css +371 -110
- package/public/empty.html +1 -1
- package/public/empty.js +9887 -9264
- package/public/examples.html +10 -8
- package/public/examples.js +2035 -247
- package/public/index.html +3 -5
- package/public/manifest copy.web +35 -0
- package/public/res/audios/block.mp3 +0 -0
- package/public/res/audios/dice1.mp3 +0 -0
- package/public/res/audios/dice2.mp3 +0 -0
- package/public/res/audios/start.mp3 +0 -0
- package/public/res/meshes/jamb/bg.blend +0 -0
- package/public/res/meshes/jamb/bg.blend1 +0 -0
- package/public/res/meshes/jamb/bg.mtl +12 -0
- package/public/res/meshes/jamb/bg.obj +17 -0
- package/public/res/meshes/jamb/bg.png +0 -0
- package/public/res/meshes/jamb/dice-default.png +0 -0
- package/public/res/meshes/jamb/dice-mark.png +0 -0
- package/public/res/meshes/jamb/dice.mtl +12 -0
- package/public/res/meshes/jamb/dice.obj +40 -0
- package/public/res/meshes/jamb/dice.png +0 -0
- package/public/res/meshes/jamb/jamb-title.mtl +12 -0
- package/public/res/meshes/jamb/jamb-title.obj +26008 -0
- package/public/res/meshes/jamb/jamb.blend +0 -0
- package/public/res/meshes/jamb/jamb.blend1 +0 -0
- package/public/res/meshes/jamb/logo.png +0 -0
- package/public/res/meshes/jamb/nidzaDice.blend +0 -0
- package/public/res/meshes/jamb/nidzaDice.blend1 +0 -0
- package/public/res/meshes/jamb/pile.blend +0 -0
- package/public/res/meshes/jamb/simpleCube.blend +0 -0
- package/public/res/meshes/jamb/simpleCube.blend1 +0 -0
- package/public/res/meshes/jamb/sounds/roll1.wav +0 -0
- package/public/res/meshes/jamb/text.png +0 -0
- package/public/res/multilang/en.json +27 -0
- package/public/res/multilang/sr.json +27 -0
- package/public/test.html +636 -0
- package/public/three-test.js +165 -0
- package/public/worker.html +1 -1
- package/readme.md +193 -115
- package/src/engine/ball.js +477 -468
- package/src/engine/cube.js +486 -468
- package/src/engine/engine.js +4 -6
- package/src/engine/loader-obj.js +9 -6
- package/src/engine/matrix-class.js +237 -204
- package/src/engine/mesh-obj.js +603 -515
- package/src/engine/raycast.js +101 -0
- package/src/engine/utils.js +69 -3
- package/src/multilang/lang.js +35 -0
- package/src/physics/matrix-ammo.js +168 -15
- package/src/shaders/fragment.wgsl.js +4 -2
- package/src/shaders/shaders.js +1 -1
- package/src/shaders/vertexShadow.wgsl.js +1 -1
- package/src/sounds/sounds.js +47 -0
- package/src/world.js +311 -248
package/readme.md
CHANGED
|
@@ -1,101 +1,183 @@
|
|
|
1
1
|
# matrix-engine-wgpu
|
|
2
|
-
## [not fully operative for now - WIP]
|
|
3
|
-
## Author Nikola Lukic zlatnaspirala@gmail.com 2024
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
**Author:** Nikola Lukić
|
|
4
|
+
📧 [zlatnaspirala@gmail.com](mailto:zlatnaspirala@gmail.com)
|
|
5
|
+
📅 2025
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Logo
|
|
6
10
|
|
|
7
11
|
<img width="320" height="320" src="https://github.com/zlatnaspirala/matrix-engine-wgpu/blob/main/public/res/icons/512.png?raw=true" />
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
> Logo includes the official WebGPU logo.
|
|
14
|
+
> **WebGPU logo by [W3C](https://www.w3.org/)**
|
|
15
|
+
> Licensed under [Creative Commons Attribution 4.0](https://www.w3.org/2023/02/webgpu-logos.html)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Description
|
|
20
|
+
|
|
21
|
+
This project is a work-in-progress WebGPU engine inspired by the original **matrix-engine** for WebGL.
|
|
22
|
+
It uses the `wgpu-matrix` npm package as a modern replacement for `gl-matrix` to handle model-view-projection matrices.
|
|
23
|
+
|
|
24
|
+
Published on npm as: **`matrix-engine-wgpu`**
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Goals
|
|
10
29
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
30
|
+
* ✔️ Support for 3D objects and scene transformations
|
|
31
|
+
* 🎯 Replicate matrix-engine (WebGL) features
|
|
32
|
+
* 📦 Based on the `shadowMapping` sample from [webgpu-samples](https://webgpu.github.io/webgpu-samples/?sample=shadowMapping)
|
|
33
|
+
* ✔️ Ammo.js physics integration (basic cube)
|
|
14
34
|
|
|
15
|
-
|
|
16
|
-
I publish (this repo) npm package with name `matrix-engine-wgpu`.
|
|
35
|
+
---
|
|
17
36
|
|
|
18
|
-
##
|
|
37
|
+
## Features
|
|
19
38
|
|
|
20
|
-
|
|
21
|
-
- Make it similar to the matrix-engine webGL features.
|
|
22
|
-
- Main base example is `shadowMapping` from [webgpu-samples](https://webgpu.github.io/webgpu-samples/?sample=shadowMapping)
|
|
23
|
-
- Integrate ammojs
|
|
39
|
+
### Scene Management
|
|
24
40
|
|
|
25
|
-
|
|
41
|
+
* Canvas is dynamically created in JavaScript—no `<canvas>` element needed in HTML.
|
|
42
|
+
|
|
43
|
+
* Access the main scene objects:
|
|
26
44
|
|
|
27
|
-
- Only access to the object scene instance look like:
|
|
28
|
-
`mainRenderBundle` is scene holder.
|
|
29
45
|
```js
|
|
30
46
|
app.mainRenderBundle[0];
|
|
31
47
|
```
|
|
32
48
|
|
|
33
|
-
|
|
49
|
+
* Add meshes with `.addMeshObj()`, supporting `.obj` loading, unlit textures, cubes, spheres, etc.
|
|
50
|
+
|
|
51
|
+
* Cleanly destroy the scene:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
app.destroyProgram();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Camera Options
|
|
60
|
+
|
|
61
|
+
Supported types: `WASD`, `arcball`
|
|
34
62
|
|
|
35
|
-
### Camera
|
|
36
|
-
Camera type: `WASD | arcball`
|
|
37
63
|
```js
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
64
|
+
mainCameraParams: {
|
|
65
|
+
type: 'WASD',
|
|
66
|
+
responseCoef: 1000
|
|
67
|
+
}
|
|
42
68
|
```
|
|
43
69
|
|
|
44
|
-
|
|
45
|
-
#### app.mainRenderBundle[0] -> position
|
|
70
|
+
---
|
|
46
71
|
|
|
47
|
-
|
|
72
|
+
### Object Positioning
|
|
73
|
+
|
|
74
|
+
Control object position:
|
|
48
75
|
|
|
49
76
|
```js
|
|
50
77
|
app.mainRenderBundle[0].position.translateByX(12);
|
|
51
78
|
```
|
|
52
79
|
|
|
53
|
-
Teleport/
|
|
80
|
+
Teleport / set directly:
|
|
54
81
|
|
|
55
82
|
```js
|
|
56
83
|
app.mainRenderBundle[0].position.SetX(-2);
|
|
57
84
|
```
|
|
58
85
|
|
|
59
|
-
|
|
86
|
+
Adjust movement speed:
|
|
60
87
|
|
|
61
88
|
```js
|
|
62
89
|
app.mainRenderBundle[0].position.thrust = 0.1;
|
|
63
90
|
```
|
|
64
91
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
92
|
+
> ⚠️ For physics-enabled objects, use Ammo.js functions — `.position` and `.rotation` are not visually applied but can be read.
|
|
93
|
+
|
|
94
|
+
Example:
|
|
95
|
+
|
|
68
96
|
```js
|
|
69
|
-
app.matrixAmmo.rigidBodies[0].setAngularVelocity(new Ammo.btVector3(0,2,0))
|
|
70
|
-
app.matrixAmmo.rigidBodies[0].setLinearVelocity(new Ammo.btVector3(0,7,0))
|
|
97
|
+
app.matrixAmmo.rigidBodies[0].setAngularVelocity(new Ammo.btVector3(0, 2, 0));
|
|
98
|
+
app.matrixAmmo.rigidBodies[0].setLinearVelocity(new Ammo.btVector3(0, 7, 0));
|
|
71
99
|
```
|
|
72
100
|
|
|
73
|
-
|
|
74
|
-
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### Object Rotation
|
|
104
|
+
|
|
105
|
+
Manual rotation:
|
|
75
106
|
|
|
76
|
-
Rotate object by axis by degree:
|
|
77
107
|
```js
|
|
78
|
-
app.mainRenderBundle[0].rotation.x = 45
|
|
108
|
+
app.mainRenderBundle[0].rotation.x = 45;
|
|
79
109
|
```
|
|
80
110
|
|
|
81
|
-
|
|
111
|
+
Auto-rotate:
|
|
112
|
+
|
|
82
113
|
```js
|
|
83
|
-
app.mainRenderBundle[0].rotation.rotationSpeed.y = 10
|
|
114
|
+
app.mainRenderBundle[0].rotation.rotationSpeed.y = 10;
|
|
84
115
|
```
|
|
85
116
|
|
|
86
|
-
Stop
|
|
117
|
+
Stop rotation:
|
|
118
|
+
|
|
87
119
|
```js
|
|
88
|
-
app.mainRenderBundle[0].rotation.rotationSpeed.y = 0
|
|
120
|
+
app.mainRenderBundle[0].rotation.rotationSpeed.y = 0;
|
|
89
121
|
```
|
|
90
122
|
|
|
91
|
-
|
|
123
|
+
> ⚠️ For physics-enabled objects, use Ammo.js methods (e.g., `.setLinearVelocity()`).
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Camera Example
|
|
128
|
+
|
|
129
|
+
Manipulate WASD camera:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
app.cameras.WASD.pitch = 0.2;
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Object Interaction (Raycasting)
|
|
138
|
+
|
|
139
|
+
The raycast returns:
|
|
140
|
+
|
|
141
|
+
```js
|
|
142
|
+
{
|
|
143
|
+
rayOrigin: [x, y, z],
|
|
144
|
+
rayDirection: [x, y, z] // normalized
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Manual raycast example:
|
|
149
|
+
|
|
150
|
+
```js
|
|
151
|
+
window.addEventListener('click', (event) => {
|
|
152
|
+
let canvas = document.querySelector('canvas');
|
|
153
|
+
let camera = app.cameras.WASD;
|
|
154
|
+
const { rayOrigin, rayDirection } = getRayFromMouse(event, canvas, camera);
|
|
155
|
+
|
|
156
|
+
for (const object of app.mainRenderBundle) {
|
|
157
|
+
if (rayIntersectsSphere(rayOrigin, rayDirection, object.position, object.raycast.radius)) {
|
|
158
|
+
console.log('Object clicked:', object.name);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Automatic raycast listener:
|
|
165
|
+
|
|
166
|
+
```js
|
|
167
|
+
addRaycastListener();
|
|
168
|
+
|
|
169
|
+
window.addEventListener('ray.hit.event', (event) => {
|
|
170
|
+
console.log('Ray hit:', event.detail.hitObject);
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## How to Load `.obj` Models
|
|
92
177
|
|
|
93
|
-
## How to load obj [with uvs] file:
|
|
94
|
-
Main instance script:
|
|
95
178
|
```js
|
|
96
179
|
import MatrixEngineWGPU from "./src/world.js";
|
|
97
|
-
import {downloadMeshes} from './src/engine/loader-obj.js';
|
|
98
|
-
import {LOG_FUNNY, LOG_INFO, LOG_MATRIX} from "./src/engine/utils.js";
|
|
180
|
+
import { downloadMeshes } from './src/engine/loader-obj.js';
|
|
99
181
|
|
|
100
182
|
export let application = new MatrixEngineWGPU({
|
|
101
183
|
useSingleRenderPass: true,
|
|
@@ -105,20 +187,19 @@ export let application = new MatrixEngineWGPU({
|
|
|
105
187
|
responseCoef: 1000
|
|
106
188
|
}
|
|
107
189
|
}, () => {
|
|
108
|
-
|
|
109
190
|
addEventListener('AmmoReady', () => {
|
|
110
191
|
downloadMeshes({
|
|
111
192
|
welcomeText: "./res/meshes/blender/piramyd.obj",
|
|
112
193
|
armor: "./res/meshes/obj/armor.obj",
|
|
113
194
|
sphere: "./res/meshes/blender/sphere.obj",
|
|
114
195
|
cube: "./res/meshes/blender/cube.obj",
|
|
115
|
-
}, onLoadObj)
|
|
116
|
-
})
|
|
196
|
+
}, onLoadObj);
|
|
197
|
+
});
|
|
117
198
|
|
|
118
|
-
function onLoadObj(
|
|
119
|
-
application.myLoadedMeshes =
|
|
120
|
-
for(
|
|
121
|
-
console.log(`%c Loaded
|
|
199
|
+
function onLoadObj(meshes) {
|
|
200
|
+
application.myLoadedMeshes = meshes;
|
|
201
|
+
for (const key in meshes) {
|
|
202
|
+
console.log(`%c Loaded obj: ${key} `, LOG_MATRIX);
|
|
122
203
|
}
|
|
123
204
|
|
|
124
205
|
application.addMeshObj({
|
|
@@ -127,12 +208,12 @@ export let application = new MatrixEngineWGPU({
|
|
|
127
208
|
rotationSpeed: {x: 0, y: 0, z: 0},
|
|
128
209
|
texturesPaths: ['./res/meshes/blender/cube.png'],
|
|
129
210
|
name: 'CubePhysics',
|
|
130
|
-
mesh:
|
|
211
|
+
mesh: meshes.cube,
|
|
131
212
|
physics: {
|
|
132
213
|
enabled: true,
|
|
133
214
|
geometry: "Cube"
|
|
134
215
|
}
|
|
135
|
-
})
|
|
216
|
+
});
|
|
136
217
|
|
|
137
218
|
application.addMeshObj({
|
|
138
219
|
position: {x: 0, y: 2, z: -10},
|
|
@@ -140,92 +221,89 @@ export let application = new MatrixEngineWGPU({
|
|
|
140
221
|
rotationSpeed: {x: 0, y: 0, z: 0},
|
|
141
222
|
texturesPaths: ['./res/meshes/blender/cube.png'],
|
|
142
223
|
name: 'SpherePhysics',
|
|
143
|
-
mesh:
|
|
224
|
+
mesh: meshes.sphere,
|
|
144
225
|
physics: {
|
|
145
226
|
enabled: true,
|
|
146
227
|
geometry: "Sphere"
|
|
147
228
|
}
|
|
148
|
-
})
|
|
229
|
+
});
|
|
149
230
|
}
|
|
150
|
-
})
|
|
231
|
+
});
|
|
151
232
|
|
|
152
|
-
window.app = application
|
|
233
|
+
window.app = application;
|
|
153
234
|
```
|
|
154
235
|
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## About `main.js`
|
|
239
|
+
|
|
240
|
+
`main.js` is the main instance for the Ultimate Yahtzee game template.
|
|
241
|
+
It contains the game context, e.g., `dices`.
|
|
242
|
+
|
|
243
|
+
For a clean startup without extra logic, use `empty.js`.
|
|
244
|
+
This minimal build is ideal for online editors like CodePen or StackOverflow snippets.
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
155
248
|
## NPM Scripts
|
|
156
249
|
|
|
157
|
-
|
|
250
|
+
Uses `watchify` to bundle JavaScript.
|
|
158
251
|
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
252
|
+
```json
|
|
253
|
+
"main-worker": "watchify app-worker.js -p [esmify --noImplicitAny] -o public/app-worker.js",
|
|
254
|
+
"examples": "watchify examples.js -p [esmify --noImplicitAny] -o public/examples.js",
|
|
255
|
+
"main": "watchify main.js -p [esmify --noImplicitAny] -o public/app.js",
|
|
256
|
+
"empty": "watchify empty.js -p [esmify --noImplicitAny] -o public/empty.js",
|
|
257
|
+
"build-all": "npm run main-worker && npm run examples && npm run main && npm run build-empty"
|
|
165
258
|
```
|
|
166
259
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
5. "build-all" build all at once [every output is diff name].
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## Resources
|
|
263
|
+
|
|
264
|
+
All resources and output go into the `./public` folder — everything you need in one place.
|
|
173
265
|
|
|
174
|
-
|
|
266
|
+
---
|
|
175
267
|
|
|
176
|
-
|
|
177
|
-
after all you get all needed stuff in one public folder (www).
|
|
268
|
+
## Proof of Concept
|
|
178
269
|
|
|
179
|
-
|
|
270
|
+
🎲 The first full app example will be a WebGPU-powered **Ultimate Yahtzee** game.
|
|
180
271
|
|
|
181
|
-
|
|
182
|
-
https://codepen.io/zlatnaspirala/pen/VwNKMar?editors=0011
|
|
183
|
-
I use empty build then i add/upload to my VPS public server you can use it:
|
|
184
|
-
Usually last night build stable/unstable version.
|
|
185
|
-
https://maximumroulette.com/apps/megpu/empty.js
|
|
186
|
-
You can build your own with `npm run build-empty`.
|
|
272
|
+
---
|
|
187
273
|
|
|
188
|
-
##
|
|
274
|
+
## Live Demos & Dev Links
|
|
189
275
|
|
|
190
|
-
|
|
276
|
+
* [Jamb WebGPU Demo (WIP)](https://maximumroulette.com/apps/webgpu/)
|
|
277
|
+
* [CodePen Demo](https://codepen.io/zlatnaspirala/pen/VwNKMar?editors=0011)
|
|
278
|
+
→ Uses `empty.js` build from:
|
|
279
|
+
[https://maximumroulette.com/apps/megpu/empty.js](https://maximumroulette.com/apps/megpu/empty.js)
|
|
280
|
+
* [CodeSandbox Implementation](https://codesandbox.io/p/github/zlatnaspirala/matrix-engine-wgpu/main?file=%2Fpackage.json%3A14%2C16)
|
|
281
|
+
* 📘 Learning Resource: [WebGPU Ray Tracing](https://maierfelix.github.io/2020-01-13-webgpu-ray-tracing/)
|
|
191
282
|
|
|
192
|
-
|
|
193
|
-
and you can sell or what ever you want with your project."
|
|
283
|
+
---
|
|
194
284
|
|
|
195
|
-
|
|
196
|
-
https://webgpu.github.io/webgpu-samples/samples/renderBundles also
|
|
197
|
-
https://webgpu.github.io/webgpu-samples/?sample=shadowMapping
|
|
285
|
+
## License
|
|
198
286
|
|
|
199
|
-
|
|
200
|
-
Obj loader source http://math.hws.edu/graphicsbook/source/webgl/cube-camera.html
|
|
287
|
+
### Usage Note
|
|
201
288
|
|
|
202
|
-
|
|
289
|
+
You may use, modify, and sell projects based on this code — just keep this notice and included references intact.
|
|
203
290
|
|
|
204
|
-
|
|
291
|
+
---
|
|
205
292
|
|
|
206
|
-
|
|
293
|
+
### Attribution & Credits
|
|
207
294
|
|
|
208
|
-
|
|
209
|
-
|
|
295
|
+
* Engine design and scene structure inspired by:
|
|
296
|
+
[WebGPU Samples](https://webgpu.github.io/webgpu-samples/?sample=shadowMapping)
|
|
297
|
+
* OBJ Loader adapted from:
|
|
298
|
+
[http://math.hws.edu/graphicsbook/source/webgl/cube-camera.html](http://math.hws.edu/graphicsbook/source/webgl/cube-camera.html)
|
|
299
|
+
* Dice roll sound `roll1.wav` sourced from:
|
|
300
|
+
[https://wavbvkery.com/dice-rolling-sound/](https://wavbvkery.com/dice-rolling-sound/)
|
|
301
|
+
* Raycasting logic assisted by ChatGPT
|
|
210
302
|
|
|
211
|
-
|
|
212
|
-
this list of conditions and the following disclaimer.
|
|
303
|
+
---
|
|
213
304
|
|
|
214
|
-
|
|
215
|
-
this list of conditions and the following disclaimer in the documentation
|
|
216
|
-
and/or other materials provided with the distribution.
|
|
305
|
+
### BSD 3-Clause License (from WebGPU Samples)
|
|
217
306
|
|
|
218
|
-
|
|
219
|
-
contributors may be used to endorse or promote products derived from this
|
|
220
|
-
software without specific prior written permission.
|
|
307
|
+
[Full License Text](https://github.com/webgpu/webgpu-samples/blob/main/LICENSE.txt)
|
|
221
308
|
|
|
222
|
-
|
|
223
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
224
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
225
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
226
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
227
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
228
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
229
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
230
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
231
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
309
|
+
---
|