Techne model loader (incomplete for debugging)
This commit is contained in:
parent
02a0824716
commit
27d922d470
3 changed files with 345 additions and 1 deletions
|
@ -6,6 +6,7 @@ import java.util.Collection;
|
|||
import java.util.Map;
|
||||
|
||||
import net.minecraftforge.client.model.obj.ObjModelLoader;
|
||||
import net.minecraftforge.client.model.techne.TechneModelLoader;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
|
@ -52,7 +53,7 @@ public class AdvancedModelLoader {
|
|||
FMLLog.severe("The resource name %s is not valid", resourceName);
|
||||
throw new IllegalArgumentException("The resource name is not valid");
|
||||
}
|
||||
String suffix = resourceName.substring(i);
|
||||
String suffix = resourceName.substring(i + 1);
|
||||
IModelCustomLoader loader = instances.get(suffix);
|
||||
if (loader == null)
|
||||
{
|
||||
|
@ -78,5 +79,6 @@ public class AdvancedModelLoader {
|
|||
static
|
||||
{
|
||||
registerModelHandler(new ObjModelLoader());
|
||||
registerModelHandler(new TechneModelLoader());
|
||||
}
|
||||
}
|
||||
|
|
308
client/net/minecraftforge/client/model/techne/TechneModel.java
Normal file
308
client/net/minecraftforge/client/model/techne/TechneModel.java
Normal file
|
@ -0,0 +1,308 @@
|
|||
package net.minecraftforge.client.model.techne;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipException;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NamedNodeMap;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import cpw.mods.fml.common.FMLLog;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.model.ModelBase;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.client.renderer.RenderEngine;
|
||||
import net.minecraftforge.client.model.IModelCustom;
|
||||
import net.minecraftforge.client.model.ModelFormatException;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class TechneModel extends ModelBase implements IModelCustom {
|
||||
public static final List<String> cubeTypes = Arrays.asList(
|
||||
"d9e621f7-957f-4b77-b1ae-20dcd0da7751",
|
||||
"de81aa14-bd60-4228-8d8d-5238bcd3caaa"
|
||||
);
|
||||
|
||||
private String fileName;
|
||||
private Map<String, byte[]> zipFile = new HashMap<String, byte[]>();
|
||||
|
||||
private Map<String, ModelRenderer> parts = new LinkedHashMap<String, ModelRenderer>();
|
||||
private String texture = null;
|
||||
private int textureName;
|
||||
private boolean textureNameSet = false;
|
||||
|
||||
public TechneModel(String fileName, URL resource) throws ModelFormatException
|
||||
{
|
||||
this.fileName = fileName;
|
||||
loadTechneModel(resource);
|
||||
}
|
||||
|
||||
private void loadTechneModel(URL fileURL) throws ModelFormatException
|
||||
{
|
||||
try
|
||||
{
|
||||
ZipInputStream zipInput = new ZipInputStream(fileURL.openStream());
|
||||
|
||||
ZipEntry entry;
|
||||
while ((entry = zipInput.getNextEntry()) != null)
|
||||
{
|
||||
byte[] data = new byte[(int) entry.getSize()];
|
||||
zipInput.read(data);
|
||||
zipFile.put(entry.getName(), data);
|
||||
}
|
||||
|
||||
byte[] modelXml = zipFile.get("model.xml");
|
||||
if (modelXml == null)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " contains no model.xml file");
|
||||
}
|
||||
|
||||
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||
Document document = documentBuilder.parse(new ByteArrayInputStream(modelXml));
|
||||
|
||||
NodeList nodeListTechne = document.getElementsByTagName("Techne");
|
||||
if (nodeListTechne.getLength() < 1)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " contains no Techne tag");
|
||||
}
|
||||
|
||||
NodeList nodeListModel = document.getElementsByTagName("Model");
|
||||
if (nodeListModel.getLength() < 1)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " contains no Model tag");
|
||||
}
|
||||
|
||||
NamedNodeMap modelAttributes = nodeListModel.item(0).getAttributes();
|
||||
if (modelAttributes == null)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " contains a Model tag with no attributes");
|
||||
}
|
||||
|
||||
Node modelTexture = modelAttributes.getNamedItem("texture");
|
||||
if (modelTexture != null)
|
||||
{
|
||||
texture = modelTexture.getTextContent();
|
||||
}
|
||||
|
||||
NodeList shapes = document.getElementsByTagName("Shape");
|
||||
for (int i = 0; i < shapes.getLength(); i++)
|
||||
{
|
||||
Node shape = shapes.item(i);
|
||||
NamedNodeMap shapeAttributes = shape.getAttributes();
|
||||
if (shapeAttributes == null)
|
||||
{
|
||||
throw new ModelFormatException("Shape #" + (i + 1) + " in " + fileName + " has no attributes");
|
||||
}
|
||||
|
||||
Node name = shapeAttributes.getNamedItem("name");
|
||||
String shapeName = null;
|
||||
if (name != null)
|
||||
{
|
||||
shapeName = name.getNodeValue();
|
||||
}
|
||||
if (shapeName == null)
|
||||
{
|
||||
shapeName = "Shape #" + (i + 1);
|
||||
}
|
||||
|
||||
Node type = shapeAttributes.getNamedItem("type");
|
||||
if (type == null)
|
||||
{
|
||||
throw new ModelFormatException("Shape [" + shapeName + "] in " + fileName + " has no type");
|
||||
}
|
||||
String shapeType = type.getNodeValue();
|
||||
if (shapeType == null)
|
||||
{
|
||||
throw new ModelFormatException("Shape [" + shapeName + "] in " + fileName + " has an invalid type");
|
||||
}
|
||||
if (!cubeTypes.contains(shapeType))
|
||||
{
|
||||
FMLLog.warning("Model shape [" + shapeName + "] in " + fileName + " is not a cube, ignoring");
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
boolean mirrored = false;
|
||||
String[] offset = new String[3];
|
||||
String[] position = new String[3];
|
||||
String[] rotation = new String[3];
|
||||
String[] size = new String[3];
|
||||
String[] textureOffset = new String[2];
|
||||
|
||||
NodeList shapeChildren = shape.getChildNodes();
|
||||
for (int j = 0; j < shapeChildren.getLength(); j++)
|
||||
{
|
||||
Node shapeChild = shapeChildren.item(j);
|
||||
|
||||
String shapeChildName = shapeChild.getNodeName();
|
||||
String shapeChildValue = shapeChild.getTextContent();
|
||||
if (shapeChildValue != null)
|
||||
{
|
||||
shapeChildValue = shapeChildValue.trim();
|
||||
|
||||
if (shapeChildName.equals("IsMirrored"))
|
||||
{
|
||||
mirrored = !shapeChildValue.equals("False");
|
||||
}
|
||||
else if (shapeChildName.equals("Offset"))
|
||||
{
|
||||
offset = shapeChildValue.split(",");
|
||||
}
|
||||
else if (shapeChildName.equals("Position"))
|
||||
{
|
||||
position = shapeChildValue.split(",");
|
||||
}
|
||||
else if (shapeChildName.equals("Rotation"))
|
||||
{
|
||||
rotation = shapeChildValue.split(",");
|
||||
}
|
||||
else if (shapeChildName.equals("Size"))
|
||||
{
|
||||
size = shapeChildValue.split(",");
|
||||
}
|
||||
else if (shapeChildName.equals("TextureOffset"))
|
||||
{
|
||||
textureOffset = shapeChildValue.split(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// That's what the ModelBase subclassing is needed for
|
||||
ModelRenderer cube = new ModelRenderer(this, Integer.parseInt(textureOffset[0]), Integer.parseInt(textureOffset[1]));
|
||||
cube.mirror = mirrored;
|
||||
cube.addBox(Float.parseFloat(offset[0]), Float.parseFloat(offset[1]), Float.parseFloat(offset[2]), Integer.parseInt(size[0]), Integer.parseInt(size[1]), Integer.parseInt(size[2]));
|
||||
cube.setRotationPoint(Float.parseFloat(position[0]), Float.parseFloat(position[1]) - 23.4F, Float.parseFloat(position[2]));
|
||||
|
||||
cube.rotateAngleX = (float)Math.toRadians(Float.parseFloat(rotation[0]));
|
||||
cube.rotateAngleY = (float)Math.toRadians(Float.parseFloat(rotation[1]));
|
||||
cube.rotateAngleZ = (float)Math.toRadians(Float.parseFloat(rotation[2]));
|
||||
|
||||
parts.put(shapeName, cube);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
FMLLog.warning("Model shape [" + shapeName + "] in " + fileName + " contains malformed integers within its data, ignoring");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ZipException e)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " is not a valid zip file");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " could not be read", e);
|
||||
}
|
||||
catch (ParserConfigurationException e)
|
||||
{
|
||||
// hush
|
||||
}
|
||||
catch (SAXException e)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " contains invalid XML", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void bindTexture()
|
||||
{
|
||||
if (texture != null)
|
||||
{
|
||||
if (!textureNameSet)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
byte[] textureEntry = zipFile.get(texture);
|
||||
if (textureEntry == null)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " has no such texture " + texture);
|
||||
}
|
||||
System.out.println(textureEntry.length);
|
||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(textureEntry));
|
||||
textureName = Minecraft.getMinecraft().renderEngine.allocateAndSetupTexture(image);
|
||||
textureNameSet = true;
|
||||
}
|
||||
catch (ZipException e)
|
||||
{
|
||||
throw new ModelFormatException("Model " + fileName + " is not a valid zip file");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileOutputStream fileOutput = new FileOutputStream("techne_texture_debug.png");
|
||||
fileOutput.write(zipFile.get(texture));
|
||||
fileOutput.flush();
|
||||
fileOutput.close();
|
||||
}
|
||||
catch (Throwable e1)
|
||||
{
|
||||
}
|
||||
|
||||
throw new ModelFormatException("Texture for model " + fileName + " could not be read", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (textureNameSet)
|
||||
{
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureName);
|
||||
Minecraft.getMinecraft().renderEngine.resetBoundTexture();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType()
|
||||
{
|
||||
return "tcn";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderAll()
|
||||
{
|
||||
bindTexture();
|
||||
|
||||
for (ModelRenderer part : parts.values())
|
||||
{
|
||||
part.renderWithRotation(1.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderPart(String partName)
|
||||
{
|
||||
bindTexture();
|
||||
|
||||
ModelRenderer part = parts.get(partName);
|
||||
if (part != null)
|
||||
{
|
||||
part.renderWithRotation(1.0F);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package net.minecraftforge.client.model.techne;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
|
||||
import net.minecraftforge.client.model.IModelCustom;
|
||||
import net.minecraftforge.client.model.IModelCustomLoader;
|
||||
import net.minecraftforge.client.model.ModelFormatException;
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class TechneModelLoader implements IModelCustomLoader {
|
||||
|
||||
@Override
|
||||
public String getType()
|
||||
{
|
||||
return "Techne model";
|
||||
}
|
||||
|
||||
private static final String[] types = { "tcn" };
|
||||
@Override
|
||||
public String[] getSuffixes()
|
||||
{
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IModelCustom loadInstance(String resourceName, URL resource) throws ModelFormatException
|
||||
{
|
||||
return new TechneModel(resourceName, resource);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue