@zephyr3d/scene 0.4.0 → 0.5.0

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.
Files changed (116) hide show
  1. package/dist/animation/animation.js +25 -117
  2. package/dist/animation/animation.js.map +1 -1
  3. package/dist/animation/animationset.js +164 -24
  4. package/dist/animation/animationset.js.map +1 -1
  5. package/dist/animation/animationtrack.js +6 -18
  6. package/dist/animation/animationtrack.js.map +1 -1
  7. package/dist/animation/eulerrotationtrack.js +16 -6
  8. package/dist/animation/eulerrotationtrack.js.map +1 -1
  9. package/dist/animation/morphtarget.js +104 -0
  10. package/dist/animation/morphtarget.js.map +1 -0
  11. package/dist/animation/morphtrack.js +68 -0
  12. package/dist/animation/morphtrack.js.map +1 -0
  13. package/dist/animation/rotationtrack.js +15 -7
  14. package/dist/animation/rotationtrack.js.map +1 -1
  15. package/dist/animation/scaletrack.js +15 -7
  16. package/dist/animation/scaletrack.js.map +1 -1
  17. package/dist/animation/skeleton.js +101 -1
  18. package/dist/animation/skeleton.js.map +1 -1
  19. package/dist/animation/translationtrack.js +15 -7
  20. package/dist/animation/translationtrack.js.map +1 -1
  21. package/dist/animation/usertrack.js +2 -2
  22. package/dist/app.js +4 -26
  23. package/dist/app.js.map +1 -1
  24. package/dist/asset/assetmanager.js +58 -107
  25. package/dist/asset/assetmanager.js.map +1 -1
  26. package/dist/asset/loaders/dds/dds.js +77 -3
  27. package/dist/asset/loaders/dds/dds.js.map +1 -1
  28. package/dist/asset/loaders/dds/dds_loader.js +1 -1
  29. package/dist/asset/loaders/gltf/gltf_loader.js +280 -37
  30. package/dist/asset/loaders/gltf/gltf_loader.js.map +1 -1
  31. package/dist/asset/loaders/image/tga_Loader.js +1 -1
  32. package/dist/asset/model.js +13 -0
  33. package/dist/asset/model.js.map +1 -1
  34. package/dist/blitter/blitter.js +2 -2
  35. package/dist/camera/camera.js +58 -3
  36. package/dist/camera/camera.js.map +1 -1
  37. package/dist/index.d.ts +3026 -2839
  38. package/dist/index.js +2 -5
  39. package/dist/index.js.map +1 -1
  40. package/dist/material/blinn.js +9 -4
  41. package/dist/material/blinn.js.map +1 -1
  42. package/dist/material/lambert.js +22 -17
  43. package/dist/material/lambert.js.map +1 -1
  44. package/dist/material/material.js +11 -2
  45. package/dist/material/material.js.map +1 -1
  46. package/dist/material/meshmaterial.js +36 -4
  47. package/dist/material/meshmaterial.js.map +1 -1
  48. package/dist/material/mixins/albedocolor.js +1 -1
  49. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +3 -3
  50. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +3 -3
  51. package/dist/material/mixins/lit.js +2 -2
  52. package/dist/material/mixins/pbr/common.js +433 -10
  53. package/dist/material/mixins/pbr/common.js.map +1 -1
  54. package/dist/material/pbrmr.js +17 -6
  55. package/dist/material/pbrmr.js.map +1 -1
  56. package/dist/material/pbrsg.js +16 -9
  57. package/dist/material/pbrsg.js.map +1 -1
  58. package/dist/material/shader/helper.js +94 -4
  59. package/dist/material/shader/helper.js.map +1 -1
  60. package/dist/material/unlit.js +8 -4
  61. package/dist/material/unlit.js.map +1 -1
  62. package/dist/posteffect/bloom.js +33 -43
  63. package/dist/posteffect/bloom.js.map +1 -1
  64. package/dist/posteffect/compositor.js +8 -37
  65. package/dist/posteffect/compositor.js.map +1 -1
  66. package/dist/posteffect/sao.js +11 -24
  67. package/dist/posteffect/sao.js.map +1 -1
  68. package/dist/posteffect/water.js +2 -4
  69. package/dist/posteffect/water.js.map +1 -1
  70. package/dist/render/cull_visitor.js +3 -3
  71. package/dist/render/depthpass.js +13 -13
  72. package/dist/render/drawable_mixin.js +48 -6
  73. package/dist/render/drawable_mixin.js.map +1 -1
  74. package/dist/render/envlight.js +165 -31
  75. package/dist/render/envlight.js.map +1 -1
  76. package/dist/render/lightpass.js +35 -27
  77. package/dist/render/lightpass.js.map +1 -1
  78. package/dist/render/objectcolorpass.js +50 -0
  79. package/dist/render/objectcolorpass.js.map +1 -0
  80. package/dist/render/objectpool.js +295 -0
  81. package/dist/render/objectpool.js.map +1 -0
  82. package/dist/render/render_queue.js +189 -156
  83. package/dist/render/render_queue.js.map +1 -1
  84. package/dist/render/renderer.js +97 -20
  85. package/dist/render/renderer.js.map +1 -1
  86. package/dist/render/renderpass.js +18 -14
  87. package/dist/render/renderpass.js.map +1 -1
  88. package/dist/render/shadowmap_pass.js +14 -14
  89. package/dist/render/weightedblended_oit.js +11 -28
  90. package/dist/render/weightedblended_oit.js.map +1 -1
  91. package/dist/scene/environment.js +22 -1
  92. package/dist/scene/environment.js.map +1 -1
  93. package/dist/scene/graph_node.js +0 -9
  94. package/dist/scene/graph_node.js.map +1 -1
  95. package/dist/scene/mesh.js +32 -1
  96. package/dist/scene/mesh.js.map +1 -1
  97. package/dist/scene/scene.js +5 -8
  98. package/dist/scene/scene.js.map +1 -1
  99. package/dist/scene/scene_node.js +2 -3
  100. package/dist/scene/scene_node.js.map +1 -1
  101. package/dist/scene/terrain/grass.js +9 -0
  102. package/dist/scene/terrain/grass.js.map +1 -1
  103. package/dist/scene/terrain/patch.js +9 -0
  104. package/dist/scene/terrain/patch.js.map +1 -1
  105. package/dist/scene/terrain/quadtree.js +2 -2
  106. package/dist/shadow/esm.js +4 -22
  107. package/dist/shadow/esm.js.map +1 -1
  108. package/dist/shadow/shadowmapper.js +45 -20
  109. package/dist/shadow/shadowmapper.js.map +1 -1
  110. package/dist/shadow/vsm.js +4 -24
  111. package/dist/shadow/vsm.js.map +1 -1
  112. package/dist/utility/draco/decoder.js +116 -0
  113. package/dist/utility/draco/decoder.js.map +1 -0
  114. package/dist/values.js +18 -1
  115. package/dist/values.js.map +1 -1
  116. package/package.json +7 -6
