Animation & blend file: Preliminary support for actions.
This commit is contained in:
parent
fc39a93a94
commit
45cc6dac00
2 changed files with 110 additions and 0 deletions
|
@ -293,10 +293,70 @@ proc idPropertiesToJsonTable(prop: FNode): Table[string, JsonNode] =
|
||||||
else: discard
|
else: discard
|
||||||
prop = prop.next
|
prop = prop.next
|
||||||
|
|
||||||
|
proc loadFCurveImpl(self: BlendLoader, fcurve: FNode): (string, AnimationChannel) =
|
||||||
|
let path = fcurve.rna_path.str
|
||||||
|
let chan = new AnimationChannel
|
||||||
|
let path_parts = path.rsplit('.',1)
|
||||||
|
if path_parts.len == 1:
|
||||||
|
chan.channel_type = ChObject
|
||||||
|
else:
|
||||||
|
if path.startswith "key_blocks[":
|
||||||
|
chan.channel_type = ChShape
|
||||||
|
chan.name = path.split('"')[1]
|
||||||
|
elif path.startswith "pose.bones[":
|
||||||
|
return # TODO
|
||||||
|
else:
|
||||||
|
echo "Warning: unknown channel path ", path
|
||||||
|
return
|
||||||
|
chan.property = case path_parts[^1]:
|
||||||
|
of "value": PropValue
|
||||||
|
of "location": PropPosition
|
||||||
|
of "rotation_euler": PropRotationEuler
|
||||||
|
of "rotation_quaternion": PropRotationQuaternion
|
||||||
|
of "scale": PropScale
|
||||||
|
else:
|
||||||
|
echo "Warning: unknown property ", path
|
||||||
|
return
|
||||||
|
chan.index = fcurve.array_index.i32[0]
|
||||||
|
if chan.property == PropRotationQuaternion:
|
||||||
|
chan.index = (chan.index - 1) and 3
|
||||||
|
let count = fcurve.totvert.i32[0]
|
||||||
|
for i,floats in fcurve.bezt[0 ..< count].vec:
|
||||||
|
let fs = floats.f32
|
||||||
|
chan.points.add BezierPoint(
|
||||||
|
# left_handle: vec2(fs[0], fs[1]),
|
||||||
|
co: vec2(fs[3], fs[4]),
|
||||||
|
# right_handle: vec2(fs[6], fs[7]),
|
||||||
|
)
|
||||||
|
if chan.property != PropValue:
|
||||||
|
return (&"{path}[{chan.index}]", chan)
|
||||||
|
else:
|
||||||
|
return (path, chan)
|
||||||
|
|
||||||
|
proc loadActionImpl(self: BlendLoader, acn: FNode): Action =
|
||||||
|
new(result)
|
||||||
|
let flags = acn.flag.i32[0]
|
||||||
|
result.manual_range = (flags and 4096).bool
|
||||||
|
result.frame_start = acn.frame_start.f32[0]
|
||||||
|
result.frame_end = acn.frame_end.f32[0]
|
||||||
|
var curve = acn.curves.first
|
||||||
|
while curve.valid:
|
||||||
|
let (path, ch) = self.loadFCurveImpl(curve)
|
||||||
|
if ch != nil:
|
||||||
|
result.channels[path] = ch
|
||||||
|
curve = curve.next
|
||||||
|
|
||||||
|
proc loadAction*(self: BlendLoader, name: string): Action =
|
||||||
|
for n in self.blend_file.named_blocks["AC"]:
|
||||||
|
if n.id.name.str.strip2 == name:
|
||||||
|
return self.loadActionImpl(n)
|
||||||
|
raise KeyError.newException &"Could not find action '{name}'"
|
||||||
|
|
||||||
proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, string) =
|
proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, string) =
|
||||||
let name = obn.id.name.str.strip2
|
let name = obn.id.name.str.strip2
|
||||||
let data = obn.data
|
let data = obn.data
|
||||||
let ob = case obn["type"].i16[0]:
|
let ob = case obn["type"].i16[0]:
|
||||||
|
var shape_key_adt: FNode
|
||||||
of BMesh.int16:
|
of BMesh.int16:
|
||||||
var ob = self.engine.new_mesh(name=name)
|
var ob = self.engine.new_mesh(name=name)
|
||||||
let mat_count = obn.totcol.i32[0]
|
let mat_count = obn.totcol.i32[0]
|
||||||
|
@ -377,6 +437,8 @@ proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, s
|
||||||
if v.vtype == Tangent and v.attname notin tangents:
|
if v.vtype == Tangent and v.attname notin tangents:
|
||||||
tangents.add v.attname
|
tangents.add v.attname
|
||||||
|
|
||||||
|
if data.key.valid:
|
||||||
|
shape_key_adt = data.key.adt
|
||||||
# TODO: defer this by storing the name of the mesh as hash
|
# TODO: defer this by storing the name of the mesh as hash
|
||||||
# (maybe the address too)
|
# (maybe the address too)
|
||||||
|
|
||||||
|
@ -514,6 +576,20 @@ proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, s
|
||||||
|
|
||||||
ob.object_color = obn.col.f32.vec4
|
ob.object_color = obn.col.f32.vec4
|
||||||
|
|
||||||
|
var animation_datas: seq[FNode]
|
||||||
|
for adt in [obn.adt, shape_key_adt]:
|
||||||
|
if adt.valid:
|
||||||
|
animation_datas.add adt
|
||||||
|
# TODO: make animation strips. we'll just merge the actions for now.
|
||||||
|
for adt in animation_datas:
|
||||||
|
if adt.action.valid:
|
||||||
|
let ac = self.loadActionImpl(adt.action)
|
||||||
|
if ob.action == nil:
|
||||||
|
ob.action = ac
|
||||||
|
else:
|
||||||
|
for k,v in ac.channels:
|
||||||
|
ob.action.channels[k] = v
|
||||||
|
|
||||||
let prop = obn.id.properties
|
let prop = obn.id.properties
|
||||||
if prop.valid:
|
if prop.valid:
|
||||||
ob.properties = idPropertiesToJsonTable(prop.data.group.first)
|
ob.properties = idPropertiesToJsonTable(prop.data.group.first)
|
||||||
|
|
|
@ -125,6 +125,7 @@ type
|
||||||
# probe_cube*: Probe
|
# probe_cube*: Probe
|
||||||
# probe_planar*: Probe
|
# probe_planar*: Probe
|
||||||
properties*: Table[string, JsonNode]
|
properties*: Table[string, JsonNode]
|
||||||
|
action*: Action # TODO: remove when strips are implemented
|
||||||
# animation_strips*: seq[AnimationStrip]
|
# animation_strips*: seq[AnimationStrip]
|
||||||
name*: string
|
name*: string
|
||||||
original_name*: string
|
original_name*: string
|
||||||
|
@ -823,6 +824,39 @@ type
|
||||||
cache_dir_bc*: string ## Cache directory for writing bc
|
cache_dir_bc*: string ## Cache directory for writing bc
|
||||||
cache_dir_astc*: string ## Cache directory for writing astc
|
cache_dir_astc*: string ## Cache directory for writing astc
|
||||||
|
|
||||||
|
# action.nim
|
||||||
|
|
||||||
|
Action* = ref object
|
||||||
|
manual_range*: bool
|
||||||
|
frame_start*, frame_end*: float32
|
||||||
|
channels*: OrderedTable[string, AnimationChannel]
|
||||||
|
|
||||||
|
ChannelType* = enum
|
||||||
|
ChObject
|
||||||
|
ChPose
|
||||||
|
ChShape
|
||||||
|
ChObProperty
|
||||||
|
|
||||||
|
ChannelProperty* = enum
|
||||||
|
PropValue
|
||||||
|
PropPosition
|
||||||
|
PropRotationEuler
|
||||||
|
PropRotationQuaternion
|
||||||
|
PropScale
|
||||||
|
|
||||||
|
AnimationChannel* = ref object
|
||||||
|
channel_type*: ChannelType
|
||||||
|
name*: string
|
||||||
|
property*: ChannelProperty
|
||||||
|
property_name*: string
|
||||||
|
index*: int
|
||||||
|
points*: seq[BezierPoint]
|
||||||
|
last_eval_point*: int
|
||||||
|
|
||||||
|
BezierPoint* = object
|
||||||
|
# left_handle*: Vec2
|
||||||
|
co*: Vec2
|
||||||
|
# right_handle*: Vec2
|
||||||
|
|
||||||
# INCOMPLETE
|
# INCOMPLETE
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue