⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 objtojme.java

📁 java 3d game jme 工程开发源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 2003-2009 jMonkeyEngine
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jmex.model.converters;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.logging.Logger;

import com.jme.bounding.BoundingBox;
import com.jme.image.Image;
import com.jme.image.Texture;
import com.jme.image.Texture2D;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.TexCoords;
import com.jme.scene.TriMesh;
import com.jme.scene.state.BlendState;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.system.dummy.DummySystemProvider;
import com.jme.util.TextureKey;
import com.jme.util.TextureManager;
import com.jme.util.export.binary.BinaryExporter;
import com.jme.util.geom.BufferUtils;
import com.jme.util.geom.GeometryTool;

/**
 * Started Date: Jul 17, 2004<br>
 * <br>
 * Converts .obj files into .jme binary format. In order for ObjToJme to find
 * the .mtl library, you must specify the "mtllib" tag to the baseURL where the
 * mtl libraries are to be found: eg.
 * setProperty("mtllib",new File("c:/my material dir/").toURL());
 * 
 * Textures will be loaded from the directory indicated in the model unless you
 * specify a directory to load them from via setting a property: eg.
 * setProperty("texdir", new File("c:/my texdir/").toURL());
 * 
 * @author Jack Lindamood
 * @author Joshua Slack - revamped to improve speed
 */
public class ObjToJme extends FormatConverter {
    private static final Logger logger = Logger.getLogger(ObjToJme.class
            .getName());
    
    private BufferedReader inFile;
    /** Every vertex in the file */
    private ArrayList<Vector3f> vertexList = new ArrayList<Vector3f>();
    /** Every texture coordinate in the file */
    private ArrayList<Vector2f> textureList = new ArrayList<Vector2f>();
    /** Every normal in the file */
    private ArrayList<Vector3f> normalList = new ArrayList<Vector3f>();
    /** Generated normals */
    private ArrayList<Vector3f> genNormalList = new ArrayList<Vector3f>();
    /** Last 'material' flag in the file */
    private MaterialGrouping curGroup;
    /** Last 'Object' name in the file */
    private String curObjectName = null;
    /** Last 'Group' name in the file */
    private String curGroupName = null;
    /** Default material group for groups without a material */
    private MaterialGrouping defaultMaterialGroup;
    /** Maps material names to the actual material object * */
    private HashMap<String, MaterialGrouping> materialNames = new HashMap<String, MaterialGrouping>();
    /** Maps Materials to their vertex usage * */
    private HashMap<MaterialGrouping, ArraySet> materialSets = new HashMap<MaterialGrouping, ArraySet>();
    /** Reference to the renderer for creating RenderState objects **/
    private Renderer renderer;
    private boolean generateMissingNormals = true;
    
    /**
     * Converts an Obj file to jME format. The syntax is: "ObjToJme file.obj
     * outfile.jme".
     * 
     * @param args
     *            The array of parameters
     */
    public static void main(String[] args) {
    	DisplaySystem.getDisplaySystem(DummySystemProvider.DUMMY_SYSTEM_IDENTIFIER);
        new ObjToJme().attemptFileConvert(args);
    }
    
    /**
     * Converts an .obj file to .jme format. If you wish to use a .mtl to load
     * the obj's material information please specify the base url where the .mtl
     * is located with setProperty("mtllib",new URL(baseURL))
     * 
     * @param format
     *            The .obj file's stream.
     * @param jMEFormat
     *            The .jme file's stream.
     * @throws IOException
     *             If anything bad happens.
     */
    @Override
    public void convert(InputStream format, OutputStream jMEFormat)
            throws IOException {
        renderer = DisplaySystem.getDisplaySystem().getRenderer();
        defaultMaterialGroup = new MaterialGrouping();
        vertexList.clear();
        textureList.clear();
        normalList.clear();
        genNormalList.clear();
        materialSets.clear();
        materialNames.clear();
        inFile = new BufferedReader(new InputStreamReader(format));
        String in;
        curGroup = defaultMaterialGroup;
        materialSets.put(defaultMaterialGroup, new ArraySet());
        while ((in = inFile.readLine()) != null) {
            processLine(in);
        }
        BinaryExporter.getInstance().save(buildStructure(),jMEFormat);
        nullAll();
    }

    /**
     * Nulls all to let the gc do its job.
     * 
     * @throws IOException
     */
    private void nullAll() throws IOException {
        vertexList.clear();
        textureList.clear();
        normalList.clear();
        genNormalList.clear();
        curGroup = null;
        materialSets.clear();
        materialNames.clear();
        inFile.close();
        inFile = null;
        defaultMaterialGroup = null;
        renderer = null;
    }

