Add in a generic factory interface, allowing for additional model support
to be added at runtime.
This commit is contained in:
parent
d4b71ef964
commit
1ae7fa0080
|
@ -0,0 +1,82 @@
|
||||||
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.minecraftforge.client.model.obj.ObjModelLoader;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.FMLLog;
|
||||||
|
import cpw.mods.fml.relauncher.Side;
|
||||||
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common interface for advanced model loading from files, based on file suffix
|
||||||
|
* Model support can be queried through the {@link #getSupportedSuffixes()} method.
|
||||||
|
* Instances can be created by calling {@link #loadModel(String)} with a class-loadable-path
|
||||||
|
*
|
||||||
|
* @author cpw
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
public class AdvancedModelLoader {
|
||||||
|
private static Map<String, IModelCustomLoader> instances = Maps.newHashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new model handler
|
||||||
|
* @param modelHandler The model handler to register
|
||||||
|
*/
|
||||||
|
public static void registerModelHandler(IModelCustomLoader modelHandler)
|
||||||
|
{
|
||||||
|
for (String suffix : modelHandler.getSuffixes())
|
||||||
|
{
|
||||||
|
instances.put(suffix, modelHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the model from the supplied classpath resolvable resource name
|
||||||
|
* @param resourceName The resource name
|
||||||
|
* @return A model
|
||||||
|
* @throws IllegalArgumentException if the resource name cannot be understood
|
||||||
|
* @throws ModelFormatException if the underlying model handler cannot parse the model format
|
||||||
|
*/
|
||||||
|
public static IModelCustom loadModel(String resourceName) throws IllegalArgumentException, ModelFormatException
|
||||||
|
{
|
||||||
|
int i = resourceName.lastIndexOf('.');
|
||||||
|
if (i == -1)
|
||||||
|
{
|
||||||
|
FMLLog.severe("The resource name %s is not valid", resourceName);
|
||||||
|
throw new IllegalArgumentException("The resource name is not valid");
|
||||||
|
}
|
||||||
|
String suffix = resourceName.substring(i);
|
||||||
|
IModelCustomLoader loader = instances.get(suffix);
|
||||||
|
if (loader == null)
|
||||||
|
{
|
||||||
|
FMLLog.severe("The resource name %s is not supported", resourceName);
|
||||||
|
throw new IllegalArgumentException("The resource name is not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
URL resource = AdvancedModelLoader.class.getResource(resourceName);
|
||||||
|
if (resource == null)
|
||||||
|
{
|
||||||
|
FMLLog.severe("The resource name %s could not be found", resourceName);
|
||||||
|
throw new IllegalArgumentException("The resource name could not be found");
|
||||||
|
}
|
||||||
|
return loader.loadInstance(resourceName, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Collection<String> getSupportedSuffixes()
|
||||||
|
{
|
||||||
|
return instances.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
registerModelHandler(new ObjModelLoader());
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,11 +3,7 @@ package net.minecraftforge.client.model;
|
||||||
|
|
||||||
|
|
||||||
public interface IModelCustom {
|
public interface IModelCustom {
|
||||||
|
String getType();
|
||||||
public abstract IModelCustom load(String fileName);
|
void renderAll();
|
||||||
|
void renderPart(String partName);
|
||||||
public abstract void renderAll();
|
|
||||||
|
|
||||||
public abstract void renderPart(String partName);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instances of this class act as factories for their model type
|
||||||
|
*
|
||||||
|
* @author cpw
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IModelCustomLoader {
|
||||||
|
/**
|
||||||
|
* Get the main type name for this loader
|
||||||
|
* @return the type name
|
||||||
|
*/
|
||||||
|
String getType();
|
||||||
|
/**
|
||||||
|
* Get resource suffixes this model loader recognizes
|
||||||
|
* @return a list of suffixes
|
||||||
|
*/
|
||||||
|
String[] getSuffixes();
|
||||||
|
/**
|
||||||
|
* Load a model instance from the supplied path
|
||||||
|
* @param resourceName The resource name to load
|
||||||
|
* @param resource The URL associated with the classloader resource
|
||||||
|
* @return A model instance
|
||||||
|
* @throws ModelFormatException if the model format is not correct
|
||||||
|
*/
|
||||||
|
IModelCustom loadInstance(String resourceName, URL resource) throws ModelFormatException;
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package net.minecraftforge.client.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown if there is a problem parsing the model
|
||||||
|
*
|
||||||
|
* @author cpw
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ModelFormatException extends RuntimeException {
|
||||||
|
|
||||||
|
public ModelFormatException()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelFormatException(String message, Throwable cause)
|
||||||
|
{
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelFormatException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelFormatException(Throwable cause)
|
||||||
|
{
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package net.minecraftforge.client.model.obj;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import net.minecraftforge.client.model.IModelCustom;
|
||||||
|
import net.minecraftforge.client.model.IModelCustomLoader;
|
||||||
|
import net.minecraftforge.client.model.ModelFormatException;
|
||||||
|
|
||||||
|
public class ObjModelLoader implements IModelCustomLoader {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType()
|
||||||
|
{
|
||||||
|
return "OBJ model";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String[] types = { "obj" };
|
||||||
|
@Override
|
||||||
|
public String[] getSuffixes()
|
||||||
|
{
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IModelCustom loadInstance(String resourceName, URL resource) throws ModelFormatException
|
||||||
|
{
|
||||||
|
return new WavefrontObject(resourceName, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,10 +8,10 @@ import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.DataFormatException;
|
|
||||||
|
|
||||||
import net.minecraft.client.renderer.Tessellator;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
import net.minecraftforge.client.model.IModelCustom;
|
import net.minecraftforge.client.model.IModelCustom;
|
||||||
|
import net.minecraftforge.client.model.ModelFormatException;
|
||||||
|
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
@ -46,38 +46,13 @@ public class WavefrontObject implements IModelCustom
|
||||||
private GroupObject currentGroupObject;
|
private GroupObject currentGroupObject;
|
||||||
private String fileName;
|
private String fileName;
|
||||||
|
|
||||||
public WavefrontObject(String fileName)
|
public WavefrontObject(String fileName, URL resource) throws ModelFormatException
|
||||||
{
|
{
|
||||||
this.fileName = fileName;
|
this.fileName = fileName;
|
||||||
|
loadObjModel(resource);
|
||||||
try
|
|
||||||
{
|
|
||||||
loadObjModel(this.getClass().getResource(fileName));
|
|
||||||
}
|
|
||||||
catch (DataFormatException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IModelCustom load(String fileName)
|
private void loadObjModel(URL fileURL) throws ModelFormatException
|
||||||
{
|
|
||||||
return new WavefrontObject(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void load()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
loadObjModel(this.getClass().getResource(fileName));
|
|
||||||
}
|
|
||||||
catch (DataFormatException e)
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadObjModel(URL fileURL) throws DataFormatException
|
|
||||||
{
|
{
|
||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
InputStream inputStream = null;
|
InputStream inputStream = null;
|
||||||
|
@ -158,7 +133,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
throw new ModelFormatException("IO Exception reading model format", e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -168,7 +143,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
// hush
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -177,7 +152,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
// hush
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,7 +217,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vertex parseVertex(String line, int lineCount) throws DataFormatException
|
private Vertex parseVertex(String line, int lineCount) throws ModelFormatException
|
||||||
{
|
{
|
||||||
Vertex vertex = null;
|
Vertex vertex = null;
|
||||||
|
|
||||||
|
@ -253,29 +228,29 @@ public class WavefrontObject implements IModelCustom
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (tokens.length == 3)
|
if (tokens.length == 2)
|
||||||
|
{
|
||||||
|
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]));
|
||||||
|
}
|
||||||
|
else if (tokens.length == 3)
|
||||||
{
|
{
|
||||||
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
|
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]));
|
||||||
}
|
}
|
||||||
else if (tokens.length == 4)
|
|
||||||
{
|
|
||||||
return new Vertex(Float.parseFloat(tokens[0]), Float.parseFloat(tokens[1]), Float.parseFloat(tokens[2]), Float.parseFloat(tokens[3]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
throw new ModelFormatException(String.format("Number formatting error at line %d",lineCount), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
||||||
}
|
}
|
||||||
|
|
||||||
return vertex;
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Vertex parseVertexNormal(String line, int lineCount) throws DataFormatException
|
private Vertex parseVertexNormal(String line, int lineCount) throws ModelFormatException
|
||||||
{
|
{
|
||||||
Vertex vertexNormal = null;
|
Vertex vertexNormal = null;
|
||||||
|
|
||||||
|
@ -291,18 +266,18 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
throw new ModelFormatException(String.format("Number formatting error at line %d",lineCount), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
||||||
}
|
}
|
||||||
|
|
||||||
return vertexNormal;
|
return vertexNormal;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TextureCoordinate parseTextureCoordinate(String line, int lineCount) throws DataFormatException
|
private TextureCoordinate parseTextureCoordinate(String line, int lineCount) throws ModelFormatException
|
||||||
{
|
{
|
||||||
TextureCoordinate textureCoordinate = null;
|
TextureCoordinate textureCoordinate = null;
|
||||||
|
|
||||||
|
@ -320,18 +295,18 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e)
|
catch (NumberFormatException e)
|
||||||
{
|
{
|
||||||
e.printStackTrace();
|
throw new ModelFormatException(String.format("Number formatting error at line %d",lineCount), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
||||||
}
|
}
|
||||||
|
|
||||||
return textureCoordinate;
|
return textureCoordinate;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Face parseFace(String line, int lineCount) throws DataFormatException
|
private Face parseFace(String line, int lineCount) throws ModelFormatException
|
||||||
{
|
{
|
||||||
Face face = null;
|
Face face = null;
|
||||||
|
|
||||||
|
@ -351,7 +326,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
else if (currentGroupObject.glDrawingMode != GL11.GL_TRIANGLES)
|
else if (currentGroupObject.glDrawingMode != GL11.GL_TRIANGLES)
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Invalid number of points for face (expected 4, found " + tokens.length + ")");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Invalid number of points for face (expected 4, found " + tokens.length + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tokens.length == 4)
|
else if (tokens.length == 4)
|
||||||
|
@ -362,7 +337,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
else if (currentGroupObject.glDrawingMode != GL11.GL_QUADS)
|
else if (currentGroupObject.glDrawingMode != GL11.GL_QUADS)
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Invalid number of points for face (expected 3, found " + tokens.length + ")");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Invalid number of points for face (expected 3, found " + tokens.length + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,18 +397,18 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
||||||
}
|
}
|
||||||
|
|
||||||
return face;
|
return face;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GroupObject parseGroupObject(String line, int lineCount) throws DataFormatException
|
private GroupObject parseGroupObject(String line, int lineCount) throws ModelFormatException
|
||||||
{
|
{
|
||||||
GroupObject group = null;
|
GroupObject group = null;
|
||||||
|
|
||||||
|
@ -448,7 +423,7 @@ public class WavefrontObject implements IModelCustom
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new DataFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
throw new ModelFormatException("Error parsing entry ('" + line + "'" + ", line " + lineCount + ") in file '" + fileName + "' - Incorrect format");
|
||||||
}
|
}
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
|
@ -591,4 +566,10 @@ public class WavefrontObject implements IModelCustom
|
||||||
groupObjectMatcher = groupObjectPattern.matcher(line);
|
groupObjectMatcher = groupObjectPattern.matcher(line);
|
||||||
return groupObjectMatcher.matches();
|
return groupObjectMatcher.matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType()
|
||||||
|
{
|
||||||
|
return "obj";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue