マイペースなプログラミング日記

DTMやプログラミングにお熱なd-kamiがマイペースに書くブログ

mqoを読み込んでみる その3 パース編

今回はMQOファイルをパースする。まずはObject要素のvertex要素から。単純にtrimでタブとって、空白を区切り文字としてsplitして文字列をfloatにするだけ。}が来たら終了

package net.d_kami.mqo.parser;

import net.d_kami.mqo.MQOObject;
import net.d_kami.mqo.MQOLines;
import net.d_kami.mqo.MQOVertex;

public class VertexParser{
    public static void parse(MQOObject object, MQOLines lines){
        while(true){
            String line = lines.next();
            
            if(line == null){
                throw new ParseException("Vertex要素解析中にファイルが終了しました");
            }
            
            line = line.trim();
            
            if(line.equals("}")){
                break;
            }

            String[] elements = line.split(" ");
        
            if(elements.length != 3){
                throw new ParseException("Vertexの要素数が異常です: " + lines.current() + "行目");
            }
        
            float x = Float.parseFloat(elements[0]);
            float y = Float.parseFloat(elements[1]);
            float z = Float.parseFloat(elements[2]);
        
            object.addVertex(x, y, z);
        }
    }
}

次にface要素の取出し。手抜きで()の中の数字を取り出してるだけ。UVは無視。マテリアルも無視、最初のインデックス数も無視。酷い

package net.d_kami.mqo.parser;

import net.d_kami.mqo.MQOObject;
import net.d_kami.mqo.MQOLines;
import net.d_kami.mqo.MQOFace;

public class FaceParser{
    public static void parse(MQOObject object, MQOLines lines){
        while(true){
            String line = lines.next();
            
            if(line == null){
                throw new ParseException("Vertex要素解析中にファイルが終了しました");
            }
            
            line = line.trim();
            
            if(line.equals("}")){
                break;
            }
            
            int start = line.indexOf("(");
            int end = line.indexOf(")");
            
            String element = line.substring(start + 1, end);
            String[] elements = element.split(" ");
            
            object.addFace(elements);
        }
    }
}

次にObject要素のパース。vertexが来たらVertexParser、faceが来たらFaceParserに任せる。

package net.d_kami.mqo.parser;

import net.d_kami.mqo.MQOContainer;
import net.d_kami.mqo.MQOObject;
import net.d_kami.mqo.MQOLines;

public class ObjectParser{
    public static void parse(MQOContainer container, MQOLines lines){
        MQOObject object = new MQOObject();
        container.addObject(object);
        
        while(true){
            String line = lines.next();
            
            if(line == null){
                throw new ParseException("Object要素解析中にファイルが終了しました");
            }
            
            line = line.trim();
            
            if(line.equals("}")){
                break;
            }
            
            if(line.startsWith("vertex ")){
                VertexParser.parse(object, lines);
            }else if(line.startsWith("face ")){
                FaceParser.parse(object, lines);
            }
        }
    }
}

最後にMQO全体のパース。とは言ってもObject要素が来たらObjectParserに任せるのみ。他の要素は無視。手抜き!

package net.d_kami.mqo.parser;

import net.d_kami.mqo.MQOContainer;
import net.d_kami.mqo.MQOLines;

public class MQOParser{
    public static MQOContainer parse(MQOLines lines){
        String line;
        MQOContainer container = new MQOContainer();
        
        while((line = lines.next()) != null){
            line = line.trim();
            
            if(line.startsWith("Object")){
                ObjectParser.parse(container, lines);
            }
        }
        
        return container;
    }
}

ついでにサンプル

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;

import java.util.List;
import java.util.ArrayList;

import net.d_kami.mqo.MQOLines;
import net.d_kami.mqo.MQOFace;
import net.d_kami.mqo.MQOVertex;
import net.d_kami.mqo.MQOObject;
import net.d_kami.mqo.MQOContainer;
import net.d_kami.mqo.parser.MQOParser;

public class MQO{
    public static void main(String[] args) throws IOException{
        BufferedReader br = new BufferedReader(new FileReader(args[0]));
        String line;
        List<String> list = new ArrayList<String>();

        while((line = br.readLine()) != null){
            list.add(line);
        }
        
        br.close();
        
        MQOLines lines = new MQOLines(list.toArray(new String[0]));
        MQOContainer container = MQOParser.parse(lines);

        for(MQOObject object : container){
            System.out.println("Vertices");
            
            for(MQOVertex vertex : object.getVertices()){
                System.out.printf("%f %f %f\n", vertex.x, vertex.y, vertex.z);
            }
            
            System.out.println("Faces");
            for(MQOFace face : object.getFaces()){
                for(int i = 0; i < face.getSize(); i++){
                    System.out.printf("%d ", face.getIndex(i));
                }
                
                System.out.println();
            }
        }
    }
}

次はAndroidOpenGL ES使ってモデルの表示までやりたい。