All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.badlogic.gdx.graphics.g3d.loaders.obj.ObjLoader Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/

package com.badlogic.gdx.graphics.g3d.loaders.obj;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import com.badlogic.gdx.graphics.Mesh;
import com.badlogic.gdx.graphics.VertexAttribute;
import com.badlogic.gdx.graphics.VertexAttributes.Usage;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

/** Loads Wavefront OBJ files, ignores material files.
 * @author mzechner */
public class ObjLoader {
	/** Loads a Wavefront OBJ file from the given input stream.
	 * 
	 * @param in the InputStream */
	public static Mesh loadObj (InputStream in) {
		return loadObj(in, false);
	}

	/** Loads a Wavefront OBJ file from the given input stream.
	 * 
	 * @param in the InputStream
	 * @param flipV whether to flip the v texture coordinate or not */
	public static Mesh loadObj (InputStream in, boolean flipV) {
		String line = "";

		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			StringBuffer b = new StringBuffer();
			String l = reader.readLine();
			while (l != null) {
				b.append(l);
				b.append("\n");
				l = reader.readLine();
			}

			line = b.toString();
			reader.close();
		} catch (Exception ex) {
			return null;
		}
		return loadObjFromString(line, flipV);
	}
	
	/** Loads a Wavefront OBJ file from the given input stream.
	 * 
	 * @param in the InputStream
	 * @param flipV whether to flip the v texture coordinate or not */
	public static Mesh loadObj (InputStream in, boolean flipV, boolean useIndices) {
		String line = "";

		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(in));
			StringBuffer b = new StringBuffer();
			String l = reader.readLine();
			while (l != null) {
				b.append(l);
				b.append("\n");
				l = reader.readLine();
			}

			line = b.toString();
			reader.close();
		} catch (Exception ex) {
			return null;
		}
		return loadObjFromString(line, flipV, useIndices);
	}

	/** Loads a mesh from the given string in Wavefront OBJ format
	 * 
	 * @param obj The string
	 * @return The Mesh */
	public static Mesh loadObjFromString (String obj) {
		return loadObjFromString(obj, false);
	}

	/** Loads a mesh from the given string in Wavefront OBJ format
	 * 
	 * @param obj The string
	 * @param flipV whether to flip the v texture coordinate or not
	 * @return The Mesh */
	public static Mesh loadObjFromString (String obj, boolean flipV) {
		return loadObjFromString(obj, flipV, false);
	}

	/** Loads a mesh from the given string in Wavefront OBJ format
	 * 
	 * @param obj The string
	 * @param flipV whether to flip the v texture coordinate or not
	 * @param useIndices whether to create an array of indices or not
	 * @return The Mesh */
	public static Mesh loadObjFromString (String obj, boolean flipV, boolean useIndices) {
		String[] lines = obj.split("\n");
		float[] vertices = new float[lines.length * 3];
		float[] normals = new float[lines.length * 3];
		float[] uv = new float[lines.length * 3];

		int numVertices = 0;
		int numNormals = 0;
		int numUV = 0;
		int numFaces = 0;

		int[] facesVerts = new int[lines.length * 3];
		int[] facesNormals = new int[lines.length * 3];
		int[] facesUV = new int[lines.length * 3];
		int vertexIndex = 0;
		int normalIndex = 0;
		int uvIndex = 0;
		int faceIndex = 0;

		for (int i = 0; i < lines.length; i++) {
			String line = lines[i];
			if (line.startsWith("v ")) {
				String[] tokens = line.split("[ ]+");
				vertices[vertexIndex] = Float.parseFloat(tokens[1]);
				vertices[vertexIndex + 1] = Float.parseFloat(tokens[2]);
				vertices[vertexIndex + 2] = Float.parseFloat(tokens[3]);
				vertexIndex += 3;
				numVertices++;
				continue;
			}

			if (line.startsWith("vn ")) {
				String[] tokens = line.split("[ ]+");
				normals[normalIndex] = Float.parseFloat(tokens[1]);
				normals[normalIndex + 1] = Float.parseFloat(tokens[2]);
				normals[normalIndex + 2] = Float.parseFloat(tokens[3]);
				normalIndex += 3;
				numNormals++;
				continue;
			}

			if (line.startsWith("vt")) {
				String[] tokens = line.split("[ ]+");
				uv[uvIndex] = Float.parseFloat(tokens[1]);
				uv[uvIndex + 1] = flipV ? 1 - Float.parseFloat(tokens[2]) : Float.parseFloat(tokens[2]);
				uvIndex += 2;
				numUV++;
				continue;
			}

			if (line.startsWith("f ")) {
				String[] tokens = line.split("[ ]+");

				String[] parts = tokens[1].split("/");
				facesVerts[faceIndex] = getIndex(parts[0], numVertices);
				if (parts.length > 2) facesNormals[faceIndex] = getIndex(parts[2], numNormals);
				if (parts.length > 1) facesUV[faceIndex] = getIndex(parts[1], numUV);
				faceIndex++;

				parts = tokens[2].split("/");
				facesVerts[faceIndex] = getIndex(parts[0], numVertices);
				if (parts.length > 2) facesNormals[faceIndex] = getIndex(parts[2], numNormals);
				if (parts.length > 1) facesUV[faceIndex] = getIndex(parts[1], numUV);
				faceIndex++;

				parts = tokens[3].split("/");
				facesVerts[faceIndex] = getIndex(parts[0], numVertices);
				if (parts.length > 2) facesNormals[faceIndex] = getIndex(parts[2], numNormals);
				if (parts.length > 1) facesUV[faceIndex] = getIndex(parts[1], numUV);
				faceIndex++;
				numFaces++;
				continue;
			}
		}

		Mesh mesh = null;

		ArrayList attributes = new ArrayList();
		attributes.add(new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE));
		if (numNormals > 0) attributes.add(new VertexAttribute(Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE));
		if (numUV > 0) attributes.add(new VertexAttribute(Usage.TextureCoordinates, 2, ShaderProgram.TEXCOORD_ATTRIBUTE + "0"));

		if (useIndices) {
			int attrCount = 3 + (numNormals > 0 ? 3 : 0) + (numUV > 0 ? 2 : 0);
			int normOffset = 3;
			int uvOffset = 3 + (numNormals > 0 ? 3 : 0);

			float verts[] = new float[numVertices * attrCount];

			for (int i = 0; i < numVertices; i++) {
				verts[i * attrCount] = vertices[i * 3];
				verts[i * attrCount + 1] = vertices[i * 3 + 1];
				verts[i * attrCount + 2] = vertices[i * 3 + 2];
			}

			for (int i = 0; i < numFaces * 3; i++) {
				int vertexIdx = facesVerts[i];

				if (numNormals > 0) {
					int normalIdx = facesNormals[i] * 3;
					verts[vertexIdx * attrCount + normOffset] = normals[normalIdx];
					verts[vertexIdx * attrCount + normOffset + 1] = normals[normalIdx + 1];
					verts[vertexIdx * attrCount + normOffset + 2] = normals[normalIdx + 2];
				}
				if (numUV > 0) {
					int uvIdx = facesUV[i] * 2;
					verts[vertexIdx * attrCount + uvOffset] = uv[uvIdx];
					verts[vertexIdx * attrCount + uvOffset + 1] = uv[uvIdx + 1];
				}
			}

			short[] indices = new short[numFaces * 3];
			for (int i = 0; i < indices.length; i++)
				indices[i] = (short) facesVerts[i];

			mesh = new Mesh(true, verts.length, indices.length, attributes.toArray(new VertexAttribute[attributes.size()]));
			mesh.setVertices(verts);
			mesh.setIndices(indices);
		} else {
			float[] verts = new float[(numFaces * 3) * (3 + (numNormals > 0 ? 3 : 0) + (numUV > 0 ? 2 : 0))];

			for (int i = 0, vi = 0; i < numFaces * 3; i++) {
				int vertexIdx = facesVerts[i] * 3;
				verts[vi++] = vertices[vertexIdx];
				verts[vi++] = vertices[vertexIdx + 1];
				verts[vi++] = vertices[vertexIdx + 2];

				if (numNormals > 0) {
					int normalIdx = facesNormals[i] * 3;
					verts[vi++] = normals[normalIdx];
					verts[vi++] = normals[normalIdx + 1];
					verts[vi++] = normals[normalIdx + 2];
				}
				if (numUV > 0) {
					int uvIdx = facesUV[i] * 2;
					verts[vi++] = uv[uvIdx];
					verts[vi++] = uv[uvIdx + 1];
				}
			}

			mesh = new Mesh(true, numFaces * 3, 0, attributes.toArray(new VertexAttribute[attributes.size()]));
			mesh.setVertices(verts);
		}

		return mesh;
	}

	private static int getIndex (String index, int size) {
		if (index == null || index.length() == 0) return 0;
		int idx = Integer.parseInt(index);
		if (idx < 0)
			return size + idx;
		else
			return idx - 1;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy