2013-03-21 17:38:04 -07:00

1916 lines
75 KiB
Java

package mods.tinker.tconstruct.client.tmt;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.model.PositionTextureVertex;
import net.minecraft.client.model.TexturedQuad;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.RenderEngine;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.MathHelper;
import org.lwjgl.opengl.GL11;
/**
* An extension to the ModelRenderer class. It basically is a copy to ModelRenderer,
* however, it contains various new methods to make your models.
* <br /><br />
* Since the ModelRendererTurbo class gets loaded during startup, the models made
* can be very complex. This is why I can afford to add, for example, Wavefont OBJ
* support or have the addSprite method, methods that add a lot of vertices and
* polygons.
* @author GaryCXJk
*
*/
public class ModelRendererTurbo extends ModelRenderer
{
public ModelRendererTurbo(ModelBase modelbase, String s)
{
super(modelbase, s);
flip = false;
compiled = false;
displayList = 0;
mirror = false;
showModel = true;
field_1402_i = false;
vertices = new PositionTextureVertex[0];
faces = new TexturedPolygon[0];
forcedRecompile = false;
transformGroup = new HashMap<String, TransformGroup>();
transformGroup.put("0", new TransformGroupBone(new Bone(0, 0, 0, 0), 1D));
textureGroup = new HashMap<String, TextureGroup>();
textureGroup.put("0", new TextureGroup());
currentTextureGroup = textureGroup.get("0");
boxName = s;
defaultTexture = "";
useLegacyCompiler = false;
}
public ModelRendererTurbo(ModelBase modelbase)
{
this(modelbase, null);
}
/**
* Creates a new ModelRenderTurbo object. It requires the coordinates of the
* position of the texture.
* @param modelbase
* @param textureX the x-coordinate on the texture
* @param textureY the y-coordinate on the texture
*/
public ModelRendererTurbo(ModelBase modelbase, int textureX, int textureY)
{
this(modelbase, textureX, textureY, 64, 32);
}
/**
* Creates a new ModelRenderTurbo object. It requires the coordinates of the
* position of the texture, but also allows you to specify the width and height
* of the texture, allowing you to use bigger textures instead.
* @param modelbase
* @param textureX
* @param textureY
* @param textureU
* @param textureV
*/
public ModelRendererTurbo(ModelBase modelbase, int textureX, int textureY, int textureU, int textureV)
{
this(modelbase);
textureOffsetX = textureX;
textureOffsetY = textureY;
textureWidth = textureU;
textureHeight = textureV;
}
/**
* Creates a new polygon.
* @param verts an array of vertices
*/
public void addPolygon(PositionTextureVertex[] verts)
{
copyTo(verts, new TexturedPolygon[] {new TexturedPolygon(verts)});
}
/**
* Creates a new polygon, and adds UV mapping to it.
* @param verts an array of vertices
* @param uv an array of UV coordinates
*/
public void addPolygon(PositionTextureVertex[] verts, int[][] uv)
{
try
{
for(int i = 0; i < verts.length; i++)
{
verts[i] = verts[i].setTexturePosition((float)uv[i][0] / textureWidth, (float)uv[i][1] / textureHeight);
}
}
finally
{
addPolygon(verts);
}
}
/**
* Creates a new polygon with a given UV.
* @param verts an array of vertices
* @param u1
* @param v1
* @param u2
* @param v2
*/
public void addPolygon(PositionTextureVertex[] verts, int u1, int v1, int u2, int v2)
{
copyTo(verts, new TexturedPolygon[] {addPolygonReturn(verts, u1, v1, u2, v2)});
}
private TexturedPolygon addPolygonReturn(PositionTextureVertex[] verts, int u1, int v1, int u2, int v2)
{
if(verts.length < 3)
return null;
float uOffs = 1.0F / ((float) textureWidth * 10.0F);
float vOffs = 1.0F / ((float) textureHeight * 10.0F);
if(verts.length < 4)
{
float xMin = -1;
float yMin = -1;
float xMax = 0;
float yMax = 0;
for(int i = 0; i < verts.length; i++)
{
float xPos = verts[i].texturePositionX;
float yPos = verts[i].texturePositionY;
xMax = Math.max(xMax, xPos);
xMin = (xMin < -1 ? xPos : Math.min(xMin, xPos));
yMax = Math.max(yMax, yPos);
yMin = (yMin < -1 ? yPos : Math.min(yMin, yPos));
}
float uMin = (float) u1 / (float) textureWidth + uOffs;
float vMin = (float) v1 / (float) textureHeight + vOffs;
float uSize = (float) (u2 - u1) / (float) textureWidth - uOffs * 2;
float vSize = (float) (v2 - v1) / (float) textureHeight - vOffs * 2;
float xSize = xMax - xMin;
float ySize = yMax - yMin;
for(int i = 0; i < verts.length; i++)
{
float xPos = verts[i].texturePositionX;
float yPos = verts[i].texturePositionY;
xPos = (xPos - xMin) / xSize;
yPos = (yPos - yMin) / ySize;
verts[i] = verts[i].setTexturePosition(uMin + (xPos * uSize), vMin + (yPos * vSize));
}
}
else
{
verts[0] = verts[0].setTexturePosition((float)u2 / (float) textureWidth - uOffs, (float)v1 / (float)textureHeight + vOffs);
verts[1] = verts[1].setTexturePosition((float)u1 / (float) textureWidth + uOffs, (float)v1 / (float)textureHeight + vOffs);
verts[2] = verts[2].setTexturePosition((float)u1 / (float) textureWidth + uOffs, (float)v2 / (float)textureHeight - vOffs);
verts[3] = verts[3].setTexturePosition((float)u2 / (float) textureWidth - uOffs, (float)v2 / (float)textureHeight - vOffs);
}
return new TexturedPolygon(verts);
}
/**
* Adds a rectangular shape. Basically, you can make any eight-pointed shape you want,
* as the method requires eight vector coordinates.
* @param v a float array with three values, the x, y and z coordinates of the vertex
* @param v1 a float array with three values, the x, y and z coordinates of the vertex
* @param v2 a float array with three values, the x, y and z coordinates of the vertex
* @param v3 a float array with three values, the x, y and z coordinates of the vertex
* @param v4 a float array with three values, the x, y and z coordinates of the vertex
* @param v5 a float array with three values, the x, y and z coordinates of the vertex
* @param v6 a float array with three values, the x, y and z coordinates of the vertex
* @param v7 a float array with three values, the x, y and z coordinates of the vertex
* @param w the width of the shape, used in determining the texture
* @param h the height of the shape, used in determining the texture
* @param d the depth of the shape, used in determining the texture
*/
public void addRectShape(float[] v, float[] v1, float[] v2, float[] v3, float[] v4, float[] v5, float[] v6, float[] v7, int w, int h, int d)
{
PositionTextureVertex[] verts = new PositionTextureVertex[8];
TexturedPolygon[] poly = new TexturedPolygon[6];
PositionTextureVertex positionTexturevertex = new PositionTextureVertex(v[0], v[1], v[2], 0.0F, 0.0F);
PositionTextureVertex positionTexturevertex1 = new PositionTextureVertex(v1[0], v1[1], v1[2], 0.0F, 8F);
PositionTextureVertex positionTexturevertex2 = new PositionTextureVertex(v2[0], v2[1], v2[2], 8F, 8F);
PositionTextureVertex positionTexturevertex3 = new PositionTextureVertex(v3[0], v3[1], v3[2], 8F, 0.0F);
PositionTextureVertex positionTexturevertex4 = new PositionTextureVertex(v4[0], v4[1], v4[2], 0.0F, 0.0F);
PositionTextureVertex positionTexturevertex5 = new PositionTextureVertex(v5[0], v5[1], v5[2], 0.0F, 8F);
PositionTextureVertex positionTexturevertex6 = new PositionTextureVertex(v6[0], v6[1], v6[2], 8F, 8F);
PositionTextureVertex positionTexturevertex7 = new PositionTextureVertex(v7[0], v7[1], v7[2], 8F, 0.0F);
verts[0] = positionTexturevertex;
verts[1] = positionTexturevertex1;
verts[2] = positionTexturevertex2;
verts[3] = positionTexturevertex3;
verts[4] = positionTexturevertex4;
verts[5] = positionTexturevertex5;
verts[6] = positionTexturevertex6;
verts[7] = positionTexturevertex7;
poly[0] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex5, positionTexturevertex1, positionTexturevertex2, positionTexturevertex6
}, textureOffsetX + d + w, textureOffsetY + d, textureOffsetX + d + w + d, textureOffsetY + d + h);
poly[1] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex, positionTexturevertex4, positionTexturevertex7, positionTexturevertex3
}, textureOffsetX + 0, textureOffsetY + d, textureOffsetX + d, textureOffsetY + d + h);
poly[2] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex5, positionTexturevertex4, positionTexturevertex, positionTexturevertex1
}, textureOffsetX + d, textureOffsetY + 0, textureOffsetX + d + w, textureOffsetY + d);
poly[3] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex2, positionTexturevertex3, positionTexturevertex7, positionTexturevertex6
}, textureOffsetX + d + w, textureOffsetY + 0, textureOffsetX + d + w + w, textureOffsetY + d);
poly[4] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex1, positionTexturevertex, positionTexturevertex3, positionTexturevertex2
}, textureOffsetX + d, textureOffsetY + d, textureOffsetX + d + w, textureOffsetY + d + h);
poly[5] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex4, positionTexturevertex5, positionTexturevertex6, positionTexturevertex7
}, textureOffsetX + d + w + d, textureOffsetY + d, textureOffsetX + d + w + d + w, textureOffsetY + d + h);
if(mirror ^ flip)
{
for(int l = 0; l < poly.length; l++)
{
poly[l].flipFace();
}
}
copyTo(verts, poly);
}
/**
* Adds a new box to the model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width (over the x-direction)
* @param h the height (over the y-direction)
* @param d the depth (over the z-direction)
*/
public ModelRendererTurbo addBox(float x, float y, float z, int w, int h, int d)
{
addBox(x, y, z, w, h, d, 0.0F);
return this;
}
/**
* Adds a new box to the model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width (over the x-direction)
* @param h the height (over the y-direction)
* @param d the depth (over the z-direction)
* @param expansion the expansion of the box. It increases the size in each direction by that many.
*/
public void addBox(float x, float y, float z, int w, int h, int d, float expansion)
{
addBox(x, y, z, w, h, d, expansion, 1F);
}
/**
* Adds a new box to the model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width (over the x-direction)
* @param h the height (over the y-direction)
* @param d the depth (over the z-direction)
* @param expansion the expansion of the box. It increases the size in each direction by that many. It's independent from the scale.
* @param scale
*/
public void addBox(float x, float y, float z, int w, int h, int d, float expansion, float scale)
{
float scaleX = (float)w * scale;
float scaleY = (float)h * scale;
float scaleZ = (float)d * scale;
float x1 = x + scaleX;
float y1 = y + scaleY;
float z1 = z + scaleZ;
float expX = expansion + scaleX - (float)w;
float expY = expansion + scaleY - (float)h;
float expZ = expansion + scaleZ - (float)d;
x -= expX;
y -= expY;
z -= expZ;
x1 += expansion;
y1 += expansion;
z1 += expansion;
if(mirror)
{
float xTemp = x1;
x1 = x;
x = xTemp;
}
float[] v = {x, y, z};
float[] v1 = {x1, y, z};
float[] v2 = {x1, y1, z};
float[] v3 = {x, y1, z};
float[] v4 = {x, y, z1};
float[] v5 = {x1, y, z1};
float[] v6 = {x1, y1, z1};
float[] v7 = {x, y1, z1};
addRectShape(v, v1, v2, v3, v4, v5, v6, v7, w, h, d);
}
/**
* Adds a trapezoid-like shape. It's achieved by expanding the shape on one side.
* You can use the static variables <code>MR_RIGHT</code>, <code>MR_LEFT</code>,
* <code>MR_FRONT</code>, <code>MR_BACK</code>, <code>MR_TOP</code> and
* <code>MR_BOTTOM</code>.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width (over the x-direction)
* @param h the height (over the y-direction)
* @param d the depth (over the z-direction)
* @param scale the "scale" of the box. It only increases the size in each direction by that many.
* @param bottomScale the "scale" of the bottom
* @param dir the side the scaling is applied to
*/
public void addTrapezoid(float x, float y, float z, int w, int h, int d, float scale, float bottomScale, int dir)
{
float width = x + (float)w;
float height = y + (float)h;
float depth = z + (float)d;
x -= scale;
y -= scale;
z -= scale;
width += scale;
height += scale;
depth += scale;
int m = (mirror ? -1 : 1);
if(mirror)
{
float f7 = width;
width = x;
x = f7;
}
float[] v = {x, y, z};
float[] v1 = {width, y, z};
float[] v2 = {width, height, z};
float[] v3 = {x, height, z};
float[] v4 = {x, y, depth};
float[] v5 = {width, y, depth};
float[] v6 = {width, height, depth};
float[] v7 = {x, height, depth};
switch(dir)
{
case MR_RIGHT:
v[1] -= bottomScale;
v[2] -= bottomScale;
v3[1] += bottomScale;
v3[2] -= bottomScale;
v4[1] -= bottomScale;
v4[2] += bottomScale;
v7[1] += bottomScale;
v7[2] += bottomScale;
break;
case MR_LEFT:
v1[1] -= bottomScale;
v1[2] -= bottomScale;
v2[1] += bottomScale;
v2[2] -= bottomScale;
v5[1] -= bottomScale;
v5[2] += bottomScale;
v6[1] += bottomScale;
v6[2] += bottomScale;
break;
case MR_FRONT:
v[0] -= m * bottomScale;
v[1] -= bottomScale;
v1[0] += m * bottomScale;
v1[1] -= bottomScale;
v2[0] += m * bottomScale;
v2[1] += bottomScale;
v3[0] -= m * bottomScale;
v3[1] += bottomScale;
break;
case MR_BACK:
v4[0] -= m * bottomScale;
v4[1] -= bottomScale;
v5[0] += m * bottomScale;
v5[1] -= bottomScale;
v6[0] += m * bottomScale;
v6[1] += bottomScale;
v7[0] -= m * bottomScale;
v7[1] += bottomScale;
break;
case MR_TOP:
v[0] -= m * bottomScale;
v[2] -= bottomScale;
v1[0] += m * bottomScale;
v1[2] -= bottomScale;
v4[0] -= m * bottomScale;
v4[2] += bottomScale;
v5[0] += m * bottomScale;
v5[2] += bottomScale;
break;
case MR_BOTTOM:
v2[0] += m * bottomScale;
v2[2] -= bottomScale;
v3[0] -= m * bottomScale;
v3[2] -= bottomScale;
v6[0] += m * bottomScale;
v6[2] += bottomScale;
v7[0] -= m * bottomScale;
v7[2] += bottomScale;
break;
}
addRectShape(v, v1, v2, v3, v4, v5, v6, v7, w, h, d);
}
/**
* Adds a trapezoid-like shape. It's achieved by expanding the shape on one side.
* You can use the static variables <code>MR_RIGHT</code>, <code>MR_LEFT</code>,
* <code>MR_FRONT</code>, <code>MR_BACK</code>, <code>MR_TOP</code> and
* <code>MR_BOTTOM</code>.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width (over the x-direction)
* @param h the height (over the y-direction)
* @param d the depth (over the z-direction)
* @param scale the "scale" of the box. It only increases the size in each direction by that many.
* @param bottomScale the "scale" of the bottom
* @param dir the side the scaling is applied to
*/
/*public void addTrapezoid(float x, float y, float z, int w, int h, int d, float scale, float bottomScale, int dir)
{
float width = x + (float)w;
float height = y + (float)h;
float depth = z + (float)d;
x -= scale;
y -= scale;
z -= scale;
width += scale;
height += scale;
depth += scale;
int m = (mirror ? -1 : 1);
if(mirror)
{
float f7 = width;
width = x;
x = f7;
}
float[] v = {x, y, z};
float[] v1 = {width, y, z};
float[] v2 = {width, height, z};
float[] v3 = {x, height, z};
float[] v4 = {x, y, depth};
float[] v5 = {width, y, depth};
float[] v6 = {width, height, depth};
float[] v7 = {x, height, depth};
switch(dir)
{
case MR_RIGHT:
v[1] -= bottomScale;
v[2] -= bottomScale;
v3[1] += bottomScale;
v3[2] -= bottomScale;
v4[1] -= bottomScale;
v4[2] += bottomScale;
v7[1] += bottomScale;
v7[2] += bottomScale;
break;
case MR_LEFT:
v1[1] -= bottomScale;
v1[2] -= bottomScale;
v2[1] += bottomScale;
v2[2] -= bottomScale;
v5[1] -= bottomScale;
v5[2] += bottomScale;
v6[1] += bottomScale;
v6[2] += bottomScale;
break;
case MR_FRONT:
v[0] -= m * bottomScale;
v[1] -= bottomScale;
v1[0] += m * bottomScale;
v1[1] -= bottomScale;
v2[0] += m * bottomScale;
v2[1] += bottomScale;
v3[0] -= m * bottomScale;
v3[1] += bottomScale;
break;
case MR_BACK:
v4[0] -= m * bottomScale;
v4[1] -= bottomScale;
v5[0] += m * bottomScale;
v5[1] -= bottomScale;
v6[0] += m * bottomScale;
v6[1] += bottomScale;
v7[0] -= m * bottomScale;
v7[1] += bottomScale;
break;
case MR_TOP:
v[0] -= m * bottomScale;
v[2] -= bottomScale;
v1[0] += m * bottomScale;
v1[2] -= bottomScale;
v4[0] -= m * bottomScale;
v4[2] += bottomScale;
v5[0] += m * bottomScale;
v5[2] += bottomScale;
break;
case MR_BOTTOM:
v2[0] += m * bottomScale;
v2[2] -= bottomScale;
v3[0] -= m * bottomScale;
v3[2] -= bottomScale;
v6[0] += m * bottomScale;
v6[2] += bottomScale;
v7[0] -= m * bottomScale;
v7[2] += bottomScale;
break;
}
addRectShape(v, v1, v2, v3, v4, v5, v6, v7, w, h, d);
}*/
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param coordinates an array of coordinates that form the shape
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param direction the direction the starting point of the shape is facing
*/
public void addShape3D(float x, float y, float z, Coord2D[] coordinates, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, int direction)
{
addShape3D(x, y, z, coordinates, depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, direction, null);
}
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param coordinates an array of coordinates that form the shape
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param direction the direction the starting point of the shape is facing
* @param faceLengths An array with the length of each face. Used to set
* the texture width of each face on the side manually.
*/
public void addShape3D(float x, float y, float z, Coord2D[] coordinates, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, int direction, float[] faceLengths)
{
addShape3D(x, y, z, new Shape2D(coordinates), depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, direction, faceLengths);
}
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param coordinates an ArrayList of coordinates that form the shape
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param direction the direction the starting point of the shape is facing
*/
public void addShape3D(float x, float y, float z, ArrayList<Coord2D> coordinates, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, int direction)
{
addShape3D(x, y, z, coordinates, depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, direction, null);
}
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param coordinates an ArrayList of coordinates that form the shape
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param direction the direction the starting point of the shape is facing
* @param faceLengths An array with the length of each face. Used to set
* the texture width of each face on the side manually.
*/
public void addShape3D(float x, float y, float z, ArrayList<Coord2D> coordinates, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, int direction, float[] faceLengths)
{
addShape3D(x, y, z, new Shape2D(coordinates), depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, direction, faceLengths);
}
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param shape a Shape2D which contains the coordinates of the shape points
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param direction the direction the starting point of the shape is facing
*/
public void addShape3D(float x, float y, float z, Shape2D shape, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, int direction)
{
addShape3D(x, y, z, shape, depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, direction, null);
}
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param shape a Shape2D which contains the coordinates of the shape points
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param direction the direction the starting point of the shape is facing
* @param faceLengths An array with the length of each face. Used to set
* the texture width of each face on the side manually.
*/
public void addShape3D(float x, float y, float z, Shape2D shape, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, int direction, float[] faceLengths)
{
float rotX = 0;
float rotY = 0;
float rotZ = 0;
switch(direction)
{
case MR_LEFT:
rotY = pi / 2;
break;
case MR_RIGHT:
rotY = -pi / 2;
break;
case MR_TOP:
rotX = pi / 2;
break;
case MR_BOTTOM:
rotX = -pi / 2;
break;
case MR_FRONT:
rotY = pi;
break;
case MR_BACK:
break;
}
addShape3D(x, y, z, shape, depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, rotX, rotY, rotZ, faceLengths);
}
/**
* Creates a shape from a 2D vector shape.
* @param x the starting x position
* @param y the starting y position
* @param z the starting z position
* @param shape a Shape2D which contains the coordinates of the shape points
* @param depth the depth of the shape
* @param shapeTextureWidth the width of the texture of one side of the shape
* @param shapeTextureHeight the height of the texture the shape
* @param sideTextureWidth the width of the texture of the side of the shape
* @param sideTextureHeight the height of the texture of the side of the shape
* @param rotX the rotation around the x-axis
* @param rotY the rotation around the y-axis
* @param rotZ the rotation around the z-axis
*/
public void addShape3D(float x, float y, float z, Shape2D shape, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, float rotX, float rotY, float rotZ)
{
addShape3D(x, y, z, shape, depth, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, rotX, rotY, rotZ, null);
}
public void addShape3D(float x, float y, float z, Shape2D shape, float depth, int shapeTextureWidth, int shapeTextureHeight, int sideTextureWidth, int sideTextureHeight, float rotX, float rotY, float rotZ, float[] faceLengths)
{
Shape3D shape3D = shape.extrude(x, y, z, rotX, rotY, rotZ, depth, textureOffsetX, textureOffsetY, textureWidth, textureHeight, shapeTextureWidth, shapeTextureHeight, sideTextureWidth, sideTextureHeight, faceLengths);
if(flip)
{
for(int idx = 0; idx < shape3D.faces.length; idx++)
{
shape3D.faces[idx].flipFace();
}
}
copyTo(shape3D.vertices, shape3D.faces);
}
/**
* Adds a cube the size of one pixel. It will take a pixel from the texture and
* uses that as the texture of said cube. The accurate name would actually be
* "addVoxel". This method has been added to make it more compatible with Techne,
* and allows for easy single-colored boxes.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param width the width of the box
* @param height the height of the box
* @param length the length of the box
*/
public void addPixel(float x, float y, float z, float width, float height, float length)
{
addPixel(x, y, z, new float[] {width, height, length}, textureOffsetX, textureOffsetY);
}
/**
* Adds a cube the size of one pixel. It will take a pixel from the texture and
* uses that as the texture of said cube. The accurate name would actually be
* "addVoxel". It will not overwrite the model data, but rather, it will add to
* the model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param scale the "scale" of the cube, where scale is a float integer consisting of three values
* @param w the x-coordinate on the texture
* @param h the y-coordinate on the texture
*/
public void addPixel(float x, float y, float z, float[] scale, int w, int h)
{
PositionTextureVertex[] verts = new PositionTextureVertex[8];
TexturedPolygon[] poly = new TexturedPolygon[6];
float x1 = x + scale[0];
float y1 = y + scale[1];
float z1 = z + scale[2];
float[] f = {x, y, z};
float[] f1 = {x1, y, z};
float[] f2 = {x1, y1, z};
float[] f3 = {x, y1, z};
float[] f4 = {x, y, z1};
float[] f5 = {x1, y, z1};
float[] f6 = {x1, y1, z1};
float[] f7 = {x, y1, z1};
PositionTextureVertex positionTexturevertex = new PositionTextureVertex(f[0], f[1], f[2], 0.0F, 0.0F);
PositionTextureVertex positionTexturevertex1 = new PositionTextureVertex(f1[0], f1[1], f1[2], 0.0F, 8F);
PositionTextureVertex positionTexturevertex2 = new PositionTextureVertex(f2[0], f2[1], f2[2], 8F, 8F);
PositionTextureVertex positionTexturevertex3 = new PositionTextureVertex(f3[0], f3[1], f3[2], 8F, 0.0F);
PositionTextureVertex positionTexturevertex4 = new PositionTextureVertex(f4[0], f4[1], f4[2], 0.0F, 0.0F);
PositionTextureVertex positionTexturevertex5 = new PositionTextureVertex(f5[0], f5[1], f5[2], 0.0F, 8F);
PositionTextureVertex positionTexturevertex6 = new PositionTextureVertex(f6[0], f6[1], f6[2], 8F, 8F);
PositionTextureVertex positionTexturevertex7 = new PositionTextureVertex(f7[0], f7[1], f7[2], 8F, 0.0F);
verts[0] = positionTexturevertex;
verts[1] = positionTexturevertex1;
verts[2] = positionTexturevertex2;
verts[3] = positionTexturevertex3;
verts[4] = positionTexturevertex4;
verts[5] = positionTexturevertex5;
verts[6] = positionTexturevertex6;
verts[7] = positionTexturevertex7;
poly[0] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex5, positionTexturevertex1, positionTexturevertex2, positionTexturevertex6
}, w, h, w + 1, h + 1);
poly[1] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex, positionTexturevertex4, positionTexturevertex7, positionTexturevertex3
}, w, h, w + 1, h + 1);
poly[2] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex5, positionTexturevertex4, positionTexturevertex, positionTexturevertex1
}, w, h, w + 1, h + 1);
poly[3] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex2, positionTexturevertex3, positionTexturevertex7, positionTexturevertex6
}, w, h, w + 1, h + 1);
poly[4] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex1, positionTexturevertex, positionTexturevertex3, positionTexturevertex2
}, w, h, w + 1, h + 1);
poly[5] = addPolygonReturn(new PositionTextureVertex[] {
positionTexturevertex4, positionTexturevertex5, positionTexturevertex6, positionTexturevertex7
}, w, h, w + 1, h + 1);
copyTo(verts, poly);
}
/**
* Creates a model shaped like the exact image on the texture. Note that this method will
* increase the amount of quads on your model, which could effectively slow down your
* PC, so unless it is really a necessity to use it, I'd suggest you avoid using this
* method to create your model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width of the sprite
* @param h the height of the sprite
* @param expansion the expansion of the sprite. It only increases the size in each direction by that many.
*/
public void addSprite(float x, float y, float z, int w, int h, float expansion)
{
addSprite(x, y, z, w, h, 1, false, false, false, false, false, expansion);
}
/**
* Creates a model shaped like the exact image on the texture. Note that this method will
* increase the amount of quads on your model, which could effectively slow down your
* PC, so unless it is really a necessity to use it, I'd suggest you avoid using this
* method to create your model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width of the sprite
* @param h the height of the sprite
* @param rotX a boolean to define if it rotates 90 degrees around its yaw-axis
* @param rotY a boolean to define if it rotates 90 degrees around its pitch-axis
* @param rotZ a boolean to define if it rotates 90 degrees around its roll-axis
* @param mirrorX a boolean to define if the sprite should be mirrored
* @param mirrorY a boolean to define if the sprite should be flipped
* @param expansion the expansion of the sprite. It only increases the size in each direction by that many.
*/
public void addSprite(float x, float y, float z, int w, int h, boolean rotX, boolean rotY, boolean rotZ, boolean mirrorX, boolean mirrorY, float expansion)
{
addSprite(x, y, z, w, h, 1, rotX, rotY, rotZ, mirrorX, mirrorY, expansion);
}
/**
* Creates a model shaped like the exact image on the texture. Note that this method will
* increase the amount of quads on your model, which could effectively slow down your
* PC, so unless it is really a necessity to use it, I'd suggest you avoid using this
* method to create your model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width of the sprite
* @param h the height of the sprite
* @param d the depth of the shape itself
* @param rotX a boolean to define if it rotates 90 degrees around its yaw-axis
* @param rotY a boolean to define if it rotates 90 degrees around its pitch-axis
* @param rotZ a boolean to define if it rotates 90 degrees around its roll-axis
* @param mirrorX a boolean to define if the sprite should be mirrored
* @param mirrorY a boolean to define if the sprite should be flipped
* @param expansion the expansion of the sprite. It only increases the size in each direction by that many.
*/
public void addSprite(float x, float y, float z, int w, int h, int d, boolean rotX, boolean rotY, boolean rotZ, boolean mirrorX, boolean mirrorY, float expansion)
{
addSprite(x, y, z, w, h, d, 1.0F, rotX, rotY, rotZ, mirrorX, mirrorY, expansion);
}
/**
* Creates a model shaped like the exact image on the texture. Note that this method will
* increase the amount of quads on your model, which could effectively slow down your
* PC, so unless it is really a necessity to use it, I'd suggest you avoid using this
* method to create your model.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param w the width of the sprite
* @param h the height of the sprite
* @param d the depth of the shape itself
* @param pixelScale the scale of each individual pixel
* @param rotX a boolean to define if it rotates 90 degrees around its yaw-axis
* @param rotY a boolean to define if it rotates 90 degrees around its pitch-axis
* @param rotZ a boolean to define if it rotates 90 degrees around its roll-axis
* @param mirrorX a boolean to define if the sprite should be mirrored
* @param mirrorY a boolean to define if the sprite should be flipped
* @param expansion the expansion of the sprite. It only increases the size in each direction by that many.
*/
public void addSprite(float x, float y, float z, int w, int h, int d, float pixelScale, boolean rotX, boolean rotY, boolean rotZ, boolean mirrorX, boolean mirrorY, float expansion)
{
String[] mask = new String[h];
char[] str = new char[w];
Arrays.fill(str, '1');
Arrays.fill(mask, new String(str));
addSprite(x, y, z, mask, d, pixelScale, rotX, rotY, rotZ, mirrorX, mirrorY, expansion);
}
/**
* Creates a model shaped like the exact image on the texture. Note that this method will
* increase the amount of quads on your model, which could effectively slow down your
* PC, so unless it is really a necessity to use it, I'd suggest you avoid using this
* method to create your model.
* <br /><br />
* This method uses a mask string. This way you can reduce the amount of quads used. To
* use this, create a String array, where you use a 1 to signify that the pixel will be
* drawn. Any other character will cause that pixel to not be drawn.
* @param x the starting x-position
* @param y the starting y-position
* @param z the starting z-position
* @param mask an array with the mask string
* @param d the depth of the shape itself
* @param pixelScale the scale of each individual pixel
* @param rotX a boolean to define if it rotates 90 degrees around its yaw-axis
* @param rotY a boolean to define if it rotates 90 degrees around its pitch-axis
* @param rotZ a boolean to define if it rotates 90 degrees around its roll-axis
* @param mirrorX a boolean to define if the sprite should be mirrored
* @param mirrorY a boolean to define if the sprite should be flipped
* @param expansion the expansion of the sprite. It only increases the size in each direction by that many.
*/
public void addSprite(float x, float y, float z, String[] mask, int d, float pixelScale, boolean rotX, boolean rotY, boolean rotZ, boolean mirrorX, boolean mirrorY, float expansion)
{
int w = mask[0].length();
int h = mask.length;
float x1 = x - expansion;
float y1 = y - expansion;
float z1 = z - expansion;
int wDir = 0;
int hDir = 0;
int dDir = 0;
float wScale = 1F + (expansion / ((float) w * pixelScale));
float hScale = 1F + (expansion / ((float) h * pixelScale));
if(!rotX)
{
if(!rotY)
{
if(!rotZ)
{
wDir = 0;
hDir = 1;
dDir = 2;
}
else
{
wDir = 1;
hDir = 0;
dDir = 2;
}
}
else
{
if(!rotZ)
{
wDir = 2;
hDir = 1;
dDir = 0;
}
else
{
wDir = 2;
hDir = 0;
dDir = 1;
}
}
}
else
{
if(!rotY)
{
if(!rotZ)
{
wDir = 0;
hDir = 2;
dDir = 1;
}
else
{
wDir = 1;
hDir = 2;
dDir = 0;
}
}
else
{
if(!rotZ)
{
wDir = 2;
hDir = 0;
dDir = 1;
}
else
{
wDir = 2;
hDir = 1;
dDir = 0;
}
}
}
int texStartX = textureOffsetX + (mirrorX ? w * 1 - 1 : 0);
int texStartY = textureOffsetY + (mirrorY ? h * 1 - 1 : 0);
int texDirX = (mirrorX ? -1 : 1);
int texDirY = (mirrorY ? -1 : 1);
float wVoxSize = getPixelSize(wScale, hScale, d * pixelScale + expansion * 2, 0, 1, wDir, 1, 1);
float hVoxSize = getPixelSize(wScale, hScale, d * pixelScale + expansion * 2, 0, 1, hDir, 1, 1);
float dVoxSize = getPixelSize(wScale, hScale, d * pixelScale + expansion * 2, 0, 1, dDir, 1, 1);
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
if(mask[j].charAt(i) == '1')
{
addPixel(x1 + getPixelSize(wScale, hScale, 0, wDir, hDir, 0, i, j),
y1 + getPixelSize(wScale, hScale, 0, wDir, hDir, 1, i, j),
z1 + getPixelSize(wScale, hScale, 0, wDir, hDir, 2, i, j),
new float[] {wVoxSize, hVoxSize, dVoxSize}, texStartX + texDirX * i, texStartY + texDirY * j);
}
}
}
}
private float getPixelSize(float wScale, float hScale, float dScale, int wDir, int hDir, int checkDir, int texPosX, int texPosY)
{
return (wDir == checkDir ? wScale * texPosX : (hDir == checkDir ? hScale * texPosY : dScale));
}
/**
* Adds a spherical shape.
* @param x
* @param y
* @param z
* @param r
* @param segs
* @param rings
* @param textureW
* @param textureH
*/
public void addSphere(float x, float y, float z, float r, int segs, int rings, int textureW, int textureH)
{
if(segs < 3)
segs = 3;
rings++;
PositionTextureVertex[] tempVerts = new PositionTextureVertex[segs * (rings - 1) + 2];
TexturedPolygon[] poly = new TexturedPolygon[segs * rings];
tempVerts[0] = new PositionTextureVertex(x, y - r, z, 0, 0);
tempVerts[tempVerts.length - 1] = new PositionTextureVertex(x, y + r, z, 0, 0);
float uOffs = 1.0F / ((float) textureWidth * 10.0F);
float vOffs = 1.0F / ((float) textureHeight * 10.0F);
float texW = (float) textureW / (float)textureWidth - 2F * uOffs;
float texH = (float) textureH / (float)textureHeight - 2F * vOffs;
float segW = texW / (float) segs;
float segH = texH / (float) rings;
float startU = (float) textureOffsetX / (float) textureWidth;
float startV = (float) textureOffsetY / (float) textureHeight;
int currentFace = 0;
for(int j = 1; j < rings; j++)
{
for(int i = 0; i < segs; i++)
{
float yWidth = MathHelper.cos(-pi / 2 + (pi / (float)rings) * (float) j);
float yHeight = MathHelper.sin(-pi / 2 + (pi / (float)rings) * (float) j);
float xSize = MathHelper.sin((pi / (float)segs) * i * 2F + pi) * yWidth;
float zSize = -MathHelper.cos((pi / (float)segs) * i * 2F + pi) * yWidth;
int curVert = 1 + i + segs * (j - 1);
tempVerts[curVert] = new PositionTextureVertex(x + xSize * r, y + yHeight * r, z + zSize * r, 0, 0);
if(i > 0)
{
PositionTextureVertex[] verts;
if(j == 1)
{
verts = new PositionTextureVertex[4];
verts[0] = tempVerts[curVert].setTexturePosition(startU + segW * i, startV + segH * j);
verts[1] = tempVerts[curVert - 1].setTexturePosition(startU + segW * (i - 1), startV + segH * j);
verts[2] = tempVerts[0].setTexturePosition(startU + segW * (i - 1), startV);
verts[3] = tempVerts[0].setTexturePosition(startU + segW + segW * i, startV);
}
else
{
verts = new PositionTextureVertex[4];
verts[0] = tempVerts[curVert].setTexturePosition(startU + segW * i, startV + segH * j);
verts[1] = tempVerts[curVert - 1].setTexturePosition(startU + segW * (i - 1), startV + segH * j);
verts[2] = tempVerts[curVert - 1 - segs].setTexturePosition(startU + segW * (i - 1), startV + segH * (j - 1));
verts[3] = tempVerts[curVert - segs].setTexturePosition(startU + segW * i, startV + segH * (j - 1));
}
poly[currentFace] = new TexturedPolygon(verts);
currentFace++;
}
}
PositionTextureVertex[] verts;
if(j == 1)
{
verts = new PositionTextureVertex[4];
verts[0] = tempVerts[1].setTexturePosition(startU + segW * segs, startV + segH * j);
verts[1] = tempVerts[segs].setTexturePosition(startU + segW * (segs - 1), startV + segH * j);
verts[2] = tempVerts[0].setTexturePosition(startU + segW * (segs - 1), startV);
verts[3] = tempVerts[0].setTexturePosition(startU + segW * segs, startV);
}
else
{
verts = new PositionTextureVertex[4];
verts[0] = tempVerts[1 + segs * (j - 1)].setTexturePosition(startU + texW, startV + segH * j);
verts[1] = tempVerts[segs * (j - 1) + segs].setTexturePosition(startU + texW - segW, startV + segH * j);
verts[2] = tempVerts[segs * (j - 1)].setTexturePosition(startU + texW - segW, startV + segH * (j - 1));
verts[3] = tempVerts[1 + segs * (j - 1) - segs].setTexturePosition(startU + texW, startV + segH * (j - 1));
}
poly[currentFace] = new TexturedPolygon(verts);
currentFace++;
}
for(int i = 0; i < segs; i++)
{
PositionTextureVertex[] verts = new PositionTextureVertex[3];
int curVert = tempVerts.length - (segs + 1);
verts[0] = tempVerts[tempVerts.length - 1].setTexturePosition(startU + segW * (i + 0.5F), startV + texH);
verts[1] = tempVerts[curVert + i].setTexturePosition(startU + segW * i, startV + texH - segH);
verts[2] = tempVerts[curVert + ((i + 1) % segs)].setTexturePosition(startU + segW * (i + 1), startV + texH - segH);
poly[currentFace] = new TexturedPolygon(verts);
currentFace++;
}
copyTo(tempVerts, poly);
}
/**
* Adds a cone.
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
*/
public void addCone(float x, float y, float z, float radius, float length, int segments)
{
addCone(x, y, z, radius, length, segments, 1F);
}
/**
* Adds a cone.
*
* baseScale cannot be zero. If it is, it will automatically be set to 1F.
*
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
* @param baseScale the scaling of the base. Can be negative.
*/
public void addCone(float x, float y, float z, float radius, float length, int segments, float baseScale)
{
addCone(x, y, z, radius, length, segments, baseScale, MR_TOP);
}
/**
* Adds a cone.
*
* baseScale cannot be zero. If it is, it will automatically be set to 1F.
*
* Setting the baseDirection to either MR_LEFT, MR_BOTTOM or MR_BACK will result in
* the top being placed at the (x,y,z).
*
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
* @param baseScale the scaling of the base. Can be negative.
* @param baseDirection the direction it faces
*/
public void addCone(float x, float y, float z, float radius, float length, int segments, float baseScale, int baseDirection)
{
addCone(x, y, z, radius, length, segments, baseScale, baseDirection, (int)Math.floor(radius * 2F), (int)Math.floor(radius * 2F));
}
/**
* Adds a cone.
*
* baseScale cannot be zero. If it is, it will automatically be set to 1F.
*
* Setting the baseDirection to either MR_LEFT, MR_BOTTOM or MR_BACK will result in
* the top being placed at the (x,y,z).
*
* The textures for the sides are placed next to each other.
*
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
* @param baseScale the scaling of the base. Can be negative.
* @param baseDirection the direction it faces
* @param textureCircleDiameterW the diameter width of the circle on the texture
* @param textureCircleDiameterH the diameter height of the circle on the texture
*/
public void addCone(float x, float y, float z, float radius, float length, int segments, float baseScale, int baseDirection, int textureCircleDiameterW, int textureCircleDiameterH)
{
addCylinder(x, y, z, radius, length, segments, baseScale, 0.0F, baseDirection, textureCircleDiameterW, textureCircleDiameterH, 1);
}
/**
* Adds a cylinder.
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
*/
public void addCylinder(float x, float y, float z, float radius, float length, int segments)
{
addCylinder(x, y, z, radius, length, segments, 1F, 1F);
}
/**
* Adds a cylinder.
*
* You can make cones by either setting baseScale or topScale to zero. Setting both
* to zero will set the baseScale to 1F.
*
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
* @param baseScale the scaling of the base. Can be negative.
* @param topScale the scaling of the top. Can be negative.
*/
public void addCylinder(float x, float y, float z, float radius, float length, int segments, float baseScale, float topScale)
{
addCylinder(x, y, z, radius, length, segments, baseScale, topScale, MR_TOP);
}
/**
* Adds a cylinder.
*
* You can make cones by either setting baseScale or topScale to zero. Setting both
* to zero will set the baseScale to 1F.
*
* Setting the baseDirection to either MR_LEFT, MR_BOTTOM or MR_BACK will result in
* the top being placed at the (x,y,z).
*
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
* @param baseScale the scaling of the base. Can be negative.
* @param topScale the scaling of the top. Can be negative.
* @param baseDirection the direction it faces
*/
public void addCylinder(float x, float y, float z, float radius, float length, int segments, float baseScale, float topScale, int baseDirection)
{
addCylinder(x, y, z, radius, length, segments, baseScale, topScale, baseDirection, (int)Math.floor(radius * 2F), (int)Math.floor(radius * 2F), (int)Math.floor(length));
}
/**
* Adds a cylinder.
*
* You can make cones by either setting baseScale or topScale to zero. Setting both
* to zero will set the baseScale to 1F.
*
* Setting the baseDirection to either MR_LEFT, MR_BOTTOM or MR_BACK will result in
* the top being placed at the (x,y,z).
*
* The textures for the base and top are placed next to each other, while the body
* will be placed below the circles.
*
* @param x the x-position of the base
* @param y the y-position of the base
* @param z the z-position of the base
* @param radius the radius of the cylinder
* @param length the length of the cylinder
* @param segments the amount of segments the cylinder is made of
* @param baseScale the scaling of the base. Can be negative.
* @param topScale the scaling of the top. Can be negative.
* @param baseDirection the direction it faces
* @param textureCircleDiameterW the diameter width of the circle on the texture
* @param textureCircleDiameterH the diameter height of the circle on the texture
* @param textureH the height of the texture of the body
*/
public void addCylinder(float x, float y, float z, float radius, float length, int segments, float baseScale, float topScale, int baseDirection, int textureCircleDiameterW, int textureCircleDiameterH, int textureH)
{
boolean dirTop = (baseDirection == MR_TOP || baseDirection == MR_BOTTOM);
boolean dirSide = (baseDirection == MR_RIGHT || baseDirection == MR_LEFT);
boolean dirFront = (baseDirection == MR_FRONT || baseDirection == MR_BACK);
boolean dirMirror = (baseDirection == MR_LEFT || baseDirection == MR_BOTTOM || baseDirection == MR_BACK);
boolean coneBase = (baseScale == 0);
boolean coneTop = (topScale == 0);
if(coneBase && coneTop)
{
baseScale = 1F;
coneBase = false;
}
PositionTextureVertex[] tempVerts = new PositionTextureVertex[segments * (coneBase || coneTop ? 1 : 2) + 2];
TexturedPolygon[] poly = new TexturedPolygon[segments * (coneBase || coneTop ? 2 : 3)];
float xLength = (dirSide ? length : 0);
float yLength = (dirTop ? length : 0);
float zLength = (dirFront ? length : 0);
float xStart = (dirMirror ? x + xLength : x);
float yStart = (dirMirror ? y + yLength : y);
float zStart = (dirMirror ? z + zLength : z);
float xEnd = (!dirMirror ? x + xLength : x);
float yEnd = (!dirMirror ? y + yLength : y);
float zEnd = (!dirMirror ? z + zLength : z);
tempVerts[0] = new PositionTextureVertex(xStart, yStart, zStart, 0, 0);
tempVerts[tempVerts.length - 1] = new PositionTextureVertex(xEnd, yEnd, zEnd, 0, 0);
float xCur = xStart;
float yCur = yStart;
float zCur = zStart;
float sCur = (coneBase ? topScale : baseScale);
for(int repeat = 0; repeat < (coneBase || coneTop ? 1 : 2); repeat++)
{
for(int index = 0; index < segments; index++)
{
float xSize = (mirror ^ dirMirror ? -1 : 1) * MathHelper.sin((pi / (float)segments) * index * 2F + pi) * radius * sCur;
float zSize = -MathHelper.cos((pi / (float)segments) * index * 2F + pi) * radius * sCur;
float xPlace = xCur + (!dirSide ? xSize : 0);
float yPlace = yCur + (!dirTop ? zSize : 0);
float zPlace = zCur + (dirSide ? xSize : (dirTop ? zSize : 0));
tempVerts[1 + index + repeat * segments] = new PositionTextureVertex(xPlace, yPlace, zPlace, 0, 0 );
}
xCur = xEnd;
yCur = yEnd;
zCur = zEnd;
sCur = topScale;
}
float uScale = 1.0F / (float) textureWidth;
float vScale = 1.0F / (float) textureHeight;
float uOffset = uScale / 20.0F;
float vOffset = vScale / 20.0F;
float uCircle = (float)textureCircleDiameterW * uScale;
float vCircle = (float)textureCircleDiameterH * vScale;
float uWidth = (uCircle * 2F - uOffset * 2F) / (float) segments;
float vHeight = (float)textureH * vScale - uOffset * 2f;
float uStart = (float)textureOffsetX * uScale;
float vStart = (float)textureOffsetY * vScale;
PositionTextureVertex[] vert;
for(int index = 0; index < segments; index++)
{
int index2 = (index + 1) % segments;
float uSize = MathHelper.sin((pi / (float)segments) * index * 2F + (!dirTop ? 0 : pi)) * (0.5F * uCircle - 2F * uOffset);
float vSize = MathHelper.cos((pi / (float)segments) * index * 2F + (!dirTop ? 0 : pi)) * (0.5F * vCircle - 2F * vOffset);
float uSize1 = MathHelper.sin((pi / (float)segments) * index2 * 2F + (!dirTop ? 0 : pi)) * (0.5F * uCircle - 2F * uOffset);
float vSize1 = MathHelper.cos((pi / (float)segments) * index2 * 2F + (!dirTop ? 0 : pi)) * (0.5F * vCircle - 2F * vOffset);
vert = new PositionTextureVertex[3];
vert[0] = tempVerts[0].setTexturePosition(uStart + 0.5F * uCircle, vStart + 0.5F * vCircle);
vert[1] = tempVerts[1 + index2].setTexturePosition(uStart + 0.5F * uCircle + uSize1, vStart + 0.5F * vCircle + vSize1);
vert[2] = tempVerts[1 + index].setTexturePosition(uStart + 0.5F * uCircle + uSize, vStart + 0.5F * vCircle + vSize);
poly[index] = new TexturedPolygon(vert);
if(mirror ^ flip)
poly[index].flipFace();
if(!coneBase && !coneTop)
{
vert = new PositionTextureVertex[4];
vert[0] = tempVerts[1 + index].setTexturePosition(uStart + uOffset + uWidth * (float)index, vStart + vOffset + vCircle);
vert[1] = tempVerts[1 + index2].setTexturePosition(uStart + uOffset + uWidth * (float)(index + 1), vStart + vOffset + vCircle);
vert[2] = tempVerts[1 + segments + index2].setTexturePosition(uStart + uOffset + uWidth * (float)(index + 1), vStart + vOffset + vCircle + vHeight);
vert[3] = tempVerts[1 + segments + index].setTexturePosition(uStart + uOffset + uWidth * (float)index, vStart + vOffset + vCircle + vHeight);
poly[index + segments] = new TexturedPolygon(vert);
if(mirror ^ flip)
poly[index + segments].flipFace();
}
vert = new PositionTextureVertex[3];
vert[0] = tempVerts[tempVerts.length - 1].setTexturePosition(uStart + 1.5F * uCircle, vStart + 0.5F * vCircle);
vert[1] = tempVerts[tempVerts.length - 2 - index].setTexturePosition(uStart + 1.5F * uCircle + uSize1, vStart + 0.5F * vCircle + vSize1);
vert[2] = tempVerts[tempVerts.length - (1 + segments) + ((segments - index) % segments)].setTexturePosition(uStart + 1.5F * uCircle + uSize, vStart + 0.5F * vCircle + vSize);
poly[poly.length - segments + index] = new TexturedPolygon(vert);
if(mirror ^ flip)
poly[poly.length - segments + index].flipFace();
}
copyTo(tempVerts, poly);
}
/**
* Adds a Waveform .obj file as a model. Model files use the entire texture file.
* @param file the location of the .obj file. The location is relative to the base directories,
* which are either resources/models or resources/mods/models.
*/
public void addObj(String file)
{
addModel(file, ModelPool.OBJ);
}
/**
* Adds model format support. Model files use the entire texture file.
* @param file the location of the model file. The location is relative to the base directories,
* which are either resources/models or resources/mods/models.
* @param modelFormat the class of the model format interpreter
*/
public void addModel(String file, Class modelFormat)
{
ModelPoolEntry entry = ModelPool.addFile(file, modelFormat, transformGroup, textureGroup);
if(entry == null)
return;
PositionTextureVertex[] verts = Arrays.copyOf(entry.vertices, entry.vertices.length);
TexturedPolygon[] poly = Arrays.copyOf(entry.faces, entry.faces.length);
if(flip)
{
for(int l = 0; l < faces.length; l++)
{
faces[l].flipFace();
}
}
copyTo(verts, poly, false);
}
/**
* Sets a new position for the texture offset.
* @param x the x-coordinate of the texture start
* @param y the y-coordinate of the texture start
*/
public ModelRendererTurbo setTextureOffset(int x, int y)
{
textureOffsetX = x;
textureOffsetY = y;
return this;
}
/**
* Sets the position of the shape, relative to the model's origins. Note that changing
* the offsets will not change the pivot of the model.
* @param x the x-position of the shape
* @param y the y-position of the shape
* @param z the z-position of the shape
*/
public void setPosition(float x, float y, float z)
{
rotationPointX = x;
rotationPointY = y;
rotationPointZ = z;
}
/**
* Mirrors the model in any direction.
* @param x whether the model should be mirrored in the x-direction
* @param y whether the model should be mirrored in the y-direction
* @param z whether the model should be mirrored in the z-direction
*/
public void doMirror(boolean x, boolean y, boolean z)
{
for(int i = 0; i < faces.length; i++)
{
PositionTextureVertex[] verts = faces[i].vertexPositions;
for(int j = 0; j < verts.length; j++)
{
verts[j].vector3D.xCoord *= (x ? -1 : 1);
verts[j].vector3D.yCoord *= (y ? -1 : 1);
verts[j].vector3D.zCoord *= (z ? -1 : 1);
}
if(x^y^z)
faces[i].flipFace();
}
}
/**
* Sets whether the shape is mirrored or not. This has effect on the way the textures
* get displayed. When working with addSprite, addPixel and addObj, it will be ignored.
* @param isMirrored a boolean to define whether the shape is mirrored
*/
public void setMirrored(boolean isMirrored)
{
mirror = isMirrored;
}
/**
* Sets whether the shape's faces are flipped or not. When GL_CULL_FACE is enabled,
* it won't render the back faces, effectively giving you the possibility to make
* "hollow" shapes. When working with addSprite and addPixel, it will be ignored.
* @param isFlipped a boolean to define whether the shape is flipped
*/
public void setFlipped(boolean isFlipped)
{
flip = isFlipped;
}
/**
* Clears the current shape. Since all shapes are stacked into one shape, you can't
* just replace a shape by overwriting the shape with another one. In this case you
* would need to clear the shape first.
*/
public void clear()
{
vertices = new PositionTextureVertex[0];
faces = new TexturedPolygon[0];
transformGroup.clear();
transformGroup.put("0", new TransformGroupBone(new Bone(0, 0, 0, 0), 1D));
currentGroup = transformGroup.get("0");
}
/**
* Copies an array of vertices and polygons to the current shape. This mainly is
* used to copy each shape to the main class, but you can just use it to copy
* your own shapes, for example from other classes, into the current class.
* @param verts the array of vertices you want to copy
* @param poly the array of polygons you want to copy
*/
public void copyTo(PositionTextureVertex[] verts, TexturedPolygon[] poly)
{
copyTo(verts, poly, true);
}
public void copyTo(PositionTextureVertex[] verts, TexturedPolygon[] poly, boolean copyGroup)
{
vertices = Arrays.copyOf(vertices, vertices.length + verts.length);
faces = Arrays.copyOf(faces, faces.length + poly.length);
for(int idx = 0; idx < verts.length; idx++)
{
vertices[vertices.length - verts.length + idx] = verts[idx];
if(copyGroup && verts[idx] instanceof PositionTransformVertex)
((PositionTransformVertex)verts[idx]).addGroup(currentGroup);
}
for(int idx = 0; idx < poly.length; idx++)
{
faces[faces.length - poly.length + idx] = poly[idx];
if(copyGroup)
currentTextureGroup.addPoly(poly[idx]);
}
}
/**
* Copies an array of vertices and quads to the current shape. This method
* converts quads to polygons and then calls the main copyTo method.
* @param verts the array of vertices you want to copy
* @param quad the array of quads you want to copy
*/
public void copyTo(PositionTextureVertex[] verts, TexturedQuad[] quad)
{
TexturedPolygon[] poly = new TexturedPolygon[quad.length];
for(int idx = 0; idx < quad.length; idx++)
{
poly[idx] = new TexturedPolygon(quad[idx].vertexPositions);
}
copyTo(verts, poly);
}
/**
* Sets the current transformation group. The transformation group is used
* to allow for vertex transformation. If a transformation group does not exist,
* a new one will be created.
* @param groupName the name of the transformation group you want to switch to
*/
public void setGroup(String groupName)
{
setGroup(groupName, new Bone(0, 0, 0, 0), 1D);
}
/**
* Sets the current transformation group. The transformation group is used
* to allow for vertex transformation. If a transformation group does not exist,
* a new one will be created.
* @param groupName the name of the transformation group you want to switch to
* @param bone the Bone this transformation group is attached to
* @param weight the weight of the transformation group
*/
public void setGroup(String groupName, Bone bone, double weight)
{
if(!transformGroup.containsKey(groupName))
transformGroup.put(groupName, new TransformGroupBone(bone, weight));
currentGroup = transformGroup.get(groupName);
}
/**
* Gets the current transformation group.
* @return the current PositionTransformGroup.
*/
public TransformGroup getGroup()
{
return currentGroup;
}
/**
* Gets the transformation group with a given group name.
* @return the current PositionTransformGroup.
*/
public TransformGroup getGroup(String groupName)
{
if(!transformGroup.containsKey(groupName))
return null;
return transformGroup.get(groupName);
}
/**
* Sets the current texture group, which is used to switch the
* textures on a per-model base. Do note that any model that is
* rendered afterwards will use the same texture. To counter it,
* set a default texture, either at initialization or before
* rendering.
* @param groupName The name of the texture group. If the texture
* group doesn't exist, it creates a new group automatically.
*/
public void setTextureGroup(String groupName)
{
if(!textureGroup.containsKey(groupName))
{
textureGroup.put(groupName, new TextureGroup());
}
currentTextureGroup = textureGroup.get(groupName);
}
/**
* Gets the current texture group.
* @return a TextureGroup object.
*/
public TextureGroup getTextureGroup()
{
return currentTextureGroup;
}
/**
* Gets the texture group with the given name.
* @param groupName the name of the texture group to return
* @return a TextureGroup object.
*/
public TextureGroup getTextureGroup(String groupName)
{
if(!textureGroup.containsKey(groupName))
return null;
return textureGroup.get(groupName);
}
/**
* Sets the texture of the current texture group.
* @param s the filename
*/
public void setGroupTexture(String s)
{
currentTextureGroup.texture = s;
}
/**
* Sets the default texture. When left as an empty string,
* it will use the texture that has been set previously.
* Note that this will also move on to other rendered models
* of the same entity.
* @param s the filename
*/
public void setDefaultTexture(String s)
{
defaultTexture = s;
}
/**
* Renders the shape.
* @param worldScale the scale of the shape. Usually is 0.0625.
*/
public void render(float worldScale)
{
if(field_1402_i)
{
return;
}
if(!showModel)
{
return;
}
if(!compiled || forcedRecompile)
{
compileDisplayList(worldScale);
}
if(rotateAngleX != 0.0F || rotateAngleY != 0.0F || rotateAngleZ != 0.0F)
{
GL11.glPushMatrix();
GL11.glTranslatef(rotationPointX * worldScale, rotationPointY * worldScale, rotationPointZ * worldScale);
if(rotateAngleZ != 0.0F)
{
GL11.glRotatef(rotateAngleZ * 57.29578F, 0.0F, 0.0F, 1.0F);
}
if(rotateAngleY != 0.0F)
{
GL11.glRotatef(rotateAngleY * 57.29578F, 0.0F, 1.0F, 0.0F);
}
if(rotateAngleX != 0.0F)
{
GL11.glRotatef(rotateAngleX * 57.29578F, 1.0F, 0.0F, 0.0F);
}
callDisplayList();
if(childModels != null)
{
for(int i = 0; i < childModels.size(); i++)
{
((ModelRenderer)childModels.get(i)).render(worldScale);
}
}
GL11.glPopMatrix();
} else
if(rotationPointX != 0.0F || rotationPointY != 0.0F || rotationPointZ != 0.0F)
{
GL11.glTranslatef(rotationPointX * worldScale, rotationPointY * worldScale, rotationPointZ * worldScale);
callDisplayList();
if(childModels != null)
{
for(int i = 0; i < childModels.size(); i++)
{
((ModelRenderer)childModels.get(i)).render(worldScale);
}
}
GL11.glTranslatef(-rotationPointX * worldScale, -rotationPointY * worldScale, -rotationPointZ * worldScale);
} else
{
callDisplayList();
if(childModels != null)
{
for(int i = 0; i < childModels.size(); i++)
{
((ModelRenderer)childModels.get(i)).render(worldScale);
}
}
}
}
public void renderWithRotation(float f)
{
if(field_1402_i)
{
return;
}
if(!showModel)
{
return;
}
if(!compiled)
{
compileDisplayList(f);
}
GL11.glPushMatrix();
GL11.glTranslatef(rotationPointX * f, rotationPointY * f, rotationPointZ * f);
if(rotateAngleY != 0.0F)
{
GL11.glRotatef(rotateAngleY * 57.29578F, 0.0F, 1.0F, 0.0F);
}
if(rotateAngleX != 0.0F)
{
GL11.glRotatef(rotateAngleX * 57.29578F, 1.0F, 0.0F, 0.0F);
}
if(rotateAngleZ != 0.0F)
{
GL11.glRotatef(rotateAngleZ * 57.29578F, 0.0F, 0.0F, 1.0F);
}
callDisplayList();
GL11.glPopMatrix();
}
public void postRender(float f)
{
if(field_1402_i)
{
return;
}
if(!showModel)
{
return;
}
if(!compiled || forcedRecompile)
{
compileDisplayList(f);
}
if(rotateAngleX != 0.0F || rotateAngleY != 0.0F || rotateAngleZ != 0.0F)
{
GL11.glTranslatef(rotationPointX * f, rotationPointY * f, rotationPointZ * f);
if(rotateAngleZ != 0.0F)
{
GL11.glRotatef(rotateAngleZ * 57.29578F, 0.0F, 0.0F, 1.0F);
}
if(rotateAngleY != 0.0F)
{
GL11.glRotatef(rotateAngleY * 57.29578F, 0.0F, 1.0F, 0.0F);
}
if(rotateAngleX != 0.0F)
{
GL11.glRotatef(rotateAngleX * 57.29578F, 1.0F, 0.0F, 0.0F);
}
} else
if(rotationPointX != 0.0F || rotationPointY != 0.0F || rotationPointZ != 0.0F)
{
GL11.glTranslatef(rotationPointX * f, rotationPointY * f, rotationPointZ * f);
}
}
private void callDisplayList()
{
if(useLegacyCompiler)
GL11.glCallList(displayList);
else
{
RenderEngine renderEngine = RenderManager.instance.renderEngine;
Collection<TextureGroup> textures = textureGroup.values();
Iterator<TextureGroup> itr = textures.iterator();
for(int i = 0; itr.hasNext(); i++)
{
TextureGroup curTexGroup = (TextureGroup)itr.next();
curTexGroup.loadTexture();
GL11.glCallList(displayListArray[i]);
if(!defaultTexture.equals(""))
renderEngine.bindTexture(defaultTexture);
}
}
}
private void compileDisplayList(float worldScale)
{
if(useLegacyCompiler)
compileLegacyDisplayList(worldScale);
else
{
Collection<TextureGroup> textures = textureGroup.values();
Iterator<TextureGroup> itr = textures.iterator();
displayListArray = new int[textureGroup.size()];
for(int i = 0; itr.hasNext(); i++)
{
displayListArray[i] = GLAllocation.generateDisplayLists(1);
GL11.glNewList(displayListArray[i], 4864);
Tessellator tessellator = Tessellator.instance;
TextureGroup usedGroup = (TextureGroup)itr.next();
for(int j = 0; j < usedGroup.poly.size(); j++)
{
usedGroup.poly.get(j).draw(tessellator, worldScale);
}
GL11.glEndList();
}
}
compiled = true;
}
private void compileLegacyDisplayList(float worldScale)
{
displayList = GLAllocation.generateDisplayLists(1);
GL11.glNewList(displayList, 4864 /*GL_COMPILE*/);
Tessellator tessellator = Tessellator.instance;
for(int i = 0; i < faces.length; i++)
{
faces[i].draw(tessellator, worldScale);
}
GL11.glEndList();
}
private PositionTextureVertex vertices[];
private TexturedPolygon faces[];
private int textureOffsetX;
private int textureOffsetY;
private boolean compiled;
private int displayList;
private int displayListArray[];
private Map<String, TransformGroup> transformGroup;
private Map<String, TextureGroup> textureGroup;
private TransformGroup currentGroup;
private TextureGroup currentTextureGroup;
public boolean mirror;
public boolean flip;
public boolean showModel;
public boolean field_1402_i;
public boolean forcedRecompile;
public boolean useLegacyCompiler;
public List cubeList;
public List childModels;
public final String boxName;
private String defaultTexture;
public static final int MR_FRONT = 0;
public static final int MR_BACK = 1;
public static final int MR_LEFT = 2;
public static final int MR_RIGHT = 3;
public static final int MR_TOP = 4;
public static final int MR_BOTTOM = 5;
private static final float pi = (float) Math.PI;
}