@@ -1,47 +1,22 @@
1
- import { Quaternion, Vector3, Matrix4x4 } from '@zephyr3d/base';
2
- import { BoundingBox } from '../utility/bounding_volume.js';
3
- import { Application } from '../app.js';
4
-
5
1
  /**
6
2
  * Animation that contains multiple tracks
7
3
  * @public
8
4
  */ class AnimationClip {
9
5
  /** @internal */ _name;
10
- /** @internal */ _model;
11
- /** @internal */ _repeat;
12
- /** @internal */ _speedRatio;
13
- /** @internal */ _repeatCounter;
14
6
  /** @internal */ _duration;
15
- /** @internal */ _isPlaying;
16
- /** @internal */ _lastUpdateFrame;
17
- /** @internal */ _currentPlayTime;
18
7
  /** @internal */ _tracks;
19
8
  /** @internal */ _skeletons;
20
- /** @internal */ _tmpPosition;
21
- /** @internal */ _tmpRotation;
22
- /** @internal */ _tmpScale;
23
9
  /**
24
10
  * Creates an animation instance
25
11
  * @param name - Name of the animation
26
12
  * @param model - Parent node if this is a skeleton animation
27
- */ constructor(name, model){
13
+ */ constructor(name){
28
14
  this._name = name;
29
- this._model = model ?? null;
30
15
  this._tracks = new Map();
31
16
  this._duration = 0;
32
- this._repeat = 0;
33
- this._repeatCounter = 0;
34
- this._speedRatio = 1;
35
- this._isPlaying = false;
36
- this._currentPlayTime = 0;
37
- this._lastUpdateFrame = 0;
38
- this._skeletons = new Map();
39
- this._tmpRotation = new Quaternion();
40
- this._tmpPosition = new Vector3();
41
- this._tmpScale = new Vector3();
17
+ this._skeletons = new Set();
42
18
  }
43
19
  /** Disposes self */ dispose() {
44
- this._model = null;
45
20
  this._tracks = null;
46
21
  this._skeletons?.forEach((val, key)=>key.dispose());
47
22
  this._skeletons = null;
@@ -52,6 +27,9 @@ import { Application } from '../app.js';
52
27
  /** Gets all the tracks of this animation */ get tracks() {
53
28
  return this._tracks;
54
29
  }
30
+ /** Gets all skeletons */ get skeletons() {
31
+ return this._skeletons;
32
+ }
55
33
  /** The duration of the animation */ get timeDuration() {
56
34
  return this._duration;
57
35
  }
@@ -60,19 +38,8 @@ import { Application } from '../app.js';
60
38
  * @param skeleton - The skeleton to be added
61
39
  * @param meshList - The meshes controlled by the skeleton
62
40
  * @param boundingBoxInfo - Bounding box information for the skeleton
63
- */ addSkeleton(skeleton, meshList, boundingBoxInfo) {
64
- let meshes = this._skeletons.get(skeleton);
65
- if (!meshes) {
66
- meshes = [];
67
- this._skeletons.set(skeleton, meshes);
68
- }
69
- for(let i = 0; i < meshList.length; i++){
70
- meshes.push({
71
- mesh: meshList[i],
72
- bounding: boundingBoxInfo[i],
73
- box: new BoundingBox()
74
- });
75
- }
41
+ */ addSkeleton(skeleton) {
42
+ this._skeletons.add(skeleton);
76
43
  }
77
44
  /**
78
45
  * Adds an animation track to the animation
@@ -83,90 +50,31 @@ import { Application } from '../app.js';
83
50
  if (!track) {
84
51
  return;
85
52
  }
53
+ if (track.animation) {
54
+ if (track.animation === this) {
55
+ return;
56
+ } else {
57
+ console.error('Track is already in another animation');
58
+ return;
59
+ }
60
+ }
61
+ const blendId = track.getBlendId();
62
+ const tracks = this._tracks.get(node);
63
+ if (tracks && tracks.findIndex((track)=>track.getBlendId() === blendId) >= 0) {
64
+ console.error('Tracks with same BlendId could not be added to same animation');
65
+ return;
66
+ }
67
+ track.animation = this;
86
68
  let trackInfo = this._tracks.get(node);
87
69
  if (!trackInfo) {
88
- trackInfo = {
89
- poseTranslation: new Vector3(node.position),
90
- poseRotation: new Quaternion(node.rotation),
91
- poseScaling: new Vector3(node.scale),
92
- tracks: []
93
- };
70
+ trackInfo = [];
94
71
  this._tracks.set(node, trackInfo);
95
72
  }
96
- trackInfo.tracks.push(track);
73
+ trackInfo.push(track);
97
74
  this._duration = Math.max(this._duration, track.interpolator.maxTime);
75
+ track.reset(node);
98
76
  return this;
99
77
  }
100
- /**
101
- * Check if the animation is playing
102
- * @returns true if the animation is playing, otherwise false
103
- */ isPlaying() {
104
- return this._isPlaying;
105
- }
106
- /**
107
- * Updates the animation state
108
- */ update() {
109
- const device = Application.instance.device;
110
- if (!this._isPlaying || this._lastUpdateFrame === device.frameInfo.frameCounter) {
111
- return;
112
- }
113
- this._lastUpdateFrame = device.frameInfo.frameCounter;
114
- this._tracks.forEach((trackInfo, node)=>{
115
- for (const track of trackInfo.tracks){
116
- track.apply(node, this._currentPlayTime, this._duration);
117
- }
118
- });
119
- this._skeletons.forEach((meshes, skeleton)=>{
120
- skeleton.computeJoints();
121
- for (const mesh of meshes){
122
- skeleton.computeBoundingBox(mesh.bounding, mesh.mesh.invWorldMatrix);
123
- mesh.mesh.setBoneMatrices(skeleton.jointTexture);
124
- mesh.mesh.setInvBindMatrix(mesh.mesh.invWorldMatrix);
125
- mesh.mesh.setAnimatedBoundingBox(mesh.bounding.boundingBox);
126
- }
127
- });
128
- const timeAdvance = device.frameInfo.elapsedFrame * 0.001 * this._speedRatio;
129
- this._currentPlayTime += timeAdvance;
130
- if (this._currentPlayTime > this._duration) {
131
- this._repeatCounter++;
132
- this._currentPlayTime = 0;
133
- } else if (this._currentPlayTime < 0) {
134
- this._repeatCounter++;
135
- this._currentPlayTime = this._duration;
136
- }
137
- if (this._repeat !== 0 && this._repeatCounter >= this._repeat) {
138
- this.stop();
139
- }
140
- }
141
- /**
142
- * Starts playing the animation
143
- */ play(repeat, speedRatio) {
144
- this._isPlaying = true;
145
- this._repeat = repeat;
146
- this._speedRatio = speedRatio;
147
- this._currentPlayTime = speedRatio < 0 ? this._duration : 0;
148
- this.update();
149
- }
150
- /**
151
- * Stops the animation
152
- */ stop() {
153
- this._isPlaying = false;
154
- this._skeletons.forEach((meshes, skeleton)=>{
155
- skeleton.computeBindPose();
156
- for (const mesh of meshes){
157
- const invWorldMatrix = Matrix4x4.multiply(mesh.mesh.invWorldMatrix, this._model.worldMatrix);
158
- skeleton.computeBoundingBox(mesh.bounding, invWorldMatrix);
159
- mesh.mesh.setBoneMatrices(skeleton.jointTexture);
160
- mesh.mesh.setInvBindMatrix(invWorldMatrix);
161
- mesh.mesh.setAnimatedBoundingBox(mesh.bounding.boundingBox);
162
- }
163
- });
164
- }
165
- /**
166
- * Rewind the animation to the first frame
167
- */ rewind() {
168
- this._currentPlayTime = 0;
169
- }
170
78
  }
171
79
 
172
80
  export { AnimationClip };
@@ -1 +1 @@
1
- {"version":3,"file":"animation.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"animation.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,16 +1,27 @@
1
+ import { weightedAverage } from '@zephyr3d/base';
2
+ import { Application } from '../app.js';
3
+
1
4
  /**
2
5
  * Animation set
3
6
  * @public
4
7
  */ class AnimationSet {
8
+ /** @internal */ _model;
5
9
  /** @internal */ _animations;
6
10
  /** @internal */ _scene;
11
+ /** @internal */ _activeTracks;
12
+ /** @internal */ _activeSkeletons;
13
+ /** @internal */ _activeAnimations;
7
14
  /**
8
15
  * Creates an instance of AnimationSet
9
16
  * @param scene - The scene to which the animation set belongs
10
- */ constructor(scene){
17
+ */ constructor(scene, model){
11
18
  this._scene = scene;
19
+ this._model = model;
12
20
  this._scene.animationSet.push(this);
13
21
  this._animations = {};
22
+ this._activeTracks = new Map();
23
+ this._activeSkeletons = new Map();
24
+ this._activeAnimations = new Map();
14
25
  }
15
26
  /**
16
27
  * How many animations in this set
@@ -37,47 +48,173 @@
37
48
  /**
38
49
  * Updates all animations of the model
39
50
  */ update() {
40
- for(const k in this._animations){
41
- this._animations[k].update();
42
- }
51
+ this._activeAnimations.forEach((v, k)=>{
52
+ if (v.fadeOut > 0 && v.fadeOutStart < 0) {
53
+ v.fadeOutStart = v.animateTime;
54
+ }
55
+ // Update animation time
56
+ if (v.firstFrame) {
57
+ v.firstFrame = false;
58
+ } else {
59
+ const timeAdvance = Application.instance.device.frameInfo.elapsedFrame * 0.001 * v.speedRatio;
60
+ v.currentTime += timeAdvance;
61
+ v.animateTime += timeAdvance;
62
+ if (v.currentTime > k.timeDuration) {
63
+ v.repeatCounter++;
64
+ v.currentTime = 0;
65
+ } else if (v.currentTime < 0) {
66
+ v.repeatCounter++;
67
+ v.currentTime = k.timeDuration;
68
+ }
69
+ if (v.repeat !== 0 && v.repeatCounter >= v.repeat) {
70
+ this.stopAnimation(k.name);
71
+ } else if (v.fadeOut > 0) {
72
+ if (v.animateTime - v.fadeOutStart >= v.fadeOut) {
73
+ this.stopAnimation(k.name);
74
+ }
75
+ }
76
+ }
77
+ });
78
+ // Update tracks
79
+ this._activeTracks.forEach((v, k)=>{
80
+ v.forEach((tracks)=>{
81
+ if (tracks.length > 0) {
82
+ const weights = tracks.map((track)=>{
83
+ const info = this._activeAnimations.get(track.animation);
84
+ const weight = info.weight;
85
+ const fadeIn = info.fadeIn === 0 ? 1 : Math.min(1, info.animateTime / info.fadeIn);
86
+ let fadeOut = 1;
87
+ if (info.fadeOut !== 0) {
88
+ fadeOut = 1 - (info.animateTime - info.fadeOutStart) / info.fadeOut;
89
+ }
90
+ return weight * fadeIn * fadeOut;
91
+ });
92
+ const states = tracks.map((track)=>track.calculateState(this._activeAnimations.get(track.animation).currentTime));
93
+ const state = weightedAverage(weights, states, (a, b, t)=>{
94
+ return tracks[0].mixState(a, b, t);
95
+ });
96
+ tracks[0].applyState(k, state);
97
+ }
98
+ });
99
+ });
100
+ // Update skeletons
101
+ this._activeSkeletons.forEach((v, k)=>{
102
+ k.apply();
103
+ });
43
104
  }
44
105
  /**
45
106
  * Checks whether an animation is playing
46
107
  * @param name - Name of the animation to be checked
47
108
  * @returns true if the animation is playing, otherwise false
48
109
  */ isPlayingAnimation(name) {
49
- if (name) {
50
- return this._animations[name]?.isPlaying();
51
- } else {
52
- for(const k in this._animations){
53
- if (this._animations[k].isPlaying()) {
54
- return true;
55
- }
56
- }
57
- return false;
110
+ return name ? this._activeAnimations.has(this._animations[name]) : this._activeAnimations.size > 0;
111
+ }
112
+ /**
113
+ * Gets the weight of specific animation which is currently playing
114
+ * @param name - Name of the animation
115
+ * @returns Weight of the animation or 0 if this animation is not playing
116
+ */ getAnimationWeight(name) {
117
+ const ani = this._animations[name];
118
+ const info = this._activeAnimations.get(ani);
119
+ return info?.weight ?? 0;
120
+ }
121
+ /**
122
+ * Sets the weight of specific animation which is currently playing
123
+ * @param name - Name of the animation
124
+ * @param weight - New weight value
125
+ */ setAnimationWeight(name, weight) {
126
+ const ani = this._animations[name];
127
+ const info = this._activeAnimations.get(ani);
128
+ if (info) {
129
+ info.weight = weight;
58
130
  }
59
131
  }
60
132
  /**
61
133
  * Starts playing an animation of the model
62
134
  * @param name - Name of the animation to play
63
- * @param repeat - The repeat times, 0 for always repeating, default is 1
64
- * @param ratio - The speed ratio, default is 1. Use negative value to play backwards
65
- */ playAnimation(name, repeat = 0, speedRatio = 1) {
135
+ * @param options - Playing options
136
+ */ playAnimation(name, options) {
66
137
  const ani = this._animations[name];
67
- if (ani && !ani.isPlaying()) {
68
- for (const name of this.getAnimationNames()){
69
- if (this.isPlayingAnimation(name)) {
70
- this.stopAnimation(name);
138
+ if (!ani) {
139
+ console.error(`Animation ${name} not exists`);
140
+ return;
141
+ }
142
+ const fadeIn = Math.max(options?.fadeIn ?? 0, 0);
143
+ const info = this._activeAnimations.get(ani);
144
+ if (info) {
145
+ info.fadeOut = 0;
146
+ info.fadeIn = fadeIn;
147
+ } else {
148
+ const repeat = options?.repeat ?? 0;
149
+ const speedRatio = options?.speedRatio ?? 1;
150
+ const weight = options?.weight ?? 1;
151
+ this._activeAnimations.set(ani, {
152
+ repeat,
153
+ weight,
154
+ speedRatio,
155
+ fadeIn,
156
+ fadeOut: 0,
157
+ repeatCounter: 0,
158
+ currentTime: speedRatio < 0 ? ani.timeDuration : 0,
159
+ animateTime: 0,
160
+ fadeOutStart: 0,
161
+ firstFrame: true
162
+ });
163
+ ani.tracks?.forEach((v, k)=>{
164
+ let nodeTracks = this._activeTracks.get(k);
165
+ if (!nodeTracks) {
166
+ nodeTracks = new Map();
167
+ this._activeTracks.set(k, nodeTracks);
71
168
  }
72
- }
73
- ani.play(repeat, speedRatio);
169
+ for (const track of v){
170
+ const blendId = track.getBlendId();
171
+ let blendedTracks = nodeTracks.get(blendId);
172
+ if (!blendedTracks) {
173
+ blendedTracks = [];
174
+ nodeTracks.set(blendId, blendedTracks);
175
+ }
176
+ blendedTracks.push(track);
177
+ }
178
+ });
179
+ ani.skeletons?.forEach((v, k)=>{
180
+ const refcount = this._activeSkeletons.get(k);
181
+ if (refcount) {
182
+ this._activeSkeletons.set(k, refcount + 1);
183
+ } else {
184
+ this._activeSkeletons.set(k, 1);
185
+ }
186
+ });
74
187
  }
75
188
  }
76
189
  /**
77
190
  * Stops playing an animation of the model
78
191
  * @param name - Name of the animation to stop playing
79
- */ stopAnimation(name) {
80
- this._animations[name]?.stop();
192
+ */ stopAnimation(name, options) {
193
+ const ani = this._animations[name];
194
+ const info = this._activeAnimations.get(ani);
195
+ if (info) {
196
+ const fadeOut = Math.max(options?.fadeOut ?? 0, 0);
197
+ if (fadeOut !== 0) {
198
+ info.fadeOut = fadeOut;
199
+ info.fadeOutStart = -1;
200
+ } else {
201
+ this._activeAnimations.delete(ani);
202
+ this._activeTracks.forEach((v, k)=>{
203
+ v.forEach((tracks, id)=>{
204
+ v.set(id, tracks.filter((track)=>track.animation !== ani));
205
+ });
206
+ });
207
+ ani.skeletons?.forEach((v, k)=>{
208
+ const refcount = this._activeSkeletons.get(k);
209
+ if (refcount === 1) {
210
+ k.reset(this._model);
211
+ this._activeSkeletons.delete(k);
212
+ } else {
213
+ this._activeSkeletons.set(k, refcount - 1);
214
+ }
215
+ });
216
+ }
217
+ }
81
218
  }
82
219
  dispose() {
83
220
  const index = this._scene.animationSet.indexOf(this);
@@ -88,6 +225,9 @@
88
225
  this._animations[k].dispose();
89
226
  }
90
227
  this._animations = {};
228
+ this._activeAnimations.clear();
229
+ this._activeSkeletons.clear();
230
+ this._activeTracks.clear();
91
231
  }
92
232
  }
93
233
 
@@ -1 +1 @@
1
- {"version":3,"file":"animationset.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"animationset.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -3,35 +3,23 @@
3
3
  * @public
4
4
  */ class AnimationTrack {
5
5
  /** @internal */ _interpolator;
6
- /** @internal */ _currentPlayTime;
7
- /** @internal */ _playing;
6
+ /** @internal */ _animation;
8
7
  /**
9
8
  * Creates a new animation track
10
9
  * @param interpolator - Interpolator for the track
11
10
  */ constructor(interpolator){
12
- this._currentPlayTime = 0;
13
- this._playing = false;
14
11
  this._interpolator = interpolator;
15
12
  }
16
13
  /** Gets the interpolator of the track */ get interpolator() {
17
14
  return this._interpolator;
18
15
  }
19
- /** Return true if the track is playing, otherwise false */ get playing() {
20
- return this._playing;
16
+ /** Animation this track belongs to */ get animation() {
17
+ return this._animation;
21
18
  }
22
- /** Starts playing the track */ start() {
23
- this._playing = true;
24
- }
25
- /** Stops playing the track */ stop() {
26
- this._playing = false;
27
- }
28
- /** Rewinds the track to the first frame */ rewind() {
29
- this._currentPlayTime = 0;
30
- }
31
- /** Stops playing the track and rewind to the first frame */ reset() {
32
- this.stop();
33
- this._currentPlayTime = 0;
19
+ set animation(ani) {
20
+ this._animation = ani;
34
21
  }
22
+ /** Stops playing the track and rewind to the first frame */ reset(node) {}
35
23
  }
36
24
 
37
25
  export { AnimationTrack };
@@ -1 +1 @@
1
- {"version":3,"file":"animationtrack.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"animationtrack.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,12 +1,12 @@
1
- import { Vector3, Quaternion, Interpolator } from '@zephyr3d/base';
1
+ import { Vector3, Interpolator, Quaternion } from '@zephyr3d/base';
2
2
  import { AnimationTrack } from './animationtrack.js';
3
3
 
4
4
  const tmpVec3 = new Vector3();
5
- const tmpQuat = new Quaternion();
6
5
  /**
7
6
  * Euler angle rotation animation track
8
7
  * @public
9
8
  */ class EulerRotationTrack extends AnimationTrack {
9
+ _state;
10
10
  /**
11
11
  * Create an instance of EulerRotationTrack from keyframe values
12
12
  * @param mode - The interpolation mode of keyframes
@@ -21,11 +21,21 @@ const tmpQuat = new Quaternion();
21
21
  }
22
22
  const interpolator = new Interpolator(mode, 'vec3', inputs, outputs);
23
23
  super(interpolator);
24
+ this._state = new Quaternion();
24
25
  }
25
- /** {@inheritDoc AnimationTrack.apply} */ apply(node, currentTime, duration) {
26
- this._interpolator.interpolate(currentTime, duration, tmpVec3);
27
- node.rotation.set(tmpQuat.fromEulerAngle(tmpVec3.x, tmpVec3.y, tmpVec3.z, 'ZYX'));
28
- return true;
26
+ calculateState(currentTime) {
27
+ this._interpolator.interpolate(currentTime, tmpVec3);
28
+ this._state.fromEulerAngle(tmpVec3.x, tmpVec3.y, tmpVec3.z, 'ZYX');
29
+ return this._state;
30
+ }
31
+ applyState(node, state) {
32
+ node.rotation.set(state);
33
+ }
34
+ mixState(a, b, t) {
35
+ return Quaternion.slerp(a, b, t);
36
+ }
37
+ getBlendId() {
38
+ return 'node-rotation';
29
39
  }
30
40
  }
31
41
 
@@ -1 +1 @@
1
- {"version":3,"file":"eulerrotationtrack.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"eulerrotationtrack.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,104 @@
1
+ import { PBStructTypeInfo, PBArrayTypeInfo, PBPrimitiveTypeInfo, PBPrimitiveType } from '@zephyr3d/device';
2
+ import { Application } from '../app.js';
3
+ import { MAX_MORPH_ATTRIBUTES, MAX_MORPH_TARGETS, MORPH_WEIGHTS_VECTOR_COUNT, MORPH_ATTRIBUTE_VECTOR_COUNT } from '../values.js';
4
+ import { ShaderHelper } from '../material/shader/helper.js';
5
+ import '../material/lambert.js';
6
+ import '../material/blinn.js';
7
+ import '../material/unlit.js';
8
+ import '../material/meshmaterial.js';
9
+ import '../material/grassmaterial.js';
10
+ import '../material/terrainmaterial.js';
11
+ import '../material/pbrmr.js';
12
+ import '../material/pbrsg.js';
13
+ import '@zephyr3d/base';
14
+ import '../utility/pmrem.js';
15
+ import '../utility/panorama.js';
16
+ import '../utility/shprojection.js';
17
+ import { BoundingBox } from '../utility/bounding_volume.js';
18
+
19
+ function processMorphData(subMesh, morphWeights) {
20
+ const numTargets = subMesh.numTargets;
21
+ if (numTargets === 0) {
22
+ return;
23
+ }
24
+ const attributes = Object.getOwnPropertyNames(subMesh.targets);
25
+ const numVertices = subMesh.primitive.getNumVertices();
26
+ const weightsAndOffsets = new Float32Array(4 + MAX_MORPH_TARGETS + MAX_MORPH_ATTRIBUTES);
27
+ for(let i = 0; i < numTargets; i++){
28
+ weightsAndOffsets[4 + i] = morphWeights?.[i] ?? 0;
29
+ }
30
+ const textureSize = Math.ceil(Math.sqrt(numVertices * attributes.length * numTargets));
31
+ if (textureSize > Application.instance.device.getDeviceCaps().textureCaps.maxTextureSize) {
32
+ // TODO: reduce morph attributes
33
+ throw new Error(`Morph target data too large`);
34
+ }
35
+ weightsAndOffsets[0] = textureSize;
36
+ weightsAndOffsets[1] = textureSize;
37
+ weightsAndOffsets[2] = numVertices;
38
+ weightsAndOffsets[3] = numTargets;
39
+ let offset = 0;
40
+ const textureData = new Float32Array(textureSize * textureSize * 4);
41
+ for(let attrib = 0; attrib < MAX_MORPH_ATTRIBUTES; attrib++){
42
+ const index = attributes.indexOf(String(attrib));
43
+ if (index < 0) {
44
+ weightsAndOffsets[4 + MAX_MORPH_TARGETS + attrib] = -1;
45
+ continue;
46
+ }
47
+ weightsAndOffsets[4 + MAX_MORPH_TARGETS + attrib] = offset >> 2;
48
+ const info = subMesh.targets[attrib];
49
+ if (info.data.length !== numTargets) {
50
+ console.error(`Invalid morph target data`);
51
+ return;
52
+ }
53
+ for(let t = 0; t < numTargets; t++){
54
+ const data = info.data[t];
55
+ for(let i = 0; i < numVertices; i++){
56
+ for(let j = 0; j < 4; j++){
57
+ textureData[offset++] = j < info.numComponents ? data[i * info.numComponents + j] : 1;
58
+ }
59
+ }
60
+ }
61
+ }
62
+ const morphTexture = Application.instance.device.createTexture2D('rgba32f', textureSize, textureSize, {
63
+ samplerOptions: {
64
+ minFilter: 'nearest',
65
+ magFilter: 'nearest',
66
+ mipFilter: 'none'
67
+ }
68
+ });
69
+ morphTexture.update(textureData, 0, 0, textureSize, textureSize);
70
+ const bufferType = new PBStructTypeInfo('dummy', 'std140', [
71
+ {
72
+ name: ShaderHelper.getMorphInfoUniformName(),
73
+ type: new PBArrayTypeInfo(new PBPrimitiveTypeInfo(PBPrimitiveType.F32VEC4), 1 + MORPH_WEIGHTS_VECTOR_COUNT + MORPH_ATTRIBUTE_VECTOR_COUNT)
74
+ }
75
+ ]);
76
+ const morphUniformBuffer = Application.instance.device.createStructuredBuffer(bufferType, {
77
+ usage: 'uniform'
78
+ }, weightsAndOffsets);
79
+ const morphBoundingBox = new BoundingBox();
80
+ calculateMorphBoundingBox(morphBoundingBox, subMesh.targetBox, weightsAndOffsets.subarray(4, 4 + MAX_MORPH_TARGETS), numTargets);
81
+ const meshAABB = subMesh.mesh.getBoundingVolume().toAABB();
82
+ morphBoundingBox.minPoint.addBy(meshAABB.minPoint);
83
+ morphBoundingBox.maxPoint.addBy(meshAABB.maxPoint);
84
+ subMesh.mesh.setMorphData(morphTexture);
85
+ subMesh.mesh.setMorphInfo(morphUniformBuffer);
86
+ subMesh.mesh.setAnimatedBoundingBox(morphBoundingBox);
87
+ }
88
+ /** @internal */ function calculateMorphBoundingBox(morphBoundingBox, keyframeBoundingBox, weights, numTargets) {
89
+ morphBoundingBox.minPoint.setXYZ(0, 0, 0);
90
+ morphBoundingBox.maxPoint.setXYZ(0, 0, 0);
91
+ for(let i = 0; i < numTargets; i++){
92
+ const weight = weights[i];
93
+ const keyframeBox = keyframeBoundingBox[i];
94
+ morphBoundingBox.minPoint.x += keyframeBox.minPoint.x * weight;
95
+ morphBoundingBox.minPoint.y += keyframeBox.minPoint.y * weight;
96
+ morphBoundingBox.minPoint.y += keyframeBox.minPoint.z * weight;
97
+ morphBoundingBox.maxPoint.x += keyframeBox.maxPoint.x * weight;
98
+ morphBoundingBox.maxPoint.y += keyframeBox.maxPoint.y * weight;
99
+ morphBoundingBox.maxPoint.y += keyframeBox.maxPoint.z * weight;
100
+ }
101
+ }
102
+
103
+ export { calculateMorphBoundingBox, processMorphData };
104
+ //# sourceMappingURL=morphtarget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"morphtarget.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}