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 //------------------------------------------------------------------------------

Generated on Wed Mar 16 10:29:56 2005 for LampForMaya by doxygen 1.3.2