Skip to content

Commit c9882b0

Browse files
Animation export: Fix initial orientation
- Use consistently Float64 for animation data to avoid wrong initial orientation caused by round-off errors (e.g. in test models BouncingCapsules.jl, BouncingCones.jl and NewtonsCradle.jl). - Simplify total quaternion calculation for animation.
1 parent 1230006 commit c9882b0

File tree

3 files changed

+14
-14
lines changed

3 files changed

+14
-14
lines changed

src/AnimationExport/exportAnimation.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ end
188188

189189
function getObjectInfo(obj, geometry, material, initPos, initRot; r_obj=Modia3D.ZeroVector3D, R_obj=Modia3D.NullRotation, scale=ones(3))
190190
name = String(Modia3D.fullName(obj))
191-
return (; name=name, uuid=name2uuid(name), type=:Mesh, geometry=get(geometry, :uuid, nothing), material=get(material, :uuid, ""), position=initPos+initRot'*r_obj, rotation=Modia3D.rot123fromR(R_obj*initRot), scale=scale )
191+
return (; name=name, uuid=name2uuid(name), type=:Mesh, geometry=get(geometry, :uuid, nothing), material=get(material, :uuid, ""), position=initPos+initRot'*r_obj, rotation=Modia3D.rot123fromR(R_obj*initRot), scale=scale)
192192
end
193193

194194
printVisuMaterialToJSON(obj, visuMaterial) = nothing
@@ -264,7 +264,7 @@ function addCameras!(object, uuid4, position, orientation)
264264

265265
name = "Perspective Camera"
266266
uuid = string(UUIDs.uuid5(UUIDs.UUID(uuid4), name))
267-
camera = (; name=name, uuid=uuid, type="PerspectiveCamera", position=position, rotation=Modia3D.rot123fromR(SMatrix{3,3,Float64}(orientation)))
267+
camera = (; name=name, uuid=uuid, type="PerspectiveCamera", position=position, rotation=Modia3D.rot123fromR(orientation))
268268
push!(object.children, camera)
269269

270270
name="Orthographic Camera XY"
@@ -286,7 +286,7 @@ end
286286
function createAnimationPositionTrack(tracks, animation, obj, iobj, r_obj)
287287
keys = []
288288
for istep in 1:length(animation)
289-
r_all = animation[istep].objectData[iobj].position + (Modia3D.from_q(SVector{4,Float64}(animation[istep].objectData[iobj].quaternion)))'*r_obj
289+
r_all = animation[istep].objectData[iobj].position + (Modia3D.from_q(animation[istep].objectData[iobj].quaternion))'*r_obj
290290
push!(keys, (; time=animation[istep].time, value=r_all) )
291291
end
292292
name = string(Modia3D.fullName(obj), ".position")
@@ -296,8 +296,8 @@ end
296296
function createAnimationQuaternionTrack(tracks, animation, obj, iobj, R_obj)
297297
keys = []
298298
for istep in 1:length(animation)
299-
R_all = Modia3D.from_R(R_obj*Modia3D.from_q(SVector{4,Float64}(animation[istep].objectData[iobj].quaternion)) )
300-
push!(keys, (; time=animation[istep].time, value=R_all) )
299+
q_all = Modia3D.absoluteRotation(animation[istep].objectData[iobj].quaternion, Modia3D.from_R(R_obj))
300+
push!(keys, (; time=animation[istep].time, value=q_all) )
301301
end
302302
name = string(Modia3D.fullName(obj), ".quaternion")
303303
push!(tracks, (; name=name, uuid=name2uuid(name), type="quaternion", keys ) )
@@ -339,7 +339,7 @@ function exportAnimation(scene)
339339
tracks = []
340340
for obj in allVisuElements
341341
iobj = iobj + 1
342-
(r_obj, R_obj) = printObjectToJSON(object, elements, obj, initPos=animation[1].objectData[iobj].position, initRot=Modia3D.from_q(SVector{4,Float64}(animation[1].objectData[iobj].quaternion)) )
342+
(r_obj, R_obj) = printObjectToJSON(object, elements, obj, initPos=animation[1].objectData[iobj].position, initRot=Modia3D.from_q(animation[1].objectData[iobj].quaternion))
343343
if !isnothing(R_obj)
344344
createAnimationPositionTrack(tracks, animation, obj, iobj, r_obj)
345345
createAnimationQuaternionTrack(tracks, animation, obj, iobj, R_obj)

src/Composition/joints/FreeMotion.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ In case of singular state (angle2 +-90 deg, x and z axes parallel) `rot3_guess`
1717
"""
1818
function rot123fromR(R::Frames.RotationMatrix; rot3_guess=0.0)
1919

20-
sbe = R[3,1]
20+
sbe = clamp(R[3,1], -1.0, 1.0)
2121
cbe2 = 1.0 - sbe*sbe
2222
if (cbe2 > 1e-12)
2323
al = atan(-R[3,2], R[3,3])
2424
be = atan(sbe/sqrt(cbe2))
2525
ga = atan(-R[2,1], R[1,1])
2626
else
27-
# be is 90 deg -> singular, only al+ga is defined -> set ga to zero
27+
# be is 90 deg -> singular, only al+ga is defined -> set ga to rot3_guess
2828
al = atan(R[2,3], R[2,2]) - sign(sbe)*rot3_guess # ???
2929
be = sign(sbe)*0.5*pi
3030
ga = rot3_guess
@@ -41,7 +41,7 @@ In case of singular state (angle2 +-90 deg, x and y axes parallel) `rot3_guess`
4141
"""
4242
function rot132fromR(R::Frames.RotationMatrix; rot3_guess=0.0)
4343

44-
sga = - R[2,1]
44+
sga = clamp(-R[2,1], -1.0, 1.0)
4545
cga2 = 1.0 - sga*sga
4646
if (cga2 > 1e-12)
4747
al = atan(R[2,3], R[2,2])

src/Composition/scene.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ function cameraPosition(distance, longitude, latitude, cameraUpDir, sceneUpDir)
252252
else
253253
# camera upwards := +y direction
254254
end
255-
r_Camera = R_view' * r_Camera
256-
R_Camera = R_Camera * R_view
255+
r_Camera = SVector{3,Float64}(R_view' * r_Camera)
256+
R_Camera = SMatrix{3,3,Float64}(R_Camera * R_view)
257257
return (r_Camera, R_Camera)
258258
end
259259

@@ -396,12 +396,12 @@ struct SceneOptions <: Modia3D.AbstractSceneOptions
396396
end
397397

398398
struct animationData
399-
position::SVector{3,Float32} # abs. Object3D position
400-
quaternion::SVector{4,Float32} # abs. Object3D quaternion
399+
position::SVector{3,Float64} # abs. Object3D position
400+
quaternion::SVector{4,Float64} # abs. Object3D quaternion
401401
end
402402

403403
struct animationStep
404-
time::Float32 # simulation time
404+
time::Float64 # simulation time
405405
objectData::Vector{animationData} # animation data of Object3Ds
406406
end
407407

0 commit comments

Comments
 (0)