    /**
     * Converts the structures of the .obj file to a scene to write
     * 
     * @return The TriMesh or Node that represents the .obj file.
     */
    private Spatial buildStructure() {
        Node toReturn = new Node("obj file");
        Object[] o = materialSets.keySet().toArray();
        for (int i = 0; i < o.length; i++) {
            MaterialGrouping thisGroup = (MaterialGrouping) o[i];
            ArraySet thisSet = materialSets.get(thisGroup);
            if (thisSet.indexes.size() < 3)
                continue;
            TriMesh thisMesh = new TriMesh(thisSet.objName == null ? "temp" + i : thisSet.objName);
            Vector3f[] vert = new Vector3f[thisSet.sets.size()];
            Vector3f[] norm = new Vector3f[vert.length];
            Vector2f[] text = new Vector2f[vert.length];
            boolean hasNorm = false, hasTex = false;

            int j = 0;
            for (IndexSet set : thisSet.sets) {
                vert[j] = vertexList.get(set.vIndex);
                if (set.nIndex >= 0) {
                    norm[j] = normalList.get(set.nIndex);
                    hasNorm = true;
                } else if (set.nIndex < -1) {
                    norm[j] = genNormalList.get((-1*set.nIndex)-2);
                    hasNorm = true;
                }
                if (set.tIndex >= 0) {
                    text[j] = textureList.get(set.tIndex);
                    hasTex = true;
                }
                j++;
            }
            
            int[] indexes = new int[thisSet.indexes.size()];
            for (j = 0; j < thisSet.indexes.size(); j++)
                indexes[j] = thisSet.indexes.get(j);
            
            thisMesh.reconstruct(BufferUtils.createFloatBuffer(vert),
                    hasNorm ? BufferUtils.createFloatBuffer(norm) : null, 
                    null,
                    hasTex ? TexCoords.makeNew(text) : null,
                    BufferUtils.createIntBuffer(indexes));
            if (properties.get("sillycolors") != null)
                thisMesh.setRandomColors();
            if (thisGroup.ts != null)
                thisMesh.setRenderState(thisGroup.ts);
            thisMesh.setRenderState(thisGroup.m);
            if (thisGroup.as != null) {
                thisMesh.setRenderState(thisGroup.as);
                thisMesh.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
            }
            thisMesh.setModelBound(new BoundingBox());
            thisMesh.updateModelBound();
            GeometryTool.minimizeVerts(thisMesh, GeometryTool.MV_SAME_COLORS | GeometryTool.MV_SAME_NORMALS | GeometryTool.MV_SAME_TEXS);
            toReturn.attachChild(thisMesh);
        }
        if (toReturn.getQuantity() == 1)
            return toReturn.getChild(0);
        
        return toReturn;
    }

    /**
     * Processes a line of text in the .obj file.
     * 
     * @param s
     *            The line of text in the file.
     * @throws IOException
     */
    private void processLine(String s) throws IOException {
        if (s == null)
            return;
        if (s.length() == 0)
            return;
        String[] parts = s.split("\\s+");
        parts = removeEmpty(parts);
        if (parts.length == 0) return;
        if (parts[0].charAt(0) == '#')
            return;
        if ("v".equals(parts[0])) {
            addVertextoList(parts);
            return;
        } else if ("vt".equals(parts[0])) {
            addTextoList(parts);
            return;
        } else if ("vn".equals(parts[0])) {
            addNormalToList(parts);
            return;
        } else if ("g".equals(parts[0])) {
            // see what the material name is if there isn't a name, assume its
            // the default group
            if (parts.length >= 2 && materialNames.get(parts[1]) != null) {
                curGroupName = parts[1];
                curGroup = materialNames.get(parts[1]);
            }
            else
                setDefaultGroup();
            return;
        } else if ("f".equals(parts[0])) {
            addFaces(parts);
            return;
        } else if ("mtllib".equals(parts[0])) {
            loadMaterials(parts);
            return;
        } else if ("newmtl".equals(parts[0])) {
            addMaterial(parts);
            return;
        } else if ("usemtl".equals(parts[0])) {
            if (materialNames.get(parts[1]) != null)
                curGroup = materialNames.get(parts[1]);
            else
                setDefaultGroup();
            return;
        } else if ("Ka".equals(parts[0])) {
            curGroup.m.setAmbient(new ColorRGBA(Float.parseFloat(parts[1]),
                    Float.parseFloat(parts[2]), Float.parseFloat(parts[3]), 1));
            return;
        } else if ("Kd".equals(parts[0])) {
            curGroup.m.setDiffuse(new ColorRGBA(Float.parseFloat(parts[1]),
                    Float.parseFloat(parts[2]), Float.parseFloat(parts[3]), 1));
            return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -