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

# TextCollisionLoader.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 "LampBasic.h"
    00026 #include "Collision/InputOutput/TextCollisionLoader.h"
    00027 #include "Core/InputOutput/TextFileReader.h"
    00028 #include "Core/InputOutput/StreamTokenizer.h"
    00029 #include "Core/InputOutput/FilePath.h"
    00030 #include "Collision/System/CollisionScene.h"
    00031 #include "Collision/System/CollisionNode.h"
    00032 #include "Collision/Leaf/StaticSphereCollision.h"
    00033 #include "Collision/Leaf/StaticDeformedMeshCollision.h"
    00034
    00035 namespace Lamp{
    00036
    00037 //------------------------------------------------------------------------------
    00038 // コンストラクタ
    00039 TextCollisionLoader::TextCollisionLoader(){
    00040 }
    00041 //------------------------------------------------------------------------------
    00042 // デストラクタ
    00043 TextCollisionLoader::~TextCollisionLoader(){
    00044 }
    00045 //------------------------------------------------------------------------------
    00046 // ロード
    00047 void TextCollisionLoader::load(const String& filePath, CollisionScene* scene){
    00048     load(filePath, scene, scene->getRootNode());
    00049 }
    00050 //------------------------------------------------------------------------------
    00051 // ロード
    00052 void TextCollisionLoader::load(const String& filePath, CollisionScene* scene,
    00053     CollisionNode* node){
    00054     FilePath path(filePath);
    00055     if(!path.existFile()){
    00056         ErrorOut("TextCollisionLoader::load() ファイルが見つかりませんでした %s",
    00057             filePath.getBytes());
    00058         return;
    00059     }
    00060     TextFileReader* textFileReader = new TextFileReader(filePath);
    00061     load(textFileReader, scene, node);
    00062     delete textFileReader;
    00063 }
    00064 //------------------------------------------------------------------------------
    00065 // ロード
    00066 void TextCollisionLoader::load(TextReader* textReader, CollisionScene* scene){
    00067     load(textReader, scene, scene->getRootNode());
    00068 }
    00069 //------------------------------------------------------------------------------
    00070 // ロード
    00071 void TextCollisionLoader::load(TextReader* textReader, CollisionScene* scene,
    00072     CollisionNode* node){
    00073     // 初期化
    00074     tokenizer_ = new StreamTokenizer(textReader);
    00075     scene_ = scene;
    00076     rootNode_ = node;
    00077
    00078     // ルートノードを無効にしておく
    00079     bool rootNodeEnabled = rootNode_->isEnabled();
    00080     rootNode_->setEnabled(false);
    00081
    00082     // ヘッダの読み込み
    00083     readHeader();
    00084
    00085     while(true){
    00086         // トークン読み終わり
    00087         if(!tokenizer_->nextToken()){ break; }
    00088         String chunkName = tokenizer_->getToken();
    00089         if(chunkName == "CollisionNode"){
    00090             readCollisionNodeList();
    00091         }else if(chunkName == "CollisionLeaf"){
    00092             readCollisionLeafList();
    00093         }else if(chunkName == "CollisionNodeLink"){
    00094             readCollisionLinkList();
    00095         }else{
    00096             ErrorOut("TextCollisionLoader::load() "
    00097                 "invalid chunk %s (line %d)",
    00098                 chunkName.getBytes(), tokenizer_->getLineNumber());
    00099         }
    00100     }
    00101     delete tokenizer_;
    00102
    00103     rootNode_->setEnabled(rootNodeEnabled);
    00104 }
    00105 ///------------------------------------------------------------------------------
    00106 // ヘッダの読み込み
    00107 void TextCollisionLoader::readHeader(){
    00108     skipWord("Header");
    00109     openChunk();
    00110     skipWord("type");
    00111     skipWord("LampTextCollisionFormat");
    00112     skipWord("version");
    00113     skipWord("0_1_0");
    00114     closeChunk();
    00115 }
    00116 //------------------------------------------------------------------------------
    00117 // コリジョンノード
    00118 //------------------------------------------------------------------------------
    00119 // コリジョンノードリストの読み込み
    00120 void TextCollisionLoader::readCollisionNodeList(){
    00121     openChunk();
    00122     while(true){
    00123         String token = readToken("readCollisionNodeList()");
    00124         if(token == "}"){ break; }
    00125         readCollisionNode(token);
    00126     }
    00127 }
    00128 //------------------------------------------------------------------------------
    00129 // コリジョンノードの読み込み
    00130 void TextCollisionLoader::readCollisionNode(const String& name){
    00131     CollisionNode* node = scene_->createCollisionNode(name);
    00132     openChunk();
    00133     // スケール
    00134     skipWord("scale");
    00135     node->setScale(readVector3());
    00136     // 回転
    00137     skipWord("rotation");
    00138     node->setRotationXYZ(readVector3());
    00139     // 移動
    00140     skipWord("translation");
    00141     node->setTranslation(readVector3());
    00142     // 有効、無効フラグ
    00143     skipWord("enabled");
    00144     node->setEnabled(readBool());
    00145     closeChunk();
    00146 }
    00147 //------------------------------------------------------------------------------
    00148 // コリジョンリーフ
    00149 //------------------------------------------------------------------------------
    00150 // コリジョンリーフリストの読み込み
    00151 void TextCollisionLoader::readCollisionLeafList(){
    00152     openChunk();
    00153     while(true){
    00154         String token = readToken("readCollisionLeafList()");
    00155         if(token == "}"){ break; }
    00156         openChunk();
    00157         skipWord("type");
    00158         String type = readToken("readCollisionLeafList()");
    00159         if(type == "StaticSphere"){
    00160             readStaticSphere(token);
    00161         }else if(type == "StaticDeformedMesh"){
    00162             readStaticDeformedMesh(token);
    00163         }else{
    00164             ErrorOut("TextCollisionLoader::readCollisionLeafList() "
    00165                 "不正なタイプです %s (line %d)",
    00166                 type.getBytes(), tokenizer_->getLineNumber());
    00167         }
    00168         closeChunk();
    00169     }
    00170 }
    00171 //------------------------------------------------------------------------------
    00172 // 静的球コリジョンの読み込み
    00173 void TextCollisionLoader::readStaticSphere(const String& name){
    00174     StaticSphereCollision* sphere = scene_->createStaticSphereCollision(name);
    00175     // コリジョンマスク
    00176     skipWord("collisionMask");
    00177     sphere->setCollisionMask(readUInt());
    00178     // 有効、無効フラグ
    00179     skipWord("enabled");
    00180     sphere->setEnabled(readBool());
    00181     // 球
    00182     skipWord("sphere");
    00183     sphere->setSphere(readSphere());
    00184 }
    00185 //------------------------------------------------------------------------------
    00186 // 静的変形メッシュコリジョンの読み込み
    00187 void TextCollisionLoader::readStaticDeformedMesh(const String& name){
    00188     StaticDeformedMeshCollision* mesh =
    00189         scene_->createStaticDeformedMeshCollision(name);
    00190     // コリジョンマスク
    00191     skipWord("collisionMask");
    00192     mesh->setCollisionMask(readUInt());
    00193     // 有効、無効フラグ
    00194     skipWord("enabled");
    00195     mesh->setEnabled(readBool());
    00196     // バウンディングボックス
    00197     skipWord("boundingBox");
    00198     mesh->setBoundingBox(readAxisAlignedBox());
    00199     // バウンディングスフィア
    00200     skipWord("boundingSphere");
    00201     mesh->setBoundingSphere(readSphere());
    00202     // トライアングル数
    00203     skipWord("triangleCount");
    00204     int triangleCount = readInt();
    00205     mesh->setTriangleCount(triangleCount);
    00206     openChunk();
    00207     for(int i = 0; i < triangleCount; i++){
    00208         mesh->setTriangle(i, readTriangle());
    00209     }
    00210     closeChunk();
    00211 }
    00212 //------------------------------------------------------------------------------
    00213 // コリジョンリンク
    00214 //------------------------------------------------------------------------------
    00215 // コリジョンリンクリストの読み込み
    00216 void TextCollisionLoader::readCollisionLinkList(){
    00217     openChunk();
    00218     while(true){
    00219         String token = readToken("readCollisionLinkList()");
    00220         if(token == "}"){ break; }
    00221         readCollisionLink(token);
    00222     }
    00223 }
    00224 //------------------------------------------------------------------------------
    00225 // コリジョンリンクの読み込み
    00226 void TextCollisionLoader::readCollisionLink(const String& name){
    00227     CollisionNode* node;
    00228     if(name.equals("RootNode")){
    00229         node = rootNode_;
    00230     }else{
    00231         node = scene_->searchNode(name);
    00232         if(node == NULL){
    00233             ErrorOut("TextCollisionLoader::readCollisionLink() "
    00234                 "親ノードが見つかりません %s (line %d)",
    00235                 name.getBytes(), tokenizer_->getLineNumber());
    00236         }
    00237     }
    00238
    00239     openChunk();
    00240     while(true){
    00241         String token = readToken("readCollisionLink()");
    00242         if(token == "}"){ break; }
    00243         if(token == "node"){
    00244             String childName = readToken("readCollisionLink()");
    00245             CollisionNode* child = scene_->searchNode(childName);
    00246             if(child == NULL){
    00247                 ErrorOut("TextCollisionLoader::readCollisionLink() "
    00248                     "子ノードが見つかりません %s (line %d)",
    00249                     childName.getBytes(), tokenizer_->getLineNumber());
    00250             }
    00251             node->addChild(child);
    00252         }else if(token == "leaf"){
    00253             String childName = readToken("readCollisionLink()");
    00254             CollisionLeaf* child = scene_->searchLeaf(childName);
    00255             if(child == NULL){
    00256                 ErrorOut("TextCollisionLoader::readCollisionLink() "
    00257                     "子リーフが見つかりません %s (line %d)",
    00258                     childName.getBytes(), tokenizer_->getLineNumber());
    00259             }
    00260             node->addChild(child);
    00261         }else{
    00262             ErrorOut("TextCollisionLoader::readCollisionLink() "
    00263                 "不正なトークンです %s (line %d)",
    00264                 token.getBytes(), tokenizer_->getLineNumber());
    00265         }
    00266     }
    00267 }
    00268 //------------------------------------------------------------------------------
    00269 // 値の読み込み
    00270 //------------------------------------------------------------------------------
    00271 // bool値の読み込み
    00272 bool TextCollisionLoader::readBool(){
    00273     String token = readToken("readBool()");
    00274     if(token == "true"){ return true; }
    00275     else if(token == "false"){ return false; }
    00276     ErrorOut("TextCollisionLoader::readBool() 不正なトークンです %s (line %d)",
    00277         token.getBytes(), tokenizer_->getLineNumber());
    00278     return false;
    00279 }
    00280 //------------------------------------------------------------------------------
    00281 // int値の読み込み
    00282 int TextCollisionLoader::readInt(){
    00283     String token = readToken("readInt()");
    00284     int value = 0;
    00285     bool result = token.parseInt(&value);
    00286     if(!result){
    00287         ErrorOut("TextCollisionLoader::readInt() "
    00288             "不正なトークンです %s (line %d)",
    00289             token.getBytes(), tokenizer_->getLineNumber());
    00290     }
    00291     return value;
    00292 }
    00293 //------------------------------------------------------------------------------
    00294 // u_int値の読み込み
    00295 u_int TextCollisionLoader::readUInt(){
    00296     String token = readToken("readInt()");
    00297     u_int value = 0;
    00298     bool result = token.parseUInt(&value);
    00299     if(!result){
    00300         ErrorOut("TextCollisionLoader::readUInt() "
    00301             "不正なトークンです %s (line %d)",
    00302             token.getBytes(), tokenizer_->getLineNumber());
    00303     }
    00304     return value;
    00305 }
    00306 //------------------------------------------------------------------------------
    00307 // float値の読み込み
    00308 float TextCollisionLoader::readFloat(){
    00309     String token = readToken("readFloat()");
    00310     float value = 0.f;
    00311     bool result = token.parseFloat(&value);
    00312     if(!result){
    00313         ErrorOut("TextCollisionLoader::readFloat() "
    00314             "不正なトークンです %s (line %d)",
    00315             token.getBytes(), tokenizer_->getLineNumber());
    00316     }
    00317     return value;
    00318 }
    00319 //------------------------------------------------------------------------------
    00320 // Vector3値の読み込み
    00321 Vector3 TextCollisionLoader::readVector3(){
    00322     Vector3 result;
    00323     openChunk();
    00324     result.x = readFloat();
    00325     result.y = readFloat();
    00326     result.z = readFloat();
    00327     closeChunk();
    00328     return result;
    00329 }
    00330 //------------------------------------------------------------------------------
    00331 // 軸沿いボックスの読み込み
    00332 AxisAlignedBox TextCollisionLoader::readAxisAlignedBox(){
    00333     AxisAlignedBox result;
    00334     Vector3 minimum, maximum;
    00335     openChunk();
    00336     minimum.x = readFloat();
    00337     minimum.y = readFloat();
    00338     minimum.z = readFloat();
    00339     closeChunk();
    00340     openChunk();
    00341     maximum.x = readFloat();
    00342     maximum.y = readFloat();
    00343     maximum.z = readFloat();
    00344     closeChunk();
    00345     result.set(minimum, maximum);
    00346     return result;
    00347 }
    00348 //------------------------------------------------------------------------------
    00349 // 球の読み込み
    00350 Sphere TextCollisionLoader::readSphere(){
    00351     Sphere result;
    00352     Vector3 vector;
    00353     openChunk();
    00354     vector.x = readFloat();
    00355     vector.y = readFloat();
    00356     vector.z = readFloat();
    00357     result.setCenter(vector);
    00358     result.setRadius(readFloat());
    00359     closeChunk();
    00360     return result;
    00361 }
    00362 //------------------------------------------------------------------------------
    00363 // 三角の読み込み
    00364 Triangle TextCollisionLoader::readTriangle(){
    00365     Triangle result;
    00366     Vector3 vector;
    00367     for(int i = 0; i < 3; i++){
    00368         openChunk();
    00369         vector.x = readFloat();
    00370         vector.y = readFloat();
    00371         vector.z = readFloat();
    00372         result.setVertex(i, vector);
    00373         closeChunk();
    00374     }
    00375     return result;
    00376 }
    00377 //------------------------------------------------------------------------------
    00378 // ユーティリティ
    00379 //------------------------------------------------------------------------------
    00380 // トークンの読み込み
    00381 String TextCollisionLoader::readToken(const String& caller){
    00382     bool hasNext = tokenizer_->nextToken();
    00383     if(!hasNext){
    00384         ErrorOut("TextCollisionLoader::%s トークンがありません (line %d)",
    00385             caller.getBytes(), tokenizer_->getLineNumber());
    00386     }
    00387     return tokenizer_->getToken();
    00388 }
    00389 //------------------------------------------------------------------------------
    00390 // 指定ワードの読み飛ばし
    00391 void TextCollisionLoader::skipWord(const String& word){
    00392     String token = readToken("skipWord()");
    00393     if(token != word){
    00394         ErrorOut("TextCollisionLoader::skipWord(%s) "
    00395             "不正なトークンです %s (line %d)",
    00396             word.getBytes(), token.getBytes(), tokenizer_->getLineNumber());
    00397     }
    00398 }
    00399 //------------------------------------------------------------------------------
    00400 // チャンクの読み飛ばし
    00401 void TextCollisionLoader::skipChunk(){
    00402     int chunkLine = tokenizer_->getLineNumber();
    00403     int chunkCounter = 0;
    00404     while(true){
    00405         bool hasNext = tokenizer_->nextToken();
    00406         if(!hasNext){
    00407             ErrorOut("TextCollisionLoader::skipChunk(%d) "
    00408                 "トークンがありません (line %d)",
    00409                 chunkLine, tokenizer_->getLineNumber());
    00410         }
    00411         String token = tokenizer_->getToken();
    00412         if(token == "{"){
    00413             chunkCounter++;
    00414         }else if(token == "}"){
    00415             chunkCounter--;
    00416             // デクリメント時にループを抜けるチェックを行う
    00417             if(chunkCounter == 0){ break; }
    00418             if(chunkCounter < 0){
    00419                 ErrorOut("TextCollisionLoader::skipChunk(%d) "
    00420                     "不正なチャンクです (line %d)",
    00421                     chunkLine, tokenizer_->getLineNumber());
    00422             }
    00423         }
    00424     }
    00425 }
    00426 //------------------------------------------------------------------------------
    00427 } // End of namespace Lamp
    00428 //------------------------------------------------------------------------------