1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_SkeletalModel.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 25728 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/gfx/gfx_SkeletalModel.h>
19 #include <nw/gfx/gfx_ISceneVisitor.h>
20 #include <nw/gfx/gfx_AnimObject.h>
21
22 #include <nw/anim/res/anim_ResAnimGroup.h>
23
24 #include <nw/ut/ut_ResUtil.h>
25 #include <nw/ut/ut_ResDictionary.h>
26 #include <nw/ut/ut_Foreach.h>
27
28 namespace nw
29 {
30 namespace gfx
31 {
32
33 NW_UT_RUNTIME_TYPEINFO_DEFINITION( SkeletalModel, Model );
34
35 //----------------------------------------
36 SkeletalModel*
Create(SceneNode * parent,ResSceneObject resource,os::IAllocator * allocator)37 SkeletalModel::Builder::Create(
38 SceneNode* parent,
39 ResSceneObject resource,
40 os::IAllocator* allocator)
41 {
42 NW_NULL_ASSERT(allocator);
43
44 ResSkeletalModel resModel = ResStaticCast<ResSkeletalModel>(resource);
45
46 GfxPtr<Skeleton> skeleton;
47 bool isSharedSkeleton = true;
48 if (m_Description.sharedSkeleton != NULL)
49 {
50 // 所有権の移動を行いません。
51 skeleton.Reset(m_Description.sharedSkeleton, false);
52 isSharedSkeleton = true;
53 }
54 else
55 {
56 // スケルトン作成
57 ResSkeleton resSkeleton = resModel.GetSkeleton();
58 NW_ASSERT(resSkeleton.IsValid());
59 Skeleton::TransformPose::TransformArray poseTransforms(resSkeleton.GetBonesCount(), allocator);
60 ResBoneArray bones = resSkeleton.GetBones();
61 ResBoneArray::iterator bonesEnd = bones.end();
62 for (ResBoneArray::iterator bone = bones.begin(); bone != bonesEnd; ++bone)
63 {
64 // リソースから計算済みトランスフォームへデータをコピーします。
65 poseTransforms.PushBackFast(*bone);
66 }
67 skeleton.Reset(StandardSkeleton::Create(
68 resSkeleton,
69 m_Description.maxCallbacks,
70 m_Description.isFixedSizeMemory,
71 poseTransforms,
72 allocator));
73
74 isSharedSkeleton = false;
75 }
76
77 // モデル作成
78 void* memory = allocator->Alloc(sizeof(SkeletalModel));
79 NW_NULL_ASSERT(memory);
80
81 SkeletalModel* model = new(memory) SkeletalModel(
82 allocator,
83 resModel,
84 skeleton,
85 isSharedSkeleton,
86 m_Description);
87
88 Result result = model->Initialize(allocator);
89 NW_ASSERT(result.IsSuccess());
90
91 if (parent)
92 {
93 bool isAttached = parent->AttachChild(model);
94 NW_ASSERT(isAttached);
95 }
96
97 return model;
98 }
99
100 //----------------------------------------
101 void
Accept(ISceneVisitor * visitor)102 SkeletalModel::Accept(
103 ISceneVisitor* visitor
104 )
105 {
106 visitor->VisitSkeletalModel(this);
107 AcceptChildren(visitor);
108 }
109
110 //----------------------------------------
111 Result
CreateSkeletalAnimGroup(os::IAllocator * allocator)112 SkeletalModel::CreateSkeletalAnimGroup(os::IAllocator* allocator)
113 {
114 Result result = INITIALIZE_RESULT_OK;
115
116 AnimBinding* animBinding = GetAnimBinding();
117 if (animBinding == NULL)
118 {
119 return result;
120 }
121
122 ResSceneObject resSceneObject = GetResSceneObject();
123 ResSkeletalModel resModel = *reinterpret_cast<ResSkeletalModel*>(&resSceneObject);
124 NW_ASSERT(resModel.IsValid());
125
126 ResSkeleton resSkeleton = resModel.GetSkeleton();
127 Skeleton::TransformPose& pose = m_Skeleton->LocalTransformPose();
128 Skeleton::OriginalPose& originalPose = m_Skeleton->LocalOriginalPose();
129
130 const int animGroupCount = resModel.GetAnimGroupsCount();
131 for (int animGroupIdx = 0; animGroupIdx < animGroupCount; ++animGroupIdx)
132 {
133 anim::ResAnimGroup resAnimGroup = resModel.GetAnimGroups(animGroupIdx);
134 const int targetType = resAnimGroup.GetTargetType();
135 const bool transformFlag =
136 (resAnimGroup.GetFlags() & anim::ResAnimGroup::FLAG_IS_CALCULATED_TRANSFORM) != 0;
137 if (transformFlag &&
138 targetType == anim::ResGraphicsAnimGroup::TARGET_TYPE_BONE)
139 {
140 AnimGroup* animGroup = AnimGroup::Builder()
141 .ResAnimGroup(resAnimGroup)
142 .SetSceneNode(this)
143 .UseOriginalValue(true)
144 .Create(allocator);
145
146 if (animGroup == NULL)
147 {
148 result |= Result::MASK_FAIL_BIT;
149 }
150
151 NW_ENSURE_AND_RETURN(result);
152
153 const int animMemberCount = animGroup->GetMemberCount();
154 for (int memberIdx = 0; memberIdx < animMemberCount; ++memberIdx)
155 {
156 anim::ResAnimGroupMember resAnimGroupMember =
157 animGroup->GetResAnimGroupMember(memberIdx);
158
159 // TODO: ResBoneMemberDataの情報を利用する
160 ResBone bone = resSkeleton.GetBones(resAnimGroupMember.GetPath());
161 NW_ASSERT(bone.IsValid());
162 const int boneIdx = bone.GetIndex();
163 animGroup->SetTargetObjectIndex(memberIdx, boneIdx);
164 animGroup->SetTargetPtr(memberIdx, pose.GetTransform(boneIdx));
165 animGroup->SetOriginalValue(memberIdx, originalPose.GetTransform(boneIdx));
166
167 void* object = GetAnimTargetObject(resAnimGroupMember);
168 animGroup->SetTargetObject(memberIdx, object);
169 }
170 animBinding->SetAnimGroup(animGroupIdx, animGroup);
171 m_SkeletalAnimGroup = animGroup;
172 m_SkeletalAnimBindingIndex = animGroupIdx;
173 break; // 他にスケルタルモデル専用のアニメーショングループがないので
174 }
175 }
176
177 return result;
178 }
179
180 //----------------------------------------
181 void*
GetAnimTargetObject(const anim::ResAnimGroupMember & anim)182 SkeletalModel::GetAnimTargetObject(const anim::ResAnimGroupMember& anim)
183 {
184 switch(anim.GetObjectType())
185 {
186 case nw::anim::ResAnimGroupMember::OBJECT_TYPE_BONE:
187 {
188 nw::anim::ResBoneMember member = ResStaticCast<nw::anim::ResBoneMember>(anim);
189 const char* boneName = member.GetBoneName();
190
191 const int boneIndex =
192 GetResSkeletalModel().GetSkeleton().GetBones(boneName).GetIndex();
193
194 // 型が変更されたらコンパイルエラーが起きるよう、
195 // いったん目的の型に代入してからreturnで返す
196 CalculatedTransform* ptr =
197 GetSkeleton()->LocalTransformPose().GetTransform(boneIndex);
198 return ptr;
199 }
200
201 default:
202 NW_ASSERT(false);
203 return NULL;
204 }
205 }
206
207 //----------------------------------------
208 Result
Initialize(os::IAllocator * allocator)209 SkeletalModel::Initialize(os::IAllocator* allocator)
210 {
211 Result result = INITIALIZE_RESULT_OK;
212
213 result |= Model::Initialize(allocator);
214 NW_ENSURE_AND_RETURN(result);
215
216 result |= CreateSkeletalAnimGroup(allocator);
217 NW_ENSURE_AND_RETURN(result);
218
219 return result;
220 }
221
222 } // namespace gfx
223 } // namespace nw
224