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

Generated on Wed Mar 16 10:29:37 2005 for Lamp by doxygen 1.3.2