Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

# TranslationSceneNode.cpp

Go to the documentation of this file.

    00001 //------------------------------------------------------------------------------
    00002 // Lamp : Open source game middleware
    00003 // Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
    00004 //
    00005 // This library is free software; you can redistribute it and/or
    00006 // modify it under the terms of the GNU Lesser General Public
    00007 // License as published by the Free Software Foundation; either
    00008 // version 2.1 of the License, or (at your option) any later version.
    00009 //
    00010 // This library is distributed in the hope that it will be useful,
    00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00013 // Lesser General Public License for more details.
    00014 //
    00015 // You should have received a copy of the GNU Lesser General Public
    00016 // License along with this library; if not, write to the Free Software
    00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    00018 //------------------------------------------------------------------------------
    00019
    00020 /** @file
    00021  * 変換シーンノード実装
    00022  * @author Junpee
    00023  */
    00024
    00025 #include "System/stdafx.h"
    00026 #include "Translator/SceneNode/TranslationSceneNode.h"
    00027 #include "Translator/SceneNode/TranslationSceneNodeManager.h"
    00028 #include "Translator/Model/TranslationModelManager.h"
    00029 #include "Translator/Animation/TranslationAnimationUtility.h"
    00030 #include "Graphics/Scene/Scene.h"
    00031 #include "Graphics/SceneNode/SceneNodeManager.h"
    00032 #include "Graphics/Light/LightManager.h"
    00033 #include "Graphics/Model/ModelManager.h"
    00034 #include "Animation/VectorInterpolator/VectorArrayInterpolator.h"
    00035 #include "Animation/RotationInterpolator/EulerArrayInterpolator.h"
    00036 #include "Animation/System/AnimationManager.h"
    00037 #include "Animation/System/AnimationSet.h"
    00038 #include "Animation/SceneNode/SceneNodeAnimation.h"
    00039
    00040 namespace LampForMaya{
    00041
    00042 //------------------------------------------------------------------------------
    00043 // コンストラクタ
    00044 TranslationSceneNode::TranslationSceneNode(
    00045     const MDagPath& initializePath, const String& initializeName) :
    00046     dagPath_(initializePath), name_(initializeName),
    00047     lodThresholdCount_(0), lodThreshold_(NULL),
    00048     scaleAnimation_(NULL), rotationAnimation_(NULL),
    00049     translationAnimation_(NULL), hasAnimation_(false){
    00050     MStatus result;
    00051     // オブジェクトの取得
    00052     object_ = dagPath_.node(&result);
    00053     MayaStatusCheck(result);
    00054 }
    00055 //------------------------------------------------------------------------------
    00056 // デストラクタ
    00057 TranslationSceneNode::~TranslationSceneNode(){
    00058     SafeDelete(translationAnimation_);
    00059     SafeDelete(rotationAnimation_);
    00060     SafeDelete(scaleAnimation_);
    00061     SafeArrayDelete(lodThreshold_);
    00062 }
    00063 //------------------------------------------------------------------------------
    00064 // 分析
    00065 bool TranslationSceneNode::analyze(){
    00066     MStatus result;
    00067     String errorString;
    00068     MFnDagNode dagNode(dagPath_, &result);
    00069     MayaStatusCheck(result);
    00070     // lengthが1なら最上位DAGノード
    00071     u_int length = dagPath_.length(&result);
    00072     MayaStatusCheck(result);
    00073     isTopLevelNode_ = (length == 1);
    00074
    00075     // 子供の解析
    00076     MItDag childIterator(MItDag::kBreadthFirst, MFn::kInvalid, &result);
    00077     MayaStatusCheck(result);
    00078     result = childIterator.reset(
    00079         dagPath_, MItDag::kBreadthFirst, MFn::kInvalid);
    00080     MayaStatusCheck(result);
    00081     // 自分自身を読み飛ばす
    00082     childIterator.next();
    00083     MDagPath childPath;
    00084     for( ; !childIterator.isDone(); childIterator.next()){
    00085         result = childIterator.getPath(childPath);
    00086         MayaStatusCheck(result);
    00087         // 一階層下以下になったらループを抜ける
    00088         u_int childLength = childPath.length(&result);
    00089         MayaStatusCheck(result);
    00090         if(childLength > length + 1){ break; }
    00091         // 有効なDagノードかチェック
    00092         if(!TranslationSceneNodeManager::checkValidDagNode(childPath)){
    00093             continue;
    00094         }
    00095         // インスタンス化されていればキャンセル
    00096         u_int instanceNumber = childPath.instanceNumber(&result);
    00097         MayaStatusCheck(result);
    00098         if(instanceNumber > 0){ continue; }
    00099         // 名前の取得
    00100         MFnDagNode childNode(childPath, &result);
    00101         MayaStatusCheck(result);
    00102         String childName(childNode.name(&result).asChar());
    00103         MayaStatusCheck(result);
    00104         // モデルかシーンノードか
    00105         bool childIsSceneNode = childPath.hasFn(MFn::kTransform);
    00106         // リストに追加
    00107         if(childIsSceneNode){
    00108             sceneNodes_.add(childName);
    00109         }else{
    00110             // ロケータは無視する
    00111             if(childPath.hasFn(MFn::kLocator)){ continue; }
    00112             if(childPath.hasFn(MFn::kLight)){
    00113                 // ライトの追加
    00114                 lights_.add(childName);
    00115             }else{
    00116                 // モデルの追加
    00117                 models_.add(childName);
    00118             }
    00119         }
    00120     }
    00121
    00122     // 表示フラグ
    00123     visibility_ = MayaAttributeUtility::getBool(object_, "visibility");
    00124
    00125     // トランスフォーム初期化
    00126     MFnTransform transform(dagPath_, &result);
    00127     MayaStatusCheck(result);
    00128
    00129     // スケールピボット移動値が0であるかチェック
    00130     MPoint scalePivotTrans =
    00131         transform.scalePivotTranslation(MSpace::kTransform, &result);
    00132     MayaStatusCheck(result);
    00133     if(!zeroCheck(scalePivotTrans)){
    00134         errorString.format("TranslationSceneNode::analyze() "
    00135             "scalePivotTranslationが0でない ( %8f, %8f, %8f ) %s",
    00136             scalePivotTrans.x, scalePivotTrans.y, scalePivotTrans.z,
    00137             name_.getBytes());
    00138         MayaErrorOut(errorString);
    00139         return false;
    00140     }
    00141
    00142     // 回転ピボット移動値が0であるかチェック
    00143     MPoint rotationPivotTrans =
    00144         transform.rotatePivotTranslation(MSpace::kTransform, &result);
    00145     MayaStatusCheck(result);
    00146     if(!zeroCheck(rotationPivotTrans)){
    00147         errorString.format("TranslationSceneNode::analyze() "
    00148             "rotationPivotTransが0でない ( %8f, %8f, %8f ) %s",
    00149             rotationPivotTrans.x, rotationPivotTrans.y,
    00150             rotationPivotTrans.z, name_.getBytes());
    00151         MayaErrorOut(errorString);
    00152         return false;
    00153     }
    00154
    00155     // シアーが0であるかチェック
    00156     double shearArray[3];
    00157     result = transform.getShear(shearArray);
    00158     MPoint shear(shearArray);
    00159     if(!zeroCheck(shear)){
    00160         errorString.format("TranslationSceneNode::analyze() "
    00161             "shearが0でない ( %8f, %8f, %8f ) %s",
    00162             shear.x, shear.y, shear.z, name_.getBytes());
    00163         MayaErrorOut(errorString);
    00164         return false;
    00165     }
    00166
    00167     // スケールピボットとローテーションピボットが同値であることをチェック
    00168     MPoint scalePivot = transform.scalePivot(MSpace::kTransform, &result);
    00169     MayaStatusCheck(result);
    00170     MPoint rotationPivot = transform.rotatePivot(MSpace::kTransform, &result);
    00171     MayaStatusCheck(result);
    00172     MPoint pivotDifference = scalePivot - rotationPivot;
    00173     if(!zeroCheck(pivotDifference)){
    00174         errorString.format("TranslationSceneNode::analyze() "
    00175             "scalePivotとrotationPivotが同じでない "
    00176             "scale ( %8f, %8f, %8f ) rotation ( %8f, %8f, %8f ) %s",
    00177             scalePivot.x, scalePivot.y, scalePivot.z,
    00178             rotationPivot.x, rotationPivot.y, rotationPivot.z,
    00179             name_.getBytes());
    00180         MayaErrorOut(errorString);
    00181         return false;
    00182     }
    00183     pivot_.set((float)rotationPivot.x,
    00184         (float)rotationPivot.y, (float)rotationPivot.z);
    00185
    00186     // スケール
    00187     double scale[3];
    00188     result = transform.getScale(scale);
    00189     MayaStatusCheck(result);
    00190     scale_.set((float)scale[0], (float)scale[1], (float)scale[2]);
    00191
    00192     // 回転
    00193     MEulerRotation rotation;
    00194     result = transform.getRotation(rotation);
    00195     MayaStatusCheck(result);
    00196     if(rotation.order != MEulerRotation::kXYZ){
    00197         errorString.format("TranslationSceneNode::analyze() "
    00198             "回転順序はXYZしかサポートしていません %s", name_.getBytes());
    00199         MayaErrorOut(errorString);
    00200         return false;
    00201     }
    00202     rotation_.set((float)rotation.x, (float)rotation.y, (float)rotation.z);
    00203
    00204     // 移動
    00205     MVector translation = transform.translation(MSpace::kTransform, &result);
    00206     MayaStatusCheck(result);
    00207     translation_.set(
    00208         (float)translation.x, (float)translation.y, (float)translation.z);
    00209
    00210     // LOD
    00211     if(object_.hasFn(MFn::kLodGroup)){
    00212         MObject thresholdAttribute = dagNode.attribute("threshold", &result);
    00213         MayaStatusCheck(result);
    00214         MPlug thresholdPlug(object_, thresholdAttribute);
    00215         u_int thresholdValueCount = thresholdPlug.numElements();
    00216         lodThresholdCount_ = thresholdValueCount + 2;// 最大値、最小値分
    00217         lodThreshold_ = new float[lodThresholdCount_];
    00218         lodThreshold_[0] = 0.f;
    00219         lodThreshold_[lodThresholdCount_ - 1] = Limit::floatMax;
    00220         for(u_int i = 0; i < thresholdValueCount; i++){
    00221             MPlug thresholdValuePlug = thresholdPlug[i];
    00222             double doubleValue;
    00223             MayaStatusCheck(thresholdValuePlug.getValue(doubleValue));
    00224             lodThreshold_[i + 1] = (float)doubleValue;
    00225         }
    00226         // 最小値、最大値
    00227         MObject minMaxAttribute = dagNode.attribute("minMaxDistance", &result);
    00228         MayaStatusCheck(result);
    00229         MPlug minMaxPlug(object_, minMaxAttribute);
    00230         bool minMax;
    00231         MayaStatusCheck(minMaxPlug.getValue(minMax));
    00232         if(minMax){
    00233             // 最小値
    00234             MObject minAttribute = dagNode.attribute("minDistance", &result);
    00235             MayaStatusCheck(result);
    00236             MPlug minPlug(object_, minAttribute);
    00237             double minValue;
    00238             MayaStatusCheck(minPlug.getValue(minValue));
    00239             lodThreshold_[0] = (float)minValue;
    00240             if(lodThreshold_[0] < 0.f){ lodThreshold_[0] = 0.f; }
    00241             // 最大値
    00242             MObject maxAttribute = dagNode.attribute("maxDistance", &result);
    00243             MayaStatusCheck(result);
    00244             MPlug maxPlug(object_, maxAttribute);
    00245             double maxValue;
    00246             MayaStatusCheck(maxPlug.getValue(maxValue));
    00247             lodThreshold_[lodThresholdCount_ - 1] = (float)maxValue;
    00248         }
    00249     }
    00250     return true;
    00251 }
    00252 //------------------------------------------------------------------------------
    00253 // ゼロチェック
    00254 bool TranslationSceneNode::zeroCheck(const MPoint& point){
    00255     if( (Math::abs((float)point.x) > Math::epsilon) ||
    00256         (Math::abs((float)point.y) > Math::epsilon) ||
    00257         (Math::abs((float)point.z) > Math::epsilon)){
    00258         return false;
    00259     }
    00260     return true;
    00261 }
    00262 //------------------------------------------------------------------------------
    00263 // ピボットのコンパイル
    00264 bool TranslationSceneNode::compilePivot(
    00265     TranslationSceneNodeManager* sceneNodeManager,
    00266     TranslationModelManager* modelManager){
    00267     // ピボットのコンパイル
    00268     translation_ += pivot_;
    00269     // 子ノードのコンパイル
    00270     for(int i = 0; i < sceneNodes_.getCount(); i++){
    00271         String sceneNodeName = sceneNodes_.get(i);
    00272         TranslationSceneNode* sceneNode =
    00273             sceneNodeManager->search(sceneNodeName);
    00274         if(sceneNode == NULL){
    00275             MayaErrorOut(String("TranslationSceneNode::compilePivot() ") +
    00276                 name_ + "の子シーンノードが見つかりません " + sceneNodeName);
    00277             return false;
    00278         }
    00279         sceneNode->translation_ -= pivot_;
    00280     }
    00281     // 子モデルのコンパイル
    00282     for(int i = 0; i < models_.getCount(); i++){
    00283         String modelName = models_.get(i);
    00284         TranslationModel* model = modelManager->search(modelName);
    00285         if(model == NULL){
    00286             MayaErrorOut(String("TranslationSceneNode::compilePivot() ") +
    00287                 name_ + "の子モデルが見つかりません " + modelName);
    00288             return false;
    00289         }
    00290         model->compilePivot(pivot_);
    00291     }
    00292 // 子ライトのコンパイル必要？
    00293     pivot_.set(0.f, 0.f, 0.f);
    00294     return true;
    00295 }
    00296 //------------------------------------------------------------------------------
    00297 // アニメーションの分析
    00298 bool TranslationSceneNode::analyzeAnimation(){
    00299     // シーケンスの分析、シーケンスが無ければアニメーション無し
    00300     if(!sequence_.analyze(object_)){ return true; }
    00301     hasAnimation_ = false;
    00302     int startTime = sequence_.getStartTime(0);
    00303     int endTime = sequence_.getEndTime(sequence_.getSequenceCount() - 1);
    00304     // スケールアニメーション
    00305     scaleAnimation_ =
    00306         TranslationAnimationUtility::analyzeVectorAnimation(
    00307         object_, "scale", scale_, startTime, endTime);
    00308     if(scaleAnimation_ != NULL){ hasAnimation_ = true; }
    00309     // 回転アニメーション
    00310     rotationAnimation_ =
    00311         TranslationAnimationUtility::analyzeRotationAnimation(
    00312         object_, "rotate", rotation_, startTime, endTime);
    00313     if(rotationAnimation_ != NULL){ hasAnimation_ = true; }
    00314     // 移動アニメーション
    00315     translationAnimation_ =
    00316         TranslationAnimationUtility::analyzeVectorAnimation(
    00317         object_, "translate", (translation_ - pivot_), startTime, endTime);
    00318     if(translationAnimation_ != NULL){ hasAnimation_ = true; }
    00319     // ピボット足しこみ
    00320     if(translationAnimation_ != NULL){
    00321         int size = translationAnimation_->getSize();
    00322         for(int i = 0; i < size; i++){
    00323             Vector3 value = translationAnimation_->getValue(i);
    00324             value += pivot_;
    00325             translationAnimation_->setValue(i, value);
    00326         }
    00327     }
    00328     return true;
    00329 }
    00330 //------------------------------------------------------------------------------
    00331 // Lampへの変換
    00332 bool TranslationSceneNode::convertToLamp(Scene* scene){
    00333     SceneNodeManager* sceneNodeManager = scene->getSceneNodeManager();
    00334     if(lodThresholdCount_ != 0){
    00335         // LODシーンノード設定
    00336         LODSceneNode* lodSceneNode =
    00337             sceneNodeManager->createLODSceneNode(name_);
    00338         lodSceneNode->setLODThresholdCount(lodThresholdCount_);
    00339         for(int i = 0; i < lodThresholdCount_; i++){
    00340             lodSceneNode->setLODThreshold(i, lodThreshold_[i]);
    00341         }
    00342         sceneNode_ = lodSceneNode;
    00343     }else{
    00344         sceneNode_ = sceneNodeManager->createSceneNode(name_);
    00345     }
    00346     sceneNode_->setScale(scale_);
    00347     sceneNode_->setRotationXYZ(rotation_);
    00348     sceneNode_->setTranslation(translation_);
    00349     sceneNode_->setEnabled(visibility_);
    00350     return true;
    00351 }
    00352 //------------------------------------------------------------------------------
    00353 // リンク接続
    00354 bool TranslationSceneNode::linkConnect(Scene* scene){
    00355     // ルートノードとのリンク
    00356     SceneNodeManager* sceneNodeManager = scene->getSceneNodeManager();
    00357     if(isTopLevelNode_){
    00358         scene->getRootNode()->addSceneNode(sceneNode_);
    00359     }
    00360     // シーンノードとのリンク
    00361     for(int i = 0; i < sceneNodes_.getCount(); i++){
    00362         SceneNode* sceneNode = sceneNodeManager->search(sceneNodes_.get(i));
    00363         if(sceneNode == NULL){
    00364             MayaErrorOut(String("TranslationSceneNode::linkConnect() ") +
    00365                 name_ + "の子シーンノードが見つかりません " +
    00366                 sceneNodes_.get(i));
    00367             return false;
    00368         }
    00369         sceneNode_->addSceneNode(sceneNode);
    00370     }
    00371     // ライトとのリンク
    00372     LightManager* lightManager = scene->getLightManager();
    00373     for(int i = 0; i < lights_.getCount(); i++){
    00374         Light* light = lightManager->search(lights_[i]);
    00375         if(light == NULL){
    00376             MayaErrorOut(String("TranslationSceneNode::linkConnect() ") +
    00377                 name_ + "の子ライトが見つかりません " + lights_[i]);
    00378             return false;
    00379         }
    00380         sceneNode_->addSceneLeaf(light);
    00381     }
    00382     // モデルとのリンク
    00383     ModelManager* modelManager = scene->getModelManager();
    00384     for(int i = 0; i < models_.getCount(); i++){
    00385         Model* model = modelManager->search(models_[i]);
    00386         if(model == NULL){
    00387             MayaErrorOut(String("TranslationSceneNode::linkConnect() ") +
    00388                 name_ + "の子モデルが見つかりません " + models_.get(i));
    00389             return false;
    00390         }
    00391         sceneNode_->addSceneLeaf(model);
    00392     }
    00393     return true;
    00394 }
    00395 //------------------------------------------------------------------------------
    00396 // アニメーションの変換
    00397 bool TranslationSceneNode::convertAnimation(
    00398     AnimationManager* animationManager, AnimationSet* animationSet){
    00399     if(!hasAnimation_){ return true; }
    00400     SceneNodeAnimation* animation = animationManager->createSceneNode(name_);
    00401     if(animation->getName() != name_){
    00402         MayaErrorOut(String("TranslationSceneNode::convertAnimation() ") +
    00403             name_ + "の名前が重複しています ");
    00404         return false;
    00405     }
    00406     SceneNodeAnimationData* data =
    00407         animationManager->createSceneNodeData(name_);
    00408     if(data->getName() != name_){
    00409         MayaErrorOut(String("TranslationSceneNode::convertAnimation() ") +
    00410             name_ + "の名前が重複しています ");
    00411         return false;
    00412     }
    00413     // アニメーションの設定
    00414     animation->setTargetName(name_);
    00415     animation->setSceneNodeAnimationData(data);
    00416     animationSet->addAnimation(animation);
    00417     // アニメーションデータの設定
    00418     int sequenceCount = sequence_.getSequenceCount();
    00419     data->setSequenceCount(sequenceCount);
    00420     for(int i = 0; i < sequenceCount; i++){
    00421         int startTime = sequence_.getStartTime(i);
    00422         int endTime = sequence_.getEndTime(i);
    00423         int size = endTime - startTime + 1;
    00424         // スケールアニメーションの準備
    00425         VectorArrayInterpolator* scale = NULL;
    00426         if(scaleAnimation_ != NULL){
    00427             scale = new VectorArrayInterpolator();
    00428             scale->setSize(size);
    00429             for(int j = 0; j < size; j++){
    00430                 scale->setValue(j, scaleAnimation_->getValue(startTime + j));
    00431             }
    00432         }
    00433         // 回転アニメーションの準備
    00434         EulerArrayInterpolator* rotation = NULL;
    00435         if(rotationAnimation_ != NULL){
    00436             rotation = new EulerArrayInterpolator();
    00437             rotation->setSize(size);
    00438             for(int j = 0; j < size; j++){
    00439                 rotation->setValue(j,
    00440                     rotationAnimation_->getValue(startTime + j));
    00441             }
    00442         }
    00443         // 移動アニメーションの準備
    00444         VectorArrayInterpolator* translation = NULL;
    00445         if(translationAnimation_ != NULL){
    00446             translation = new VectorArrayInterpolator();
    00447             translation->setSize(size);
    00448             for(int j = 0; j < size; j++){
    00449                 translation->setValue(j,
    00450                     translationAnimation_->getValue(startTime + j));
    00451             }
    00452         }
    00453         // データの設定
    00454         if(scale != NULL){ data->setScale(i, scale); }
    00455         if(rotation != NULL){ data->setRotation(i, rotation); }
    00456         if(translation != NULL){
    00457             data->setTranslation(i, translation);
    00458         }
    00459         data->setLooped(i, sequence_.isLooped(i));
    00460     }
    00461     return true;
    00462 }
    00463 //------------------------------------------------------------------------------
    00464 } // End of namespace LampForMaya
    00465 //------------------------------------------------------------------------------