bestguigui_lab 0.14.0 → 0.14.2
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.
- checksums.yaml +4 -4
- data/lib/bestguigui_lab/gltf_animator.rb +17 -27
- data/lib/bestguigui_lab/gltf_model.rb +14 -19
- data/lib/bestguigui_lab/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ccc420dcc4710f176292b2cec9b80a01ceed0cc297073dfddf847c2ca12ac65f
|
|
4
|
+
data.tar.gz: 940b1c9e78ecdb11bb51ed75371ba38f72c4960730decf85eb231b5c2db62002
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d21defb2e306380d7fbb4d6a26dd7679dabdd97e89405c34217f4021a1c5f06148a8d8fe39f3618f180e846eca0398f66ed14c76872439504adddb3292e06460
|
|
7
|
+
data.tar.gz: bdfee9d22037dd9c3b37e857e67665cb8b7b4f9e617d25a491c181a029de19ef7fc99b06c32f01da79a34f3543b390f3878e4b3ddc8f4051eec41233234247b2
|
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Bestguigui
|
|
4
|
-
# Lit le temps d'une
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
4
|
+
# Lit le temps d'une GLTFAnimation et renvoie sa pose locale — fondu
|
|
5
|
+
# enchaine (en temps reel, quel que soit speed) depuis la pose FIGEE de
|
|
6
|
+
# l'animation precedente au moment du #play, jamais depuis une pose
|
|
7
|
+
# qu'on continuerait a faire avancer/boucler pendant le fondu (ca
|
|
8
|
+
# blend deux cibles mouvantes, incoherent des que speed est eleve).
|
|
8
9
|
class GLTFAnimator
|
|
9
|
-
|
|
10
|
+
attr_accessor :speed
|
|
11
|
+
|
|
12
|
+
def initialize(speed: 1.0)
|
|
10
13
|
@current = nil
|
|
11
14
|
@time = 0.0
|
|
12
15
|
@loop = true
|
|
13
|
-
@
|
|
14
|
-
@previous_time = 0.0
|
|
15
|
-
@previous_loop = true
|
|
16
|
+
@previous_pose = nil
|
|
16
17
|
@transition_duration = 0.0
|
|
17
18
|
@transition_elapsed = 0.0
|
|
19
|
+
@speed = speed
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
#
|
|
21
|
-
# (secondes) du fondu enchaine depuis l'animation en cours ; 0 = coupe
|
|
22
|
-
# net (par defaut pour la toute premiere animation, rien avant elle).
|
|
22
|
+
# transition: duree reelle (secondes) du fondu, independante de speed.
|
|
23
23
|
def play(animation, loop: true, transition: 0.0)
|
|
24
|
-
|
|
25
|
-
@previous = transitioning ? @current : nil
|
|
26
|
-
@previous_time = @time
|
|
27
|
-
@previous_loop = @loop
|
|
24
|
+
@previous_pose = transition.positive? && @current ? pose : nil
|
|
28
25
|
@current = animation
|
|
29
26
|
@loop = loop
|
|
30
27
|
@time = 0.0
|
|
@@ -35,25 +32,21 @@ module Bestguigui
|
|
|
35
32
|
def update(dt)
|
|
36
33
|
return unless @current
|
|
37
34
|
|
|
38
|
-
@time = advance_time(@time, dt, @current, @loop)
|
|
39
|
-
return unless @
|
|
35
|
+
@time = advance_time(@time, dt * @speed, @current, @loop)
|
|
36
|
+
return unless @previous_pose
|
|
40
37
|
|
|
41
|
-
@previous_time = advance_time(@previous_time, dt, @previous, @previous_loop)
|
|
42
38
|
@transition_elapsed += dt
|
|
43
|
-
@
|
|
39
|
+
@previous_pose = nil if @transition_elapsed >= @transition_duration
|
|
44
40
|
end
|
|
45
41
|
|
|
46
|
-
# Pose locale courante, fondue enchainee si une transition est en
|
|
47
|
-
# cours — Hash node => {translation:/rotation:/scale: => [...]},
|
|
48
|
-
# partiel (seuls les noeuds/proprietes reellement animes ici).
|
|
49
42
|
def pose
|
|
50
43
|
return {} unless @current
|
|
51
44
|
|
|
52
45
|
current_pose = @current.local_pose_at(@time)
|
|
53
|
-
return current_pose unless @
|
|
46
|
+
return current_pose unless @previous_pose
|
|
54
47
|
|
|
55
48
|
blend_t = @transition_duration.zero? ? 1.0 : (@transition_elapsed / @transition_duration).clamp(0.0, 1.0)
|
|
56
|
-
blend_poses(@
|
|
49
|
+
blend_poses(@previous_pose, current_pose, blend_t)
|
|
57
50
|
end
|
|
58
51
|
|
|
59
52
|
private
|
|
@@ -76,9 +69,6 @@ module Bestguigui
|
|
|
76
69
|
(from.keys | dest.keys).to_h { |path| [path, blend_property(path, from[path], dest[path], progress)] }
|
|
77
70
|
end
|
|
78
71
|
|
|
79
|
-
# Si une seule des deux animations definit cette propriete pour ce
|
|
80
|
-
# noeud, pas de vraie valeur "avant" a interpoler — on la garde telle
|
|
81
|
-
# quelle plutot que d'inventer une pose de depart arbitraire.
|
|
82
72
|
def blend_property(path, from, dest, progress)
|
|
83
73
|
return dest unless from
|
|
84
74
|
return from unless dest
|
|
@@ -3,34 +3,31 @@
|
|
|
3
3
|
require 'tempfile'
|
|
4
4
|
|
|
5
5
|
module Bestguigui
|
|
6
|
-
# Charge un modele .glb (glTF binaire
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# sur le CPU (voir GLTFPrimitive). Un seul skin/squelette par fichier
|
|
11
|
-
# (cf. GLTFSkeleton).
|
|
6
|
+
# Charge un modele .glb (glTF binaire auto-suffisant, cf. GLTFBuffer) :
|
|
7
|
+
# squelette + animations (GLTFSkeleton/GLTFAnimation/GLTFAnimator),
|
|
8
|
+
# skinning CPU (GLTFPrimitive), shading: :texture ou :gouraud, rigid:
|
|
9
|
+
# true pour ignorer la mise a l'echelle des os.
|
|
12
10
|
#
|
|
13
11
|
# model = Bestguigui::Assets.gltf_model('assets/jill.glb')
|
|
14
12
|
# model.play('Idle')
|
|
15
|
-
#
|
|
16
|
-
# model.
|
|
17
|
-
# model.draw
|
|
18
|
-
# model.play('walk', transition: 0.3) # fondu enchaine de 0.3s vers walk
|
|
19
|
-
#
|
|
20
|
-
# rigid: true interdit toute deformation du maillage par mise a
|
|
21
|
-
# l'echelle d'un os (seules rotation et translation l'articulent) — voir
|
|
22
|
-
# GLTFSkeleton.
|
|
13
|
+
# model.update(dt) # puis model.draw, dans ta Scene
|
|
14
|
+
# model.play('walk', transition: 0.3)
|
|
23
15
|
class GLTFModel
|
|
24
|
-
def initialize(path, shading: :texture, rigid: false)
|
|
16
|
+
def initialize(path, shading: :texture, rigid: false, speed: 1.0)
|
|
25
17
|
super()
|
|
26
18
|
@shading = shading
|
|
27
19
|
@rigid = rigid
|
|
28
20
|
load_scene(path)
|
|
29
|
-
@animator = GLTFAnimator.new
|
|
21
|
+
@animator = GLTFAnimator.new(speed: speed)
|
|
30
22
|
reskin
|
|
31
23
|
end
|
|
32
24
|
|
|
33
25
|
def animation_names = @animations.keys
|
|
26
|
+
def speed = @animator.speed
|
|
27
|
+
|
|
28
|
+
def speed=(value)
|
|
29
|
+
@animator.speed = value
|
|
30
|
+
end
|
|
34
31
|
|
|
35
32
|
def play(name, loop: true, transition: 0.0)
|
|
36
33
|
animation = @animations.fetch(name) { raise ArgumentError, "animation glTF inconnue : #{name.inspect}" }
|
|
@@ -121,9 +118,7 @@ module Bestguigui
|
|
|
121
118
|
return nil unless material_index
|
|
122
119
|
|
|
123
120
|
texture_ref = @json['materials'][material_index].dig('pbrMetallicRoughness', 'baseColorTexture')
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
@textures[@json['textures'][texture_ref['index']]['source']]
|
|
121
|
+
texture_ref && @textures[@json['textures'][texture_ref['index']]['source']]
|
|
127
122
|
end
|
|
128
123
|
|
|
129
124
|
# --- Texture embarquee : ecrite dans un fichier temporaire le temps
|